109 lines
3.4 KiB
C
109 lines
3.4 KiB
C
|
|
#define _GNU_SOURCE
|
||
|
|
#include "tiny_static_route_box.h"
|
||
|
|
#include "smallobject_policy_v7_box.h"
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <stdatomic.h>
|
||
|
|
|
||
|
|
TinyStaticRoute g_tiny_static_route = {.inited = 0};
|
||
|
|
|
||
|
|
static 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 learner is enabled, force disable (static route doesn't track learner updates)
|
||
|
|
// Check: if HAKMEM_TINY_LEARNER_ENABLED is set to 1, disable static route
|
||
|
|
const char* learner_e = getenv("HAKMEM_TINY_LEARNER_ENABLED");
|
||
|
|
if (learner_e && *learner_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()) {
|
||
|
|
g_tiny_static_route.inited = 0;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Atomic initialization
|
||
|
|
static _Atomic int init_started = 0;
|
||
|
|
int expected = 0;
|
||
|
|
|
||
|
|
if (!atomic_compare_exchange_strong_explicit(&init_started, &expected, 1,
|
||
|
|
memory_order_acq_rel,
|
||
|
|
memory_order_relaxed)) {
|
||
|
|
// Someone else is initializing or already initialized
|
||
|
|
while (!__builtin_expect(g_tiny_static_route.inited, 1)) {
|
||
|
|
__builtin_ia32_pause();
|
||
|
|
}
|
||
|
|
return g_tiny_static_route.inited;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 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 (!g_tiny_static_route.inited) {
|
||
|
|
return 0; // Not available
|
||
|
|
}
|
||
|
|
if (class_idx < 0 || class_idx >= 8) {
|
||
|
|
return 0; // Invalid class
|
||
|
|
}
|
||
|
|
return g_tiny_static_route.route_kind[class_idx];
|
||
|
|
}
|
||
|
|
|
||
|
|
void tiny_static_route_refresh_from_env(void) {
|
||
|
|
// Re-initialize if needed (for bench_apply_profile sync)
|
||
|
|
if (!static_route_should_be_enabled()) {
|
||
|
|
g_tiny_static_route.inited = 0;
|
||
|
|
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) {
|
||
|
|
// Check cached enable flag
|
||
|
|
if (static_route_cached_enabled < 0) {
|
||
|
|
static_route_cached_enabled = static_route_should_be_enabled();
|
||
|
|
}
|
||
|
|
return static_route_cached_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 (!g_tiny_static_route.inited && tiny_static_route_enabled()) {
|
||
|
|
tiny_static_route_init_once();
|
||
|
|
}
|
||
|
|
}
|