Files
hakmem/core/box/super_reg_box.c

144 lines
5.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "super_reg_box.h"
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}