// mid_tcache.h - Mid-size TLS tcache (classes 4..7) // Box: Per-thread, per-class singly-linked stack. No atomics, no sharing. // Goal: O(1) pop/push on alloc/free for 128..1024B while keeping Box boundaries. #pragma once #include #include #ifndef TINY_NUM_CLASSES #define TINY_NUM_CLASSES 8 #endif static inline int midtc_enabled(void) { static int en = -1; if (__builtin_expect(en == -1, 0)) { const char* s = getenv("HAKMEM_MID_TC"); en = (s && *s && *s != '0') ? 1 : 0; } return en; } static inline int midtc_cap_global(void) { static int cap = -1; if (__builtin_expect(cap == -1, 0)) { const char* s = getenv("HAKMEM_MID_TC_CAP"); int v = (s && *s) ? atoi(s) : 32; // conservative default if (v < 0) v = 0; if (v > 1024) v = 1024; cap = v; } return cap; } // Per-thread state static __thread void* g_midtc_head[TINY_NUM_CLASSES]; static __thread uint16_t g_midtc_count[TINY_NUM_CLASSES]; // Push returns 1 on accept, 0 to fallback to existing path. static inline int midtc_push(int class_idx, void* p) { if (!midtc_enabled()) return 0; if (class_idx < 4 || class_idx >= TINY_NUM_CLASSES) return 0; // only 128..1024B uint16_t cnt = g_midtc_count[class_idx]; int cap = midtc_cap_global(); if (cnt >= (uint16_t)cap) return 0; *(void**)p = g_midtc_head[class_idx]; g_midtc_head[class_idx] = p; g_midtc_count[class_idx] = (uint16_t)(cnt + 1); return 1; } static inline void* midtc_pop(int class_idx) { if (!midtc_enabled()) return NULL; if (class_idx < 4 || class_idx >= TINY_NUM_CLASSES) return NULL; void* h = g_midtc_head[class_idx]; if (!h) return NULL; g_midtc_head[class_idx] = *(void**)h; if (g_midtc_count[class_idx] > 0) g_midtc_count[class_idx]--; return h; }