#include "super_reg_box.h" #include #include #include #include #include "hakmem_super_registry.h" // プロファイル別の実容量・論理上限 static _Atomic int g_super_reg_effective_size = SUPER_REG_SIZE; static _Atomic int g_super_reg_effective_mask = SUPER_REG_MASK; static _Atomic int g_super_reg_effective_per_class = SUPER_REG_PER_CLASS; static _Atomic int g_super_reg_profile_inited = 0; // 動的に確保する実配列 static SuperRegEntry* g_super_reg_entries = NULL; static SuperSlab** g_super_reg_by_class_slots = NULL; static int g_super_reg_by_class_stride = SUPER_REG_PER_CLASS; static _Atomic int g_super_reg_allocated = 0; static inline int super_reg_clamp_power_of_two(int requested, int fallback) { // SUPER_REG_SIZE は 2 のべき乗なので、requested もそれ未満のべき乗に丸める。 if (requested <= 0 || requested > SUPER_REG_SIZE) { return fallback; } // 丸め: 最上位ビットだけを残す(2 のべき乗に丸め下げ) int v = requested; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v = v - (v >> 1); // 有効値は最低でも 1024 にしておく if (v < 1024) { v = 1024; } return v; } static void super_reg_apply_profile(const char* profile) { if (g_super_reg_profile_inited) { return; } const char* env_profile = profile ? profile : getenv("HAKMEM_PROFILE"); const int is_bench = (env_profile && strcmp(env_profile, "bench") == 0); int eff_size = SUPER_REG_SIZE; int eff_per_class = SUPER_REG_PER_CLASS; if (is_bench) { // 論理上の利用範囲だけ縮める(配列は従来サイズのまま) eff_size = SUPER_REG_SIZE >> 3; // 1/8 に論理制限 eff_per_class = SUPER_REG_PER_CLASS >> 4; // 1/16 } eff_size = super_reg_clamp_power_of_two(eff_size, SUPER_REG_SIZE); eff_per_class = eff_per_class > 0 ? eff_per_class : SUPER_REG_PER_CLASS; atomic_store_explicit(&g_super_reg_effective_size, eff_size, memory_order_relaxed); atomic_store_explicit(&g_super_reg_effective_mask, eff_size - 1, memory_order_relaxed); atomic_store_explicit(&g_super_reg_effective_per_class, eff_per_class, memory_order_relaxed); atomic_store_explicit(&g_super_reg_profile_inited, 1, memory_order_release); } void super_reg_init(SuperRegBox* box, const char* profile) { (void)box; super_reg_apply_profile(profile); if (atomic_load_explicit(&g_super_reg_allocated, memory_order_acquire)) { return; } int eff_size = super_reg_effective_size(); int per_class = super_reg_effective_per_class(); // Allocate registry table size_t reg_bytes = (size_t)eff_size * sizeof(SuperRegEntry); g_super_reg_entries = (SuperRegEntry*)calloc(eff_size, sizeof(SuperRegEntry)); if (!g_super_reg_entries) { fprintf(stderr, "[SUPER_REG] failed to allocate %zu bytes for registry\n", reg_bytes); abort(); } // Allocate per-class table (contiguous 1D block) size_t per_class_bytes = (size_t)TINY_NUM_CLASSES * (size_t)per_class * sizeof(SuperSlab*); g_super_reg_by_class_slots = (SuperSlab**)calloc(TINY_NUM_CLASSES * (size_t)per_class, sizeof(SuperSlab*)); if (!g_super_reg_by_class_slots) { fprintf(stderr, "[SUPER_REG] failed to allocate %zu bytes for per-class registry\n", per_class_bytes); abort(); } g_super_reg_by_class_stride = per_class; atomic_store_explicit(&g_super_reg_allocated, 1, memory_order_release); } int super_reg_effective_size(void) { if (!atomic_load_explicit(&g_super_reg_profile_inited, memory_order_acquire)) { super_reg_apply_profile(NULL); } return atomic_load_explicit(&g_super_reg_effective_size, memory_order_relaxed); } int super_reg_effective_mask(void) { if (!atomic_load_explicit(&g_super_reg_profile_inited, memory_order_acquire)) { super_reg_apply_profile(NULL); } return atomic_load_explicit(&g_super_reg_effective_mask, memory_order_relaxed); } int super_reg_effective_per_class(void) { if (!atomic_load_explicit(&g_super_reg_profile_inited, memory_order_acquire)) { super_reg_apply_profile(NULL); } return atomic_load_explicit(&g_super_reg_effective_per_class, memory_order_relaxed); } SuperRegEntry* super_reg_entries(void) { if (!atomic_load_explicit(&g_super_reg_allocated, memory_order_acquire)) { super_reg_init(NULL, NULL); } return g_super_reg_entries; } SuperSlab** super_reg_by_class_slots(void) { if (!atomic_load_explicit(&g_super_reg_allocated, memory_order_acquire)) { super_reg_init(NULL, NULL); } return g_super_reg_by_class_slots; } int super_reg_by_class_stride(void) { if (!atomic_load_explicit(&g_super_reg_allocated, memory_order_acquire)) { super_reg_init(NULL, NULL); } return g_super_reg_by_class_stride; }