diff --git a/include/nuttx/mm/mempool.h b/include/nuttx/mm/mempool.h index 7b991292f1..7af6558728 100644 --- a/include/nuttx/mm/mempool.h +++ b/include/nuttx/mm/mempool.h @@ -354,10 +354,14 @@ FAR void *mempool_multiple_realloc(FAR struct mempool_multiple_s *mpool, * Input Parameters: * mpool - The handle of multiple memory pool to be used. * blk - The pointer of memory block. + * + * Returned Value: + * Zero on success; Negative number mean the block doesn't come from pool. + * ****************************************************************************/ -void mempool_multiple_free(FAR struct mempool_multiple_s *mpool, - FAR void *blk); +int mempool_multiple_free(FAR struct mempool_multiple_s *mpool, + FAR void *blk); /**************************************************************************** * Name: mempool_multiple_alloc_size @@ -370,12 +374,13 @@ void mempool_multiple_free(FAR struct mempool_multiple_s *mpool, * blk - The pointer of memory block. * * Returned Value: - * The size of memory block. + * The size of memory block on success. Negative number mean the block + * doesn't come from pool. * ****************************************************************************/ -size_t mempool_multiple_alloc_size(FAR struct mempool_multiple_s *mpool, - FAR void *blk); +ssize_t mempool_multiple_alloc_size(FAR struct mempool_multiple_s *mpool, + FAR void *blk); /**************************************************************************** * Name: mempool_multiple_memalign diff --git a/mm/Kconfig b/mm/Kconfig index e47eda7d9c..8b572f142b 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -190,7 +190,7 @@ config MM_HEAP_MEMPOOL_THRESHOLD config MM_HEAP_MEMPOOL_EXPAND int "The expand size for each mempool in multiple mempool" - default 1024 + default 4096 depends on MM_HEAP_MEMPOOL_THRESHOLD != 0 ---help--- This size describes the size of each expansion of each memory diff --git a/mm/mempool/mempool.c b/mm/mempool/mempool.c index c64ab8dc2f..d1ee35caf2 100644 --- a/mm/mempool/mempool.c +++ b/mm/mempool/mempool.c @@ -38,9 +38,8 @@ # define MM_PTR_FMT_WIDTH 19 #endif -#ifndef ALIGN_UP -# define ALIGN_UP(x, a) (((x) + ((a) - 1)) & (~((a) - 1))) -#endif +#undef ALIGN_UP +#define ALIGN_UP(x, a) (((x) + ((a) - 1)) & (~((a) - 1))) /**************************************************************************** * Private Types diff --git a/mm/mempool/mempool_multiple.c b/mm/mempool/mempool_multiple.c index 843964d0c8..d03b541f25 100644 --- a/mm/mempool/mempool_multiple.c +++ b/mm/mempool/mempool_multiple.c @@ -29,21 +29,36 @@ * Pre-processor Definitions ****************************************************************************/ -#define SIZEOF_HEAD sizeof(FAR struct mempool_s *) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define ALIGN_BIT (1 << 1) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#undef ALIGN_UP +#define ALIGN_UP(x, a) ((((size_t)x) + ((a) - 1)) & (~((a) - 1))) +#undef ALIGN_DOWN +#define ALIGN_DOWN(x, a) ((size_t)(x) & (~((a) - 1))) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct mpool_dict_s +{ + FAR struct mempool_s *pool; /* Record pool when expanding */ + FAR void *addr; /* Record expand memary address */ + size_t size; /* Record expand memary size */ +}; struct mempool_multiple_s { - FAR struct mempool_s * pools; /* The memory pool array */ - size_t npools; /* The number of memory pool array elements */ - - FAR void *arg; /* This pointer is used to store the user's - * private data - */ - mempool_multiple_alloc_t alloc; /* The alloc function for mempool */ - mempool_multiple_free_t free; /* The free function for mempool */ + FAR struct mempool_s * pools; /* The memory pool array */ + size_t npools; /* The number of memory pool array elements */ + size_t expandsize; /* The number not will use it to init erery + * pool expandsize + */ + size_t minpoolsize; /* The number is align for each memory pool */ + FAR void *arg; /* This pointer is used to store the user's + * private data + */ + mempool_multiple_alloc_t alloc; /* The alloc function for mempool */ + mempool_multiple_free_t free; /* The free function for mempool */ /* This delta describes the relationship between the block size of each * mempool in multiple mempool by user initialized. It is automatically @@ -53,6 +68,14 @@ struct mempool_multiple_s */ size_t delta; + + /* It is used to record the information recorded by the mempool during + * expansion, and find the mempool by adding an index + */ + + size_t dict_alloc; + size_t dict_used; + FAR struct mpool_dict_s *dict; }; /**************************************************************************** @@ -75,6 +98,11 @@ mempool_multiple_find(FAR struct mempool_multiple_s *mpool, size_t size) if (mpool->delta != 0) { left = mpool->pools[0].blocksize; + if (left >= size) + { + return &mpool->pools[0]; + } + mid = (size - left + mpool->delta - 1) / mpool->delta; return mid < right ? &mpool->pools[mid] : NULL; } @@ -100,6 +128,95 @@ mempool_multiple_find(FAR struct mempool_multiple_s *mpool, size_t size) return &mpool->pools[left]; } +static FAR void *mempool_multiple_alloc_callback(FAR struct mempool_s *pool, + size_t size) +{ + FAR struct mempool_multiple_s *mpool = pool->priv; + FAR void *ret; + + if (mpool->dict_used >= mpool->dict_alloc) + { + ret = mpool->alloc(mpool->arg, sizeof(uintptr_t), + mpool->dict_alloc * + sizeof(struct mpool_dict_s) * 2); + if (ret == NULL) + { + return NULL; + } + + memcpy(ret, mpool->dict, + mpool->dict_alloc * sizeof(struct mpool_dict_s)); + mpool->free(mpool->arg, mpool->dict); + mpool->dict = ret; + mpool->dict_alloc *= 2; + } + + ret = mpool->alloc(mpool->arg, mpool->expandsize, + mpool->minpoolsize + size); + if (ret == NULL) + { + return NULL; + } + + mpool->dict[mpool->dict_used].pool = pool; + mpool->dict[mpool->dict_used].addr = ret; + mpool->dict[mpool->dict_used].size = mpool->minpoolsize + size; + *(FAR size_t *)ret = mpool->dict_used++; + return (FAR char *)ret + mpool->minpoolsize; +} + +static void mempool_multiple_free_callback(FAR struct mempool_s *pool, + FAR void *addr) +{ + FAR struct mempool_multiple_s *mpool = pool->priv; + + return mpool->free(mpool->arg, (FAR char *)addr - mpool->minpoolsize); +} + +/**************************************************************************** + * Name: mempool_multiple_get_dict + * + * Description: + * Obtain the dict through mpool and blk + * + * Input Parameters: + * mpool - The handle of the multiple memory pool to be used. + * blk - The pointer of memory block. + * + * Returned Value: + * Address of the dict to be used or NULL is not find. + * + ****************************************************************************/ + +static FAR struct mpool_dict_s * +mempool_multiple_get_dict(FAR struct mempool_multiple_s *mpool, + FAR void *blk) +{ + FAR void *addr; + size_t index; + + if (mpool == NULL || blk == NULL) + { + return NULL; + } + + addr = (FAR void *)ALIGN_DOWN(blk, mpool->expandsize); + + index = *(FAR size_t *)addr; + if (index >= mpool->dict_used) + { + return NULL; + } + + if (mpool->dict[index].addr != addr || + blk - addr >= mpool->dict[index].size) + { + return NULL; + } + + return &mpool->dict[index]; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -141,9 +258,31 @@ mempool_multiple_init(FAR const char *name, { FAR struct mempool_multiple_s *mpool; FAR struct mempool_s *pools; + size_t maxpoolszie; + size_t minpoolsize; int ret; int i; + if (expandsize & (expandsize - 1)) + { + return NULL; + } + + maxpoolszie = poolsize[0]; + minpoolsize = poolsize[0]; + for (i = 0; i < npools; i++) + { + if (maxpoolszie < poolsize[i]) + { + maxpoolszie = poolsize[i]; + } + + if (minpoolsize > poolsize[i]) + { + minpoolsize = poolsize[i]; + } + } + mpool = alloc(arg, sizeof(uintptr_t), sizeof(struct mempool_multiple_s)); if (mpool == NULL) { @@ -159,6 +298,8 @@ mempool_multiple_init(FAR const char *name, mpool->pools = pools; mpool->npools = npools; + mpool->expandsize = expandsize; + mpool->minpoolsize = minpoolsize; mpool->alloc = alloc; mpool->free = free; mpool->arg = arg; @@ -166,17 +307,16 @@ mempool_multiple_init(FAR const char *name, for (i = 0; i < npools; i++) { pools[i].blocksize = poolsize[i]; - pools[i].expandsize = expandsize; + pools[i].expandsize = expandsize - mpool->minpoolsize; pools[i].initialsize = 0; pools[i].interruptsize = 0; + pools[i].priv = mpool; + pools[i].alloc = mempool_multiple_alloc_callback; + pools[i].free = mempool_multiple_free_callback; + ret = mempool_init(pools + i, name); if (ret < 0) { - while (--i >= 0) - { - mempool_deinit(pools + i); - } - goto err_with_pools; } @@ -195,9 +335,23 @@ mempool_multiple_init(FAR const char *name, } } + mpool->dict_alloc = maxpoolszie / sizeof(struct mpool_dict_s) + 1; + mpool->dict_used = 0; + mpool->dict = alloc(arg, sizeof(uintptr_t), + mpool->dict_alloc * sizeof(struct mpool_dict_s)); + if (mpool->dict == NULL) + { + goto err_with_pools; + } + return mpool; err_with_pools: + while (--i >= 0) + { + mempool_deinit(pools + i); + } + free(arg, pools); err_with_mpool: free(arg, mpool); @@ -225,22 +379,28 @@ err_with_mpool: FAR void *mempool_multiple_alloc(FAR struct mempool_multiple_s *mpool, size_t size) { - FAR struct mempool_s *end = mpool->pools + mpool->npools; + FAR struct mempool_s *end; FAR struct mempool_s *pool; - pool = mempool_multiple_find(mpool, size + SIZEOF_HEAD); + if (size < 1) + { + return NULL; + } + + pool = mempool_multiple_find(mpool, size); if (pool == NULL) { return NULL; } + end = mpool->pools + mpool->npools; do { FAR void *blk = mempool_alloc(pool); - if (blk != NULL) + + if (blk) { - *(FAR struct mempool_s **)blk = pool; - return (FAR char *)blk + SIZEOF_HEAD; + return blk; } } while (++pool < end); @@ -267,33 +427,30 @@ FAR void *mempool_multiple_alloc(FAR struct mempool_multiple_s *mpool, FAR void *mempool_multiple_realloc(FAR struct mempool_multiple_s *mpool, FAR void *oldblk, size_t size) { + FAR struct mpool_dict_s *dict; FAR void *blk; + if (oldblk == NULL) + { + return mempool_multiple_alloc(mpool, size); + } + if (size < 1) { mempool_multiple_free(mpool, oldblk); return NULL; } + dict = mempool_multiple_get_dict(mpool, oldblk); + if (dict == NULL) + { + return NULL; + } + blk = mempool_multiple_alloc(mpool, size); if (blk != NULL && oldblk != NULL) { - FAR struct mempool_s *oldpool; - - oldpool = *(FAR struct mempool_s **) - ((FAR char *)oldblk - SIZEOF_HEAD); - if ((uintptr_t)oldpool & ALIGN_BIT) - { - oldpool = (FAR struct mempool_s *) - ((uintptr_t)oldpool & ~ALIGN_BIT); - size = MIN(size, oldpool->blocksize - - *(FAR size_t *)((FAR char *)oldblk - 2 * SIZEOF_HEAD)); - } - else - { - size = MIN(size, oldpool->blocksize - SIZEOF_HEAD); - } - + size = MIN(size, dict->pool->blocksize); memcpy(blk, oldblk, size); mempool_multiple_free(mpool, oldblk); } @@ -311,25 +468,28 @@ FAR void *mempool_multiple_realloc(FAR struct mempool_multiple_s *mpool, * Input Parameters: * mpool - The handle of multiple memory pool to be used. * blk - The pointer of memory block. + * + * Returned Value: + * Zero on success; Negative number on any failure. + * ****************************************************************************/ -void mempool_multiple_free(FAR struct mempool_multiple_s *mpool, - FAR void *blk) +int mempool_multiple_free(FAR struct mempool_multiple_s *mpool, + FAR void *blk) { - FAR struct mempool_s *pool; - FAR char *mem; + FAR struct mpool_dict_s *dict; - DEBUGASSERT(mpool != NULL && blk != NULL); - - mem = (FAR char *)blk - SIZEOF_HEAD; - pool = *(FAR struct mempool_s **)mem; - if ((uintptr_t)pool & ALIGN_BIT) + dict = mempool_multiple_get_dict(mpool, blk); + if (dict == NULL) { - pool = (FAR struct mempool_s *)((uintptr_t)pool & ~ALIGN_BIT); - mem = (FAR char *)blk - *(FAR size_t *)(mem - SIZEOF_HEAD); + return -EINVAL; } - mempool_free(pool, mem); + blk = (FAR char *)blk - (((FAR char *)blk - + ((FAR char *)dict->addr + mpool->minpoolsize)) % + dict->pool->blocksize); + mempool_free(dict->pool, blk); + return 0; } /**************************************************************************** @@ -343,29 +503,24 @@ void mempool_multiple_free(FAR struct mempool_multiple_s *mpool, * blk - The pointer of memory block. * * Returned Value: - * The size of memory block. + * The size of memory block on success. Negative number on any failure. * ****************************************************************************/ -size_t mempool_multiple_alloc_size(FAR struct mempool_multiple_s *mpool, - FAR void *blk) +ssize_t mempool_multiple_alloc_size(FAR struct mempool_multiple_s *mpool, + FAR void *blk) { - FAR struct mempool_s *pool; - FAR char *mem; + FAR struct mpool_dict_s *dict; DEBUGASSERT(blk != NULL); - mem = (FAR char *)blk - SIZEOF_HEAD; - pool = *(FAR struct mempool_s **)mem; - if ((uintptr_t)pool & ALIGN_BIT) + dict = mempool_multiple_get_dict(mpool, blk); + if (dict == NULL) { - pool = (FAR struct mempool_s *)((uintptr_t)pool & ~ALIGN_BIT); - return pool->blocksize - *(FAR size_t *)(mem - SIZEOF_HEAD); - } - else - { - return pool->blocksize - SIZEOF_HEAD; + return -EINVAL; } + + return dict->pool->blocksize; } /**************************************************************************** @@ -398,31 +553,24 @@ size_t mempool_multiple_alloc_size(FAR struct mempool_multiple_s *mpool, FAR void *mempool_multiple_memalign(FAR struct mempool_multiple_s *mpool, size_t alignment, size_t size) { - FAR struct mempool_s *end = mpool->pools + mpool->npools; + FAR struct mempool_s *end; FAR struct mempool_s *pool; DEBUGASSERT((alignment & (alignment - 1)) == 0); - pool = mempool_multiple_find(mpool, size + alignment + 2 * SIZEOF_HEAD); + pool = mempool_multiple_find(mpool, size + alignment); if (pool == NULL) { return NULL; } + end = mpool->pools + mpool->npools; do { FAR char *blk = mempool_alloc(pool); if (blk != NULL) { - FAR char *mem; - - mem = blk + 2 * SIZEOF_HEAD; - mem = (FAR char *)(((uintptr_t)mem + alignment - 1) & - ~(alignment - 1)); - *(FAR uintptr_t *)(mem - SIZEOF_HEAD) = - (uintptr_t)pool | ALIGN_BIT; - *(FAR size_t *)(mem - 2 * SIZEOF_HEAD) = mem - blk; - return mem; + return (FAR void *)ALIGN_UP(blk, alignment); } } while (++pool < end); @@ -495,6 +643,7 @@ void mempool_multiple_deinit(FAR struct mempool_multiple_s *mpool) DEBUGVERIFY(mempool_deinit(mpool->pools + i)); } + mpool->free(mpool->arg, mpool->dict); mpool->free(mpool->arg, mpool->pools); mpool->free(mpool->arg, mpool); } diff --git a/mm/mm_heap/mm.h b/mm/mm_heap/mm.h index 3b1d60d3a5..958b3f3008 100644 --- a/mm/mm_heap/mm.h +++ b/mm/mm_heap/mm.h @@ -134,11 +134,6 @@ #define SIZEOF_MM_FREENODE sizeof(struct mm_freenode_s) -#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 -# define MM_IS_FROM_MEMPOOL(mem) \ - ((*((FAR mmsize_t *)mem - 1) & MM_ALLOC_BIT) == 0) -#endif - /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/mm/mm_heap/mm_free.c b/mm/mm_heap/mm_free.c index ba6d06269b..cef44775a2 100644 --- a/mm/mm_heap/mm_free.c +++ b/mm/mm_heap/mm_free.c @@ -83,9 +83,8 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem) } #if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 - if (MM_IS_FROM_MEMPOOL(mem)) + if (mempool_multiple_free(heap->mm_mpool, mem) >= 0) { - mempool_multiple_free(heap->mm_mpool, mem); return; } #endif diff --git a/mm/mm_heap/mm_malloc_size.c b/mm/mm_heap/mm_malloc_size.c index 987635780e..96eb27c4e6 100644 --- a/mm/mm_heap/mm_malloc_size.c +++ b/mm/mm_heap/mm_malloc_size.c @@ -38,6 +38,14 @@ size_t mm_malloc_size(FAR struct mm_heap_s *heap, FAR void *mem) { FAR struct mm_freenode_s *node; +#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 + ssize_t size = mempool_multiple_alloc_size(heap->mm_mpool, mem); + + if (size >= 0) + { + return size; + } +#endif /* Protect against attempts to query a NULL reference */ @@ -46,13 +54,6 @@ size_t mm_malloc_size(FAR struct mm_heap_s *heap, FAR void *mem) return 0; } -#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 - if (MM_IS_FROM_MEMPOOL(mem)) - { - return mempool_multiple_alloc_size(heap->mm_mpool, mem); - } -#endif - /* Map the memory chunk into a free node */ node = (FAR struct mm_freenode_s *)((FAR char *)mem - SIZEOF_MM_ALLOCNODE); diff --git a/mm/mm_heap/mm_realloc.c b/mm/mm_heap/mm_realloc.c index b423c190df..85239783b4 100644 --- a/mm/mm_heap/mm_realloc.c +++ b/mm/mm_heap/mm_realloc.c @@ -95,30 +95,18 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, } #if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 - if (MM_IS_FROM_MEMPOOL(oldmem)) + newmem = mempool_multiple_realloc(heap->mm_mpool, oldmem, size); + if (newmem != NULL) + { + return newmem; + } + else if (size <= CONFIG_MM_HEAP_MEMPOOL_THRESHOLD || + mempool_multiple_alloc_size(heap->mm_mpool, oldmem) >= 0) { - newmem = mempool_multiple_realloc(heap->mm_mpool, oldmem, size); - if (newmem != NULL) - { - return newmem; - } - newmem = mm_malloc(heap, size); if (newmem != NULL) { - memcpy(newmem, oldmem, - mempool_multiple_alloc_size(heap->mm_mpool, oldmem)); - mempool_multiple_free(heap->mm_mpool, oldmem); - } - - return newmem; - } - else - { - newmem = mempool_multiple_alloc(heap->mm_mpool, size); - if (newmem != NULL) - { - memcpy(newmem, oldmem, MIN(size, mm_malloc_size(heap, oldmem))); + memcpy(newmem, oldmem, size); mm_free(heap, oldmem); return newmem; } diff --git a/mm/tlsf/mm_tlsf.c b/mm/tlsf/mm_tlsf.c index 6b90456148..0bd36e20dc 100644 --- a/mm/tlsf/mm_tlsf.c +++ b/mm/tlsf/mm_tlsf.c @@ -56,12 +56,6 @@ #define MIN(x, y) ((x) < (y) ? (x) : (y)) -#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 -# define MM_MPOOL_BIT (1 << 0) -# define MM_IS_FROM_MEMPOOL(mem) \ - ((*((FAR size_t *)(mem) - 1)) & MM_MPOOL_BIT) == 0 -#endif - #if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 # define MEMPOOL_NPOOLS (CONFIG_MM_HEAP_MEMPOOL_THRESHOLD / tlsf_align_size()) #endif @@ -654,9 +648,8 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem) } #if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 - if (MM_IS_FROM_MEMPOOL(mem)) + if (mempool_multiple_free(heap->mm_mpool, mem) >= 0) { - mempool_multiple_free(heap->mm_mpool, mem); return; } #endif @@ -954,9 +947,10 @@ void mm_memdump(FAR struct mm_heap_s *heap, pid_t pid) size_t mm_malloc_size(FAR struct mm_heap_s *heap, FAR void *mem) { #if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 - if (MM_IS_FROM_MEMPOOL(mem)) + ssize_t size = mempool_multiple_alloc_size(heap->mm_mpool, mem); + if (size >= 0) { - return mempool_multiple_alloc_size(heap->mm_mpool, mem); + return size; } #endif @@ -1113,29 +1107,18 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, } #if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD != 0 - if (MM_IS_FROM_MEMPOOL(oldmem)) + newmem = mempool_multiple_realloc(heap->mm_mpool, oldmem, size); + if (newmem != NULL) { - newmem = mempool_multiple_realloc(heap->mm_mpool, oldmem, size); - if (newmem != NULL) - { - return newmem; - } - - newmem = mm_malloc(heap, size); - if (newmem != NULL) - { - memcpy(newmem, oldmem, size); - mempool_multiple_free(heap->mm_mpool, oldmem); - } - return newmem; } - else + else if (size <= CONFIG_MM_HEAP_MEMPOOL_THRESHOLD || + mempool_multiple_alloc_size(heap->mm_mpool, oldmem) >= 0) { - newmem = mempool_multiple_alloc(heap->mm_mpool, size); - if (newmem != NULL) + newmem = mm_malloc(heap, size); + if (newmem != 0) { - memcpy(newmem, oldmem, MIN(size, mm_malloc_size(heap, oldmem))); + memcpy(newmem, oldmem, size); mm_free(heap, oldmem); return newmem; }