Files
hakmem/core/box/ss_addr_map_box.h

149 lines
5.3 KiB
C
Raw Normal View History

// 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 <stddef.h>
#include <stdint.h>
#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