**問題:**
- Larson 4T で 100% SEGV (1T は 2.09M ops/s で完走)
- System/mimalloc は 4T で 33.52M ops/s 正常動作
- SS OFF + Remote OFF でも 4T で SEGV
**根本原因: (Task agent ultrathink 調査結果)**
```
CRASH: mov (%r15),%r13
R15 = 0x6261 ← ASCII "ba" (ゴミ値、未初期化TLS)
```
Worker スレッドの TLS 変数が未初期化:
- `__thread void* g_tls_sll_head[TINY_NUM_CLASSES];` ← 初期化なし
- pthread_create() で生成されたスレッドでゼロ初期化されない
- NULL チェックが通過 (0x6261 != NULL) → dereference → SEGV
**修正内容:**
全 TLS 配列に明示的初期化子 `= {0}` を追加:
1. **core/hakmem_tiny.c:**
- `g_tls_sll_head[TINY_NUM_CLASSES] = {0}`
- `g_tls_sll_count[TINY_NUM_CLASSES] = {0}`
- `g_tls_live_ss[TINY_NUM_CLASSES] = {0}`
- `g_tls_bcur[TINY_NUM_CLASSES] = {0}`
- `g_tls_bend[TINY_NUM_CLASSES] = {0}`
2. **core/tiny_fastcache.c:**
- `g_tiny_fast_cache[TINY_FAST_CLASS_COUNT] = {0}`
- `g_tiny_fast_count[TINY_FAST_CLASS_COUNT] = {0}`
- `g_tiny_fast_free_head[TINY_FAST_CLASS_COUNT] = {0}`
- `g_tiny_fast_free_count[TINY_FAST_CLASS_COUNT] = {0}`
3. **core/hakmem_tiny_magazine.c:**
- `g_tls_mags[TINY_NUM_CLASSES] = {0}`
4. **core/tiny_sticky.c:**
- `g_tls_sticky_ss[TINY_NUM_CLASSES][TINY_STICKY_RING] = {0}`
- `g_tls_sticky_idx[TINY_NUM_CLASSES][TINY_STICKY_RING] = {0}`
- `g_tls_sticky_pos[TINY_NUM_CLASSES] = {0}`
**効果:**
```
Before: 1T: 2.09M ✅ | 4T: SEGV 💀
After: 1T: 2.41M ✅ | 4T: 4.19M ✅ (+15% 1T, SEGV解消)
```
**テスト:**
```bash
# 1 thread: 完走
./larson_hakmem 2 8 128 1024 1 12345 1
→ Throughput = 2,407,597 ops/s ✅
# 4 threads: 完走(以前は SEGV)
./larson_hakmem 2 8 128 1024 1 12345 4
→ Throughput = 4,192,155 ops/s ✅
```
**調査協力:** Task agent (ultrathink mode) による完璧な根本原因特定
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
76 lines
2.6 KiB
C
76 lines
2.6 KiB
C
// tiny_route.h - Route Fingerprint (Box-boundary tracing, ultra-light)
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdatomic.h>
|
|
#include "tiny_debug_ring.h"
|
|
|
|
// Bits (keep <= 63 to stay in one 64-bit word)
|
|
// 0: refill_enter
|
|
// 1/2: ready_try/ready_hit
|
|
// 3/4: mail_try/mail_hit
|
|
// 5/6: sticky_try/sticky_hit
|
|
// 7/8: hot_try/hot_hit
|
|
// 9/10: bench_try/bench_hit
|
|
// 11/12: reg_try/reg_hit
|
|
// 13/14: adopt_try/adopt_hit
|
|
// 15: mmap_path
|
|
// 16: free_enter
|
|
// 17: free_same_thread
|
|
// 18: free_remote_transition
|
|
// 19: first_free_transition
|
|
// 20: mailbox_publish
|
|
|
|
static __thread uint64_t g_route_fp;
|
|
static __thread uint32_t g_route_seq;
|
|
static __thread int g_route_active;
|
|
static int g_route_enable_env = -1;
|
|
static int g_route_sample_lg = -1;
|
|
|
|
static inline int route_enabled_runtime(void) {
|
|
if (__builtin_expect(g_route_enable_env == -1, 0)) {
|
|
const char* e = getenv("HAKMEM_ROUTE");
|
|
g_route_enable_env = (e && *e && *e != '0') ? 1 : 0;
|
|
}
|
|
return g_route_enable_env;
|
|
}
|
|
|
|
static inline uint32_t route_sample_mask(void) {
|
|
if (__builtin_expect(g_route_sample_lg == -1, 0)) {
|
|
const char* e = getenv("HAKMEM_ROUTE_SAMPLE_LG");
|
|
int lg = (e && *e) ? atoi(e) : 10; // 1/1024 既定
|
|
if (lg < 0) lg = 0; if (lg > 24) lg = 24;
|
|
g_route_sample_lg = lg;
|
|
}
|
|
return (g_route_sample_lg >= 31) ? 0xFFFFFFFFu : ((1u << g_route_sample_lg) - 1u);
|
|
}
|
|
|
|
#define ROUTE_BEGIN(cls) do { \
|
|
if (__builtin_expect(!route_enabled_runtime(), 1)) { g_route_active = 0; break; } \
|
|
uint32_t m = route_sample_mask(); \
|
|
uint32_t s = ++g_route_seq; \
|
|
g_route_active = ((s & m) == 0u); \
|
|
g_route_fp = 0ull; \
|
|
(void)(cls); \
|
|
} while(0)
|
|
|
|
#define ROUTE_MARK(bit) do { if (__builtin_expect(g_route_active, 0)) { g_route_fp |= (1ull << (bit)); } } while(0)
|
|
|
|
#define ROUTE_COMMIT(cls, tag) do { \
|
|
if (__builtin_expect(g_route_active, 0)) { \
|
|
uintptr_t aux = ((uintptr_t)(tag & 0xFFFF) << 48) | (uintptr_t)(g_route_fp & 0x0000FFFFFFFFFFFFull); \
|
|
tiny_debug_ring_record(TINY_RING_EVENT_ROUTE, (uint16_t)(cls), (void*)(uintptr_t)g_route_fp, aux); \
|
|
g_route_active = 0; \
|
|
} \
|
|
} while(0)
|
|
|
|
// Free-side one-shot route commit (independent of alloc-side COMMIT)
|
|
static inline void route_free_commit(int class_idx, uint64_t bits, uint16_t tag) {
|
|
if (!route_enabled_runtime()) return;
|
|
uintptr_t aux = ((uintptr_t)(tag & 0xFFFF) << 48) | (uintptr_t)(bits & 0x0000FFFFFFFFFFFFull);
|
|
tiny_debug_ring_record(TINY_RING_EVENT_ROUTE, (uint16_t)class_idx, (void*)(uintptr_t)bits, aux);
|
|
}
|
|
|
|
// Note: Build-time gate removed to keep integration simple; runtime env controls activation.
|