Add initialization and discard functions to mem-pool type. As part of
this, we now also track "large" allocations of memory so that these
can also be cleaned up when discarding the memory pool.

These changes are in preparation for a future commit that will utilize
creating and discarding memory pool.

Signed-off-by: Jameson Miller <jam...@microsoft.com>
---
 fast-import.c |  2 +-
 mem-pool.c    | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 mem-pool.h    | 12 +++++++++++-
 3 files changed, 71 insertions(+), 6 deletions(-)

diff --git a/fast-import.c b/fast-import.c
index 34edf3fb8f..571898e5db 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -300,7 +300,7 @@ static int global_argc;
 static const char **global_argv;
 
 /* Memory pools */
-static struct mem_pool fi_mem_pool =  {NULL, 2*1024*1024 -
+static struct mem_pool fi_mem_pool =  {NULL, NULL, 2*1024*1024 -
                                       sizeof(struct mp_block), 0 };
 
 /* Atom management */
diff --git a/mem-pool.c b/mem-pool.c
index c80124f1fe..01595bcca5 100644
--- a/mem-pool.c
+++ b/mem-pool.c
@@ -5,20 +5,77 @@
 #include "cache.h"
 #include "mem-pool.h"
 
+#define BLOCK_GROWTH_SIZE 1024*1024 - sizeof(struct mp_block);
+
 static struct mp_block *mem_pool_alloc_block(struct mem_pool *mem_pool, size_t 
block_alloc)
 {
        struct mp_block *p;
 
        mem_pool->pool_alloc += sizeof(struct mp_block) + block_alloc;
        p = xmalloc(st_add(sizeof(struct mp_block), block_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 (!mem_pool->mp_block_tail)
+               mem_pool->mp_block_tail = p;
+
+       return p;
+}
+
+static void *mem_pool_alloc_custom(struct mem_pool *mem_pool, size_t 
block_alloc)
+{
+       struct mp_block *p;
+
+       mem_pool->pool_alloc += sizeof(struct mp_block) + block_alloc;
+       p = xmalloc(st_add(sizeof(struct mp_block), block_alloc));
+
+       p->next_block = NULL;
+       p->next_free = (char *)p->space;
+       p->end = p->next_free + block_alloc;
+
+       if (mem_pool->mp_block_tail)
+               mem_pool->mp_block_tail->next_block = p;
+       else
+               mem_pool->mp_block = p;
+
+       mem_pool->mp_block_tail = 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);
+
+       *mem_pool = pool;
+}
+
+void mem_pool_discard(struct mem_pool *mem_pool)
+{
+       struct mp_block *block, *block_to_free;
+       for (block = mem_pool->mp_block; 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,10 +90,8 @@ void *mem_pool_alloc(struct mem_pool *mem_pool, size_t len)
                p = mem_pool->mp_block;
 
        if (!p) {
-               if (len >= (mem_pool->block_alloc / 2)) {
-                       mem_pool->pool_alloc += len;
-                       return xmalloc(len);
-               }
+               if (len >= (mem_pool->block_alloc / 2))
+                       return mem_pool_alloc_custom(mem_pool, len);
 
                p = mem_pool_alloc_block(mem_pool, mem_pool->block_alloc);
        }
diff --git a/mem-pool.h b/mem-pool.h
index 829ad58ecf..5d3e6a367a 100644
--- a/mem-pool.h
+++ b/mem-pool.h
@@ -9,7 +9,7 @@ struct mp_block {
 };
 
 struct mem_pool {
-       struct mp_block *mp_block;
+       struct mp_block *mp_block, *mp_block_tail;
 
        /*
         * The amount of available memory to grow the pool by.
@@ -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

Reply via email to