diff --git a/core/box/hak_free_api.inc.h b/core/box/hak_free_api.inc.h index 74e9ce21..c37aa4b5 100644 --- a/core/box/hak_free_api.inc.h +++ b/core/box/hak_free_api.inc.h @@ -5,11 +5,11 @@ #include // For mincore() in AllocHeader safety check #include "hakmem_tiny_superslab.h" // For SUPERSLAB_MAGIC, SuperSlab -#include "../tiny_free_fast_v2.inc.h" // Phase 7: Header-based ultra-fast free #include "../ptr_trace.h" // Debug: pointer trace immediate dump on libc fallback #include "front_gate_v2.h" // Phase 15: Box FG V2 - 1-byte header classification #include "external_guard_box.h" // Phase 15: Box ExternalGuard - mincore (ENV controlled) #include "fg_tiny_gate_box.h" // Tiny gate guard box (Superslab check) +#include "tiny_free_gate_box.h" // Tiny Free Gatekeeper Box (USER→Fast Path 境界) #ifdef HAKMEM_POOL_TLS_PHASE1 #include "../pool_tls.h" @@ -112,7 +112,7 @@ void hak_free_at(void* ptr, size_t size, hak_callsite_t site) { } #if HAKMEM_TINY_HEADER_CLASSIDX if (__builtin_expect(g_bench_fast_front && ptr != NULL, 0)) { - if (__builtin_expect(hak_tiny_free_fast_v2(ptr), 1)) { + if (__builtin_expect(tiny_free_gate_try_fast(ptr), 1)) { #if HAKMEM_DEBUG_TIMING HKM_TIME_END(HKM_CAT_HAK_FREE, t0); #endif @@ -144,7 +144,7 @@ void hak_free_at(void* ptr, size_t size, hak_callsite_t site) { case FG_DOMAIN_TINY: { // Fast path: Tiny (C0-C7) with 1-byte header (0xa0 | class_idx) #if HAKMEM_TINY_HEADER_CLASSIDX - if (__builtin_expect(hak_tiny_free_fast_v2(ptr), 1)) { + if (__builtin_expect(tiny_free_gate_try_fast(ptr), 1)) { #if !HAKMEM_BUILD_RELEASE hak_free_v2_track_fast(); #endif diff --git a/core/box/tiny_free_gate_box.h b/core/box/tiny_free_gate_box.h new file mode 100644 index 00000000..ea909b1a --- /dev/null +++ b/core/box/tiny_free_gate_box.h @@ -0,0 +1,162 @@ +// tiny_free_gate_box.h - Box: Tiny Free Gatekeeper +// +// 役割: +// - free エントリで Tiny 向け USER ポインタを一度だけ受け取り、 +// 将来の USER→BASE 変換・Bridge・Guard を集約する「門番」の箱。 +// - 現時点では既存の header-based fast free +// hak_tiny_free_fast_v2(ptr) +// への薄いラッパとして実装し、挙動を変えずに Box 境界だけを確立する。 +// +// Box 理論: +// - Single Responsibility: +// 「Tiny free の入口で、Tiny Fast Path に渡すかどうかを決める」だけに限定。 +// - Clear Boundary: +// hak_free_at() から Tiny Fast Path への入口は tiny_free_gate_try_fast() +// に一本化し、今後 USER→BASE / Bridge / Guard をここに集約できるようにする。 +// - Reversible: +// ENV での診断強化や Guard 追加をこの箱の内側に閉じ込め、 +// OFF にすれば既存挙動に戻せる構造にする。 + +#ifndef HAKMEM_TINY_FREE_GATE_BOX_H +#define HAKMEM_TINY_FREE_GATE_BOX_H + +#include "../hakmem_build_flags.h" + +#include +#include +#include + +#include "ptr_type_box.h" +#include "ptr_conversion_box.h" +#include "tiny_ptr_bridge_box.h" +#include "../tiny_region_id.h" + +// Header-based Tiny Fast Free 実装本体 +#include "../tiny_free_fast_v2.inc.h" + +// 将来の拡張用コンテキスト: +// - user : 元の USER ポインタ +// - base : USER→BASE 変換後の BASE ポインタ +// - bridge: Superslab / slab / meta / class の Bridge 情報 +// - class_idx: meta 由来のクラス (>=0 のとき有効) +typedef struct TinyFreeGateContext { + hak_user_ptr_t user; + hak_base_ptr_t base; + TinyPtrBridgeInfo bridge; + int class_idx; +} TinyFreeGateContext; + +// 診断用 Gatekeeper 拡張の ON/OFF(ENV: HAKMEM_TINY_FREE_GATE_DIAG) +static inline int tiny_free_gate_diag_enabled(void) +{ + static __thread int s_diag = -1; + if (__builtin_expect(s_diag == -1, 0)) { +#if !HAKMEM_BUILD_RELEASE + // Debug ビルドでは env が立っていれば有効化(デフォルト OFF) + const char* e = getenv("HAKMEM_TINY_FREE_GATE_DIAG"); + s_diag = (e && *e && *e != '0') ? 1 : 0; +#else + (void)getenv; + s_diag = 0; +#endif + } + return s_diag; +} + +// 診断用: USER ポインタから Bridge + USER→BASE を一箇所で求める。 +// 戻り値: +// 1: Tiny Superslab 上の有効なブロックと判定(ctx に情報を格納) +// 0: Tiny 管理外または Bridge 失敗(ctx は部分的/空のまま) +static inline int tiny_free_gate_classify(void* user_ptr, TinyFreeGateContext* ctx) +{ + if (!ctx) return 0; + + ctx->user = HAK_USER_FROM_RAW(user_ptr); + ctx->base = HAK_BASE_FROM_RAW(NULL); + ctx->bridge.ss = NULL; + ctx->bridge.meta = NULL; + ctx->bridge.slab_idx = -1; + ctx->bridge.meta_cls = 0xffu; + ctx->class_idx = -1; + + if (!user_ptr) { + return 0; + } + + uintptr_t addr = (uintptr_t)user_ptr; + if (addr < 4096 || addr > 0x00007fffffffffffULL) { + // 明らかにユーザ空間外とみなして Tiny では扱わない + return 0; + } + + TinyPtrBridgeInfo info = tiny_ptr_bridge_classify_raw(user_ptr); + ctx->bridge = info; + if (!info.ss || !info.meta || info.slab_idx < 0) { + return 0; + } + if (info.meta_cls >= TINY_NUM_CLASSES) { + return 0; + } + + ctx->class_idx = (int)info.meta_cls; + ctx->base = ptr_user_to_base(ctx->user, ctx->class_idx); + +#if !HAKMEM_BUILD_RELEASE + // 任意の追加診断: Header の class と meta class の不一致を検出 + int hdr_cls = tiny_region_id_read_header(user_ptr); + if (hdr_cls >= 0 && hdr_cls != ctx->class_idx) { + static _Atomic uint32_t g_gate_hdr_meta_mis = 0; + uint32_t n = atomic_fetch_add_explicit(&g_gate_hdr_meta_mis, 1, memory_order_relaxed); + if (n < 8) { + fprintf(stderr, + "[TINY_FREE_GATE_HDR_META_MISMATCH] hdr_cls=%d meta_cls=%d ptr=%p ss=%p slab=%d\n", + hdr_cls, ctx->class_idx, user_ptr, + (void*)info.ss, info.slab_idx); + fflush(stderr); + } + } +#endif + + return 1; +} + +// Tiny Free Gatekeeper 本体: +// - free() ラッパから Tiny Fast Path を呼ぶ唯一の入口。 +// - 既存の hak_tiny_free_fast_v2(ptr) をそのまま呼び出しつつ、 +// 将来の USER→BASE+Bridge+Guard を差し込むためのフックを提供する。 +// +// 戻り値: +// 1: Fast Path で処理済み(TLS SLL 等に push 済み) +// 0: Slow Path にフォールバックすべき(hak_tiny_free へ) +static inline int tiny_free_gate_try_fast(void* user_ptr) +{ +#if !HAKMEM_TINY_HEADER_CLASSIDX + (void)user_ptr; + // Header 無効構成では Tiny Fast Path 自体を使わない + return 0; +#else + if (__builtin_expect(!user_ptr, 0)) { + return 0; + } + + // 将来の拡張ポイント: + // - DIAG ON のときだけ Bridge + Guard を実行し、 + // Tiny 管理外と判定された場合は Fast Path をスキップする。 +#if !HAKMEM_BUILD_RELEASE + if (__builtin_expect(tiny_free_gate_diag_enabled(), 0)) { + TinyFreeGateContext ctx; + if (!tiny_free_gate_classify(user_ptr, &ctx)) { + // Tiny 管理外 or Bridge 失敗 → Fast Path は使わない + return 0; + } + (void)ctx; // 現時点ではログ専用。将来はここから Guard を挿入。 + } +#endif + + // 本体は既存の ultra-fast free に丸投げ(挙動を変えない) + return hak_tiny_free_fast_v2(user_ptr); +#endif +} + +#endif // HAKMEM_TINY_FREE_GATE_BOX_H +