/* * Copyright (C) 2008 Philippe Gerum . * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include #include #include #include "boilerplate/tlsf/tlsf.h" #include "copperplate/heapobj.h" #include "copperplate/debug.h" #include "copperplate/threadobj.h" #include "xenomai/init.h" #include "internal.h" #if LONG_BIT == 32 #define TLSF_BLOCK_ALIGN (8 * 2) #else #define TLSF_BLOCK_ALIGN (16 * 2) #endif static int tlsf_pool_overhead; int __heapobj_init_private(struct heapobj *hobj, const char *name, size_t size, void *mem) { if (mem == NULL) { /* * When the memory area is unspecified, obtain it from * the main pool, accounting for the TLSF overhead. */ size += tlsf_pool_overhead; mem = tlsf_malloc(size); if (mem == NULL) return __bt(-ENOMEM); } if (name) snprintf(hobj->name, sizeof(hobj->name), "%s", name); else snprintf(hobj->name, sizeof(hobj->name), "%p", hobj); hobj->pool = mem; /* Make sure to wipe out tlsf's signature. */ memset(mem, 0, size < 32 ? size : 32); hobj->size = init_memory_pool(size, mem); if (hobj->size == (size_t)-1) return __bt(-EINVAL); return 0; } int heapobj_init_array_private(struct heapobj *hobj, const char *name, size_t size, int elems) { size_t poolsz; if (size == 0 || elems <= 0) return __bt(-EINVAL); poolsz = (size + TLSF_BLOCK_ALIGN - 1) & ~(TLSF_BLOCK_ALIGN - 1); poolsz *= elems; return __bt(__heapobj_init_private(hobj, name, poolsz, NULL)); } int heapobj_pkg_init_private(void) { size_t alloc_size, available_size; void *mem; #ifdef CONFIG_XENO_PSHARED alloc_size = MIN_TLSF_HEAPSZ; #else alloc_size = __copperplate_setup_data.mem_pool; if (alloc_size < MIN_TLSF_HEAPSZ) alloc_size = MIN_TLSF_HEAPSZ; #endif /* * We want to know how many bytes from a memory pool TLSF will * use for its own internal use. We get the probe memory from * tlsf_malloc(), so that the main pool will be set up in the * same move. * * We include 1k of additional memory to cope with the * per-block overhead for an undefined number of individual * allocation requests. Ugly. * * CAUTION: in pshared mode, private heaps are subsidiary * storage pools, so no need to pre-commit as much memory as * we will be preallocating for the main shared pool, * especially with memory locking in effect. In that case, * creating a temporary single-page pool is enough to figure * out the allocation overhead. */ mem = tlsf_malloc(alloc_size); available_size = init_memory_pool(alloc_size, mem); if (available_size == (size_t)-1) panic("cannot initialize TLSF memory manager"); destroy_memory_pool(mem); tlsf_pool_overhead = alloc_size - available_size; tlsf_pool_overhead = (tlsf_pool_overhead + 1024) & ~15; tlsf_free(mem); return 0; }