From 2dfc8417cf99d85760457b444f107c35bedfaa5d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 3 Mar 2026 14:02:38 +0100 Subject: [PATCH] MINOR: memprof: prepare to consider exec_ctx in reporting This now allows to report the same function in multiple bins based on the th_ctx's exec_ctx discriminant. It's also worth noting that the context is not atomically committed, but this shouldn't be a problem since a single entry can get it. In the worst case, a second thread trying to create the same context in parallel would create a different bin just for this call, which is harmless. The same situation already exists with the caller pointer. --- include/haproxy/activity-t.h | 2 ++ src/activity.c | 26 +++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/haproxy/activity-t.h b/include/haproxy/activity-t.h index 37fdeb10a..e84643b95 100644 --- a/include/haproxy/activity-t.h +++ b/include/haproxy/activity-t.h @@ -24,6 +24,7 @@ #include #include +#include /* bit fields for the "profiling" global variable */ #define HA_PROF_TASKS_OFF 0x00000000 /* per-task CPU profiling forced disabled */ @@ -84,6 +85,7 @@ struct memprof_stats { unsigned long long alloc_tot; unsigned long long free_tot; void *info; // for pools, ptr to the pool + struct thread_exec_ctx exec_ctx; }; #endif diff --git a/src/activity.c b/src/activity.c index d270a6500..61648ba40 100644 --- a/src/activity.c +++ b/src/activity.c @@ -308,9 +308,12 @@ struct memprof_stats *memprof_get_bin(const void *ra, enum memprof_method meth) bin = MEMPROF_HASH_BUCKETS; goto leave; } - hash = _ptr_hash(ra); - bin = _ptr_hash_reduce(hash, MEMPROF_HASH_BITS); - for (; memprof_stats[bin].caller != ra; bin = (bin + (hash | 1)) & (MEMPROF_HASH_BUCKETS - 1)) { + hash = _ptr2_hash_arg(ra, th_ctx->exec_ctx.pointer, th_ctx->exec_ctx.type); + for (bin = _ptr_hash_reduce(hash, MEMPROF_HASH_BITS); + memprof_stats[bin].caller != ra || + memprof_stats[bin].exec_ctx.type != th_ctx->exec_ctx.type || + memprof_stats[bin].exec_ctx.pointer != th_ctx->exec_ctx.pointer; + bin = (bin + (hash | 1)) & (MEMPROF_HASH_BUCKETS - 1)) { if (!--retries) { bin = MEMPROF_HASH_BUCKETS; break; @@ -319,6 +322,7 @@ struct memprof_stats *memprof_get_bin(const void *ra, enum memprof_method meth) old = NULL; if (!memprof_stats[bin].caller && HA_ATOMIC_CAS(&memprof_stats[bin].caller, &old, ra)) { + memprof_stats[bin].exec_ctx = th_ctx->exec_ctx; memprof_stats[bin].method = meth; break; } @@ -923,6 +927,14 @@ static int cmp_memprof_stats(const void *a, const void *b) return -1; else if (l->alloc_tot + l->free_tot < r->alloc_tot + r->free_tot) return 1; + else if (l->exec_ctx.type > r->exec_ctx.type) + return -1; + else if (l->exec_ctx.type < r->exec_ctx.type) + return 1; + else if (l->exec_ctx.pointer > r->exec_ctx.pointer) + return -1; + else if (l->exec_ctx.pointer < r->exec_ctx.pointer) + return 1; else return 0; } @@ -936,6 +948,14 @@ static int cmp_memprof_addr(const void *a, const void *b) return -1; else if (l->caller < r->caller) return 1; + else if (l->exec_ctx.type > r->exec_ctx.type) + return -1; + else if (l->exec_ctx.type < r->exec_ctx.type) + return 1; + else if (l->exec_ctx.pointer > r->exec_ctx.pointer) + return -1; + else if (l->exec_ctx.pointer < r->exec_ctx.pointer) + return 1; else return 0; }