forked from nuttx/nuttx-update
mempool:Allocate a chunk for multiple mempool avoid memory fragmentation
Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
parent
acb3ac95da
commit
6572081e07
5 changed files with 146 additions and 41 deletions
|
@ -322,6 +322,7 @@ void mempool_procfs_unregister(FAR struct mempool_procfs_entry_s *entry);
|
||||||
* alloc - The alloc memory function for multiples pool.
|
* alloc - The alloc memory function for multiples pool.
|
||||||
* free - The free memory function for multiples pool.
|
* free - The free memory function for multiples pool.
|
||||||
* arg - The alloc & free memory fuctions used arg.
|
* arg - The alloc & free memory fuctions used arg.
|
||||||
|
* chunksize - The multiples pool chunk size.
|
||||||
* expandsize - The expend mempry for all pools in multiples pool.
|
* expandsize - The expend mempry for all pools in multiples pool.
|
||||||
* dict_expendsize - The expend size for multiple dictnoary.
|
* dict_expendsize - The expend size for multiple dictnoary.
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
|
@ -336,8 +337,8 @@ FAR struct mempool_multiple_s *
|
||||||
mempool_multiple_init(FAR const char *name,
|
mempool_multiple_init(FAR const char *name,
|
||||||
FAR size_t *poolsize, size_t npools,
|
FAR size_t *poolsize, size_t npools,
|
||||||
mempool_multiple_alloc_t alloc,
|
mempool_multiple_alloc_t alloc,
|
||||||
mempool_multiple_free_t free,
|
mempool_multiple_free_t free, FAR void *arg,
|
||||||
FAR void *arg, size_t expandsize,
|
size_t chunksize, size_t expandsize,
|
||||||
size_t dict_expendsize);
|
size_t dict_expendsize);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
13
mm/Kconfig
13
mm/Kconfig
|
@ -207,7 +207,7 @@ config MM_HEAP_MEMPOOL_THRESHOLD
|
||||||
than the threshold, the memory will be requested from the
|
than the threshold, the memory will be requested from the
|
||||||
multiple mempool by default.
|
multiple mempool by default.
|
||||||
|
|
||||||
config MM_HEAP_MEMPOOL_EXPAND
|
config MM_HEAP_MEMPOOL_EXPAND_SIZE
|
||||||
int "The expand size for each mempool in multiple mempool"
|
int "The expand size for each mempool in multiple mempool"
|
||||||
default 4096
|
default 4096
|
||||||
depends on MM_HEAP_MEMPOOL_THRESHOLD != 0
|
depends on MM_HEAP_MEMPOOL_THRESHOLD != 0
|
||||||
|
@ -215,13 +215,20 @@ config MM_HEAP_MEMPOOL_EXPAND
|
||||||
This size describes the size of each expansion of each memory
|
This size describes the size of each expansion of each memory
|
||||||
pool with insufficient memory in the multi-level memory pool.
|
pool with insufficient memory in the multi-level memory pool.
|
||||||
|
|
||||||
config MM_HEAP_MEMPOOL_DICTIONARY_EXPAND
|
config MM_HEAP_MEMPOOL_DICTIONARY_EXPAND_SIZE
|
||||||
int "The expand size for multiple mempool's dictonary"
|
int "The expand size for multiple mempool's dictonary"
|
||||||
default MM_HEAP_MEMPOOL_EXPAND
|
default MM_HEAP_MEMPOOL_EXPAND_SIZE
|
||||||
depends on MM_HEAP_MEMPOOL_THRESHOLD != 0
|
depends on MM_HEAP_MEMPOOL_THRESHOLD != 0
|
||||||
---help---
|
---help---
|
||||||
This size describes the multiple mempool dictonary expend.
|
This size describes the multiple mempool dictonary expend.
|
||||||
|
|
||||||
|
config MM_HEAP_MEMPOOL_CHUNK_SIZE
|
||||||
|
int "The multiples pool chunk size"
|
||||||
|
default 0
|
||||||
|
depends on MM_HEAP_MEMPOOL_THRESHOLD != 0
|
||||||
|
---help---
|
||||||
|
This size describes the multiple mempool chunk size.
|
||||||
|
|
||||||
config FS_PROCFS_EXCLUDE_MEMPOOL
|
config FS_PROCFS_EXCLUDE_MEMPOOL
|
||||||
bool "Exclude mempool"
|
bool "Exclude mempool"
|
||||||
default DEFAULT_SMALL
|
default DEFAULT_SMALL
|
||||||
|
|
|
@ -52,6 +52,15 @@ struct mpool_dict_s
|
||||||
size_t size; /* Record expand memary size */
|
size_t size; /* Record expand memary size */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mpool_chunk_s
|
||||||
|
{
|
||||||
|
sq_entry_t entry;
|
||||||
|
FAR void *start;
|
||||||
|
FAR void *next;
|
||||||
|
FAR void *end;
|
||||||
|
size_t used;
|
||||||
|
};
|
||||||
|
|
||||||
struct mempool_multiple_s
|
struct mempool_multiple_s
|
||||||
{
|
{
|
||||||
FAR struct mempool_s *pools; /* The memory pool array */
|
FAR struct mempool_s *pools; /* The memory pool array */
|
||||||
|
@ -79,7 +88,9 @@ struct mempool_multiple_s
|
||||||
* expansion, and find the mempool by adding an index
|
* expansion, and find the mempool by adding an index
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mutex_t dict_lock;
|
mutex_t lock;
|
||||||
|
sq_queue_t chunk_queue;
|
||||||
|
size_t chunk_size;
|
||||||
size_t dict_used;
|
size_t dict_used;
|
||||||
size_t dict_col_num_log2;
|
size_t dict_col_num_log2;
|
||||||
size_t dict_row_num;
|
size_t dict_row_num;
|
||||||
|
@ -136,6 +147,83 @@ mempool_multiple_find(FAR struct mempool_multiple_s *mpool, size_t size)
|
||||||
return &mpool->pools[left];
|
return &mpool->pools[left];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FAR void *
|
||||||
|
mempool_multiple_alloc_chunk(FAR struct mempool_multiple_s *mpool,
|
||||||
|
size_t align, size_t size)
|
||||||
|
{
|
||||||
|
FAR struct mpool_chunk_s *chunk;
|
||||||
|
FAR char *tmp;
|
||||||
|
FAR void *ret;
|
||||||
|
|
||||||
|
if (mpool->chunk_size < mpool->expandsize)
|
||||||
|
{
|
||||||
|
return mpool->alloc(mpool->arg, align, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = (FAR struct mpool_chunk_s *)sq_peek(&mpool->chunk_queue);
|
||||||
|
if (chunk == NULL)
|
||||||
|
{
|
||||||
|
retry:
|
||||||
|
tmp = mpool->alloc(mpool->arg, mpool->expandsize,
|
||||||
|
mpool->chunk_size +
|
||||||
|
sizeof(struct mpool_chunk_s));
|
||||||
|
|
||||||
|
if (tmp == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = (FAR struct mpool_chunk_s *)(tmp + mpool->chunk_size);
|
||||||
|
chunk->end = tmp + mpool->chunk_size;
|
||||||
|
chunk->start = tmp;
|
||||||
|
chunk->next = tmp;
|
||||||
|
chunk->used = 0;
|
||||||
|
sq_addfirst(&chunk->entry, &mpool->chunk_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = (FAR void *)ALIGN_UP(chunk->next, align);
|
||||||
|
if (chunk->end - ret < size)
|
||||||
|
{
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk->used++;
|
||||||
|
chunk->next = ret + size;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mempool_multiple_free_chunk(FAR struct mempool_multiple_s *mpool,
|
||||||
|
FAR void *ptr)
|
||||||
|
{
|
||||||
|
FAR struct mpool_chunk_s *chunk;
|
||||||
|
FAR sq_entry_t *entry;
|
||||||
|
|
||||||
|
if (mpool->chunk_size < mpool->expandsize)
|
||||||
|
{
|
||||||
|
mpool->free(mpool->arg, ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxmutex_lock(&mpool->lock);
|
||||||
|
sq_for_every(&mpool->chunk_queue, entry)
|
||||||
|
{
|
||||||
|
chunk = (FAR struct mpool_chunk_s *)entry;
|
||||||
|
if (ptr >= chunk->start && ptr < chunk->next)
|
||||||
|
{
|
||||||
|
if (--chunk->used == 0)
|
||||||
|
{
|
||||||
|
sq_rem(&chunk->entry, &mpool->chunk_queue);
|
||||||
|
mpool->free(mpool->arg, chunk->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nxmutex_unlock(&mpool->lock);
|
||||||
|
}
|
||||||
|
|
||||||
static FAR void *mempool_multiple_alloc_callback(FAR struct mempool_s *pool,
|
static FAR void *mempool_multiple_alloc_callback(FAR struct mempool_s *pool,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
|
@ -144,14 +232,15 @@ static FAR void *mempool_multiple_alloc_callback(FAR struct mempool_s *pool,
|
||||||
size_t row;
|
size_t row;
|
||||||
size_t col;
|
size_t col;
|
||||||
|
|
||||||
ret = mpool->alloc(mpool->arg, mpool->expandsize,
|
nxmutex_lock(&mpool->lock);
|
||||||
mpool->minpoolsize + size);
|
ret = mempool_multiple_alloc_chunk(mpool, mpool->expandsize,
|
||||||
|
mpool->minpoolsize + size);
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
{
|
{
|
||||||
|
nxmutex_unlock(&mpool->lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxmutex_lock(&mpool->dict_lock);
|
|
||||||
row = mpool->dict_used >> mpool->dict_col_num_log2;
|
row = mpool->dict_used >> mpool->dict_col_num_log2;
|
||||||
|
|
||||||
/* There is no new pointer address to store the dictionarys */
|
/* There is no new pointer address to store the dictionarys */
|
||||||
|
@ -162,16 +251,17 @@ static FAR void *mempool_multiple_alloc_callback(FAR struct mempool_s *pool,
|
||||||
|
|
||||||
if (mpool->dict[row] == NULL)
|
if (mpool->dict[row] == NULL)
|
||||||
{
|
{
|
||||||
mpool->dict[row] = mpool->alloc(mpool->arg, sizeof(uintptr_t),
|
mpool->dict[row] =
|
||||||
(1 << mpool->dict_col_num_log2) *
|
mempool_multiple_alloc_chunk(mpool, sizeof(uintptr_t),
|
||||||
sizeof(struct mpool_dict_s));
|
(1 << mpool->dict_col_num_log2)
|
||||||
|
* sizeof(struct mpool_dict_s));
|
||||||
}
|
}
|
||||||
|
|
||||||
mpool->dict[row][col].pool = pool;
|
mpool->dict[row][col].pool = pool;
|
||||||
mpool->dict[row][col].addr = ret;
|
mpool->dict[row][col].addr = ret;
|
||||||
mpool->dict[row][col].size = mpool->minpoolsize + size;
|
mpool->dict[row][col].size = mpool->minpoolsize + size;
|
||||||
*(FAR size_t *)ret = mpool->dict_used++;
|
*(FAR size_t *)ret = mpool->dict_used++;
|
||||||
nxmutex_unlock(&mpool->dict_lock);
|
nxmutex_unlock(&mpool->lock);
|
||||||
return (FAR char *)ret + mpool->minpoolsize;
|
return (FAR char *)ret + mpool->minpoolsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +270,8 @@ static void mempool_multiple_free_callback(FAR struct mempool_s *pool,
|
||||||
{
|
{
|
||||||
FAR struct mempool_multiple_s *mpool = pool->priv;
|
FAR struct mempool_multiple_s *mpool = pool->priv;
|
||||||
|
|
||||||
mpool->free(mpool->arg, (FAR char *)addr - mpool->minpoolsize);
|
mempool_multiple_free_chunk(mpool,
|
||||||
|
(FAR char *)addr - mpool->minpoolsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -256,6 +347,7 @@ mempool_multiple_get_dict(FAR struct mempool_multiple_s *mpool,
|
||||||
* alloc - The alloc memory function for multiples pool.
|
* alloc - The alloc memory function for multiples pool.
|
||||||
* free - The free memory function for multiples pool.
|
* free - The free memory function for multiples pool.
|
||||||
* arg - The alloc & free memory fuctions used arg.
|
* arg - The alloc & free memory fuctions used arg.
|
||||||
|
* chunksize - The multiples pool chunk size.
|
||||||
* expandsize - The expend mempry for all pools in multiples pool.
|
* expandsize - The expend mempry for all pools in multiples pool.
|
||||||
* dict_expendsize - The expend size for multiple dictnoary.
|
* dict_expendsize - The expend size for multiple dictnoary.
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
|
@ -268,8 +360,8 @@ FAR struct mempool_multiple_s *
|
||||||
mempool_multiple_init(FAR const char *name,
|
mempool_multiple_init(FAR const char *name,
|
||||||
FAR size_t *poolsize, size_t npools,
|
FAR size_t *poolsize, size_t npools,
|
||||||
mempool_multiple_alloc_t alloc,
|
mempool_multiple_alloc_t alloc,
|
||||||
mempool_multiple_free_t free,
|
mempool_multiple_free_t free, FAR void *arg,
|
||||||
FAR void *arg, size_t expandsize,
|
size_t chunksize, size_t expandsize,
|
||||||
size_t dict_expendsize)
|
size_t dict_expendsize)
|
||||||
{
|
{
|
||||||
FAR struct mempool_multiple_s *mpool;
|
FAR struct mempool_multiple_s *mpool;
|
||||||
|
@ -305,8 +397,14 @@ mempool_multiple_init(FAR const char *name,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pools = alloc(arg, sizeof(uintptr_t),
|
mpool->expandsize = expandsize;
|
||||||
npools * sizeof(FAR struct mempool_s));
|
mpool->chunk_size = chunksize;
|
||||||
|
mpool->alloc = alloc;
|
||||||
|
mpool->free = free;
|
||||||
|
mpool->arg = arg;
|
||||||
|
sq_init(&mpool->chunk_queue);
|
||||||
|
pools = mempool_multiple_alloc_chunk(mpool, sizeof(uintptr_t),
|
||||||
|
npools * sizeof(struct mempool_s));
|
||||||
if (pools == NULL)
|
if (pools == NULL)
|
||||||
{
|
{
|
||||||
goto err_with_mpool;
|
goto err_with_mpool;
|
||||||
|
@ -314,11 +412,7 @@ mempool_multiple_init(FAR const char *name,
|
||||||
|
|
||||||
mpool->pools = pools;
|
mpool->pools = pools;
|
||||||
mpool->npools = npools;
|
mpool->npools = npools;
|
||||||
mpool->expandsize = expandsize;
|
|
||||||
mpool->minpoolsize = minpoolsize;
|
mpool->minpoolsize = minpoolsize;
|
||||||
mpool->alloc = alloc;
|
|
||||||
mpool->free = free;
|
|
||||||
mpool->arg = arg;
|
|
||||||
mpool->delta = 0;
|
mpool->delta = 0;
|
||||||
|
|
||||||
for (i = 0; i < npools; i++)
|
for (i = 0; i < npools; i++)
|
||||||
|
@ -358,17 +452,18 @@ mempool_multiple_init(FAR const char *name,
|
||||||
mpool->dict_col_num_log2 = fls(dict_expendsize /
|
mpool->dict_col_num_log2 = fls(dict_expendsize /
|
||||||
sizeof(struct mpool_dict_s));
|
sizeof(struct mpool_dict_s));
|
||||||
|
|
||||||
mpool->dict_row_num = dict_expendsize / sizeof(struct mpool_dict_s *);
|
mpool->dict_row_num = dict_expendsize / sizeof(FAR struct mpool_dict_s *);
|
||||||
mpool->dict = alloc(arg, sizeof(struct mpool_dict_s *),
|
mpool->dict = mempool_multiple_alloc_chunk(
|
||||||
sizeof(struct mpool_dict_s *) * mpool->dict_row_num);
|
mpool, sizeof(FAR struct mpool_dict_s *),
|
||||||
|
sizeof(FAR struct mpool_dict_s *) * mpool->dict_row_num);
|
||||||
if (mpool->dict == NULL)
|
if (mpool->dict == NULL)
|
||||||
{
|
{
|
||||||
goto err_with_pools;
|
goto err_with_pools;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(mpool->dict, 0,
|
memset(mpool->dict, 0,
|
||||||
mpool->dict_row_num * sizeof(struct mpool_dict_s *));
|
mpool->dict_row_num * sizeof(FAR struct mpool_dict_s *));
|
||||||
nxmutex_init(&mpool->dict_lock);
|
nxmutex_init(&mpool->lock);
|
||||||
|
|
||||||
return mpool;
|
return mpool;
|
||||||
|
|
||||||
|
@ -378,7 +473,7 @@ err_with_pools:
|
||||||
mempool_deinit(pools + i);
|
mempool_deinit(pools + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(arg, pools);
|
mempool_multiple_free_chunk(mpool, pools);
|
||||||
err_with_mpool:
|
err_with_mpool:
|
||||||
free(arg, mpool);
|
free(arg, mpool);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -687,7 +782,7 @@ void mempool_multiple_deinit(FAR struct mempool_multiple_s *mpool)
|
||||||
{
|
{
|
||||||
if (mpool->dict[i] != NULL)
|
if (mpool->dict[i] != NULL)
|
||||||
{
|
{
|
||||||
mpool->free(mpool->arg, mpool->dict[i]);
|
mempool_multiple_free_chunk(mpool, mpool->dict[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -695,8 +790,8 @@ void mempool_multiple_deinit(FAR struct mempool_multiple_s *mpool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mpool->free(mpool->arg, mpool->dict);
|
mempool_multiple_free_chunk(mpool, mpool->dict);
|
||||||
mpool->free(mpool->arg, mpool->pools);
|
mempool_multiple_free_chunk(mpool, mpool->pools);
|
||||||
mpool->free(mpool->arg, mpool);
|
nxmutex_destroy(&mpool->lock);
|
||||||
nxmutex_destroy(&mpool->dict_lock);
|
mpool->free(mpool, mpool);
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,10 +287,11 @@ FAR struct mm_heap_s *mm_initialize(FAR const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
heap->mm_mpool = mempool_multiple_init(name, poolsize, MEMPOOL_NPOOLS,
|
heap->mm_mpool = mempool_multiple_init(name, poolsize, MEMPOOL_NPOOLS,
|
||||||
(mempool_multiple_alloc_t)mempool_memalign,
|
(mempool_multiple_alloc_t)mempool_memalign,
|
||||||
(mempool_multiple_free_t)mm_free, heap,
|
(mempool_multiple_free_t)mm_free, heap,
|
||||||
CONFIG_MM_HEAP_MEMPOOL_EXPAND,
|
CONFIG_MM_HEAP_MEMPOOL_CHUNK_SIZE,
|
||||||
CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND);
|
CONFIG_MM_HEAP_MEMPOOL_EXPAND_SIZE,
|
||||||
|
CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND_SIZE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return heap;
|
return heap;
|
||||||
|
|
|
@ -844,10 +844,11 @@ FAR struct mm_heap_s *mm_initialize(FAR const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
heap->mm_mpool = mempool_multiple_init(name, poolsize, MEMPOOL_NPOOLS,
|
heap->mm_mpool = mempool_multiple_init(name, poolsize, MEMPOOL_NPOOLS,
|
||||||
(mempool_multiple_alloc_t)mempool_memalign,
|
(mempool_multiple_alloc_t)mempool_memalign,
|
||||||
(mempool_multiple_free_t)mm_free, heap,
|
(mempool_multiple_free_t)mm_free, heap,
|
||||||
CONFIG_MM_HEAP_MEMPOOL_EXPAND,
|
CONFIG_MM_HEAP_MEMPOOL_CHUNK_SIZE,
|
||||||
CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND);
|
CONFIG_MM_HEAP_MEMPOOL_EXPAND_SIZE,
|
||||||
|
CONFIG_MM_HEAP_MEMPOOL_DICTIONARY_EXPAND_SIZE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return heap;
|
return heap;
|
||||||
|
|
Loading…
Reference in a new issue