// ss_addr_map_box.c - Phase 9-1: SuperSlab Address Map Implementation // Purpose: O(1) hash table for address → SuperSlab* mapping #include "ss_addr_map_box.h" #include "../hakmem_tiny_superslab.h" #include "../hakmem_tiny_superslab_constants.h" #include #include #include // ============================================================================ // Global Instance // ============================================================================ SSAddrMap g_ss_addr_map = {0}; // ============================================================================ // Internal Helpers // ============================================================================ // Allocate entry (use libc to avoid recursion) static SSMapEntry* alloc_entry(void) { extern void* __libc_malloc(size_t); return (SSMapEntry*)__libc_malloc(sizeof(SSMapEntry)); } // Free entry (use libc to match allocation) static void free_entry(SSMapEntry* entry) { extern void __libc_free(void*); __libc_free(entry); } // Get SuperSlab base address from any pointer within it // Strategy: Mask lower bits based on SuperSlab size // Note: SuperSlab can be 512KB, 1MB, or 2MB // Solution: Try each alignment until we find a valid SuperSlab static __attribute__((unused)) void* get_superslab_base(void* ptr, struct SuperSlab* ss) { // SuperSlab stores its own size in header // For now, use conservative approach: align to minimum size (512KB) // Phase 9-1-2: Optimize with actual size from SuperSlab header uintptr_t addr = (uintptr_t)ptr; uintptr_t mask = ~((1UL << SUPERSLAB_LG_MIN) - 1); // 512KB mask (void)ss; return (void*)(addr & mask); } // ============================================================================ // API Implementation // ============================================================================ void ss_map_init(SSAddrMap* map) { memset(map, 0, sizeof(SSAddrMap)); #if !HAKMEM_BUILD_RELEASE if (getenv("HAKMEM_SS_MAP_TRACE")) { fprintf(stderr, "[SS_MAP_INIT] Initialized with %d buckets\n", SS_MAP_HASH_SIZE); } #endif } void ss_map_insert(SSAddrMap* map, void* base, struct SuperSlab* ss) { if (!map || !base || !ss) { #if !HAKMEM_BUILD_RELEASE fprintf(stderr, "[SS_MAP_INSERT] ERROR: NULL parameter (map=%p base=%p ss=%p)\n", (void*)map, base, (void*)ss); #endif return; } // Hash to bucket size_t bucket_idx = ss_map_hash(base); // Check for duplicate (should not happen, but defensive) SSMapEntry* entry = map->buckets[bucket_idx]; while (entry) { if (entry->base == base) { #if !HAKMEM_BUILD_RELEASE fprintf(stderr, "[SS_MAP_INSERT] WARNING: Duplicate base=%p (overwriting)\n", base); #endif entry->ss = ss; return; } entry = entry->next; } // Allocate new entry SSMapEntry* new_entry = alloc_entry(); if (!new_entry) { #if !HAKMEM_BUILD_RELEASE fprintf(stderr, "[SS_MAP_INSERT] ERROR: Failed to allocate entry\n"); #endif return; } // Initialize entry new_entry->base = base; new_entry->ss = ss; new_entry->next = map->buckets[bucket_idx]; // Insert at head of chain map->buckets[bucket_idx] = new_entry; map->count++; // Track collisions (for statistics) if (new_entry->next != NULL) { map->collisions++; } } struct SuperSlab* ss_map_lookup(SSAddrMap* map, void* ptr) { if (!map || !ptr) { return NULL; } // Try each possible SuperSlab alignment (512KB, 1MB, 2MB) // Start with most common (512KB) for (int lg = SUPERSLAB_LG_MIN; lg <= SUPERSLAB_LG_MAX; lg++) { uintptr_t addr = (uintptr_t)ptr; uintptr_t mask = ~((1UL << lg) - 1); void* base = (void*)(addr & mask); // Hash to bucket size_t bucket_idx = ss_map_hash(base); // Search chain SSMapEntry* entry = map->buckets[bucket_idx]; while (entry) { if (entry->base == base) { // Found! Verify pointer is within SuperSlab range // Phase 9-1-2: Add range check for safety return entry->ss; } entry = entry->next; } } // Not found return NULL; } void ss_map_remove(SSAddrMap* map, void* base) { if (!map || !base) { return; } // Hash to bucket size_t bucket_idx = ss_map_hash(base); // Search and remove SSMapEntry** prev_next = &map->buckets[bucket_idx]; SSMapEntry* entry = map->buckets[bucket_idx]; while (entry) { if (entry->base == base) { // Found - remove from chain *prev_next = entry->next; map->count--; // Free entry free_entry(entry); #if !HAKMEM_BUILD_RELEASE if (getenv("HAKMEM_SS_MAP_TRACE")) { fprintf(stderr, "[SS_MAP_REMOVE] Removed base=%p\n", base); } #endif return; } prev_next = &entry->next; entry = entry->next; } #if !HAKMEM_BUILD_RELEASE fprintf(stderr, "[SS_MAP_REMOVE] WARNING: base=%p not found\n", base); #endif } void ss_map_shutdown(SSAddrMap* map) { if (!map) { return; } // Free all entries for (size_t i = 0; i < SS_MAP_HASH_SIZE; i++) { SSMapEntry* entry = map->buckets[i]; while (entry) { SSMapEntry* next = entry->next; free_entry(entry); entry = next; } map->buckets[i] = NULL; } map->count = 0; map->collisions = 0; #if !HAKMEM_BUILD_RELEASE if (getenv("HAKMEM_SS_MAP_TRACE")) { fprintf(stderr, "[SS_MAP_SHUTDOWN] All entries freed\n"); } #endif } // ============================================================================ // Statistics (Debug builds only) // ============================================================================ #if !HAKMEM_BUILD_RELEASE void ss_map_print_stats(SSAddrMap* map) { if (!map) { return; } fprintf(stderr, "\n[SS_MAP_STATS] SuperSlab Address Map Statistics:\n"); fprintf(stderr, " Total entries: %zu\n", map->count); fprintf(stderr, " Hash buckets: %d\n", SS_MAP_HASH_SIZE); fprintf(stderr, " Collisions: %zu\n", map->collisions); if (map->count > 0) { double load_factor = (double)map->count / SS_MAP_HASH_SIZE; double collision_rate = (double)map->collisions / map->count; fprintf(stderr, " Load factor: %.2f\n", load_factor); fprintf(stderr, " Collision rate: %.1f%%\n", collision_rate * 100.0); // Find longest chain size_t max_chain = 0; size_t empty_buckets = 0; for (size_t i = 0; i < SS_MAP_HASH_SIZE; i++) { size_t chain_len = 0; SSMapEntry* entry = map->buckets[i]; if (!entry) { empty_buckets++; } while (entry) { chain_len++; entry = entry->next; } if (chain_len > max_chain) { max_chain = chain_len; } } fprintf(stderr, " Longest chain: %zu\n", max_chain); fprintf(stderr, " Empty buckets: %zu (%.1f%%)\n", empty_buckets, (double)empty_buckets / SS_MAP_HASH_SIZE * 100.0); } } double ss_map_collision_rate(SSAddrMap* map) { if (!map || map->count == 0) { return 0.0; } return (double)map->collisions / map->count; } #endif