diff --git a/core/box/mailbox_box.c b/core/box/mailbox_box.c index 5acaa1a3..8ab99f56 100644 --- a/core/box/mailbox_box.c +++ b/core/box/mailbox_box.c @@ -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 #include @@ -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); diff --git a/core/hakmem_trace_master.h b/core/hakmem_trace_master.h new file mode 100644 index 00000000..60cc759a --- /dev/null +++ b/core/hakmem_trace_master.h @@ -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 +#include + +// 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 diff --git a/core/tiny_refill.h b/core/tiny_refill.h index 4ae66052..5bc02a55 100644 --- a/core/tiny_refill.h +++ b/core/tiny_refill.h @@ -2,6 +2,7 @@ #pragma once #include #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;