mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-01 17:10:42 +00:00
DEBUG/MEDIUM: memory: optionally protect free data in pools
When debugging a core file, it's sometimes convenient to be able to visit the released entries in the pools (typically last released session). Unfortunately the first bytes of these entries are destroyed by the link elements of the pool. And of course, most structures have their most accessed elements at the beginning of the structure (typically flags). Let's add a build-time option DEBUG_MEMORY_POOLS which allocates an extra pointer in each pool to put the link at the end of each pool item instead of the beginning.
This commit is contained in:
parent
a84dcb8440
commit
ac421118db
@ -34,6 +34,15 @@
|
||||
#define MEM_F_SHARED 0
|
||||
#endif
|
||||
|
||||
/* reserve an extra void* at the end of a pool for linking */
|
||||
#ifdef DEBUG_MEMORY_POOLS
|
||||
#define POOL_EXTRA (sizeof(void *))
|
||||
#define POOL_LINK(pool, item) (void **)(((char *)item) + (pool->size))
|
||||
#else
|
||||
#define POOL_EXTRA (0)
|
||||
#define POOL_LINK(pool, item) ((void **)(item))
|
||||
#endif
|
||||
|
||||
struct pool_head {
|
||||
void **free_list;
|
||||
struct list list; /* list of all known pools */
|
||||
@ -113,7 +122,7 @@ static inline void *pool_get_first(struct pool_head *pool)
|
||||
void *p;
|
||||
|
||||
if ((p = pool->free_list) != NULL) {
|
||||
pool->free_list = *(void **)pool->free_list;
|
||||
pool->free_list = *POOL_LINK(pool, p);
|
||||
pool->used++;
|
||||
}
|
||||
return p;
|
||||
@ -162,7 +171,7 @@ static inline void *pool_alloc2(struct pool_head *pool)
|
||||
static inline void pool_free2(struct pool_head *pool, void *ptr)
|
||||
{
|
||||
if (likely(ptr != NULL)) {
|
||||
*(void **)ptr= (void *)pool->free_list;
|
||||
*POOL_LINK(pool, ptr) = (void *)pool->free_list;
|
||||
pool->free_list = (void *)ptr;
|
||||
pool->used--;
|
||||
}
|
||||
|
14
src/memory.c
14
src/memory.c
@ -33,14 +33,16 @@ struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
|
||||
struct list *start;
|
||||
unsigned int align;
|
||||
|
||||
/* We need to store at least a (void *) in the chunks. Since we know
|
||||
/* We need to store a (void *) at the end of the chunks. Since we know
|
||||
* that the malloc() function will never return such a small size,
|
||||
* let's round the size up to something slightly bigger, in order to
|
||||
* ease merging of entries. Note that the rounding is a power of two.
|
||||
* This extra (void *) is not accounted for in the size computation
|
||||
* so that the visible parts outside are not affected.
|
||||
*/
|
||||
|
||||
align = 16;
|
||||
size = (size + align - 1) & -align;
|
||||
size = ((size + POOL_EXTRA + align - 1) & -align) - POOL_EXTRA;
|
||||
|
||||
start = &pools;
|
||||
pool = NULL;
|
||||
@ -99,7 +101,7 @@ void *pool_refill_alloc(struct pool_head *pool, unsigned int avail)
|
||||
if (pool->limit && pool->allocated >= pool->limit)
|
||||
return NULL;
|
||||
|
||||
ptr = MALLOC(pool->size);
|
||||
ptr = MALLOC(pool->size + POOL_EXTRA);
|
||||
if (!ptr) {
|
||||
if (failed)
|
||||
return NULL;
|
||||
@ -110,7 +112,7 @@ void *pool_refill_alloc(struct pool_head *pool, unsigned int avail)
|
||||
if (++pool->allocated > avail)
|
||||
break;
|
||||
|
||||
*(void **)ptr = (void *)pool->free_list;
|
||||
*POOL_LINK(pool, ptr) = (void *)pool->free_list;
|
||||
pool->free_list = ptr;
|
||||
}
|
||||
pool->used++;
|
||||
@ -129,7 +131,7 @@ void pool_flush2(struct pool_head *pool)
|
||||
next = pool->free_list;
|
||||
while (next) {
|
||||
temp = next;
|
||||
next = *(void **)temp;
|
||||
next = *POOL_LINK(pool, temp);
|
||||
pool->allocated--;
|
||||
FREE(temp);
|
||||
}
|
||||
@ -158,7 +160,7 @@ void pool_gc2()
|
||||
while (next &&
|
||||
(int)(entry->allocated - entry->used) > (int)entry->minavail) {
|
||||
temp = next;
|
||||
next = *(void **)temp;
|
||||
next = *POOL_LINK(entry, temp);
|
||||
entry->allocated--;
|
||||
FREE(temp);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user