#define _GNU_SOURCE #include "tiny_static_route_box.h" #include "smallobject_policy_v7_box.h" #include #include TinyStaticRoute g_tiny_static_route = {.inited = ATOMIC_VAR_INIT(0)}; static _Atomic int static_route_cached_enabled = -1; // -1 = uninitialized // Check if static routing should be enabled // (Returns 0 if learner is active, or if ENV is explicitly off) static inline int static_route_should_be_enabled(void) { const char* e = getenv("HAKMEM_TINY_STATIC_ROUTE"); // Explicit disable if (e && *e == '0') return 0; // If v7 learner is enabled, force disable (static route doesn't track learner updates). // Mirrors smallobject_policy_v7.c::learner_v7_enabled(): // - If HAKMEM_SMALL_LEARNER_V7_ENABLED=0 → learner disabled // - Else learner enabled iff HAKMEM_SMALL_HEAP_V7_ENABLED is enabled { const char* learner_e = getenv("HAKMEM_SMALL_LEARNER_V7_ENABLED"); if (!(learner_e && *learner_e && *learner_e == '0')) { const char* v7_e = getenv("HAKMEM_SMALL_HEAP_V7_ENABLED"); if (v7_e && *v7_e && *v7_e != '0') { return 0; // Learner ON → static route OFF } } } // Explicit enable or default OFF return (e && *e != '0') ? 1 : 0; } int tiny_static_route_init_once(void) { // Check if static routing is enabled if (!static_route_should_be_enabled()) { atomic_store_explicit(&g_tiny_static_route.inited, 0, memory_order_release); return 0; } int state = atomic_load_explicit(&g_tiny_static_route.inited, memory_order_acquire); if (__builtin_expect(state == 1, 1)) { return 1; } if (__builtin_expect(state == -1, 0)) { while (atomic_load_explicit(&g_tiny_static_route.inited, memory_order_acquire) == -1) { __builtin_ia32_pause(); } return atomic_load_explicit(&g_tiny_static_route.inited, memory_order_acquire) == 1; } // Try to become the initializer: 0 → -1 int expected = 0; if (!atomic_compare_exchange_strong_explicit(&g_tiny_static_route.inited, &expected, -1, memory_order_acq_rel, memory_order_relaxed)) { // Someone else is initializing or already initialized while (atomic_load_explicit(&g_tiny_static_route.inited, memory_order_acquire) == -1) { __builtin_ia32_pause(); } return atomic_load_explicit(&g_tiny_static_route.inited, memory_order_acquire) == 1; } // We own the initialization SmallPolicyV7 tmp = {0}; small_policy_v7_init_from_env(&tmp); // Copy static route table from policy snapshot (no learner update) for (int i = 0; i < 8; i++) { g_tiny_static_route.route_kind[i] = tmp.route_kind[i]; } // Mark as initialized atomic_store_explicit(&g_tiny_static_route.inited, 1, memory_order_release); return 1; } SmallRouteKind tiny_static_route_get_kind(int class_idx) { if ((unsigned)class_idx >= 8u) { return SMALL_ROUTE_LEGACY; } if (atomic_load_explicit(&g_tiny_static_route.inited, memory_order_acquire) != 1) { if (!tiny_static_route_init_once()) { return SMALL_ROUTE_LEGACY; } } return g_tiny_static_route.route_kind[class_idx]; } void tiny_static_route_refresh_from_env(void) { // Refresh cached enable flag first (bench_apply_profile sync). int enabled = static_route_should_be_enabled(); atomic_store_explicit(&static_route_cached_enabled, enabled, memory_order_release); if (!enabled) { atomic_store_explicit(&g_tiny_static_route.inited, 0, memory_order_release); return; } // Re-read route table from policy SmallPolicyV7 tmp = {0}; small_policy_v7_init_from_env(&tmp); for (int i = 0; i < 8; i++) { g_tiny_static_route.route_kind[i] = tmp.route_kind[i]; } atomic_store_explicit(&g_tiny_static_route.inited, 1, memory_order_release); } int tiny_static_route_enabled(void) { int cached = atomic_load_explicit(&static_route_cached_enabled, memory_order_acquire); if (__builtin_expect(cached >= 0, 1)) { return cached; } int enabled = static_route_should_be_enabled(); atomic_store_explicit(&static_route_cached_enabled, enabled, memory_order_release); return enabled; } __attribute__((constructor(102))) static void tiny_static_route_ctor(void) { // Constructor priority 102 runs after wrapper_env_ctor (101) // Initialize static route table if enabled if (atomic_load_explicit(&g_tiny_static_route.inited, memory_order_acquire) != 1 && tiny_static_route_enabled()) { tiny_static_route_init_once(); } }