MEDIUM: debug: improve DEBUG_MEM_STATS to also report pool alloc/free

Sometimes using "debug dev memstats" can be frustrating because all
pool allocations are reported through pool-os.h and that's all.

But in practice there's nothing wrong with also intercepting pool_alloc,
pool_free and pool_zalloc and report their call counts and locations,
so that's what this patch does. It only uses an alternate set of macroes
for these 3 calls when DEBUG_MEM_STATS is defined. The outputs are
reported as P_ALLOC (for both pool_malloc() and pool_zalloc()) and
P_FREE (for pool_free()).
This commit is contained in:
Willy Tarreau 2022-06-23 10:54:17 +02:00
parent b8dec4a01a
commit 27061cd144
3 changed files with 55 additions and 0 deletions

View File

@ -233,6 +233,8 @@ enum {
MEM_STATS_TYPE_MALLOC,
MEM_STATS_TYPE_REALLOC,
MEM_STATS_TYPE_STRDUP,
MEM_STATS_TYPE_P_ALLOC,
MEM_STATS_TYPE_P_FREE,
};
struct mem_stats {

View File

@ -224,6 +224,8 @@ static inline void *pool_get_from_cache(struct pool_head *pool, const void *call
/****************** Common high-level code ******************/
#if !defined(DEBUG_MEM_STATS)
/*
* Returns a pointer to type <type> taken from the pool <pool_type> or
* dynamically allocated. Memory poisonning is performed if enabled.
@ -247,6 +249,55 @@ static inline void *pool_get_from_cache(struct pool_head *pool, const void *call
__pool_free(pool, __ptr); \
} while (0)
#else /* DEBUG_MEM_STATS is set below */
#define pool_free(pool, ptr) ({ \
struct pool_head *__pool = (pool); \
typeof(ptr) __ptr = (ptr); \
static struct mem_stats _ __attribute__((used,__section__("mem_stats"))) = { \
.file = __FILE__, .line = __LINE__, \
.type = MEM_STATS_TYPE_P_FREE, \
}; \
HA_WEAK("__start_mem_stats"); \
HA_WEAK("__stop_mem_stats"); \
if (__ptr) { \
_HA_ATOMIC_INC(&_.calls); \
_HA_ATOMIC_ADD(&_.size, __pool->size); \
__pool_free(__pool, __ptr); \
} \
})
#define pool_alloc(pool) ({ \
struct pool_head *__pool = (pool); \
size_t __x = __pool->size; \
static struct mem_stats _ __attribute__((used,__section__("mem_stats"))) = { \
.file = __FILE__, .line = __LINE__, \
.type = MEM_STATS_TYPE_P_ALLOC, \
}; \
HA_WEAK("__start_mem_stats"); \
HA_WEAK("__stop_mem_stats"); \
_HA_ATOMIC_INC(&_.calls); \
_HA_ATOMIC_ADD(&_.size, __x); \
__pool_alloc(__pool, 0); \
})
#define pool_zalloc(pool) ({ \
struct pool_head *__pool = (pool); \
size_t __x = __pool->size; \
static struct mem_stats _ __attribute__((used,__section__("mem_stats"))) = { \
.file = __FILE__, .line = __LINE__, \
.type = MEM_STATS_TYPE_P_ALLOC, \
}; \
HA_WEAK("__start_mem_stats"); \
HA_WEAK("__stop_mem_stats"); \
_HA_ATOMIC_INC(&_.calls); \
_HA_ATOMIC_ADD(&_.size, __x); \
__pool_alloc(__pool, POOL_F_MUST_ZERO); \
})
#endif /* DEBUG_MEM_STATS */
#endif /* _HAPROXY_POOL_H */
/*

View File

@ -1269,6 +1269,8 @@ static int debug_iohandler_memstats(struct appctx *appctx)
case MEM_STATS_TYPE_MALLOC: type = "MALLOC"; break;
case MEM_STATS_TYPE_REALLOC: type = "REALLOC"; break;
case MEM_STATS_TYPE_STRDUP: type = "STRDUP"; break;
case MEM_STATS_TYPE_P_ALLOC: type = "P_ALLOC"; break;
case MEM_STATS_TYPE_P_FREE: type = "P_FREE"; break;
default: type = "UNSET"; break;
}