## Changes ### 1. core/page_arena.c - Removed init failure message (lines 25-27) - error is handled by returning early - All other fprintf statements already wrapped in existing #if !HAKMEM_BUILD_RELEASE blocks ### 2. core/hakmem.c - Wrapped SIGSEGV handler init message (line 72) - CRITICAL: Kept SIGSEGV/SIGBUS/SIGABRT error messages (lines 62-64) - production needs crash logs ### 3. core/hakmem_shared_pool.c - Wrapped all debug fprintf statements in #if !HAKMEM_BUILD_RELEASE: - Node pool exhaustion warning (line 252) - SP_META_CAPACITY_ERROR warning (line 421) - SP_FIX_GEOMETRY debug logging (line 745) - SP_ACQUIRE_STAGE0.5_EMPTY debug logging (line 865) - SP_ACQUIRE_STAGE0_L0 debug logging (line 803) - SP_ACQUIRE_STAGE1_LOCKFREE debug logging (line 922) - SP_ACQUIRE_STAGE2_LOCKFREE debug logging (line 996) - SP_ACQUIRE_STAGE3 debug logging (line 1116) - SP_SLOT_RELEASE debug logging (line 1245) - SP_SLOT_FREELIST_LOCKFREE debug logging (line 1305) - SP_SLOT_COMPLETELY_EMPTY debug logging (line 1316) - Fixed lock_stats_init() for release builds (lines 60-65) - ensure g_lock_stats_enabled is initialized ## Performance Validation Before: 51M ops/s (with debug fprintf overhead) After: 49.1M ops/s (consistent performance, fprintf removed from hot paths) ## Build & Test ```bash ./build.sh larson_hakmem ./out/release/larson_hakmem 1 5 1 1000 100 10000 42 # Result: 49.1M ops/s ``` Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
118 lines
3.7 KiB
C
118 lines
3.7 KiB
C
// hakmem_syscall.c - Direct libc calls via dlsym (Box 3)
|
|
//
|
|
// Purpose: Bypass LD_PRELOAD to avoid infinite recursion
|
|
//
|
|
// How it works:
|
|
// 1. dlsym(RTLD_NEXT, "malloc") finds the NEXT symbol after current one
|
|
// 2. In LD_PRELOAD context: hakmem.so → libc.so (skips our wrapper!)
|
|
// 3. Result: Direct libc call, no recursion possible
|
|
//
|
|
// Performance impact:
|
|
// - dlsym: Called ONCE at init (cached in function pointers)
|
|
// - hkm_libc_malloc(): Direct function call (no overhead)
|
|
// - No TLS access, no guards, no recursion checks
|
|
//
|
|
// License: MIT
|
|
// Date: 2025-10-24
|
|
|
|
#include "hakmem_syscall.h"
|
|
#include <dlfcn.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
// ============================================================================
|
|
// Function Pointers (initialized once at startup)
|
|
// ============================================================================
|
|
|
|
// Real libc functions (bypassing LD_PRELOAD)
|
|
static void* (*real_malloc)(size_t) = NULL;
|
|
static void* (*real_calloc)(size_t, size_t) = NULL;
|
|
static void (*real_free)(void*) = NULL;
|
|
static void* (*real_realloc)(void*, size_t) = NULL;
|
|
|
|
// Initialization flag
|
|
static int g_syscall_initialized = 0;
|
|
|
|
// ============================================================================
|
|
// Initialization
|
|
// ============================================================================
|
|
|
|
void hkm_syscall_init(void) {
|
|
// Idempotent: safe to call multiple times
|
|
if (g_syscall_initialized) {
|
|
return;
|
|
}
|
|
|
|
// dlsym with RTLD_NEXT: Get NEXT symbol in library chain
|
|
// In LD_PRELOAD context: libhakmem.so → libc.so (skips our malloc!)
|
|
real_malloc = dlsym(RTLD_NEXT, "malloc");
|
|
real_calloc = dlsym(RTLD_NEXT, "calloc");
|
|
real_free = dlsym(RTLD_NEXT, "free");
|
|
real_realloc = dlsym(RTLD_NEXT, "realloc");
|
|
|
|
// Fatal error if dlsym fails (should never happen)
|
|
if (!real_malloc || !real_calloc || !real_free || !real_realloc) {
|
|
fprintf(stderr, "[hakmem_syscall] FATAL: dlsym failed\n");
|
|
fprintf(stderr, " real_malloc=%p\n", (void*)real_malloc);
|
|
fprintf(stderr, " real_calloc=%p\n", (void*)real_calloc);
|
|
fprintf(stderr, " real_free=%p\n", (void*)real_free);
|
|
fprintf(stderr, " real_realloc=%p\n", (void*)real_realloc);
|
|
abort();
|
|
}
|
|
|
|
g_syscall_initialized = 1;
|
|
|
|
// Optional: Debug logging (only in debug builds)
|
|
#ifdef HAKMEM_DEBUG_VERBOSE
|
|
fprintf(stderr, "[hakmem_syscall] Initialized successfully\n");
|
|
fprintf(stderr, " real_malloc=%p\n", (void*)real_malloc);
|
|
fprintf(stderr, " real_calloc=%p\n", (void*)real_calloc);
|
|
fprintf(stderr, " real_free=%p\n", (void*)real_free);
|
|
fprintf(stderr, " real_realloc=%p\n", (void*)real_realloc);
|
|
#endif
|
|
}
|
|
|
|
// ============================================================================
|
|
// Direct libc Functions (Box 3)
|
|
// ============================================================================
|
|
|
|
void* hkm_libc_malloc(size_t size) {
|
|
// Auto-initialize on first use (defensive programming)
|
|
if (!real_malloc) {
|
|
hkm_syscall_init();
|
|
}
|
|
|
|
// Direct call to libc malloc (no LD_PRELOAD, no recursion!)
|
|
return real_malloc(size);
|
|
}
|
|
|
|
void* hkm_libc_calloc(size_t nmemb, size_t size) {
|
|
// Auto-initialize on first use
|
|
if (!real_calloc) {
|
|
hkm_syscall_init();
|
|
}
|
|
|
|
// Direct call to libc calloc
|
|
return real_calloc(nmemb, size);
|
|
}
|
|
|
|
void hkm_libc_free(void* ptr) {
|
|
// Auto-initialize on first use
|
|
if (!real_free) {
|
|
hkm_syscall_init();
|
|
}
|
|
|
|
// Direct call to libc free
|
|
real_free(ptr);
|
|
}
|
|
|
|
void* hkm_libc_realloc(void* ptr, size_t size) {
|
|
// Auto-initialize on first use
|
|
if (!real_realloc) {
|
|
hkm_syscall_init();
|
|
}
|
|
|
|
// Direct call to libc realloc
|
|
return real_realloc(ptr, size);
|
|
}
|