// ss_addr_map_box.h - Phase 9-1: SuperSlab Address Map Box // Purpose: O(1) address → SuperSlab* mapping (replace linear search) // Contract: Fast lookup with hash table (O(1) amortized, upgrade to true O(1) later) // // Box Pattern: // - Single Responsibility: Address→SuperSlab mapping ONLY // - Clear Contract: ss_map_lookup(ptr) returns SuperSlab* in O(1) amortized // - Observable: Debug macros log all lookups in non-release builds // - Composable: Can coexist with legacy registry during migration // // Performance Target: // - Current: Linear search 50-80 cycles // - Phase 9-1: Hash table ~10-20 cycles // - Future: 2-tier page table ~5-10 cycles (Phase 9-2) #ifndef HAK_BOX_SS_ADDR_MAP_H #define HAK_BOX_SS_ADDR_MAP_H #include #include #include "../hakmem_build_flags.h" // Forward declaration struct SuperSlab; // ============================================================================ // Hash Table Entry (Chaining for collision resolution) // ============================================================================ typedef struct SSMapEntry { void* base; // SuperSlab base address (key) struct SuperSlab* ss; // SuperSlab pointer (value) struct SSMapEntry* next; // Chain for collisions } SSMapEntry; // ============================================================================ // Address Map Structure // ============================================================================ // Hash table size: 8192 buckets (2^13) // - Trade-off: Memory vs collision rate // - 8K buckets × 8 bytes = 64KB (acceptable overhead) // - Load factor target: <2 entries/bucket average #define SS_MAP_HASH_SIZE 8192 typedef struct { SSMapEntry* buckets[SS_MAP_HASH_SIZE]; // Hash table buckets size_t count; // Total entries (for stats) size_t collisions; // Collision counter (for stats) } SSAddrMap; // ============================================================================ // API Functions // ============================================================================ // Initialize map (call once at startup) void ss_map_init(SSAddrMap* map); // Insert SuperSlab into map // Precondition: base must be SuperSlab-aligned (512KB/1MB/2MB) // Contract: O(1) insertion void ss_map_insert(SSAddrMap* map, void* base, struct SuperSlab* ss); // Lookup SuperSlab by pointer // Contract: O(1) amortized lookup // Returns: SuperSlab* if found, NULL if not found struct SuperSlab* ss_map_lookup(SSAddrMap* map, void* ptr); // Remove SuperSlab from map // Contract: O(1) amortized removal void ss_map_remove(SSAddrMap* map, void* base); // Shutdown map (free all entries) void ss_map_shutdown(SSAddrMap* map); // ============================================================================ // Statistics (Debug builds only) // ============================================================================ #if !HAKMEM_BUILD_RELEASE // Print map statistics (count, collisions, load factor) void ss_map_print_stats(SSAddrMap* map); // Get collision rate (for performance tuning) double ss_map_collision_rate(SSAddrMap* map); #endif // ============================================================================ // Debug Macros (Observable Box Pattern) // ============================================================================ #if !HAKMEM_BUILD_RELEASE #define SS_MAP_LOOKUP(map, ptr) \ ({ \ void* _ptr = (ptr); \ struct SuperSlab* _ss = ss_map_lookup(map, _ptr); \ if (getenv("HAKMEM_SS_MAP_TRACE")) { \ fprintf(stderr, "[SS_MAP_LOOKUP] ptr=%p -> ss=%p\n", _ptr, (void*)_ss); \ } \ _ss; \ }) #define SS_MAP_INSERT(map, base, ss) \ do { \ if (getenv("HAKMEM_SS_MAP_TRACE")) { \ fprintf(stderr, "[SS_MAP_INSERT] base=%p ss=%p\n", (void*)(base), (void*)(ss)); \ } \ ss_map_insert(map, base, ss); \ } while(0) #define SS_MAP_REMOVE(map, base) \ do { \ if (getenv("HAKMEM_SS_MAP_TRACE")) { \ fprintf(stderr, "[SS_MAP_REMOVE] base=%p\n", (void*)(base)); \ } \ ss_map_remove(map, base); \ } while(0) #else // Release builds: Direct function calls (no overhead) #define SS_MAP_LOOKUP(map, ptr) ss_map_lookup(map, ptr) #define SS_MAP_INSERT(map, base, ss) ss_map_insert(map, base, ss) #define SS_MAP_REMOVE(map, base) ss_map_remove(map, base) #endif // ============================================================================ // Hash Function (Internal, exposed for testing) // ============================================================================ // Hash pointer to bucket index // Strategy: Use upper bits (SuperSlab-aligned, lower bits are 0) // - ptr >> 19 (min SuperSlab size 512KB = 2^19) // - & (SS_MAP_HASH_SIZE - 1) for modulo static inline size_t ss_map_hash(void* ptr) { uintptr_t addr = (uintptr_t)ptr; // Shift by 19 bits (512KB alignment minimum) // Then mask to table size return (addr >> 19) & (SS_MAP_HASH_SIZE - 1); } // ============================================================================ // Global Instance (TLS or Global, TBD in Phase 9-1-4) // ============================================================================ // For now: Global instance (shared across threads, needs lock) // Phase 9-1-4: Consider TLS instance for lock-free access extern SSAddrMap g_ss_addr_map; #endif // HAK_BOX_SS_ADDR_MAP_H