Phase 3: Remove mincore() syscall completely

Problem:
- mincore() was already disabled by default (DISABLE_MINCORE=1)
- Phase 1b/2 registry-based validation made mincore obsolete
- Dead code (~60 lines) remained with complex #ifdef guards

Solution:
Complete removal of mincore() syscall and related infrastructure:

1. Makefile:
   - Removed DISABLE_MINCORE configuration (lines 167-177)
   - Added Phase 3 comment documenting removal rationale

2. core/box/hak_free_api.inc.h:
   - Removed ~60 lines of mincore logic with TLS page cache
   - Simplified to: int is_mapped = 1;
   - Added comprehensive history comment

3. core/box/external_guard_box.h:
   - Simplified external_guard_is_mapped() from 20 lines to 4 lines
   - Always returns 1 (assume mapped)
   - Added Phase 3 comment

Safety:
Trust internal metadata for all validation:
- SuperSlab registry: validates Tiny allocations (Phase 1b/2)
- AllocHeader: validates Mid/Large allocations
- FrontGate classifier: routes external allocations

Testing:
✓ Build: Clean compilation (no warnings)
✓ Stability: 100/100 test iterations passed (0% crash rate)
✓ Performance: No regression (mincore already disabled)

History:
- Phase 9: Used mincore() for safety
- 2025-11-14: Added DISABLE_MINCORE flag (+10.3% perf improvement)
- Phase 1b/2: Registry-based validation (0% crash rate)
- Phase 3: Dead code cleanup (this commit)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm (CI)
2025-11-29 09:04:32 +09:00
parent ca6e8ecaf1
commit d78baf41ce
3 changed files with 25 additions and 86 deletions

View File

@ -213,63 +213,19 @@ void hak_free_at(void* ptr, size_t size, hak_callsite_t site) {
{
void* raw = (char*)ptr - HEADER_SIZE;
// CRITICAL FIX (2025-11-14): Use real mincore() to check memory accessibility
// Phase 9 gutted hak_is_memory_readable() to always return 1 (unsafe!)
// We MUST verify memory is mapped before dereferencing AllocHeader.
// Phase 3 (2025-11-29): mincore() completely removed
//
// A/B Testing (2025-11-14): Add #ifdef guard to measure mincore performance impact.
// Expected: mincore OFF → +100-200% throughput, but may cause crashes on invalid ptrs.
// Usage: make DISABLE_MINCORE=1 to disable mincore checks.
int is_mapped = 0;
#ifndef HAKMEM_DISABLE_MINCORE_CHECK
#ifdef __linux__
{
// TLS page cache to reduce mincore() frequency.
// - Cache last-checked pages in __thread statics.
// - Typical case: many frees on the same handful of pages → 90%+ cache hit.
static __thread void* s_last_page1 = NULL;
static __thread int s_last_page1_mapped = 0;
static __thread void* s_last_page2 = NULL;
static __thread int s_last_page2_mapped = 0;
unsigned char vec;
void* page1 = (void*)((uintptr_t)raw & ~0xFFFUL);
void* page2 = (void*)(((uintptr_t)raw + sizeof(AllocHeader) - 1) & ~0xFFFUL);
// Fast path: reuse cached result for page1 when possible
if (page1 == s_last_page1) {
is_mapped = s_last_page1_mapped;
} else {
is_mapped = (mincore(page1, 1, &vec) == 0);
s_last_page1 = page1;
s_last_page1_mapped = is_mapped;
}
// If header crosses page boundary, ensure second page is also mapped
if (is_mapped && page2 != page1) {
if (page2 == s_last_page2) {
if (!s_last_page2_mapped) {
is_mapped = 0;
}
} else {
int mapped2 = (mincore(page2, 1, &vec) == 0);
s_last_page2 = page2;
s_last_page2_mapped = mapped2;
if (!mapped2) {
is_mapped = 0;
}
}
}
}
#else
is_mapped = 1; // Assume mapped on non-Linux
#endif
#else
// HAKMEM_DISABLE_MINCORE_CHECK=1: Trust internal metadata (registry/headers)
// Assumes all ptrs reaching this path are valid HAKMEM allocations.
// WARNING: May crash on invalid ptrs (libc/external allocations without headers).
is_mapped = 1;
#endif
// History:
// - Phase 9: Originally used mincore() syscall to verify memory accessibility
// - 2025-11-14: Added DISABLE_MINCORE flag for performance (+10.3% improvement)
// - Phase 1b/2: Registry-based validation provides sufficient safety
// - Phase 3: Dead code removal - mincore no longer needed
//
// Safety: Trust internal metadata (registry/headers/FrontGate classification)
// - SuperSlab registry validates all Tiny allocations (Phase 1b/2)
// - Headers validate Mid/Large allocations
// - FrontGate classifier routes external allocations correctly
int is_mapped = 1;
if (!is_mapped) {
// Memory not accessible, ptr likely has no header