diff --git a/core/box/front_gate_classifier.c b/core/box/front_gate_classifier.c index f1c3b764..aa135847 100644 --- a/core/box/front_gate_classifier.c +++ b/core/box/front_gate_classifier.c @@ -17,7 +17,7 @@ #include "../hakmem_super_registry.h" // For hak_super_lookup (Box REG) #ifdef HAKMEM_POOL_TLS_PHASE1 -#include "../pool_tls.h" // For POOL_MAGIC +#include "../pool_tls_registry.h" // Safer pool pointer lookup (no header deref) #endif // ========== Debug Stats ========== @@ -158,19 +158,10 @@ static inline ptr_classification_t registry_lookup(void* ptr) { // ========== Pool TLS Probe ========== #ifdef HAKMEM_POOL_TLS_PHASE1 -// Check if pointer has Pool TLS magic (0xb0) -// Returns: 1 if Pool TLS, 0 otherwise -static inline int is_pool_tls(void* ptr) { - // Same safety check as header probe - uintptr_t offset_in_page = (uintptr_t)ptr & 0xFFF; - if (offset_in_page == 0) { - return 0; // Page-aligned, skip header read - } - - uint8_t* header_ptr = (uint8_t*)ptr - 1; - uint8_t header = *header_ptr; - - return (header & 0xF0) == POOL_MAGIC; +// Registry-based Pool TLS probe (no memory deref) +static inline int is_pool_tls_reg(void* ptr) { + pid_t tid = 0; int cls = -1; + return pool_reg_lookup(ptr, &tid, &cls); } #endif @@ -191,35 +182,9 @@ ptr_classification_t classify_ptr(void* ptr) { return result; } - // Step 1: Try safe header probe (C0-C6 fast path: 5-10 cycles) - // Skip header probe on 1KB-aligned pointers to avoid misclassifying C7/headerless - int class_idx = -1; - if (((uintptr_t)ptr & 0x3FF) != 0) { - class_idx = safe_header_probe(ptr); - } - if (class_idx >= 0) { - // Header found - C0-C6 with header - // Additional safety: verify pointer belongs to a SuperSlab region. - // This avoids rare false positives where random header bytes look like 0xA0. - struct SuperSlab* ss_chk = hak_super_lookup(ptr); - if (!ss_chk) { - // Not in Tiny registry; treat as UNKNOWN and continue - // (fall back to later checks) - } else { - result.kind = PTR_KIND_TINY_HEADER; - result.class_idx = class_idx; - result.ss = ss_chk; - -#if !HAKMEM_BUILD_RELEASE - g_classify_header_hit++; -#endif - return result; - } - } - - // Step 2: Check Pool TLS (before Registry to avoid false positives) + // Step 1: Check Pool TLS via registry (no pointer deref) #ifdef HAKMEM_POOL_TLS_PHASE1 - if (is_pool_tls(ptr)) { + if (is_pool_tls_reg(ptr)) { result.kind = PTR_KIND_POOL_TLS; #if !HAKMEM_BUILD_RELEASE @@ -229,7 +194,7 @@ ptr_classification_t classify_ptr(void* ptr) { } #endif - // Step 3: Fallback to Registry lookup (C7 headerless or header failed) + // Step 2: Registry lookup for Tiny (header or headerless) result = registry_lookup(ptr); if (result.kind == PTR_KIND_TINY_HEADERLESS) { #if !HAKMEM_BUILD_RELEASE @@ -237,8 +202,14 @@ ptr_classification_t classify_ptr(void* ptr) { #endif return result; } + if (result.kind == PTR_KIND_TINY_HEADER) { +#if !HAKMEM_BUILD_RELEASE + g_classify_header_hit++; +#endif + return result; + } - // Step 4: Not Tiny or Pool - return UNKNOWN + // Step 3: Not Tiny or Pool - return UNKNOWN // Caller should check AllocHeader (16-byte) or delegate to system free result.kind = PTR_KIND_UNKNOWN; diff --git a/core/box/front_gate_classifier.d b/core/box/front_gate_classifier.d index f37faca6..0ce3de76 100644 --- a/core/box/front_gate_classifier.d +++ b/core/box/front_gate_classifier.d @@ -13,7 +13,7 @@ core/box/front_gate_classifier.o: core/box/front_gate_classifier.c \ core/box/../superslab/superslab_inline.h \ core/box/../hakmem_build_flags.h core/box/../hakmem_tiny_config.h \ core/box/../hakmem_super_registry.h core/box/../hakmem_tiny_superslab.h \ - core/box/../pool_tls.h + core/box/../pool_tls_registry.h core/box/front_gate_classifier.h: core/box/../tiny_region_id.h: core/box/../hakmem_build_flags.h: @@ -35,4 +35,4 @@ core/box/../hakmem_build_flags.h: core/box/../hakmem_tiny_config.h: core/box/../hakmem_super_registry.h: core/box/../hakmem_tiny_superslab.h: -core/box/../pool_tls.h: +core/box/../pool_tls_registry.h: diff --git a/core/hakmem_tiny_refill.inc.h b/core/hakmem_tiny_refill.inc.h index 11e65066..660605e1 100644 --- a/core/hakmem_tiny_refill.inc.h +++ b/core/hakmem_tiny_refill.inc.h @@ -23,6 +23,8 @@ #include "hakmem_tiny_magazine.h" #include "hakmem_tiny_tls_list.h" #include "tiny_box_geometry.h" // Box 3: Geometry & Capacity Calculator +#include "hakmem_super_registry.h" // For hak_super_lookup (Debug validation) +#include "superslab/superslab_inline.h" // For slab_index_for/ss_slabs_capacity (Debug validation) #include "box/tls_sll_box.h" // Box TLS-SLL: Safe SLL operations API #include #include @@ -97,6 +99,46 @@ static inline int ultra_sll_cap_for_class(int class_idx); // Note: tiny_small_mags_init_once and tiny_mag_init_if_needed are declared in hakmem_tiny_magazine.h static void eventq_push(int class_idx, uint32_t size); +// Debug-only: Validate that a base node belongs to the expected Tiny SuperSlab and is stride-aligned +#if !HAKMEM_BUILD_RELEASE +static inline void tiny_debug_validate_node_base(int class_idx, void* node, const char* where) { + if ((uintptr_t)node < 4096) { + fprintf(stderr, "[SLL_NODE_SMALL] %s: node=%p cls=%d\n", where, node, class_idx); + abort(); + } + SuperSlab* ss = hak_super_lookup(node); + if (!ss) { + fprintf(stderr, "[SLL_NODE_UNKNOWN] %s: node=%p cls=%d\n", where, node, class_idx); + abort(); + } + int ocls = ss->size_class; + if (ocls == 7 || ocls != class_idx) { + fprintf(stderr, "[SLL_NODE_CLASS_MISMATCH] %s: node=%p cls=%d owner_cls=%d\n", where, node, class_idx, ocls); + abort(); + } + int slab_idx = slab_index_for(ss, node); + if (slab_idx < 0 || slab_idx >= ss_slabs_capacity(ss)) { + fprintf(stderr, "[SLL_NODE_SLAB_OOB] %s: node=%p slab_idx=%d cap=%d\n", where, node, slab_idx, ss_slabs_capacity(ss)); + abort(); + } + uint8_t* base = tiny_slab_base_for_geometry(ss, slab_idx); + size_t usable = tiny_usable_bytes_for_slab(slab_idx); + size_t stride = tiny_stride_for_class(ocls); + uintptr_t a = (uintptr_t)node; + if (a < (uintptr_t)base || a >= (uintptr_t)base + usable) { + fprintf(stderr, "[SLL_NODE_RANGE] %s: node=%p base=%p usable=%zu\n", where, node, base, usable); + abort(); + } + size_t off = (size_t)(a - (uintptr_t)base); + if (off % stride != 0) { + fprintf(stderr, "[SLL_NODE_MISALIGNED] %s: node=%p off=%zu stride=%zu base=%p\n", where, node, off, stride, base); + abort(); + } +} +#else +static inline void tiny_debug_validate_node_base(int class_idx, void* node, const char* where) { (void)class_idx; (void)node; (void)where; } +#endif + // Fast cache refill and take operation static inline void* tiny_fast_refill_and_take(int class_idx, TinyTLSList* tls) { void* direct = tiny_fast_pop(class_idx); @@ -151,6 +193,10 @@ static inline int quick_refill_from_sll(int class_idx) { // CRITICAL: Use Box TLS-SLL API to avoid race condition (rbp=0xa0 SEGV) void* head = NULL; if (!tls_sll_pop(class_idx, &head)) break; + // One-shot validation for the first pop +#if !HAKMEM_BUILD_RELEASE + do { static _Atomic int once = 0; int exp = 0; if (atomic_compare_exchange_strong(&once, &exp, 1)) { tiny_debug_validate_node_base(class_idx, head, "quick_refill_from_sll"); } } while (0); +#endif qs->items[qs->top++] = head; room--; filled++; } @@ -419,6 +465,10 @@ static inline int frontend_refill_fc(int class_idx) { while (need > 0) { void* h = NULL; if (!tls_sll_pop(class_idx, &h)) break; + // One-shot validation for the first pop into FastCache +#if !HAKMEM_BUILD_RELEASE + do { static _Atomic int once_fc = 0; int exp2 = 0; if (atomic_compare_exchange_strong(&once_fc, &exp2, 1)) { tiny_debug_validate_node_base(class_idx, h, "frontend_refill_fc"); } } while (0); +#endif fc->items[fc->top++] = h; need--; filled++; if (fc->top >= TINY_FASTCACHE_CAP) break; diff --git a/core/hakmem_tiny_refill_p0.inc.h b/core/hakmem_tiny_refill_p0.inc.h index 924ac59c..d666a102 100644 --- a/core/hakmem_tiny_refill_p0.inc.h +++ b/core/hakmem_tiny_refill_p0.inc.h @@ -311,6 +311,39 @@ static inline int sll_refill_batch_from_ss(int class_idx, int max_take) { TinyRefillChain carve; trc_linear_carve(slab_base, bs, meta, batch, class_idx, &carve); + + // One-shot sanity: validate first few nodes are within the slab and stride-aligned +#if !HAKMEM_BUILD_RELEASE + do { + static _Atomic int g_once = 0; + int exp = 0; + if (atomic_compare_exchange_strong(&g_once, &exp, 1)) { + uintptr_t base_chk = (uintptr_t)(tls->slab_base ? tls->slab_base : tiny_slab_base_for(tls->ss, tls->slab_idx)); + uintptr_t limit_chk = base_chk + tiny_usable_bytes_for_slab(tls->slab_idx); + void* node = carve.head; + for (int i = 0; i < 3 && node; i++) { + uintptr_t a = (uintptr_t)node; + if (!(a >= base_chk && a < limit_chk)) { + fprintf(stderr, "[P0_SANITY_FAIL] out_of_range cls=%d node=%p base=%p limit=%p bs=%zu\n", + class_idx, node, (void*)base_chk, (void*)limit_chk, bs); + abort(); + } + size_t off = (size_t)(a - base_chk); + if ((off % bs) != 0) { + fprintf(stderr, "[P0_SANITY_FAIL] misaligned cls=%d node=%p off=%zu bs=%zu base=%p\n", + class_idx, node, off, bs, (void*)base_chk); + abort(); + } +#if HAKMEM_TINY_HEADER_CLASSIDX + const size_t next_off = (class_idx == 7) ? 0 : 1; +#else + const size_t next_off = 0; +#endif + node = *(void**)((uint8_t*)node + next_off); + } + } + } while (0); +#endif trc_splice_to_sll(class_idx, &carve, &g_tls_sll_head[class_idx], &g_tls_sll_count[class_idx]); // FIX: Update SuperSlab active counter (was missing!) ss_active_add(tls->ss, batch); diff --git a/core/ptr_trace.h b/core/ptr_trace.h index e0165db4..ecfbdeb4 100644 --- a/core/ptr_trace.h +++ b/core/ptr_trace.h @@ -107,4 +107,7 @@ static inline void ptr_trace_dump_now(const char* reason) { (void)reason; } #define PTR_NEXT_READ(tag, cls, node, off, out_var) \ ((out_var) = *(void**)((uint8_t*)(node) + (off))) +// Always provide a stub for release builds so callers can link +static inline void ptr_trace_dump_now(const char* reason) { (void)reason; } + #endif // HAKMEM_PTR_TRACE