95 lines
3.8 KiB
C
95 lines
3.8 KiB
C
|
|
// 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
|