Files
hakmem/core/hakmem_syscall.c
Moe Charm (CI) 67fb15f35f Wrap debug fprintf in !HAKMEM_BUILD_RELEASE guards (Release build optimization)
## 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>
2025-11-26 13:14:18 +09:00

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);
}