#include "free_local_box.h" #include "free_publish_box.h" #include "hakmem_tiny.h" void tiny_free_local_box(SuperSlab* ss, int slab_idx, TinySlabMeta* meta, void* ptr, uint32_t my_tid) { extern _Atomic uint64_t g_free_local_box_calls; atomic_fetch_add_explicit(&g_free_local_box_calls, 1, memory_order_relaxed); if (!(ss && ss->magic == SUPERSLAB_MAGIC)) return; if (slab_idx < 0 || slab_idx >= ss_slabs_capacity(ss)) return; (void)my_tid; if (__builtin_expect(tiny_refill_failfast_level() >= 2, 0)) { int actual_idx = slab_index_for(ss, ptr); if (actual_idx != slab_idx) { tiny_failfast_abort_ptr("free_local_box_idx", ss, slab_idx, ptr, "slab_idx_mismatch"); } else { size_t blk = g_tiny_class_sizes[ss->size_class]; uint8_t* slab_base = tiny_slab_base_for(ss, slab_idx); uintptr_t delta = (uintptr_t)ptr - (uintptr_t)slab_base; if (blk == 0 || (delta % blk) != 0) { tiny_failfast_abort_ptr("free_local_box_align", ss, slab_idx, ptr, "misaligned"); } else if (meta && delta / blk >= meta->capacity) { tiny_failfast_abort_ptr("free_local_box_range", ss, slab_idx, ptr, "out_of_capacity"); } } } void* prev = meta->freelist; *(void**)ptr = prev; meta->freelist = ptr; tiny_failfast_log("free_local_box", ss->size_class, ss, meta, ptr, prev); // BUGFIX: Memory barrier to ensure freelist visibility before used decrement // Without this, other threads can see new freelist but old used count (race) atomic_thread_fence(memory_order_release); // Optional freelist mask update on first push do { static int g_mask_en = -1; if (__builtin_expect(g_mask_en == -1, 0)) { const char* e = getenv("HAKMEM_TINY_FREELIST_MASK"); g_mask_en = (e && *e && *e != '0') ? 1 : 0; } if (__builtin_expect(g_mask_en, 0) && prev == NULL) { uint32_t bit = (1u << slab_idx); atomic_fetch_or_explicit(&ss->freelist_mask, bit, memory_order_release); } } while (0); // Track local free (debug helpers may be no-op) tiny_remote_track_on_local_free(ss, slab_idx, ptr, "local_free", my_tid); meta->used--; ss_active_dec_one(ss); if (prev == NULL) { // First-free → advertise slab to adopters tiny_free_publish_first_free((int)ss->size_class, ss, slab_idx); } }