Add initialization and discard functions to mem_pool type. As the memory allocated by mem_pool can now be freed, we also track the large memory alllocations so they can be freed as well. If the there are existing mp_blocks in the mem_pool's linked list of mp_blocks, then the mp_block for a large allocation is inserted after the head block. This is because only the head mp_block is considered when searching for availble space. This results in the following desirable properties: 1) The mp_block allocated for the large request will not be included in the search for available space in future requests, as the large mp_block is sized for the specific request and does not contain any spare space. 2) The head mp_block will not bumped from considation for future memory requests just because a request for a large chunk of memory came in. These changes are in preparation for a future commit that will utilize creating and discarding memory pool. Signed-off-by: Jameson Miller <jamill@xxxxxxxxxxxxx> --- mem-pool.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++------------ mem-pool.h | 10 ++++++++++ 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/mem-pool.c b/mem-pool.c index a5d5eed923..4e544459e9 100644 --- a/mem-pool.c +++ b/mem-pool.c @@ -5,7 +5,14 @@ #include "cache.h" #include "mem-pool.h" -static struct mp_block *mem_pool_alloc_block(struct mem_pool *mem_pool, size_t block_alloc) +#define BLOCK_GROWTH_SIZE 1024*1024 - sizeof(struct mp_block); + +/* + * Allocate a new mp_block and insert it after the block specified in + * `insert_after`. If `insert_after` is NULL, then insert block at the + * head of the linked list. + */ +static struct mp_block *mem_pool_alloc_block(struct mem_pool *mem_pool, size_t block_alloc, struct mp_block *insert_after) { struct mp_block *p; size_t total_alloc = st_add(offsetof(struct mp_block, space), block_alloc); @@ -13,14 +20,51 @@ static struct mp_block *mem_pool_alloc_block(struct mem_pool *mem_pool, size_t b mem_pool->pool_alloc = st_add(mem_pool->pool_alloc, total_alloc); p = xmalloc(total_alloc); - p->next_block = mem_pool->mp_block; p->next_free = (char *)p->space; p->end = p->next_free + block_alloc; - mem_pool->mp_block = p; + + if (insert_after) { + p->next_block = insert_after->next_block; + insert_after->next_block = p; + } else { + p->next_block = mem_pool->mp_block; + mem_pool->mp_block = p; + } return p; } +void mem_pool_init(struct mem_pool **mem_pool, size_t initial_size) +{ + struct mem_pool *pool; + + if (*mem_pool) + return; + + pool = xcalloc(1, sizeof(*pool)); + + pool->block_alloc = BLOCK_GROWTH_SIZE; + + if (initial_size > 0) + mem_pool_alloc_block(pool, initial_size, NULL); + + *mem_pool = pool; +} + +void mem_pool_discard(struct mem_pool *mem_pool) +{ + struct mp_block *block, *block_to_free; + + while ((block = mem_pool->mp_block)) + { + block_to_free = block; + block = block->next_block; + free(block_to_free); + } + + free(mem_pool); +} + void *mem_pool_alloc(struct mem_pool *mem_pool, size_t len) { struct mp_block *p = NULL; @@ -33,15 +77,10 @@ void *mem_pool_alloc(struct mem_pool *mem_pool, size_t len) if (mem_pool->mp_block && mem_pool->mp_block->end - mem_pool->mp_block->next_free >= len) p = mem_pool->mp_block; - - if (!p) { - if (len >= (mem_pool->block_alloc / 2)) { - mem_pool->pool_alloc += len; - return xmalloc(len); - } - - p = mem_pool_alloc_block(mem_pool, mem_pool->block_alloc); - } + else if (len >= (mem_pool->block_alloc / 2)) + p = mem_pool_alloc_block(mem_pool, len, mem_pool->mp_block); + else + p = mem_pool_alloc_block(mem_pool, mem_pool->block_alloc, NULL); r = p->next_free; p->next_free += len; diff --git a/mem-pool.h b/mem-pool.h index 829ad58ecf..f75b3365d5 100644 --- a/mem-pool.h +++ b/mem-pool.h @@ -21,6 +21,16 @@ struct mem_pool { size_t pool_alloc; }; +/* + * Initialize mem_pool with specified initial size. + */ +void mem_pool_init(struct mem_pool **mem_pool, size_t initial_size); + +/* + * Discard a memory pool and free all the memory it is responsible for. + */ +void mem_pool_discard(struct mem_pool *mem_pool); + /* * Alloc memory from the mem_pool. */ -- 2.14.3