// hakmem_whale.c - Whale Fast-Path Implementation // // License: MIT // Date: 2025-10-21 #include "hakmem_whale.h" #include "hakmem_sys.h" #include "hakmem_debug.h" #include "hakmem_internal.h" // Phase 6.15 P0.1: For HAKMEM_LOG macro #include #include // ============================================================================ // Internal State (FIFO Ring Buffer) // ============================================================================ typedef struct { void* ptr; // Block pointer size_t size; // Block size } WhaleSlot; static WhaleSlot g_ring[WHALE_RING_CAPACITY]; static int g_head = 0; // Next slot to read (FIFO output) static int g_tail = 0; // Next slot to write (FIFO input) static int g_count = 0; // Current number of cached blocks // Statistics static uint64_t g_hits = 0; static uint64_t g_misses = 0; static uint64_t g_puts = 0; static uint64_t g_evictions = 0; static int g_initialized = 0; // ============================================================================ // Public API Implementation // ============================================================================ void hkm_whale_init(void) { if (g_initialized) return; memset(g_ring, 0, sizeof(g_ring)); g_head = 0; g_tail = 0; g_count = 0; g_hits = 0; g_misses = 0; g_puts = 0; g_evictions = 0; g_initialized = 1; HAKMEM_LOG("[Whale] Initialized (capacity=%d, threshold=%zu MB)\n", WHALE_RING_CAPACITY, WHALE_MIN_SIZE / (1024 * 1024)); } void hkm_whale_shutdown(void) { if (!g_initialized) return; // Free all cached blocks for (int i = 0; i < g_count; i++) { int idx = (g_head + i) % WHALE_RING_CAPACITY; if (g_ring[idx].ptr) { hkm_sys_munmap(g_ring[idx].ptr, g_ring[idx].size); } } g_initialized = 0; } void* hkm_whale_get(size_t size) { if (!g_initialized) hkm_whale_init(); if (size < WHALE_MIN_SIZE) return NULL; // Not a whale HKM_TIME_START(t0); // FIFO: check if we have any cached blocks if (g_count == 0) { HKM_TIME_END(HKM_CAT_WHALE_GET, t0); g_misses++; return NULL; // Cache miss } // Get oldest block (FIFO head) WhaleSlot* slot = &g_ring[g_head]; void* ptr = slot->ptr; size_t cached_size = slot->size; // Check if size matches (exact match only for now) if (cached_size < size) { HKM_TIME_END(HKM_CAT_WHALE_GET, t0); g_misses++; return NULL; // Size mismatch } // Cache hit! Remove from ring slot->ptr = NULL; slot->size = 0; g_head = (g_head + 1) % WHALE_RING_CAPACITY; g_count--; HKM_TIME_END(HKM_CAT_WHALE_GET, t0); g_hits++; return ptr; } int hkm_whale_put(void* ptr, size_t size) { if (!g_initialized) hkm_whale_init(); if (!ptr) return 1; // Invalid pointer if (size < WHALE_MIN_SIZE) return 1; // Not a whale HKM_TIME_START(t0); g_puts++; // Check if cache is full if (g_count >= WHALE_RING_CAPACITY) { // Phase 6.11.2: Region Cache (Keep-Map Reuse) // Evict oldest block with MADV_DONTNEED instead of munmap // - Releases physical pages (RSS reduction) // - Keeps VMA mapped (faster than munmap + mmap) // - OS can reuse VMA for next mmap WhaleSlot* evict_slot = &g_ring[g_head]; if (evict_slot->ptr) { hkm_sys_madvise_dontneed(evict_slot->ptr, evict_slot->size); g_evictions++; } g_head = (g_head + 1) % WHALE_RING_CAPACITY; g_count--; } // Add new block to tail WhaleSlot* slot = &g_ring[g_tail]; slot->ptr = ptr; slot->size = size; g_tail = (g_tail + 1) % WHALE_RING_CAPACITY; g_count++; HKM_TIME_END(HKM_CAT_WHALE_PUT, t0); return 0; // Successfully cached } void hkm_whale_dump_stats(void) { if (!g_initialized) return; fprintf(stderr, "\n========================================\n"); fprintf(stderr, "Whale Fast-Path Statistics\n"); fprintf(stderr, "========================================\n"); fprintf(stderr, "Hits: %lu\n", (unsigned long)g_hits); fprintf(stderr, "Misses: %lu\n", (unsigned long)g_misses); fprintf(stderr, "Puts: %lu\n", (unsigned long)g_puts); fprintf(stderr, "Evictions: %lu\n", (unsigned long)g_evictions); uint64_t total_gets = g_hits + g_misses; double hit_rate = total_gets > 0 ? (double)g_hits / total_gets * 100.0 : 0.0; fprintf(stderr, "Hit Rate: %.1f%%\n", hit_rate); fprintf(stderr, "Cached: %d / %d slots\n", g_count, WHALE_RING_CAPACITY); fprintf(stderr, "========================================\n"); }