Phase 12: Shared SuperSlab Pool implementation (WIP - runtime crash)
## Summary
Implemented Phase 12 Shared SuperSlab Pool (mimalloc-style) to address
SuperSlab allocation churn (877 SuperSlabs → 100-200 target).
## Implementation (ChatGPT + Claude)
1. **Metadata changes** (superslab_types.h):
- Added class_idx to TinySlabMeta (per-slab dynamic class)
- Removed size_class from SuperSlab (no longer per-SuperSlab)
- Changed owner_tid (16-bit) → owner_tid_low (8-bit)
2. **Shared Pool** (hakmem_shared_pool.{h,c}):
- Global pool shared by all size classes
- shared_pool_acquire_slab() - Get free slab for class_idx
- shared_pool_release_slab() - Return slab when empty
- Per-class hints for fast path optimization
3. **Integration** (23 files modified):
- Updated all ss->size_class → meta->class_idx
- Updated all meta->owner_tid → meta->owner_tid_low
- superslab_refill() now uses shared pool
- Free path releases empty slabs back to pool
4. **Build system** (Makefile):
- Added hakmem_shared_pool.o to OBJS_BASE and TINY_BENCH_OBJS_BASE
## Status: ⚠️ Build OK, Runtime CRASH
**Build**: ✅ SUCCESS
- All 23 files compile without errors
- Only warnings: superslab_allocate type mismatch (legacy code)
**Runtime**: ❌ SEGFAULT
- Crash location: sll_refill_small_from_ss()
- Exit code: 139 (SIGSEGV)
- Test case: ./bench_random_mixed_hakmem 1000 256 42
## Known Issues
1. **SEGFAULT in refill path** - Likely shared_pool_acquire_slab() issue
2. **Legacy superslab_allocate()** still exists (type mismatch warning)
3. **Remaining TODOs** from design doc:
- SuperSlab physical layout integration
- slab_handle.h cleanup
- Remove old per-class head implementation
## Next Steps
1. Debug SEGFAULT (gdb backtrace shows sll_refill_small_from_ss)
2. Fix shared_pool_acquire_slab() or superslab_init_slab()
3. Basic functionality test (1K → 100K iterations)
4. Measure SuperSlab count reduction (877 → 100-200)
5. Performance benchmark (+650-860% expected)
## Files Changed (25 files)
core/box/free_local_box.c
core/box/free_remote_box.c
core/box/front_gate_classifier.c
core/hakmem_super_registry.c
core/hakmem_tiny.c
core/hakmem_tiny_bg_spill.c
core/hakmem_tiny_free.inc
core/hakmem_tiny_lifecycle.inc
core/hakmem_tiny_magazine.c
core/hakmem_tiny_query.c
core/hakmem_tiny_refill.inc.h
core/hakmem_tiny_superslab.c
core/hakmem_tiny_superslab.h
core/hakmem_tiny_tls_ops.h
core/slab_handle.h
core/superslab/superslab_inline.h
core/superslab/superslab_types.h
core/tiny_debug.h
core/tiny_free_fast.inc.h
core/tiny_free_magazine.inc.h
core/tiny_remote.c
core/tiny_superslab_alloc.inc.h
core/tiny_superslab_free.inc.h
Makefile
## New Files (3 files)
PHASE12_SHARED_SUPERSLAB_POOL_DESIGN.md
core/hakmem_shared_pool.c
core/hakmem_shared_pool.h
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: ChatGPT <chatgpt@openai.com>
This commit is contained in:
@ -26,14 +26,15 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
uintptr_t ss_base = (uintptr_t)ss;
|
||||
if (__builtin_expect(slab_idx < 0, 0)) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xBAD1u, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, 0xFFu, ptr, aux);
|
||||
if (g_tiny_safe_free_strict) { raise(SIGUSR2); return; }
|
||||
return;
|
||||
}
|
||||
TinySlabMeta* meta = &ss->slabs[slab_idx];
|
||||
uint8_t cls = meta->class_idx;
|
||||
|
||||
// Debug: Log first C7 alloc/free for path verification
|
||||
if (ss->size_class == 7) {
|
||||
if (cls == 7) {
|
||||
static _Atomic int c7_free_count = 0;
|
||||
int count = atomic_fetch_add_explicit(&c7_free_count, 1, memory_order_relaxed);
|
||||
if (count == 0) {
|
||||
@ -45,20 +46,20 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
if (__builtin_expect(tiny_remote_watch_is(ptr), 0)) {
|
||||
tiny_remote_watch_note("free_enter", ss, slab_idx, ptr, 0xA240u, tiny_self_u32(), 0);
|
||||
extern __thread TinyTLSSlab g_tls_slabs[];
|
||||
tiny_alloc_dump_tls_state(ss->size_class, "watch_free_enter", &g_tls_slabs[ss->size_class]);
|
||||
tiny_alloc_dump_tls_state(cls, "watch_free_enter", &g_tls_slabs[cls]);
|
||||
#if !HAKMEM_BUILD_RELEASE
|
||||
extern __thread TinyTLSMag g_tls_mags[];
|
||||
TinyTLSMag* watch_mag = &g_tls_mags[ss->size_class];
|
||||
TinyTLSMag* watch_mag = &g_tls_mags[cls];
|
||||
fprintf(stderr,
|
||||
"[REMOTE_WATCH_MAG] cls=%u mag_top=%d cap=%d\n",
|
||||
ss->size_class,
|
||||
cls,
|
||||
watch_mag->top,
|
||||
watch_mag->cap);
|
||||
#endif
|
||||
}
|
||||
// BUGFIX: Validate size_class before using as array index (prevents OOB)
|
||||
if (__builtin_expect(ss->size_class < 0 || ss->size_class >= TINY_NUM_CLASSES, 0)) {
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, 0xF1, ptr, (uintptr_t)ss->size_class);
|
||||
// BUGFIX (Phase 12): Validate class_idx before using as array index
|
||||
if (__builtin_expect(cls >= TINY_NUM_CLASSES, 0)) {
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, 0xF1, ptr, (uintptr_t)cls);
|
||||
if (g_tiny_safe_free_strict) { raise(SIGUSR2); return; }
|
||||
return;
|
||||
}
|
||||
@ -67,7 +68,7 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
// Expected impact: -10~-15% CPU (eliminates O(n) duplicate scan)
|
||||
#if !HAKMEM_BUILD_RELEASE
|
||||
if (__builtin_expect(g_tiny_safe_free, 0)) {
|
||||
size_t blk = g_tiny_class_sizes[ss->size_class];
|
||||
size_t blk = g_tiny_class_sizes[cls];
|
||||
uint8_t* base = tiny_slab_base_for(ss, slab_idx);
|
||||
uintptr_t delta = (uintptr_t)ptr - (uintptr_t)base;
|
||||
int cap_ok = (meta->capacity > 0) ? 1 : 0;
|
||||
@ -78,17 +79,17 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
if (align_ok) code |= 0x2u;
|
||||
if (range_ok) code |= 0x1u;
|
||||
uintptr_t aux = tiny_remote_pack_diag(code, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, ptr, aux);
|
||||
if (g_tiny_safe_free_strict) { raise(SIGUSR2); return; }
|
||||
return;
|
||||
}
|
||||
// Duplicate in freelist (best-effort scan up to 64)
|
||||
// NOTE: This O(n) scan is VERY expensive (can scan 64 pointers per free!)
|
||||
void* scan = meta->freelist; int scanned = 0; int dup = 0;
|
||||
while (scan && scanned < 64) { if (scan == base) { dup = 1; break; } scan = tiny_next_read(ss->size_class, scan); scanned++; }
|
||||
while (scan && scanned < 64) { if (scan == base) { dup = 1; break; } scan = tiny_next_read(cls, scan); scanned++; }
|
||||
if (dup) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xDFu, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, ptr, aux);
|
||||
if (g_tiny_safe_free_strict) { raise(SIGUSR2); return; }
|
||||
return;
|
||||
}
|
||||
@ -97,8 +98,8 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
|
||||
// Phase E1-CORRECT: C7 now has headers like other classes
|
||||
// Validation must check base pointer (ptr-1) alignment, not user pointer
|
||||
if (__builtin_expect(ss->size_class == 7, 0)) {
|
||||
size_t blk = g_tiny_class_sizes[ss->size_class];
|
||||
if (__builtin_expect(cls == 7, 0)) {
|
||||
size_t blk = g_tiny_class_sizes[cls];
|
||||
uint8_t* slab_base = tiny_slab_base_for(ss, slab_idx);
|
||||
uintptr_t delta = (uintptr_t)base - (uintptr_t)slab_base;
|
||||
int cap_ok = (meta->capacity > 0) ? 1 : 0;
|
||||
@ -106,7 +107,7 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
int range_ok = cap_ok && (delta / blk) < meta->capacity;
|
||||
if (!align_ok || !range_ok) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xA107u, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, ptr, aux);
|
||||
#if !HAKMEM_BUILD_RELEASE
|
||||
// Debug build: Print diagnostic info before failing
|
||||
fprintf(stderr, "[C7_ALIGN_CHECK_FAIL] ptr=%p base=%p slab_base=%p\n", ptr, base, (void*)slab_base);
|
||||
@ -122,25 +123,26 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 6.23: Same-thread check
|
||||
// Phase 6.23: Same-thread check (Phase 12: owner_tid_low)
|
||||
uint32_t my_tid = tiny_self_u32();
|
||||
uint8_t my_tid_low = (uint8_t)my_tid;
|
||||
const int debug_guard = g_debug_remote_guard;
|
||||
static __thread int g_debug_free_count = 0;
|
||||
// If owner is not set yet, claim ownership to avoid spurious remote path in 1T
|
||||
if (!g_tiny_force_remote && meta->owner_tid == 0) {
|
||||
meta->owner_tid = my_tid;
|
||||
// If owner is not set yet, claim ownership (low 8 bits) to avoid spurious remote path in 1T
|
||||
if (!g_tiny_force_remote && meta->owner_tid_low == 0) {
|
||||
meta->owner_tid_low = my_tid_low;
|
||||
}
|
||||
if (!g_tiny_force_remote && meta->owner_tid != 0 && meta->owner_tid == my_tid) {
|
||||
if (!g_tiny_force_remote && meta->owner_tid_low != 0 && meta->owner_tid_low == my_tid_low) {
|
||||
ROUTE_MARK(17); // free_same_thread
|
||||
// Fast path: Direct freelist push (same-thread)
|
||||
if (0 && debug_guard && g_debug_free_count < 1) {
|
||||
fprintf(stderr, "[FREE_SS] SAME-THREAD: owner=%u my=%u\n",
|
||||
meta->owner_tid, my_tid);
|
||||
meta->owner_tid_low, my_tid);
|
||||
g_debug_free_count++;
|
||||
}
|
||||
if (__builtin_expect(meta->used == 0, 0)) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0x00u, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, ptr, aux);
|
||||
if (g_tiny_safe_free_strict) { raise(SIGUSR2); return; }
|
||||
return;
|
||||
}
|
||||
@ -150,13 +152,13 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
int transitioned = tiny_free_remote_box(ss, slab_idx, meta, base, my_tid);
|
||||
if (transitioned) {
|
||||
extern unsigned long long g_remote_free_transitions[];
|
||||
g_remote_free_transitions[ss->size_class]++;
|
||||
g_remote_free_transitions[cls]++;
|
||||
// Free-side route: remote transition observed
|
||||
do {
|
||||
static int g_route_free = -1; if (__builtin_expect(g_route_free == -1, 0)) {
|
||||
const char* e = getenv("HAKMEM_TINY_ROUTE_FREE");
|
||||
g_route_free = (e && *e && *e != '0') ? 1 : 0; }
|
||||
if (g_route_free) route_free_commit((int)ss->size_class, (1ull<<18), 0xE2);
|
||||
if (g_route_free) route_free_commit((int)cls, (1ull<<18), 0xE2);
|
||||
} while (0);
|
||||
}
|
||||
return;
|
||||
@ -169,9 +171,9 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
g_free_to_ss = (e && *e && *e != '0') ? 1 : 0; // default OFF
|
||||
}
|
||||
if (!g_free_to_ss) {
|
||||
int cls = (int)ss->size_class;
|
||||
if (midtc_enabled() && cls >= 4) {
|
||||
if (midtc_push(cls, base)) {
|
||||
int mid_cls = (int)cls;
|
||||
if (midtc_enabled() && mid_cls >= 4) {
|
||||
if (midtc_push(mid_cls, base)) {
|
||||
// Treat as returned to TLS cache (not SS freelist)
|
||||
meta->used--;
|
||||
ss_active_dec_one(ss);
|
||||
@ -188,39 +190,43 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
if (prev_before == NULL) {
|
||||
ROUTE_MARK(19); // first_free_transition
|
||||
extern unsigned long long g_first_free_transitions[];
|
||||
g_first_free_transitions[ss->size_class]++;
|
||||
g_first_free_transitions[cls]++;
|
||||
ROUTE_MARK(20); // mailbox_publish
|
||||
// Free-side route commit (one-shot)
|
||||
do {
|
||||
static int g_route_free = -1; if (__builtin_expect(g_route_free == -1, 0)) {
|
||||
const char* e = getenv("HAKMEM_TINY_ROUTE_FREE");
|
||||
g_route_free = (e && *e && *e != '0') ? 1 : 0; }
|
||||
int cls = (int)ss->size_class;
|
||||
if (g_route_free) route_free_commit(cls, (1ull<<19) | (1ull<<20), 0xE1);
|
||||
} while (0);
|
||||
}
|
||||
|
||||
if (__builtin_expect(debug_guard, 0)) {
|
||||
fprintf(stderr, "[REMOTE_LOCAL] cls=%u slab=%d owner=%u my=%u ptr=%p prev=%p used=%u\n",
|
||||
ss->size_class, slab_idx, meta->owner_tid, my_tid, ptr, prev_before, meta->used);
|
||||
fprintf(stderr, "[REMOTE_LOCAL] cls=%u slab=%d owner=%u my=%u ptr=%p prev=%p used=%u\n",
|
||||
cls, slab_idx, meta->owner_tid_low, my_tid, ptr, prev_before, meta->used);
|
||||
}
|
||||
|
||||
// 空検出は別途(ホットパス除外)
|
||||
// Phase 12: slab empty → shared pool に返却
|
||||
if (meta->used == 0) {
|
||||
extern void shared_pool_release_slab(SuperSlab* ss, int slab_idx);
|
||||
shared_pool_release_slab(ss, slab_idx);
|
||||
}
|
||||
} else {
|
||||
ROUTE_MARK(18); // free_remote_transition
|
||||
if (__builtin_expect(meta->owner_tid == my_tid && meta->owner_tid == 0, 0)) {
|
||||
if (__builtin_expect(meta->owner_tid_low == my_tid_low && meta->owner_tid_low == 0, 0)) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xA300u, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, ptr, aux);
|
||||
if (debug_guard) {
|
||||
fprintf(stderr, "[REMOTE_OWNER_ZERO] cls=%u slab=%d ptr=%p my=%u used=%u\n",
|
||||
ss->size_class, slab_idx, ptr, my_tid, (unsigned)meta->used);
|
||||
cls, slab_idx, ptr, my_tid, (unsigned)meta->used);
|
||||
}
|
||||
}
|
||||
tiny_remote_track_expect_alloc(ss, slab_idx, ptr, "remote_free_enter", my_tid);
|
||||
// Slow path: Remote free (cross-thread)
|
||||
if (0 && debug_guard && g_debug_free_count < 5) {
|
||||
fprintf(stderr, "[FREE_SS] CROSS-THREAD: owner=%u my=%u slab_idx=%d\n",
|
||||
meta->owner_tid, my_tid, slab_idx);
|
||||
meta->owner_tid_low, my_tid, slab_idx);
|
||||
g_debug_free_count++;
|
||||
}
|
||||
if (__builtin_expect(g_tiny_safe_free, 0)) {
|
||||
@ -232,7 +238,7 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
while (cur && scanned < 64) {
|
||||
if ((cur < base) || (cur >= base + ss_size)) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xA200u, base, ss_size, cur);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, (void*)cur, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, (void*)cur, aux);
|
||||
if (g_tiny_safe_free_strict) { raise(SIGUSR2); return; }
|
||||
break;
|
||||
}
|
||||
@ -240,20 +246,21 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
if (__builtin_expect(g_remote_side_enable, 0)) {
|
||||
if (!tiny_remote_sentinel_ok((void*)cur)) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xA202u, base, ss_size, cur);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, (void*)cur, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, (void*)cur, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, (void*)cur, aux);
|
||||
uintptr_t observed = atomic_load_explicit((_Atomic uintptr_t*)(void*)cur, memory_order_relaxed);
|
||||
tiny_remote_report_corruption("scan", (void*)cur, observed);
|
||||
if (__builtin_expect(g_debug_remote_guard, 0)) {
|
||||
fprintf(stderr,
|
||||
"[REMOTE_SENTINEL] cls=%u slab=%d cur=%p head=%p ptr=%p scanned=%d observed=0x%016" PRIxPTR " owner=%u used=%u freelist=%p remote_head=%p\n",
|
||||
ss->size_class,
|
||||
cls,
|
||||
slab_idx,
|
||||
(void*)cur,
|
||||
(void*)head,
|
||||
ptr,
|
||||
scanned,
|
||||
observed,
|
||||
meta->owner_tid,
|
||||
meta->owner_tid_low,
|
||||
(unsigned)meta->used,
|
||||
meta->freelist,
|
||||
(void*)atomic_load_explicit(&ss->remote_heads[slab_idx], memory_order_relaxed));
|
||||
@ -265,24 +272,24 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
} else {
|
||||
if ((cur & (uintptr_t)(sizeof(void*) - 1)) != 0) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xA201u, base, ss_size, cur);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, (void*)cur, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, (void*)cur, aux);
|
||||
if (g_tiny_safe_free_strict) { raise(SIGUSR2); return; }
|
||||
break;
|
||||
}
|
||||
cur = (uintptr_t)tiny_next_read(ss->size_class, (void*)cur);
|
||||
cur = (uintptr_t)tiny_next_read(cls, (void*)cur);
|
||||
}
|
||||
scanned++;
|
||||
}
|
||||
if (dup) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xD1u, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, ptr, aux);
|
||||
if (g_tiny_safe_free_strict) { raise(SIGUSR2); return; }
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (__builtin_expect(meta->used == 0, 0)) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0x01u, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, ptr, aux);
|
||||
if (g_tiny_safe_free_strict) { raise(SIGUSR2); return; }
|
||||
return;
|
||||
}
|
||||
@ -310,9 +317,9 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
// Use remote queue
|
||||
uintptr_t head_word = __atomic_load_n((uintptr_t*)base, __ATOMIC_RELAXED);
|
||||
if (debug_guard) fprintf(stderr, "[REMOTE_PUSH_CALL] cls=%u slab=%d owner=%u my=%u ptr=%p used=%u remote_count=%u head=%p word=0x%016" PRIxPTR "\n",
|
||||
ss->size_class,
|
||||
cls,
|
||||
slab_idx,
|
||||
meta->owner_tid,
|
||||
meta->owner_tid_low,
|
||||
my_tid,
|
||||
ptr,
|
||||
(unsigned)meta->used,
|
||||
@ -330,13 +337,13 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xA214u, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_remote_watch_mark(ptr, "dup_prevent", my_tid);
|
||||
tiny_remote_watch_note("dup_prevent", ss, slab_idx, ptr, 0xA214u, my_tid, 0);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, ptr, aux);
|
||||
tiny_failfast_abort_ptr("double_free_remote", ss, slab_idx, ptr, "remote_side_contains");
|
||||
}
|
||||
if (__builtin_expect(g_remote_side_enable && (head_word & 0xFFFFu) == 0x6261u, 0)) {
|
||||
// TLS guard scribble detected on the node's first word → same-pointer double free across routes
|
||||
uintptr_t aux = tiny_remote_pack_diag(0xA213u, ss_base, ss_size, (uintptr_t)ptr);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)ss->size_class, ptr, aux);
|
||||
tiny_debug_ring_record(TINY_RING_EVENT_REMOTE_INVALID, (uint16_t)cls, ptr, aux);
|
||||
tiny_remote_watch_mark(ptr, "pre_push", my_tid);
|
||||
tiny_remote_watch_note("pre_push", ss, slab_idx, ptr, 0xA231u, my_tid, 0);
|
||||
tiny_remote_report_corruption("pre_push", ptr, head_word);
|
||||
@ -350,16 +357,17 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
// ss_active_dec_one(ss); // REMOVED: Already called inside ss_remote_push()
|
||||
if (was_empty) {
|
||||
extern unsigned long long g_remote_free_transitions[];
|
||||
g_remote_free_transitions[ss->size_class]++;
|
||||
ss_partial_publish((int)ss->size_class, ss);
|
||||
g_remote_free_transitions[cls]++;
|
||||
g_remote_free_transitions[cls]++;
|
||||
ss_partial_publish((int)cls, ss);
|
||||
}
|
||||
} else {
|
||||
// Fallback: direct freelist push (legacy)
|
||||
if (debug_guard) fprintf(stderr, "[FREE_SS] Using LEGACY freelist push (not remote queue)\n");
|
||||
void* prev = meta->freelist;
|
||||
tiny_next_write(ss->size_class, base, prev);
|
||||
tiny_next_write(cls, base, prev);
|
||||
meta->freelist = base;
|
||||
tiny_failfast_log("free_local_legacy", ss->size_class, ss, meta, ptr, prev);
|
||||
tiny_failfast_log("free_local_legacy", cls, ss, meta, ptr, prev);
|
||||
do {
|
||||
static int g_mask_en = -1;
|
||||
if (__builtin_expect(g_mask_en == -1, 0)) {
|
||||
@ -374,10 +382,15 @@ static inline void hak_tiny_free_superslab(void* ptr, SuperSlab* ss) {
|
||||
meta->used--;
|
||||
ss_active_dec_one(ss);
|
||||
if (prev == NULL) {
|
||||
ss_partial_publish((int)ss->size_class, ss);
|
||||
ss_partial_publish((int)cls, ss);
|
||||
}
|
||||
}
|
||||
|
||||
// 空検出は別途(ホットパス除外)
|
||||
// Phase 12: slab empty → shared pool に返却
|
||||
if (meta->used == 0) {
|
||||
extern void shared_pool_release_slab(SuperSlab* ss, int slab_idx);
|
||||
shared_pool_release_slab(ss, slab_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user