Files
hakmem/core/box/ss_unified_backend_box.c
Moe Charm (CI) 9b0d746407 Phase 3d-B: TLS Cache Merge - Unified g_tls_sll[] structure (+12-18% expected)
Merge separate g_tls_sll_head[] and g_tls_sll_count[] arrays into unified
TinyTLSSLL struct to improve L1D cache locality. Expected performance gain:
+12-18% from reducing cache line splits (2 loads → 1 load per operation).

Changes:
- core/hakmem_tiny.h: Add TinyTLSSLL type (16B aligned, head+count+pad)
- core/hakmem_tiny.c: Replace separate arrays with g_tls_sll[8]
- core/box/tls_sll_box.h: Update Box API (13 sites) for unified access
- Updated 32+ files: All g_tls_sll_head[i] → g_tls_sll[i].head
- Updated 32+ files: All g_tls_sll_count[i] → g_tls_sll[i].count
- core/hakmem_tiny_integrity.h: Unified canary guards
- core/box/integrity_box.c: Simplified canary validation
- Makefile: Added core/box/tiny_sizeclass_hist_box.o to link

Build:  PASS (10K ops sanity test)
Warnings: Only pre-existing LTO type mismatches (unrelated)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 07:32:30 +09:00

185 lines
7.4 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.

// Box: Unified Backend (Phase 12)
// Purpose: Unified entry point for SuperSlab allocation (shared pool + legacy fallback)
#include "ss_unified_backend_box.h"
#include "ss_legacy_backend_box.h"
#include "hakmem_tiny_superslab.h"
#include "hakmem_shared_pool.h"
#include "hakmem_tiny_config.h"
#include "ss_allocation_box.h"
#include <stdio.h>
#include <stdlib.h>
// ============================================================================
// Shared Pool Backend
// ============================================================================
/*
* Shared pool backend for hak_tiny_alloc_superslab_box().
*
* Phase 12-2:
* - Uses SharedSuperSlabPool (g_shared_pool) to obtain a SuperSlab/slab
* for the requested class_idx.
* - This backend EXPRESSLY owns only:
* - choosing (ss, slab_idx) via shared_pool_acquire_slab()
* - initializing that slab's TinySlabMeta via superslab_init_slab()
* and nothing else; all callers must go through hak_tiny_alloc_superslab_box().
*
* - For now this is a minimal, conservative implementation:
* - One linear bump-run is carved from the acquired slab using tiny_block_stride_for_class().
* - No complex per-slab freelist or refill policy yet (Phase 12-3+).
* - If shared_pool_acquire_slab() fails, we fall back to legacy backend.
*/
void* hak_tiny_alloc_superslab_backend_shared(int class_idx)
{
if (class_idx < 0 || class_idx >= TINY_NUM_CLASSES_SS) {
return NULL;
}
SuperSlab* ss = NULL;
int slab_idx = -1;
if (shared_pool_acquire_slab(class_idx, &ss, &slab_idx) != 0 || !ss) {
// Shared pool could not provide a slab; caller may choose to fall back.
return NULL;
}
TinySlabMeta* meta = &ss->slabs[slab_idx];
// Defensive: shared_pool must either hand us an UNASSIGNED slab or one
// already bound to this class. Anything else is a hard bug.
if (meta->class_idx != 255 && meta->class_idx != (uint8_t)class_idx) {
#if !HAKMEM_BUILD_RELEASE
fprintf(stderr,
"[HAKMEM][SS_SHARED] BUG: acquire_slab mismatch: cls=%d meta->class_idx=%u slab_idx=%d ss=%p\n",
class_idx, (unsigned)meta->class_idx, slab_idx, (void*)ss);
#endif
return NULL;
}
// Initialize slab geometry once for this class.
if (meta->capacity == 0) {
size_t block_size = g_tiny_class_sizes[class_idx];
// owner_tid_low is advisory; we can use 0 in this backend.
superslab_init_slab(ss, slab_idx, block_size, 0);
meta = &ss->slabs[slab_idx];
// Ensure class_idx is bound to this class after init. superslab_init_slab
// does not touch class_idx by design; shared_pool owns that field.
if (meta->class_idx == 255) {
meta->class_idx = (uint8_t)class_idx;
}
}
// Final contract check before computing addresses.
if (meta->class_idx != (uint8_t)class_idx ||
meta->capacity == 0 ||
meta->used > meta->capacity) {
#if !HAKMEM_BUILD_RELEASE
fprintf(stderr,
"[HAKMEM][SS_SHARED] BUG: invalid slab meta before alloc: "
"cls=%d slab_idx=%d meta_cls=%u used=%u cap=%u ss=%p\n",
class_idx, slab_idx,
(unsigned)meta->class_idx,
(unsigned)meta->used,
(unsigned)meta->capacity,
(void*)ss);
#endif
return NULL;
}
// Simple bump allocation within this slab.
if (meta->used >= meta->capacity) {
// Slab exhausted: in minimal Phase12-2 backend we do not loop;
// caller or future logic must acquire another slab.
return NULL;
}
size_t stride = tiny_block_stride_for_class(class_idx);
size_t offset = (size_t)meta->used * stride;
// Phase 12-2 minimal geometry:
// - slab 0 data offset via SUPERSLAB_SLAB0_DATA_OFFSET
// - subsequent slabs at fixed SUPERSLAB_SLAB_USABLE_SIZE strides.
size_t slab_base_off = SUPERSLAB_SLAB0_DATA_OFFSET
+ (size_t)slab_idx * SUPERSLAB_SLAB_USABLE_SIZE;
uint8_t* base = (uint8_t*)ss + slab_base_off + offset;
meta->used++;
atomic_fetch_add_explicit(&ss->total_active_blocks, 1, memory_order_relaxed);
hak_tiny_ss_hint_record(class_idx, ss, slab_idx);
return (void*)base;
}
// ============================================================================
// Unified Entry Point
// ============================================================================
/*
* Box API entry:
* - Single front-door for tiny-side Superslab allocations.
*
* Phase 27 policy (Unified backend line):
* - デフォルト: Shared Pool backend のみを使用legacy backend は利用しない)。
* - 回帰/デバッグ用途でのみ、ENV で legacy fallback を明示的に有効化できる。
*
* ENV:
* HAKMEM_TINY_SS_SHARED=0 → 強制的に legacy backend のみを使用(過去挙動の回帰確認用)
* HAKMEM_TINY_SS_LEGACY_FALLBACK=0 → shared 失敗時の legacy fallback を無効化(デフォルト: 1, 有効)
* HAKMEM_TINY_SS_C23_UNIFIED=1 → C2/C3 限定で legacy fallback を無効化Shared Pool のみで運転)
* HAKMEM_TINY_SS_LEGACY_HINT=1 → shared→legacy 間の軽量な hint Box を有効化
*/
void* hak_tiny_alloc_superslab_box(int class_idx)
{
static int g_ss_shared_mode = -1;
static int g_ss_legacy_fallback = -1;
static int g_ss_c23_unified = -1;
if (__builtin_expect(g_ss_shared_mode == -1, 0)) {
const char* e = getenv("HAKMEM_TINY_SS_SHARED");
// デフォルト: shared 有効。ENV=0 のときのみ legacy 専用に切り替え。
g_ss_shared_mode = (e && *e == '0') ? 0 : 1;
}
if (__builtin_expect(g_ss_legacy_fallback == -1, 0)) {
const char* e = getenv("HAKMEM_TINY_SS_LEGACY_FALLBACK");
// デフォルト: legacy fallback 有効。
// ENV=0 のときのみ fallback 無効(完全 Unified backend モード)。
g_ss_legacy_fallback = (e && *e == '0') ? 0 : 1;
}
if (__builtin_expect(g_ss_c23_unified == -1, 0)) {
const char* e = getenv("HAKMEM_TINY_SS_C23_UNIFIED");
// ENV=1 のときだけ C2/C3 を「ほぼ完全 Unified」モードに切り替える。
g_ss_c23_unified = (e && *e && *e != '0') ? 1 : 0;
}
// shared OFF 時は legacy のみ(強制回帰モード)
if (!g_ss_shared_mode) {
return hak_tiny_alloc_superslab_backend_legacy(class_idx);
}
int legacy_fallback = g_ss_legacy_fallback;
if ((class_idx == 2 || class_idx == 3) && g_ss_c23_unified == 1) {
// C2/C3 は専用の Shared Pool 実験モード:
// - ENV=1 のときだけ legacy fallback を OFF にする。
legacy_fallback = 0;
}
// Unified backend ライン: Shared Pool backend を唯一の正経路とする。
void* p = hak_tiny_alloc_superslab_backend_shared(class_idx);
if (p != NULL || !legacy_fallback) {
// shared 成功、または legacy fallback 無効 → そのまま返すNULLも許容
return p;
}
// オプション: shared 失敗時に、軽量な hint Box を一度だけ試す
void* hint = hak_tiny_alloc_superslab_backend_hint(class_idx);
if (hint != NULL) {
return hint;
}
// shared 失敗時のみ legacy backend へフォールバック(回帰/デバッグ用)
return hak_tiny_alloc_superslab_backend_legacy(class_idx);
}