Files
hakmem/core/hakmem_tiny_remote.inc

57 lines
2.2 KiB
PHP
Raw Normal View History

// hakmem_tiny_remote.inc
// Remote free operations for TinySlab cross-thread deallocation
static void tiny_remote_push(struct TinySlab* slab, void* ptr) {
if (!slab || !ptr) return;
// Push to slab's remote freelist using atomic operations
uintptr_t old_head = atomic_load_explicit(&slab->remote_head, memory_order_relaxed);
do {
*(uintptr_t*)ptr = old_head;
} while (!atomic_compare_exchange_weak_explicit(&slab->remote_head, &old_head, (uintptr_t)ptr,
memory_order_release,
memory_order_relaxed));
atomic_fetch_add_explicit(&slab->remote_count, 1, memory_order_relaxed);
}
static void tiny_remote_drain_locked(struct TinySlab* slab) {
if (!slab) return;
// Drain remote frees (assumes lock held on slab)
uintptr_t remote = atomic_exchange_explicit(&slab->remote_head, 0, memory_order_acquire);
uint32_t remote_cnt = atomic_exchange_explicit(&slab->remote_count, 0, memory_order_relaxed);
if (!remote || remote_cnt == 0) return;
// Process each remote free: mark the block as free in the bitmap
while (remote && remote_cnt > 0) {
uintptr_t next = *(uintptr_t*)remote;
// Mark block as free in bitmap
uintptr_t offset = remote - (uintptr_t)slab->base;
size_t block_size = g_tiny_class_sizes[slab->class_idx];
size_t block_idx = offset / block_size;
if (block_idx < slab->total_count) {
size_t word_idx = block_idx / 64;
size_t bit_idx = block_idx % 64;
slab->bitmap[word_idx] &= ~(1UL << bit_idx); // Clear bit = free
slab->free_count++;
}
remote = next;
remote_cnt--;
}
}
static inline void tiny_remote_drain_owner(struct TinySlab* slab) {
if (!slab) return;
if (!pthread_equal(slab->owner_tid, tiny_self_pt())) return;
if (atomic_load_explicit(&slab->remote_count, memory_order_relaxed) == 0) return;
pthread_mutex_t* lock = &g_tiny_class_locks[slab->class_idx].m;
if (pthread_mutex_trylock(lock) != 0) return;
tiny_remote_drain_locked(slab);
pthread_mutex_unlock(lock);
}