Files
hakmem/core/smallobject_mid_v35.c

162 lines
5.5 KiB
C
Raw Normal View History

// smallobject_mid_v35.c
// Phase v11a-3: MID v3.5 HotBox implementation
//
// Design:
// - TLS-cached page for fast allocation
// - Refill via ColdIface when page exhausted
// - Retire via ColdIface when page is full
// - Stats/Learner integration for observability
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "box/smallobject_mid_v35_box.h"
#include "box/smallobject_segment_mid_v3_box.h"
#include "box/smallobject_cold_iface_mid_v3_box.h"
#include "tiny_region_id.h" // For tiny_region_id_write_header
// SmallPageMeta is defined in smallobject_segment_mid_v3_box.h
// (included via smallobject_cold_iface_mid_v3_box.h)
// ============================================================================
// TLS Context (per-thread fast path state)
// ============================================================================
typedef struct {
void *page[8]; // Current page per class
uint32_t offset[8]; // Allocation offset (slot index)
uint32_t capacity[8]; // Slots per page per class
SmallPageMeta_MID_v3 *meta[8]; // Page metadata for retire check
} SmallMidV35TlsCtx;
static __thread SmallMidV35TlsCtx tls_mid_v35_ctx = {0};
// ============================================================================
// Slot Configuration (C5/C6/C7)
// ============================================================================
// Slot sizes for C5, C6, C7
static const size_t g_slot_sizes[8] = {
0, // C0: not used
0, // C1: not used
0, // C2: not used
0, // C3: not used
0, // C4: not used (ULTRA handles this)
384, // C5: 257-384 bytes → 384 byte slots
512, // C6: 385-512 bytes → 512 byte slots
1024, // C7: 513-1024 bytes → 1024 byte slots (ULTRA handles this)
};
// Slots per 64KB page
static const uint32_t g_slots_per_page[8] = {
0, 0, 0, 0, 0,
170, // C5: 65536 / 384 = 170
128, // C6: 65536 / 512 = 128
64, // C7: 65536 / 1024 = 64
};
// ============================================================================
// Init
// ============================================================================
void small_mid_v35_init(void) {
// Initialize any global state if needed
// For v11a-3: nothing to do (TLS is zero-initialized)
}
// ============================================================================
// Alloc
// ============================================================================
void* small_mid_v35_alloc(uint32_t class_idx, size_t size) {
(void)size; // Unused for now
if (class_idx < 5 || class_idx > 7) return NULL; // Only C5-C7
SmallMidV35TlsCtx *ctx = &tls_mid_v35_ctx;
// Fast path: allocate from TLS cached page
if (ctx->page[class_idx] && ctx->offset[class_idx] < ctx->capacity[class_idx]) {
size_t slot_size = g_slot_sizes[class_idx];
void *base = (char*)ctx->page[class_idx] + ctx->offset[class_idx] * slot_size;
ctx->offset[class_idx]++;
// Update page metadata
if (ctx->meta[class_idx]) {
ctx->meta[class_idx]->alloc_count++;
}
// Write header (1-byte Tiny header with class_idx)
// Note: Assumes HAKMEM_TINY_HEADER_CLASSIDX is enabled
tiny_region_id_write_header(base, class_idx);
// Return USER pointer (BASE + 1 byte header)
return (char*)base + 1;
}
// Slow path: need new page via ColdIface
SmallPageMeta_MID_v3 *page = small_cold_mid_v3_refill_page(class_idx);
if (!page) {
// Fallback to legacy or return NULL
return NULL;
}
// Update TLS cache
ctx->page[class_idx] = page->ptr;
ctx->offset[class_idx] = 1; // First slot already allocated
ctx->capacity[class_idx] = g_slots_per_page[class_idx];
ctx->meta[class_idx] = page;
// Record first allocation in page metadata
page->alloc_count = 1;
// Write header for first slot
tiny_region_id_write_header(page->ptr, class_idx);
// Return first slot (USER pointer)
return (char*)page->ptr + 1;
}
// ============================================================================
// Free (Simplified: just count, no freelist yet)
// ============================================================================
void small_mid_v35_free(void *ptr, uint32_t class_idx) {
if (!ptr || class_idx < 5 || class_idx > 7) return;
// For v11a-3: simplified free (just increment free_count)
// In future phases: implement freelist for reuse
// Calculate BASE from USER pointer
void *base = (char*)ptr - 1;
// Find page metadata via simple calculation
// Note: Assumes 64KB pages aligned to 64KB boundary
size_t page_size = 64 * 1024; // 64KB
void *page_base = (void*)((uintptr_t)base & ~(page_size - 1));
// Check if this is the current TLS page
SmallMidV35TlsCtx *ctx = &tls_mid_v35_ctx;
SmallPageMeta_MID_v3 *meta = ctx->meta[class_idx];
if (meta && meta->ptr == page_base) {
// Free to current TLS page
meta->free_count++;
// Check if page is fully empty
if (meta->free_count >= meta->capacity) {
// Retire page via ColdIface
small_cold_mid_v3_retire_page(meta);
// Clear TLS cache for this class
ctx->page[class_idx] = NULL;
ctx->offset[class_idx] = 0;
ctx->meta[class_idx] = NULL;
}
} else {
// Different page: need RegionIdBox lookup
// For v11a-3: simple fallback - just count the free
// Real implementation needs proper page lookup
// TODO: Implement cross-page free via RegionIdBox in v11b
}
}