145 lines
4.9 KiB
C
145 lines
4.9 KiB
C
|
|
// 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
|