- SmallSegment_v7: 2MiB segment with TLS slot and free page stack - ColdIface_v7: Page refill/retire between HotBox and SegmentBox - HotBox_v7: Full C6-only alloc/free with header writing (HEADER_MAGIC|class_idx) - Free path early-exit: Check v7 route BEFORE ss_fast_lookup (separate mmap segment) - RegionIdBox: Register v7 segment for ptr->region lookup - Benchmark: v7 ON ~54.5M ops/s (-7% overhead vs 58.6M legacy baseline) v7 correctly balances alloc/free counts and page lifecycle. RegionIdBox overhead identified as primary cost driver. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
430 lines
15 KiB
C
430 lines
15 KiB
C
// region_id_v6.c - RegionIdBox implementation for V6-HDR-1
|
|
//
|
|
// Purpose: Centralized ptr -> region lookup for headerless design
|
|
// Phase V6-HDR-1: OBSERVE only (no behavior change)
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include "box/region_id_v6_box.h"
|
|
#include "box/smallsegment_v6_box.h"
|
|
|
|
#ifndef likely
|
|
#define likely(x) __builtin_expect(!!(x), 1)
|
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
|
#endif
|
|
|
|
// ============================================================================
|
|
// ENV Control
|
|
// ============================================================================
|
|
|
|
#define REGION_OBSERVE_UNINIT (-1)
|
|
#define REGION_OBSERVE_OFF 0
|
|
#define REGION_OBSERVE_ON 1
|
|
|
|
static int g_region_observe = REGION_OBSERVE_UNINIT;
|
|
|
|
bool region_id_observe_enabled(void) {
|
|
if (unlikely(g_region_observe == REGION_OBSERVE_UNINIT)) {
|
|
const char* env = getenv("HAKMEM_REGION_ID_V6_OBSERVE");
|
|
g_region_observe = (env && env[0] == '1') ? REGION_OBSERVE_ON : REGION_OBSERVE_OFF;
|
|
}
|
|
return g_region_observe == REGION_OBSERVE_ON;
|
|
}
|
|
|
|
// ============================================================================
|
|
// TLS Cache + Segment Registration (Phase V6-HDR-3)
|
|
// ============================================================================
|
|
|
|
static __thread RegionIdTlsCache g_region_tls_cache;
|
|
static __thread int g_region_tls_cache_init = 0;
|
|
|
|
// TLS segment info (registered on first access)
|
|
static __thread uintptr_t g_v6_segment_base = 0;
|
|
static __thread uintptr_t g_v6_segment_end = 0;
|
|
static __thread SmallSegmentV6* g_v6_segment = NULL;
|
|
static __thread int g_v6_segment_registered = 0;
|
|
|
|
RegionIdTlsCache* region_id_tls_cache_get(void) {
|
|
if (unlikely(!g_region_tls_cache_init)) {
|
|
memset(&g_region_tls_cache, 0, sizeof(g_region_tls_cache));
|
|
g_region_tls_cache_init = 1;
|
|
}
|
|
return &g_region_tls_cache;
|
|
}
|
|
|
|
/// Register this thread's v6 segment (Phase V6-HDR-3)
|
|
/// Called from small_heap_ctx_v6() when segment is first acquired
|
|
void region_id_register_v6_segment(SmallSegmentV6* seg) {
|
|
if (!seg || g_v6_segment_registered) {
|
|
return; // Already registered or invalid
|
|
}
|
|
|
|
g_v6_segment_base = seg->base;
|
|
g_v6_segment_end = seg->base + SMALL_SEGMENT_V6_SIZE;
|
|
g_v6_segment = seg;
|
|
g_v6_segment_registered = 1;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Global RegionIdBox (V6-HDR-2: Full implementation)
|
|
// ============================================================================
|
|
|
|
// Maximum number of registered regions
|
|
#define REGION_MAX_ENTRIES 256
|
|
|
|
// RegionEntry: Single registered region
|
|
typedef struct RegionEntry {
|
|
uintptr_t base; // Region base address
|
|
uintptr_t end; // Region end address (exclusive)
|
|
region_kind_t kind; // Region type
|
|
void* metadata; // Kind-specific metadata (e.g., page_meta)
|
|
uint32_t id; // Unique region ID
|
|
uint8_t active; // 1 = active, 0 = free slot
|
|
uint8_t reserved[3]; // Padding
|
|
} RegionEntry;
|
|
|
|
// RegionIdBox: Region registry
|
|
struct RegionIdBox {
|
|
uint32_t next_id; // Next available ID
|
|
uint32_t count; // Number of active entries
|
|
RegionEntry entries[REGION_MAX_ENTRIES]; // Sorted by base address
|
|
// Note: entries are kept sorted by base for binary search lookup
|
|
};
|
|
|
|
static struct RegionIdBox g_region_id_box = {
|
|
.next_id = 2, // Start from 2 (1 is reserved for TLS segment)
|
|
.count = 0
|
|
};
|
|
|
|
RegionIdBox* region_id_box_get(void) {
|
|
return &g_region_id_box;
|
|
}
|
|
|
|
// Binary search helper: find entry containing address
|
|
static RegionEntry* region_entry_find(uintptr_t addr) {
|
|
RegionIdBox* box = &g_region_id_box;
|
|
if (box->count == 0) return NULL;
|
|
|
|
// Binary search for entry where base <= addr < end
|
|
uint32_t lo = 0, hi = box->count;
|
|
while (lo < hi) {
|
|
uint32_t mid = lo + (hi - lo) / 2;
|
|
RegionEntry* e = &box->entries[mid];
|
|
if (!e->active) {
|
|
// Skip inactive entries (shouldn't happen in sorted array)
|
|
lo = mid + 1;
|
|
continue;
|
|
}
|
|
if (addr < e->base) {
|
|
hi = mid;
|
|
} else if (addr >= e->end) {
|
|
lo = mid + 1;
|
|
} else {
|
|
// addr is in range [base, end)
|
|
return e;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// Insert entry maintaining sorted order
|
|
static int region_entry_insert(RegionEntry* entry) {
|
|
RegionIdBox* box = &g_region_id_box;
|
|
if (box->count >= REGION_MAX_ENTRIES) {
|
|
return -1; // Registry full
|
|
}
|
|
|
|
// Find insertion point (binary search)
|
|
uint32_t pos = 0;
|
|
for (uint32_t i = 0; i < box->count; i++) {
|
|
if (box->entries[i].base > entry->base) {
|
|
pos = i;
|
|
break;
|
|
}
|
|
pos = i + 1;
|
|
}
|
|
|
|
// Shift entries to make room
|
|
for (uint32_t i = box->count; i > pos; i--) {
|
|
box->entries[i] = box->entries[i - 1];
|
|
}
|
|
|
|
// Insert new entry
|
|
box->entries[pos] = *entry;
|
|
box->count++;
|
|
return 0;
|
|
}
|
|
|
|
// Remove entry by ID
|
|
static int region_entry_remove(uint32_t id) {
|
|
RegionIdBox* box = &g_region_id_box;
|
|
|
|
for (uint32_t i = 0; i < box->count; i++) {
|
|
if (box->entries[i].id == id && box->entries[i].active) {
|
|
// Shift entries to fill gap
|
|
for (uint32_t j = i; j < box->count - 1; j++) {
|
|
box->entries[j] = box->entries[j + 1];
|
|
}
|
|
box->count--;
|
|
return 0;
|
|
}
|
|
}
|
|
return -1; // Not found
|
|
}
|
|
|
|
// ============================================================================
|
|
// Lookup Implementation (V6-HDR-2: TLS + Registry)
|
|
// ============================================================================
|
|
|
|
// Forward declaration from smallsegment_v6.c
|
|
extern SmallPageMetaV6* small_page_meta_v6_of(void* ptr);
|
|
|
|
RegionLookupV6 region_id_lookup_v6(void* ptr) {
|
|
RegionLookupV6 result = {
|
|
.kind = REGION_KIND_UNKNOWN,
|
|
.region_id = 0,
|
|
.page_meta = NULL
|
|
};
|
|
|
|
if (unlikely(!ptr)) {
|
|
return result;
|
|
}
|
|
|
|
uintptr_t addr = (uintptr_t)ptr;
|
|
|
|
// Phase V6-HDR-4 P0: Direct page_meta calculation (Double validation 排除)
|
|
// TLS segment が登録済みかつ範囲内なら、small_page_meta_v6_of() を呼ばずに
|
|
// 直接 page_meta を計算する。これにより:
|
|
// - slot->in_use チェックの重複を排除
|
|
// - small_ptr_in_segment_v6() の重複を排除
|
|
// - 関数呼び出しオーバーヘッドを削減
|
|
if (g_v6_segment_registered && addr >= g_v6_segment_base && addr < g_v6_segment_end) {
|
|
// Calculate page_idx directly using TLS cached base
|
|
size_t page_idx = (addr - g_v6_segment_base) >> SMALL_PAGE_V6_SHIFT;
|
|
|
|
// Bounds check (should always pass if segment is valid)
|
|
if (likely(page_idx < SMALL_PAGES_PER_SEGMENT)) {
|
|
SmallPageMetaV6* page = &g_v6_segment->page_meta[page_idx];
|
|
|
|
// Minimal validation: only check capacity (page is in use)
|
|
if (likely(page->capacity > 0)) {
|
|
result.kind = REGION_KIND_SMALL_V6;
|
|
result.region_id = 1;
|
|
result.page_meta = page;
|
|
|
|
// Phase V6-HDR-4 P1: Update TLS cache with page-level info
|
|
RegionIdTlsCache* cache = region_id_tls_cache_get();
|
|
cache->last_base = g_v6_segment_base;
|
|
cache->last_end = g_v6_segment_end;
|
|
// Page-level cache: same-page ptr は page_meta lookup をスキップ可能
|
|
uintptr_t page_base = g_v6_segment_base + (page_idx << SMALL_PAGE_V6_SHIFT);
|
|
cache->last_page_base = page_base;
|
|
cache->last_page_end = page_base + SMALL_PAGE_V6_SIZE;
|
|
cache->last_page = page;
|
|
cache->last_result = result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// V6-HDR-2: Check registered regions (binary search)
|
|
RegionEntry* entry = region_entry_find(addr);
|
|
if (entry) {
|
|
result.kind = entry->kind;
|
|
result.region_id = entry->id;
|
|
result.page_meta = entry->metadata;
|
|
|
|
// Update TLS cache for segment-level caching
|
|
RegionIdTlsCache* cache = region_id_tls_cache_get();
|
|
cache->last_base = entry->base;
|
|
cache->last_end = entry->end;
|
|
cache->last_result = result;
|
|
// Note: page-level cache not applicable for arbitrary registered regions
|
|
|
|
return result;
|
|
}
|
|
|
|
// Legacy fallback (if TLS not registered yet)
|
|
SmallPageMetaV6* page = small_page_meta_v6_of(ptr);
|
|
if (page != NULL) {
|
|
result.kind = REGION_KIND_SMALL_V6;
|
|
result.region_id = 1;
|
|
result.page_meta = page;
|
|
|
|
RegionIdTlsCache* cache = region_id_tls_cache_get();
|
|
SmallSegmentV6* seg = (SmallSegmentV6*)page->segment;
|
|
if (seg) {
|
|
cache->last_base = seg->base;
|
|
cache->last_end = seg->base + SMALL_SEGMENT_V6_SIZE;
|
|
cache->last_result = result;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
RegionLookupV6 region_id_lookup_cached_v6(void* ptr) {
|
|
RegionIdTlsCache* cache = region_id_tls_cache_get();
|
|
uintptr_t addr = (uintptr_t)ptr;
|
|
|
|
// Phase V6-HDR-4 P1: Same-page hit optimization
|
|
// 同一ページ内なら page_meta lookup を完全にスキップ
|
|
if (addr >= cache->last_page_base && addr < cache->last_page_end &&
|
|
cache->last_page != NULL && cache->last_page->capacity > 0) {
|
|
// Same page hit - return cached page_meta directly
|
|
RegionLookupV6 result = cache->last_result;
|
|
result.page_meta = cache->last_page;
|
|
return result;
|
|
}
|
|
|
|
// Segment hit but different page - need to recalculate page_meta
|
|
if (addr >= cache->last_base && addr < cache->last_end &&
|
|
cache->last_result.kind != REGION_KIND_UNKNOWN) {
|
|
// Calculate new page_idx
|
|
size_t page_idx = (addr - cache->last_base) >> SMALL_PAGE_V6_SHIFT;
|
|
if (likely(page_idx < SMALL_PAGES_PER_SEGMENT && g_v6_segment != NULL)) {
|
|
SmallPageMetaV6* page = &g_v6_segment->page_meta[page_idx];
|
|
if (likely(page->capacity > 0)) {
|
|
RegionLookupV6 result = cache->last_result;
|
|
result.page_meta = page;
|
|
// Update page-level cache
|
|
uintptr_t page_base = cache->last_base + (page_idx << SMALL_PAGE_V6_SHIFT);
|
|
cache->last_page_base = page_base;
|
|
cache->last_page_end = page_base + SMALL_PAGE_V6_SIZE;
|
|
cache->last_page = page;
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cache miss -> slow path
|
|
return region_id_lookup_v6(ptr);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Registration API (V6-HDR-2: Full implementation)
|
|
// ============================================================================
|
|
|
|
uint32_t region_id_register_v6(void* base, size_t size, region_kind_t kind, void* metadata) {
|
|
if (!base || size == 0) {
|
|
return 0; // Invalid arguments
|
|
}
|
|
|
|
RegionIdBox* box = &g_region_id_box;
|
|
|
|
// Create new entry
|
|
RegionEntry entry = {
|
|
.base = (uintptr_t)base,
|
|
.end = (uintptr_t)base + size,
|
|
.kind = kind,
|
|
.metadata = metadata,
|
|
.id = box->next_id,
|
|
.active = 1
|
|
};
|
|
|
|
// Insert into registry
|
|
if (region_entry_insert(&entry) != 0) {
|
|
return 0; // Registry full
|
|
}
|
|
|
|
uint32_t id = box->next_id++;
|
|
|
|
// OBSERVE mode logging
|
|
region_id_observe_register(base, size, kind, id);
|
|
|
|
return id;
|
|
}
|
|
|
|
void region_id_unregister_v6(uint32_t region_id) {
|
|
if (region_id == 0 || region_id == 1) {
|
|
return; // Invalid or reserved ID
|
|
}
|
|
|
|
// OBSERVE mode logging
|
|
region_id_observe_unregister(region_id);
|
|
|
|
region_entry_remove(region_id);
|
|
}
|
|
|
|
bool region_id_is_valid_v6(uint32_t region_id) {
|
|
if (region_id == 0) return false;
|
|
if (region_id == 1) return true; // Reserved for TLS segment
|
|
|
|
RegionIdBox* box = &g_region_id_box;
|
|
for (uint32_t i = 0; i < box->count; i++) {
|
|
if (box->entries[i].id == region_id && box->entries[i].active) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Utility API
|
|
// ============================================================================
|
|
|
|
const char* region_kind_to_string(region_kind_t kind) {
|
|
switch (kind) {
|
|
case REGION_KIND_UNKNOWN: return "UNKNOWN";
|
|
case REGION_KIND_SMALL_V6: return "SMALL_V6";
|
|
case REGION_KIND_C7_ULTRA: return "C7_ULTRA";
|
|
case REGION_KIND_POOL_V1: return "POOL_V1";
|
|
case REGION_KIND_LARGE: return "LARGE";
|
|
case REGION_KIND_TINY_LEGACY: return "TINY_LEGACY";
|
|
case REGION_KIND_MID_V3: return "MID_V3";
|
|
case REGION_KIND_SMALL_V7: return "SMALL_V7";
|
|
default: return "INVALID";
|
|
}
|
|
}
|
|
|
|
void region_id_box_dump(void) {
|
|
fprintf(stderr, "[REGION_ID_BOX] V6-HDR-2: TLS segment + Registry\n");
|
|
fprintf(stderr, "[REGION_ID_BOX] observe=%d\n", region_id_observe_enabled());
|
|
|
|
RegionIdBox* box = &g_region_id_box;
|
|
fprintf(stderr, "[REGION_ID_BOX] next_id=%u count=%u\n", box->next_id, box->count);
|
|
|
|
// Dump TLS segment info
|
|
if (g_v6_segment_registered) {
|
|
fprintf(stderr, "[REGION_ID_BOX] TLS segment: base=%p end=%p (reserved id=1)\n",
|
|
(void*)g_v6_segment_base, (void*)g_v6_segment_end);
|
|
}
|
|
|
|
// Dump registered regions
|
|
for (uint32_t i = 0; i < box->count; i++) {
|
|
RegionEntry* e = &box->entries[i];
|
|
if (e->active) {
|
|
fprintf(stderr, "[REGION_ID_BOX] [%u] id=%u kind=%s base=%p end=%p meta=%p\n",
|
|
i, e->id, region_kind_to_string(e->kind),
|
|
(void*)e->base, (void*)e->end, e->metadata);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// OBSERVE Mode Logging
|
|
// ============================================================================
|
|
|
|
void region_id_observe_lookup(void* ptr, const RegionLookupV6* result) {
|
|
if (region_id_observe_enabled()) {
|
|
fprintf(stderr, "[REGION_ID] lookup ptr=%p kind=%s region_id=%u page_meta=%p\n",
|
|
ptr, region_kind_to_string(result->kind),
|
|
result->region_id, result->page_meta);
|
|
}
|
|
}
|
|
|
|
void region_id_observe_register(void* base, size_t size, region_kind_t kind, uint32_t id) {
|
|
if (region_id_observe_enabled()) {
|
|
fprintf(stderr, "[REGION_ID] register base=%p size=%zu kind=%s id=%u\n",
|
|
base, size, region_kind_to_string(kind), id);
|
|
}
|
|
}
|
|
|
|
void region_id_observe_unregister(uint32_t id) {
|
|
if (region_id_observe_enabled()) {
|
|
fprintf(stderr, "[REGION_ID] unregister id=%u\n", id);
|
|
}
|
|
}
|