mem-pool.con commit mem-pool: add life cycle management functions (158dfef)
   1/*
   2 * Memory Pool implementation logic.
   3 */
   4
   5#include "cache.h"
   6#include "mem-pool.h"
   7
   8#define BLOCK_GROWTH_SIZE 1024*1024 - sizeof(struct mp_block);
   9
  10/*
  11 * Allocate a new mp_block and insert it after the block specified in
  12 * `insert_after`. If `insert_after` is NULL, then insert block at the
  13 * head of the linked list.
  14 */
  15static struct mp_block *mem_pool_alloc_block(struct mem_pool *mem_pool, size_t block_alloc, struct mp_block *insert_after)
  16{
  17        struct mp_block *p;
  18
  19        mem_pool->pool_alloc += sizeof(struct mp_block) + block_alloc;
  20        p = xmalloc(st_add(sizeof(struct mp_block), block_alloc));
  21
  22        p->next_free = (char *)p->space;
  23        p->end = p->next_free + block_alloc;
  24
  25        if (insert_after) {
  26                p->next_block = insert_after->next_block;
  27                insert_after->next_block = p;
  28        } else {
  29                p->next_block = mem_pool->mp_block;
  30                mem_pool->mp_block = p;
  31        }
  32
  33        return p;
  34}
  35
  36void mem_pool_init(struct mem_pool **mem_pool, size_t initial_size)
  37{
  38        struct mem_pool *pool;
  39
  40        if (*mem_pool)
  41                return;
  42
  43        pool = xcalloc(1, sizeof(*pool));
  44
  45        pool->block_alloc = BLOCK_GROWTH_SIZE;
  46
  47        if (initial_size > 0)
  48                mem_pool_alloc_block(pool, initial_size, NULL);
  49
  50        *mem_pool = pool;
  51}
  52
  53void mem_pool_discard(struct mem_pool *mem_pool)
  54{
  55        struct mp_block *block, *block_to_free;
  56
  57        while ((block = mem_pool->mp_block))
  58        {
  59                block_to_free = block;
  60                block = block->next_block;
  61                free(block_to_free);
  62        }
  63
  64        free(mem_pool);
  65}
  66
  67void *mem_pool_alloc(struct mem_pool *mem_pool, size_t len)
  68{
  69        struct mp_block *p = NULL;
  70        void *r;
  71
  72        /* round up to a 'uintmax_t' alignment */
  73        if (len & (sizeof(uintmax_t) - 1))
  74                len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
  75
  76        if (mem_pool->mp_block &&
  77            mem_pool->mp_block->end - mem_pool->mp_block->next_free >= len)
  78                p = mem_pool->mp_block;
  79
  80        if (!p) {
  81                if (len >= (mem_pool->block_alloc / 2))
  82                        return mem_pool_alloc_block(mem_pool, len, mem_pool->mp_block);
  83
  84                p = mem_pool_alloc_block(mem_pool, mem_pool->block_alloc, NULL);
  85        }
  86
  87        r = p->next_free;
  88        p->next_free += len;
  89        return r;
  90}
  91
  92void *mem_pool_calloc(struct mem_pool *mem_pool, size_t count, size_t size)
  93{
  94        size_t len = st_mult(count, size);
  95        void *r = mem_pool_alloc(mem_pool, len);
  96        memset(r, 0, len);
  97        return r;
  98}