From e6ce59deb7affe66ccbb7bd154a2310e1ad3e14a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 13 May 2007 19:38:49 +0200 Subject: [PATCH] [MEDIUM] add new memory management functions Implement pool_destroy2, pool_flush2, pool_gc2. It is safe to call pool_gc2 to free whatever memory possible. --- include/common/memory.h | 33 ++++++++++++++++------ src/memory.c | 62 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 13 deletions(-) diff --git a/include/common/memory.h b/include/common/memory.h index 77346b706e..0f142f0284 100644 --- a/include/common/memory.h +++ b/include/common/memory.h @@ -134,7 +134,7 @@ struct pool_head { /* Allocate a new entry for pool , and return it for immediate use. * NULL is returned if no memory is available for a new creation. */ -void *refill_pool_alloc(struct pool_head *pool); +void *pool_refill_alloc(struct pool_head *pool); /* Try to find an existing shared pool with the same characteristics and * returns it, otherwise creates this one. NULL is returned if no memory @@ -146,6 +146,23 @@ struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags) */ void dump_pools(void); +/* + * This function frees whatever can be freed in pool . + */ +void pool_flush2(struct pool_head *pool); + +/* + * This function frees whatever can be freed in all pools, but respecting + * the minimum thresholds imposed by owners. + */ +void pool_gc2(); + +/* + * This function destroys a pull by freeing it completely. + * This should be called only under extreme circumstances. + */ +void pool_destroy2(struct pool_head *pool); + /* * Returns a pointer to type taken from the * pool or dynamically allocated. In the @@ -155,11 +172,11 @@ void dump_pools(void); #define pool_alloc2(pool) \ ({ \ void *__p; \ - if ((__p = pool.free_list) == NULL) \ - __p = pool_refill_alloc(&pool); \ + if ((__p = pool->free_list) == NULL) \ + __p = pool_refill_alloc(pool); \ else { \ - pool.free_list = *(void **)pool.free_list; \ - pool.used++; \ + pool->free_list = *(void **)pool->free_list; \ + pool->used++; \ } \ __p; \ }) @@ -174,9 +191,9 @@ void dump_pools(void); */ #define pool_free2(pool, ptr) \ ({ \ - *(void **)ptr = (void *)pool.free_list; \ - pool.free_list = (void *)ptr; \ - pool.used--; \ + *(void **)ptr = (void *)pool->free_list; \ + pool->free_list = (void *)ptr; \ + pool->used--; \ }) diff --git a/src/memory.c b/src/memory.c index 5dbbdd91f7..dd542252bb 100644 --- a/src/memory.c +++ b/src/memory.c @@ -66,7 +66,7 @@ struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags) /* Allocate a new entry for pool , and return it for immediate use. * NULL is returned if no memory is available for a new creation. */ -void *refill_pool_alloc(struct pool_head *pool) +void *pool_refill_alloc(struct pool_head *pool) { void *ret; @@ -80,6 +80,57 @@ void *refill_pool_alloc(struct pool_head *pool) return ret; } +/* + * This function frees whatever can be freed in pool . + */ +void pool_flush2(struct pool_head *pool) +{ + void *temp, *next; + next = pool->free_list; + while (next) { + temp = next; + next = *(void **)temp; + pool->allocated--; + FREE(temp); + } + pool->free_list = next; + + /* here, we should have pool->allocate == pool->used */ +} + +/* + * This function frees whatever can be freed in all pools, but respecting + * the minimum thresholds imposed by owners. + */ +void pool_gc2() +{ + struct pool_head *entry; + list_for_each_entry(entry, &pools, list) { + void *temp, *next; + //qfprintf(stderr, "Flushing pool %s\n", entry->name); + next = entry->free_list; + while (next && + entry->allocated > entry->minavail && + entry->allocated > entry->used) { + temp = next; + next = *(void **)temp; + entry->allocated--; + FREE(temp); + } + entry->free_list = next; + } +} + +/* + * This function destroys a pull by freeing it completely. + * This should be called only under extreme circumstances. + */ +void pool_destroy2(struct pool_head *pool) +{ + pool_flush2(pool); + FREE(pool); +} + /* Dump statistics on pools usage. */ void dump_pools(void) @@ -91,15 +142,16 @@ void dump_pools(void) allocated = used = nbpools = 0; qfprintf(stderr, "Dumping pools usage.\n"); list_for_each_entry(entry, &pools, list) { - qfprintf(stderr, " - Pool %s (%d bytes) : %d allocated, %d used%s\n", - entry->name, entry->size, entry->allocated, entry->used, - (entry->flags & MEM_F_SHARED) ? " (SHARED)" : ""); + qfprintf(stderr, " - Pool %s (%d bytes) : %d allocated (%lu bytes), %d used%s\n", + entry->name, entry->size, entry->allocated, + entry->size * entry->allocated, entry->used, + (entry->flags & MEM_F_SHARED) ? " [SHARED]" : ""); allocated += entry->allocated * entry->size; used += entry->used * entry->size; nbpools++; } - qfprintf(stderr, "Total: %d pools, %lu allocated, %lu used.\n", + qfprintf(stderr, "Total: %d pools, %lu bytes allocated, %lu used.\n", nbpools, allocated, used); }