Files
hakmem/core/box/capacity_box.c

119 lines
3.8 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.

// capacity_box.c - Box Capacity Manager Implementation
#include "capacity_box.h"
#include "../tiny_adaptive_sizing.h" // TLSCacheStats, adaptive_sizing_init()
#include "../hakmem_tiny.h" // g_tls_sll_count
#include "../hakmem_tiny_config.h" // TINY_NUM_CLASSES, TINY_TLS_MAG_CAP
#include "../hakmem_tiny_integrity.h" // HAK_CHECK_CLASS_IDX
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
// ============================================================================
// Internal State
// ============================================================================
// Initialization flag (atomic for thread-safety)
static _Atomic int g_box_cap_initialized = 0;
// External declarations (from adaptive_sizing and hakmem_tiny)
extern __thread TLSCacheStats g_tls_cache_stats[TINY_NUM_CLASSES]; // TLS variable!
extern __thread uint32_t g_tls_sll_count[TINY_NUM_CLASSES];
extern int g_sll_cap_override[TINY_NUM_CLASSES]; // LEGACY (Phase12以降は参照しない互換用ダミー)
extern int g_sll_multiplier;
// ============================================================================
// Box Capacity API Implementation
// ============================================================================
void box_cap_init(void) {
// Idempotent: only initialize once
int expected = 0;
if (atomic_compare_exchange_strong(&g_box_cap_initialized, &expected, 1)) {
// First call: initialize adaptive sizing
adaptive_sizing_init();
}
// Already initialized or just initialized: safe to proceed
}
bool box_cap_is_initialized(void) {
return atomic_load(&g_box_cap_initialized) != 0;
}
uint32_t box_cap_get(int class_idx) {
// PRIORITY 1: Bounds check
HAK_CHECK_CLASS_IDX(class_idx, "box_cap_get");
// Ensure initialized
if (!box_cap_is_initialized()) {
// Auto-initialize on first use (defensive)
box_cap_init();
}
// Compute SLL capacity using same logic as sll_cap_for_class()
// This centralizes the capacity calculation
// Phase12: g_sll_cap_override はレガシー互換ダミー。capacity_box では無視する。
// Get base capacity from adaptive sizing
uint32_t cap = g_tls_cache_stats[class_idx].capacity;
// Apply class-specific multipliers
if (class_idx <= 3) {
// Hot classes: multiply by g_sll_multiplier
uint32_t mult = (g_sll_multiplier > 0 ? (uint32_t)g_sll_multiplier : 1u);
uint64_t want = (uint64_t)cap * (uint64_t)mult;
if (want > (uint64_t)TINY_TLS_MAG_CAP) {
cap = TINY_TLS_MAG_CAP;
} else {
cap = (uint32_t)want;
}
} else if (class_idx >= 4) {
// Mid-large classes: halve capacity
cap = (cap > 1u ? (cap / 2u) : 1u);
}
return cap;
}
bool box_cap_has_room(int class_idx, uint32_t n) {
// PRIORITY 1: Bounds check
HAK_CHECK_CLASS_IDX(class_idx, "box_cap_has_room");
uint32_t cap = box_cap_get(class_idx);
uint32_t used = g_tls_sll_count[class_idx];
// Check if adding N would exceed capacity
if (used >= cap) return false;
uint32_t avail = cap - used;
return (n <= avail);
}
uint32_t box_cap_avail(int class_idx) {
// PRIORITY 1: Bounds check
HAK_CHECK_CLASS_IDX(class_idx, "box_cap_avail");
uint32_t cap = box_cap_get(class_idx);
uint32_t used = g_tls_sll_count[class_idx];
if (used >= cap) return 0;
return (cap - used);
}
void box_cap_update(int class_idx, uint32_t new_cap) {
// PRIORITY 1: Bounds check
HAK_CHECK_CLASS_IDX(class_idx, "box_cap_update");
// Ensure initialized
if (!box_cap_is_initialized()) {
box_cap_init();
}
// Clamp to max
if (new_cap > TINY_TLS_MAG_CAP) {
new_cap = TINY_TLS_MAG_CAP;
}
// Update adaptive sizing stats
g_tls_cache_stats[class_idx].capacity = new_cap;
}