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.
This commit is contained in:
Willy Tarreau 2026-03-03 14:02:38 +01:00
parent b7c8fab507
commit 2dfc8417cf
2 changed files with 25 additions and 3 deletions

View File

@ -24,6 +24,7 @@
#include <haproxy/api-t.h>
#include <haproxy/freq_ctr-t.h>
#include <haproxy/tinfo-t.h>
/* 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

View File

@ -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;
}