// sp_rebind_slot_box.h - SuperSlab Slot Rebinding (atomic class change) // Purpose: Atomically rebind a slab slot to a new class with consistent state // License: MIT // Date: 2025-11-30 #ifndef HAKMEM_SP_REBIND_SLOT_BOX_H #define HAKMEM_SP_REBIND_SLOT_BOX_H #include "hakmem_tiny_superslab_internal.h" #include "box/tls_sll_box.h" // TLS_SLL_RESET // ========== SuperSlab Slot Rebinding ========== // // Atomically rebind a slab slot when: // - Stage 1: EMPTY → ACTIVE (same or different class) // - Stage 2: UNUSED → ACTIVE (new class) // - Stage 3: New SuperSlab (initial class assignment) // // Operations (in order): // 1. Remember old class (for TLS cleanup) // 2. Fix geometry if needed (update capacity/class_idx) // 3. Reset TLS SLL for BOTH old and new class (防御的) // 4. Update class_map (out-of-band lookup) // // Box Theory: // - Single Responsibility: Ensure slab→class binding consistency // - Clear Contract: (ss, slab_idx, new_class) → consistent state // - Observable: Debug log shows old_cls→new_cls transitions // - Composable: Called from all acquire paths #if !HAKMEM_BUILD_RELEASE #define SP_REBIND_SLOT(ss, slab_idx, new_class_idx) \ do { \ static __thread int s_trace = -1; \ if (__builtin_expect(s_trace == -1, 0)) { \ const char* e = getenv("HAKMEM_SP_REBIND_TRACE"); \ s_trace = (e && *e && *e != '0') ? 1 : 0; \ } \ \ /* Step 1: Remember old class for TLS cleanup */ \ uint8_t old_class_idx = (ss)->slabs[slab_idx].class_idx; \ \ /* Step 2: Fix geometry (updates capacity, class_idx, etc) */ \ sp_fix_geometry_if_needed((ss), (slab_idx), (new_class_idx)); \ \ /* Step 3: Reset TLS SLL for old class (if different) */ \ if (old_class_idx != (uint8_t)(new_class_idx) && \ old_class_idx < TINY_NUM_CLASSES) { \ TLS_SLL_RESET(old_class_idx); \ if (s_trace) { \ fprintf(stderr, \ "[SP_REBIND_SLOT] OLD class TLS reset: cls=%d ss=%p slab=%d (old_cls=%d -> new_cls=%d)\n", \ old_class_idx, (void*)(ss), (slab_idx), old_class_idx, (new_class_idx)); \ } \ } \ \ /* Step 4: Reset TLS SLL for new class (防御的 - 常にクリア) */ \ if ((new_class_idx) < TINY_NUM_CLASSES) { \ TLS_SLL_RESET(new_class_idx); \ if (s_trace) { \ fprintf(stderr, \ "[SP_REBIND_SLOT] NEW class TLS reset: cls=%d ss=%p slab=%d\n", \ (new_class_idx), (void*)(ss), (slab_idx)); \ } \ } \ \ /* Step 5: Update class_map (out-of-band lookup) */ \ ss_slab_meta_class_idx_set((ss), (slab_idx), (uint8_t)(new_class_idx)); \ \ if (s_trace) { \ fprintf(stderr, \ "[SP_REBIND_SLOT] COMPLETE: ss=%p slab=%d old_cls=%d -> new_cls=%d cap=%u\n", \ (void*)(ss), (slab_idx), old_class_idx, (new_class_idx), \ (unsigned)(ss)->slabs[slab_idx].capacity); \ } \ } while (0) #else // Release build: no trace, just execute operations #define SP_REBIND_SLOT(ss, slab_idx, new_class_idx) \ do { \ uint8_t old_class_idx = (ss)->slabs[slab_idx].class_idx; \ sp_fix_geometry_if_needed((ss), (slab_idx), (new_class_idx)); \ if (old_class_idx != (uint8_t)(new_class_idx) && \ old_class_idx < TINY_NUM_CLASSES) { \ TLS_SLL_RESET(old_class_idx); \ } \ if ((new_class_idx) < TINY_NUM_CLASSES) { \ TLS_SLL_RESET(new_class_idx); \ } \ ss_slab_meta_class_idx_set((ss), (slab_idx), (uint8_t)(new_class_idx)); \ } while (0) #endif #endif // HAKMEM_SP_REBIND_SLOT_BOX_H