// 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); }