// hakmem_tiny_query.c // Phase 2B-1: Query API // Extracted from hakmem_tiny.c (lines 4295-4346) #include #include #include #include "hakmem_tiny.h" #include "hakmem_tiny_query_api.h" #include "hakmem_tiny_superslab.h" #include "hakmem_super_registry.h" #include "hakmem_config.h" // External globals (defined in hakmem_tiny.c) extern int g_tiny_initialized; extern int g_use_superslab; // g_tiny_class_sizes is in hakmem_tiny.h (static const) // External functions extern TinySlab* hak_tiny_owner_slab(void* ptr); // hak_super_lookup is static inline in hakmem_super_registry.h int hak_tiny_is_managed(void* ptr) { if (!ptr || !g_tiny_initialized) return 0; // Phase 6.12.1: O(1) slab lookup via registry/list return hak_tiny_owner_slab(ptr) != NULL || hak_super_lookup(ptr) != NULL; } int hak_tiny_is_managed_superslab(void* ptr) { if (!ptr || !g_tiny_initialized) return 0; // Safety: Only check if g_use_superslab is enabled if (g_use_superslab) { SuperSlab* ss = hak_super_lookup(ptr); // Phase 8.2 optimization: Use alignment check instead of mincore() // SuperSlabs are always SUPERSLAB_SIZE-aligned (2MB) if (ss && ((uintptr_t)ss & (SUPERSLAB_SIZE - 1)) == 0) { if (ss->magic == SUPERSLAB_MAGIC) { return 1; // Valid SuperSlab pointer } } } // Fallback to TinySlab check return hak_tiny_owner_slab(ptr) != NULL; } size_t hak_tiny_usable_size(void* ptr) { if (!ptr || !g_tiny_initialized) return 0; // Check SuperSlab first via registry (safe under direct link and LD) if (g_use_superslab) { SuperSlab* ss = hak_super_lookup(ptr); if (ss && ss->magic == SUPERSLAB_MAGIC) { int k = (int)ss->size_class; if (k >= 0 && k < TINY_NUM_CLASSES) { // Phase E1-CORRECT: g_tiny_class_sizes = total size (stride) // Usable = stride - 1 (for 1-byte header) #if HAKMEM_TINY_HEADER_CLASSIDX size_t stride = g_tiny_class_sizes[k]; return (stride > 0) ? (stride - 1) : 0; #else return g_tiny_class_sizes[k]; #endif } } } // Fallback: TinySlab owner lookup TinySlab* slab = hak_tiny_owner_slab(ptr); if (slab) { int k = slab->class_idx; if (k >= 0 && k < TINY_NUM_CLASSES) { // Phase E1-CORRECT: g_tiny_class_sizes = total size (stride) // Usable = stride - 1 (for 1-byte header) #if HAKMEM_TINY_HEADER_CLASSIDX size_t stride = g_tiny_class_sizes[k]; return (stride > 0) ? (stride - 1) : 0; #else return g_tiny_class_sizes[k]; #endif } } return 0; }