Phase 4c: Add master trace control (HAKMEM_TRACE)

Add unified trace control that allows enabling specific trace modules
using comma-separated values or "all" to enable everything.

New file: core/hakmem_trace_master.h
- HAKMEM_TRACE=all: Enable all trace modules
- HAKMEM_TRACE=ptr,refill,free,mailbox: Enable specific modules
- HAKMEM_TRACE_LEVEL=N: Set trace verbosity (1-3)
- hak_trace_check(): Check if module should enable tracing

Available trace modules:
  ptr, refill, superslab, ring, free, mailbox, registry

Priority order:
1. HAKMEM_QUIET=1 → suppress all
2. Specific module ENV (e.g., HAKMEM_PTR_TRACE=1)
3. HAKMEM_TRACE=module1,module2
4. Default → disabled

Updated files:
- core/tiny_refill.h: Use hak_trace_check() for refill tracing
- core/box/mailbox_box.c: Use hak_trace_check() for mailbox tracing

Performance: No regression (72.9M ops/s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm (CI)
2025-11-28 16:08:44 +09:00
parent 322d94ac6a
commit f36ebe83aa
3 changed files with 156 additions and 9 deletions

View File

@ -1,6 +1,7 @@
// mailbox_box.c - Publish Mailbox box (fully separated)
#include "mailbox_box.h"
#include "hakmem_tiny.h"
#include "hakmem_trace_master.h" // Phase 4c: Master trace control
#include "tiny_debug_ring.h"
#include <stdatomic.h>
#include <pthread.h>
@ -55,14 +56,15 @@ extern unsigned long long g_mailbox_slow_discoveries[];
void mailbox_box_register(int class_idx) {
if (g_tls_mailbox_registered[class_idx]) return;
g_mailbox_register_calls[class_idx]++;
// One-shot visibility trace (env: HAKMEM_TINY_RF_TRACE)
// One-shot visibility trace (env: HAKMEM_TINY_RF_TRACE or HAKMEM_TRACE=refill,mailbox)
// Phase 4c: Now uses hak_trace_check() for unified trace control
#if HAKMEM_BUILD_RELEASE
static const int trace_en = 0;
#else
static int trace_en = -1;
if (__builtin_expect(trace_en == -1, 0)) {
const char* e = getenv("HAKMEM_TINY_RF_TRACE");
trace_en = (e && atoi(e) != 0) ? 1 : 0;
trace_en = hak_trace_check("HAKMEM_TINY_RF_TRACE", "refill") ||
hak_trace_check("HAKMEM_TINY_MAILBOX_TRACE", "mailbox");
}
#endif
pthread_once(&g_mailbox_tls_once, mailbox_tls_init);
@ -167,20 +169,20 @@ uintptr_t mailbox_box_peek_one(int class_idx) {
}
uintptr_t mailbox_box_fetch(int class_idx) {
// Phase 4c: Unified trace control via hak_trace_check()
#if HAKMEM_BUILD_RELEASE
if (__builtin_expect(g_mailbox_trace_en == -1, 0)) g_mailbox_trace_en = 0;
if (__builtin_expect(g_mailbox_slowdisc_en == -1, 0)) g_mailbox_slowdisc_en = 0;
if (__builtin_expect(g_mailbox_slowdisc_period == -1, 0)) g_mailbox_slowdisc_period = 256;
#else
if (__builtin_expect(g_mailbox_trace_en == -1, 0)) {
const char* e = getenv("HAKMEM_TINY_MAILBOX_TRACE");
g_mailbox_trace_en = (e && atoi(e) != 0) ? 1 : 0;
g_mailbox_trace_en = hak_trace_check("HAKMEM_TINY_MAILBOX_TRACE", "mailbox");
const char* l = getenv("HAKMEM_TINY_MAILBOX_TRACE_LIMIT");
int v = l ? atoi(l) : 0;
if (v > 0) g_mailbox_trace_limit = v;
}
// Optional slow discovery
// Optional slow discovery (not trace-related, keep original logic)
if (__builtin_expect(g_mailbox_slowdisc_en == -1, 0)) {
const char* e = getenv("HAKMEM_TINY_MAILBOX_SLOWDISC");
g_mailbox_slowdisc_en = (e ? ((atoi(e) != 0) ? 1 : 0) : 1);

144
core/hakmem_trace_master.h Normal file
View File

@ -0,0 +1,144 @@
// hakmem_trace_master.h - Master Trace Control
//
// ENV Cleanup Phase 4c: Unified trace control
//
// Usage:
// HAKMEM_TRACE=all Enable ALL trace modules
// HAKMEM_TRACE=ptr,refill,free Enable specific modules (comma-separated)
// HAKMEM_TRACE_LEVEL=N Set trace verbosity (1=basic, 2=detailed, 3=verbose)
//
// Available trace modules:
// ptr - Pointer tracking (HAKMEM_PTR_TRACE, PTR_TRACE_ALL, PTR_TRACE_VERBOSE)
// refill - Refill path (HAKMEM_TINY_RF_TRACE)
// superslab - SuperSlab operations (HAKMEM_TINY_SUPERSLAB_TRACE)
// ring - Debug ring (HAKMEM_TINY_TRACE_RING)
// free - Free path (HAKMEM_FREE_ROUTE_TRACE, FREE_WRAP_TRACE)
// mailbox - Mailbox operations (HAKMEM_TINY_MAILBOX_TRACE)
// registry - Registry operations (HAKMEM_SUPER_REG_REQTRACE)
//
// Priority (highest to lowest):
// 1. HAKMEM_QUIET=1 → suppress all traces
// 2. Specific module ENV (e.g., HAKMEM_PTR_TRACE=1) → use that value
// 3. HAKMEM_TRACE=module1,module2 → enable listed modules
// 4. HAKMEM_TRACE=all → enable all
// 5. Default → disabled
//
// Integration example:
// Old: static int tr = -1;
// if (tr==-1) { const char* e = getenv("HAKMEM_FOO_TRACE"); tr = (e && *e != '0') ? 1 : 0; }
//
// New: static int tr = -1;
// if (tr==-1) { tr = hak_trace_check("HAKMEM_FOO_TRACE", "foo"); }
#ifndef HAKMEM_TRACE_MASTER_H
#define HAKMEM_TRACE_MASTER_H
#include <stdlib.h>
#include <string.h>
// Trace module flags (bit positions)
#define HAK_TRACE_PTR (1 << 0)
#define HAK_TRACE_REFILL (1 << 1)
#define HAK_TRACE_SUPERSLAB (1 << 2)
#define HAK_TRACE_RING (1 << 3)
#define HAK_TRACE_FREE (1 << 4)
#define HAK_TRACE_MAILBOX (1 << 5)
#define HAK_TRACE_REGISTRY (1 << 6)
#define HAK_TRACE_ALL 0xFFFFFFFF
// Master trace state (cached at first access)
static int g_trace_master_mask = -1; // -1 = uninitialized
static int g_trace_level = -1;
static int g_trace_quiet = -1;
// Map module name to bit flag
static inline int hak_trace_name_to_flag(const char* name) {
if (!name || !*name) return 0;
if (strcmp(name, "all") == 0) return HAK_TRACE_ALL;
if (strcmp(name, "ptr") == 0) return HAK_TRACE_PTR;
if (strcmp(name, "refill") == 0) return HAK_TRACE_REFILL;
if (strcmp(name, "superslab") == 0) return HAK_TRACE_SUPERSLAB;
if (strcmp(name, "ring") == 0) return HAK_TRACE_RING;
if (strcmp(name, "free") == 0) return HAK_TRACE_FREE;
if (strcmp(name, "mailbox") == 0) return HAK_TRACE_MAILBOX;
if (strcmp(name, "registry") == 0) return HAK_TRACE_REGISTRY;
return 0;
}
// Parse comma-separated module list
static inline int hak_trace_parse_modules(const char* str) {
if (!str || !*str) return 0;
int mask = 0;
char buf[256];
strncpy(buf, str, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
char* token = strtok(buf, ",");
while (token) {
// Trim whitespace
while (*token == ' ') token++;
char* end = token + strlen(token) - 1;
while (end > token && *end == ' ') *end-- = '\0';
mask |= hak_trace_name_to_flag(token);
token = strtok(NULL, ",");
}
return mask;
}
// Initialize master trace settings (called once, lazily)
static inline void hak_trace_master_init(void) {
if (__builtin_expect(g_trace_master_mask >= 0, 1)) return;
// Check HAKMEM_QUIET first (highest priority)
const char* quiet = getenv("HAKMEM_QUIET");
g_trace_quiet = (quiet && *quiet && *quiet != '0') ? 1 : 0;
// Check HAKMEM_TRACE
const char* trace = getenv("HAKMEM_TRACE");
g_trace_master_mask = hak_trace_parse_modules(trace);
// Check HAKMEM_TRACE_LEVEL
const char* lvl = getenv("HAKMEM_TRACE_LEVEL");
if (lvl && *lvl) {
int v = atoi(lvl);
if (v < 0) v = 0;
if (v > 3) v = 3;
g_trace_level = v;
} else {
g_trace_level = (g_trace_master_mask > 0) ? 1 : 0;
}
}
// Check if a specific trace module should be enabled
// env_name: The specific ENV variable (e.g., "HAKMEM_PTR_TRACE")
// module: The module name for HAKMEM_TRACE (e.g., "ptr")
// Returns: 1 if trace should be enabled, 0 otherwise
static inline int hak_trace_check(const char* env_name, const char* module) {
hak_trace_master_init();
// HAKMEM_QUIET overrides everything
if (g_trace_quiet) return 0;
// Check specific ENV first (allows explicit enable/disable)
const char* e = getenv(env_name);
if (e && *e) {
return (*e != '0') ? 1 : 0;
}
// Fall back to master trace mask
int flag = hak_trace_name_to_flag(module);
if (flag && (g_trace_master_mask & flag)) return 1;
return 0;
}
// Check trace level for a module
// Returns current trace level if module is enabled, 0 otherwise
static inline int hak_trace_level(const char* env_name, const char* module) {
if (!hak_trace_check(env_name, module)) return 0;
return g_trace_level > 0 ? g_trace_level : 1;
}
#endif // HAKMEM_TRACE_MASTER_H

View File

@ -2,6 +2,7 @@
#pragma once
#include <stdatomic.h>
#include "hakmem_tiny_superslab.h"
#include "hakmem_trace_master.h" // Phase 4c: Master trace control
#include "slab_handle.h"
#include "tiny_sticky.h"
#include "tiny_ready.h"
@ -86,13 +87,13 @@ static inline SuperSlab* tiny_refill_try_fast(int class_idx, TinyTLSSlab* tls) {
}
}
}
// One-shot entry trace (env: HAKMEM_TINY_RF_TRACE), disabled in release builds
// One-shot entry trace (env: HAKMEM_TINY_RF_TRACE or HAKMEM_TRACE=refill)
// Phase 4c: Now uses hak_trace_check() for unified trace control
#if !HAKMEM_BUILD_RELEASE
do {
static int en = -1; static _Atomic int printed[8];
if (__builtin_expect(en == -1, 0)) {
const char* e = getenv("HAKMEM_TINY_RF_TRACE");
en = (e && atoi(e) != 0) ? 1 : 0;
en = hak_trace_check("HAKMEM_TINY_RF_TRACE", "refill");
}
if (en) {
int expected = 0;