366 lines
11 KiB
Markdown
366 lines
11 KiB
Markdown
|
|
# TLS_SLL_HDR_RESET Root Cause Investigation (Gemini Edition)
|
|||
|
|
|
|||
|
|
## 背景
|
|||
|
|
|
|||
|
|
hakmemメモリアロケータのsh8benchで`[TLS_SLL_HDR_RESET]`エラーが継続発生しています。
|
|||
|
|
これまでClaude Code、ChatGPT、Task agentが調査しましたが根治に至っていません。
|
|||
|
|
Geminiに最終調査をお願いします。
|
|||
|
|
|
|||
|
|
## 現在の状況(2025-12-03 commit 6154e7656)
|
|||
|
|
|
|||
|
|
### ✅ 解決済み問題
|
|||
|
|
|
|||
|
|
1. **unified_cache_refill SEGVAULT** (commit 6154e7656)
|
|||
|
|
- 根本原因: コンパイラ最適化による操作順序入れ替え
|
|||
|
|
- 修正: ヘッダー書き込みをtiny_next_read()の前に移動 + atomic fence
|
|||
|
|
- 状態: 完全解決、sh8bench実行可能に
|
|||
|
|
|
|||
|
|
2. **LRU registry未登録** (commit 4cc2d8add)
|
|||
|
|
- 根本原因: LRU pop時にhak_super_register()未呼び出し
|
|||
|
|
- 修正: LRU pop後に明示的に再登録
|
|||
|
|
- 状態: 解決
|
|||
|
|
|
|||
|
|
3. **ChatGPTの「8bit右シフト圧縮ポインタ」仮説**
|
|||
|
|
- Task agentが否定: 意図的な圧縮スキームは存在しない
|
|||
|
|
- 真の原因: unified_cache_refillのコンパイラ最適化問題(既に解決済み)
|
|||
|
|
|
|||
|
|
### ❌ 未解決問題
|
|||
|
|
|
|||
|
|
**TLS_SLL_HDR_RESET エラー** - sh8benchで継続発生
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[TLS_SLL_HDR_RESET] cls=1 base=0x71bcf31bd858 got=0x51 expect=0xa1 count=0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- **発生箇所**: `core/box/tls_sll_box.h:585` (TLS SLL pop時のヘッダー検証失敗)
|
|||
|
|
- **期待値**: `0xa1` (class_idx=1のヘッダーマーカー)
|
|||
|
|
- **実際値**: `0x51`, `0x61` など(破損)
|
|||
|
|
- **動作**: SLL全体をリセット(安全だが非効率)
|
|||
|
|
|
|||
|
|
## エラーの詳細
|
|||
|
|
|
|||
|
|
### ヘッダーフォーマット
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
期待値: 0xa1
|
|||
|
|
bit 7-4: 0xa (固定マーカー)
|
|||
|
|
bit 3-0: 0x1 (サイズクラスインデックス)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 破損パターン
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
got=0x51: 01010001 (未初期化メモリ?)
|
|||
|
|
got=0x61: 01100001 ('a' ASCII文字?)
|
|||
|
|
got=0x00: 00000000 (mmap zero初期値?)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 発生パターン
|
|||
|
|
|
|||
|
|
- ✅ **sh8bench**: ほぼ毎回発生
|
|||
|
|
- ✅ **リリース版**: 発生
|
|||
|
|
- ❌ **cfrac, larson**: 発生しない
|
|||
|
|
- ❓ **ASan版**: Task agent報告では未再現
|
|||
|
|
|
|||
|
|
## これまでの調査と既知の修正
|
|||
|
|
|
|||
|
|
### 既に修正済みの境界(commit 3c6c76cb1, a94344c1a)
|
|||
|
|
|
|||
|
|
以下の経路でのヘッダー復元は実装済み:
|
|||
|
|
|
|||
|
|
1. **box_carve_and_push_with_freelist()** (commit 3c6c76cb1)
|
|||
|
|
```c
|
|||
|
|
void* p = meta->freelist;
|
|||
|
|
meta->freelist = tiny_next_read(class_idx, p);
|
|||
|
|
tiny_header_write_if_preserved(p, class_idx); // ← 修正済み
|
|||
|
|
if (!tls_sll_push(class_idx, p, sll_cap)) { ... }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **tiny_drain_freelist_to_sll_once()** (commit a94344c1a)
|
|||
|
|
```c
|
|||
|
|
void* p = m->freelist;
|
|||
|
|
m->freelist = tiny_next_read(class_idx, p);
|
|||
|
|
tiny_header_write_if_preserved(p, class_idx); // ← 修正済み
|
|||
|
|
if (tls_sll_push(class_idx, HAK_BASE_FROM_RAW(p), sll_capacity)) { ... }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 現在の設定(commit 6154e7656)
|
|||
|
|
|
|||
|
|
- ✅ ヘッダー書き込みデフォルトON (`g_write_header=1`)
|
|||
|
|
- ✅ HAKMEM_TINY_WRITE_HEADER=0 で旧挙動に戻せるA/B切替
|
|||
|
|
|
|||
|
|
## Geminiへの調査依頼
|
|||
|
|
|
|||
|
|
### 調査の焦点
|
|||
|
|
|
|||
|
|
**「なぜsh8benchだけでTLS_SLL_HDR_RESETが発生するのか?」**
|
|||
|
|
|
|||
|
|
cfrac/larsonでは発生しないことから、**sh8bench固有のアクセスパターン**に起因する経路がある可能性が高いです。
|
|||
|
|
|
|||
|
|
### 仮説(優先度順)
|
|||
|
|
|
|||
|
|
#### 仮説1: TLS SLL push時のヘッダー未書き込み(最有力)
|
|||
|
|
|
|||
|
|
**コード箇所**: `core/box/tls_sll_box.h` の `tiny_tls_sll_push()`
|
|||
|
|
|
|||
|
|
**確認すべきこと**:
|
|||
|
|
1. push時に本当にヘッダーを書き込んでいるか?
|
|||
|
|
```c
|
|||
|
|
*(uint8_t*)raw_base = (uint8_t)(0xa0 | (class_idx & 0x0f));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. 書き込み順序は正しいか?
|
|||
|
|
- next pointer書き込みの**前**にヘッダー書き込み
|
|||
|
|
- atomic fence有無
|
|||
|
|
|
|||
|
|
3. 条件分岐で書き込みをスキップしていないか?
|
|||
|
|
|
|||
|
|
**調査方法**:
|
|||
|
|
```bash
|
|||
|
|
grep -n "static inline.*tiny_tls_sll_push" -A 100 core/box/tls_sll_box.h | \
|
|||
|
|
grep -E "raw_base.*=.*0xa0|class_idx"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 仮説2: unified_cache経由の未発見経路
|
|||
|
|
|
|||
|
|
**背景**:
|
|||
|
|
- unified_cache_refillでヘッダーを書き込み済み(P1修正)
|
|||
|
|
- しかしその後、**別の経路**でTLS SLLに入る可能性
|
|||
|
|
|
|||
|
|
**確認すべきこと**:
|
|||
|
|
1. unified_cache_refillで返されたポインタがfree時にどの経路を通るか
|
|||
|
|
2. その経路でヘッダーが保持されているか
|
|||
|
|
3. TLS SLLに入る直前で破損していないか
|
|||
|
|
|
|||
|
|
**調査方法**:
|
|||
|
|
```bash
|
|||
|
|
# unified_cache関連のfree/drain経路
|
|||
|
|
grep -n "unified_cache.*drain\|unified_cache.*free" \
|
|||
|
|
core/front/tiny_unified_cache.c core/box/tiny_front_cold_box.h
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 仮説3: sh8bench固有のマルチスレッド競合
|
|||
|
|
|
|||
|
|
**背景**:
|
|||
|
|
- sh8benchは8スレッド並行
|
|||
|
|
- 小さいブロック(class 1など)を高速にalloc/free
|
|||
|
|
|
|||
|
|
**確認すべきこと**:
|
|||
|
|
1. TLS SLL pushがスレッドセーフか
|
|||
|
|
2. ヘッダー書き込みとnext pointer書き込みの間に競合窓がないか
|
|||
|
|
3. `__atomic_thread_fence`の配置は適切か
|
|||
|
|
|
|||
|
|
**調査方法**:
|
|||
|
|
```bash
|
|||
|
|
# TLS SLL実装の同期機構確認
|
|||
|
|
grep -n "thread_fence\|atomic\|mutex\|lock" core/box/tls_sll_box.h
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 具体的な調査手順
|
|||
|
|
|
|||
|
|
### Step 1: TLS SLL push実装の精査
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd /mnt/workdisk/public_share/hakmem
|
|||
|
|
|
|||
|
|
# push実装を確認
|
|||
|
|
cat -n core/box/tls_sll_box.h | sed -n '450,550p'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**チェックポイント**:
|
|||
|
|
- [ ] `*(uint8_t*)raw_base = 0xa0 | cls` が実行されているか
|
|||
|
|
- [ ] `tiny_class_preserves_header(class_idx)` 条件は正しいか
|
|||
|
|
- [ ] `__atomic_thread_fence(__ATOMIC_RELEASE)` があるか
|
|||
|
|
- [ ] next pointer書き込みより**前**に実行されているか
|
|||
|
|
|
|||
|
|
### Step 2: 詳細ログで経路追跡
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# デバッグビルド
|
|||
|
|
find . -name "*.o" -delete && find . -name "*.so" -delete
|
|||
|
|
make shared -j8 EXTRA_CFLAGS="-g -O1"
|
|||
|
|
|
|||
|
|
# リング有効化で実行
|
|||
|
|
HAKMEM_TINY_SLL_RING=1 HAKMEM_DEBUG_LEVEL=3 \
|
|||
|
|
LD_PRELOAD=./libhakmem.so ./mimalloc-bench/out/bench/sh8bench \
|
|||
|
|
2>&1 | tee sh8bench_gemini_debug.log
|
|||
|
|
|
|||
|
|
# push/pop/resetの順序を確認
|
|||
|
|
grep -E "TLS_SLL_PUSH|TLS_SLL_POP|TLS_SLL_HDR_RESET" \
|
|||
|
|
sh8bench_gemini_debug.log | head -100
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Step 3: コード修正テスト
|
|||
|
|
|
|||
|
|
**TLS SLL push強制ヘッダー書き込み**を試してください:
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
// core/box/tls_sll_box.h の tiny_tls_sll_push() に追加
|
|||
|
|
|
|||
|
|
static inline bool tiny_tls_sll_push(int class_idx, void* raw_base, uint32_t capacity) {
|
|||
|
|
// GEMINI FIX: Always write header before push
|
|||
|
|
#if HAKMEM_TINY_HEADER_CLASSIDX
|
|||
|
|
if (tiny_class_preserves_header(class_idx)) {
|
|||
|
|
*(uint8_t*)raw_base = (uint8_t)(0xa0 | (class_idx & 0x0f));
|
|||
|
|
__atomic_thread_fence(__ATOMIC_RELEASE);
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
// 既存のpush処理...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**テスト**:
|
|||
|
|
```bash
|
|||
|
|
find . -name "*.o" -delete && make shared -j8
|
|||
|
|
|
|||
|
|
# 5回テスト
|
|||
|
|
for i in {1..5}; do
|
|||
|
|
echo "=== Run $i ==="
|
|||
|
|
LD_PRELOAD=./libhakmem.so ./mimalloc-bench/out/bench/sh8bench 2>&1 | \
|
|||
|
|
grep -E "TLS_SLL_HDR_RESET|Total elapsed"
|
|||
|
|
done
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Step 4: SAFEHEADER検証
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
HAKMEM_TINY_SLL_SAFEHEADER=1 HAKMEM_TINY_SLL_VALIDATE_HDR=1 \
|
|||
|
|
HAKMEM_TINY_SLL_RING=1 HAKMEM_DEBUG_LEVEL=3 \
|
|||
|
|
LD_PRELOAD=./libhakmem.so ./mimalloc-bench/out/bench/sh8bench \
|
|||
|
|
2>&1 | tee sh8bench_gemini_safeheader.log
|
|||
|
|
|
|||
|
|
# push時の不正検出
|
|||
|
|
grep -E "TLS_SLL_PUSH_BAD_HDR|TLS_SLL_REJECT" sh8bench_gemini_safeheader.log
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 期待される成果物
|
|||
|
|
|
|||
|
|
### 1. 根本原因の特定
|
|||
|
|
|
|||
|
|
以下のいずれかを明確に:
|
|||
|
|
|
|||
|
|
- **パターンA**: TLS SLL push時にヘッダー未書き込み
|
|||
|
|
- どの条件でスキップされているか
|
|||
|
|
- 修正箇所の特定
|
|||
|
|
|
|||
|
|
- **パターンB**: 未発見の経路が存在
|
|||
|
|
- どの経路か(コールスタック)
|
|||
|
|
- その経路でのヘッダー復元漏れ
|
|||
|
|
|
|||
|
|
- **パターンC**: マルチスレッド競合
|
|||
|
|
- 競合が発生する箇所
|
|||
|
|
- atomic fence不足の箇所
|
|||
|
|
|
|||
|
|
### 2. 修正コード
|
|||
|
|
|
|||
|
|
修正が必要なファイルと具体的なコード変更を提示してください:
|
|||
|
|
|
|||
|
|
```c
|
|||
|
|
// 例: core/box/tls_sll_box.h
|
|||
|
|
|
|||
|
|
// 修正前:
|
|||
|
|
static inline bool tiny_tls_sll_push(...) {
|
|||
|
|
// 既存コード
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修正後:
|
|||
|
|
static inline bool tiny_tls_sll_push(...) {
|
|||
|
|
// GEMINI FIX: ヘッダー復元を追加
|
|||
|
|
#if HAKMEM_TINY_HEADER_CLASSIDX
|
|||
|
|
if (tiny_class_preserves_header(class_idx)) {
|
|||
|
|
*(uint8_t*)raw_base = (uint8_t)(0xa0 | (class_idx & 0x0f));
|
|||
|
|
__atomic_thread_fence(__ATOMIC_RELEASE);
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
// 既存のpush処理
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. テスト結果
|
|||
|
|
|
|||
|
|
修正後のsh8bench実行結果:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 期待される結果
|
|||
|
|
=== Run 1 ===
|
|||
|
|
Total elapsed time for 8 threads: XX.XX (XXX.XXXX CPU)
|
|||
|
|
# [TLS_SLL_HDR_RESET] なし
|
|||
|
|
|
|||
|
|
=== Run 2 ===
|
|||
|
|
Total elapsed time for 8 threads: XX.XX (XXX.XXXX CPU)
|
|||
|
|
# [TLS_SLL_HDR_RESET] なし
|
|||
|
|
|
|||
|
|
... (10回連続でエラーなし)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 重要な調査対象ファイル
|
|||
|
|
|
|||
|
|
**最優先**:
|
|||
|
|
- `core/box/tls_sll_box.h` - TLS SLL push/pop実装(行450-610)
|
|||
|
|
|
|||
|
|
**次点**:
|
|||
|
|
- `core/front/tiny_unified_cache.c` - unified cache実装
|
|||
|
|
- `core/box/tiny_front_cold_box.h` - cold drain処理
|
|||
|
|
- `core/hakmem_tiny_free.inc` - free経路
|
|||
|
|
|
|||
|
|
**参考**:
|
|||
|
|
- `core/tiny_region_id.h` - ヘッダー書き込み設定
|
|||
|
|
- `core/box/tiny_header_box.h` - ヘッダー管理API
|
|||
|
|
|
|||
|
|
## 環境変数・ビルド方法
|
|||
|
|
|
|||
|
|
### デバッグフラグ
|
|||
|
|
```bash
|
|||
|
|
HAKMEM_TINY_SLL_RING=1 # TLS SLLイベントログ
|
|||
|
|
HAKMEM_TINY_SLL_VALIDATE_HDR=1 # push時ヘッダー検証
|
|||
|
|
HAKMEM_TINY_SLL_SAFEHEADER=1 # 不正ヘッダーでpush拒否
|
|||
|
|
HAKMEM_DEBUG_LEVEL=3 # 詳細ログ
|
|||
|
|
HAKMEM_TINY_WRITE_HEADER=1 # ヘッダー書き込み強制(既定でON)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ビルド
|
|||
|
|
```bash
|
|||
|
|
cd /mnt/workdisk/public_share/hakmem
|
|||
|
|
|
|||
|
|
# クリーンビルド(リリース版)
|
|||
|
|
find . -name "*.o" -delete && find . -name "*.so" -delete
|
|||
|
|
make shared -j8
|
|||
|
|
|
|||
|
|
# デバッグビルド
|
|||
|
|
make shared -j8 EXTRA_CFLAGS="-g -O1 -UHAKMEM_BUILD_RELEASE"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 参考資料
|
|||
|
|
|
|||
|
|
### 関連コミット
|
|||
|
|
- `6154e7656` - unified_cache_refill SEGVAULT根治修正(最新)
|
|||
|
|
- `4cc2d8add` - LRU registry未登録修正
|
|||
|
|
- `f7d0d236e` - malloc_count最適化(17s→10s)
|
|||
|
|
- `3c6c76cb1` - box_carve_and_push_with_freelistヘッダー復元
|
|||
|
|
- `a94344c1a` - tiny_drain_freelist_to_sll_onceヘッダー復元
|
|||
|
|
|
|||
|
|
### ドキュメント
|
|||
|
|
- `docs/tls_sll_header_corruption_investigation.md` - ChatGPT初回調査
|
|||
|
|
- `docs/tls_sll_hdr_reset_investigation_v2.md` - 更新版調査指示書
|
|||
|
|
- `docs/sh8bench_debug_instruction.md` - sh8benchデバッグ手順
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Geminiへのお願い
|
|||
|
|
|
|||
|
|
1. **Step 1-2で原因を特定**してください
|
|||
|
|
- 特にTLS SLL push実装の精査が重要です
|
|||
|
|
|
|||
|
|
2. **Step 3で修正を実装**してください
|
|||
|
|
- 修正後は必ずsh8benchで10回連続テストしてください
|
|||
|
|
|
|||
|
|
3. **根治であることを証明**してください
|
|||
|
|
- 対処療法ではなく、真の根本原因を解決してください
|
|||
|
|
|
|||
|
|
4. **結果を報告**してください
|
|||
|
|
- 修正したファイル、変更内容、テスト結果を明記してください
|
|||
|
|
|
|||
|
|
よろしくお願いします!🙏
|