Fix BASE/USER pointer double conversion bugs in alloc/free fast paths
Root Cause: - TINY_ALLOC_FAST_POP_INLINE returned USER pointer (base+1), but all other frontend layers return BASE pointer → HAK_RET_ALLOC wrote header/region at wrong offset (off-by-one) - tiny_free_fast_ss() performed BASE conversion twice (ptr-1 then base-1) → Corrupted TLS SLL chain, causing SEGV at iteration 66151 Fixes: 1. tiny_alloc_fast_inline.h (Line 62): - Change POP macro to return BASE pointer (not USER) - Update PUSH macro to convert USER→BASE and restore header at BASE - Unify all frontend layers to "BASE world" 2. tiny_free_fast.inc.h (Line 125, 228): - Remove double conversion in tiny_free_fast_ss() - Pass BASE pointer from caller (already converted via ptr-1) - Add comments to prevent future regressions Impact: - Before: Crash at iteration 66151 (stack corruption) - After: 100K iterations ✅ (1.95M ops/s), 1M iterations ✅ (840K ops/s) Verified: Random mixed benchmark (WS=256, seeds 42-44), all tests pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -58,8 +58,8 @@ extern __thread uint32_t g_tls_sll_count[TINY_NUM_CLASSES];
|
||||
if (g_tls_sll_count[(class_idx)] > 0) { \
|
||||
g_tls_sll_count[(class_idx)]--; \
|
||||
} \
|
||||
/* Phase E1-CORRECT: All classes return user pointer (base+1) */ \
|
||||
(ptr_out) = (void*)((uint8_t*)_head + 1); \
|
||||
/* Phase 7: Fast path returns BASE pointer; HAK_RET_ALLOC does BASE→USER */ \
|
||||
(ptr_out) = _head; \
|
||||
} \
|
||||
} else { \
|
||||
(ptr_out) = NULL; \
|
||||
@ -88,9 +88,14 @@ extern __thread uint32_t g_tls_sll_count[TINY_NUM_CLASSES];
|
||||
// byte 0 for HEADER_MAGIC. Without restoration, it finds 0x00 → uses wrong offset → SEGV.
|
||||
// COST: 1 byte write (~1-2 cycles per free, negligible).
|
||||
#define TINY_ALLOC_FAST_PUSH_INLINE(class_idx, ptr) do { \
|
||||
*(uint8_t*)(ptr) = HEADER_MAGIC | ((class_idx) & HEADER_CLASS_MASK); \
|
||||
tiny_next_write(class_idx, (ptr), g_tls_sll_head[(class_idx)]); \
|
||||
g_tls_sll_head[(class_idx)] = (ptr); \
|
||||
if (!(ptr)) break; \
|
||||
/* Phase E1-CORRECT: API ptr is USER pointer (= base+1). Convert back to BASE. */ \
|
||||
uint8_t* _base = (uint8_t*)(ptr) - 1; \
|
||||
/* Restore header at BASE (not at user). */ \
|
||||
*_base = HEADER_MAGIC | ((class_idx) & HEADER_CLASS_MASK); \
|
||||
/* Link node using BASE as the canonical SLL node address. */ \
|
||||
tiny_next_write((class_idx), _base, g_tls_sll_head[(class_idx)]); \
|
||||
g_tls_sll_head[(class_idx)] = _base; \
|
||||
g_tls_sll_count[(class_idx)]++; \
|
||||
} while(0)
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user