Files
hakmem/CURRENT_TASK.md
Moe Charm (CI) 72b38bc994 Phase E3-FINAL: Fix Box API offset bugs - ALL classes now use correct offsets
## Root Cause Analysis (GPT5)

**Physical Layout Constraints**:
- Class 0: 8B = [1B header][7B payload] → offset 1 = 9B needed =  IMPOSSIBLE
- Class 1-6: >=16B = [1B header][15B+ payload] → offset 1 =  POSSIBLE
- Class 7: 1KB → offset 0 (compatibility)

**Correct Specification**:
- HAKMEM_TINY_HEADER_CLASSIDX != 0:
  - Class 0, 7: next at offset 0 (overwrites header when on freelist)
  - Class 1-6: next at offset 1 (after header)
- HAKMEM_TINY_HEADER_CLASSIDX == 0:
  - All classes: next at offset 0

**Previous Bug**:
- Attempted "ALL classes offset 1" unification
- Class 0 with offset 1 caused immediate SEGV (9B > 8B block size)
- Mixed 2-arg/3-arg API caused confusion

## Fixes Applied

### 1. Restored 3-Argument Box API (core/box/tiny_next_ptr_box.h)
```c
// Correct signatures
void tiny_next_write(int class_idx, void* base, void* next_value)
void* tiny_next_read(int class_idx, const void* base)

// Correct offset calculation
size_t offset = (class_idx == 0 || class_idx == 7) ? 0 : 1;
```

### 2. Updated 123+ Call Sites Across 34 Files
- hakmem_tiny_hot_pop_v4.inc.h (4 locations)
- hakmem_tiny_fastcache.inc.h (3 locations)
- hakmem_tiny_tls_list.h (12 locations)
- superslab_inline.h (5 locations)
- tiny_fastcache.h (3 locations)
- ptr_trace.h (macro definitions)
- tls_sll_box.h (2 locations)
- + 27 additional files

Pattern: `tiny_next_read(base)` → `tiny_next_read(class_idx, base)`
Pattern: `tiny_next_write(base, next)` → `tiny_next_write(class_idx, base, next)`

### 3. Added Sentinel Detection Guards
- tiny_fast_push(): Block nodes with sentinel in ptr or ptr->next
- tls_list_push(): Block nodes with sentinel in ptr or ptr->next
- Defense-in-depth against remote free sentinel leakage

## Verification (GPT5 Report)

**Test Command**: `./out/release/bench_random_mixed_hakmem --iterations=70000`

**Results**:
-  Main loop completed successfully
-  Drain phase completed successfully
-  NO SEGV (previous crash at iteration 66151 is FIXED)
- ℹ️ Final log: "tiny_alloc(1024) failed" is normal fallback to Mid/ACE layers

**Analysis**:
- Class 0 immediate SEGV:  RESOLVED (correct offset 0 now used)
- 66K iteration crash:  RESOLVED (offset consistency fixed)
- Box API conflicts:  RESOLVED (unified 3-arg API)

## Technical Details

### Offset Logic Justification
```
Class 0:  8B block → next pointer (8B) fits ONLY at offset 0
Class 1: 16B block → next pointer (8B) fits at offset 1 (after 1B header)
Class 2: 32B block → next pointer (8B) fits at offset 1
...
Class 6: 512B block → next pointer (8B) fits at offset 1
Class 7: 1024B block → offset 0 for legacy compatibility
```

### Files Modified (Summary)
- Core API: `box/tiny_next_ptr_box.h`
- Hot paths: `hakmem_tiny_hot_pop*.inc.h`, `tiny_fastcache.h`
- TLS layers: `hakmem_tiny_tls_list.h`, `hakmem_tiny_tls_ops.h`
- SuperSlab: `superslab_inline.h`, `tiny_superslab_*.inc.h`
- Refill: `hakmem_tiny_refill.inc.h`, `tiny_refill_opt.h`
- Free paths: `tiny_free_magazine.inc.h`, `tiny_superslab_free.inc.h`
- Documentation: Multiple Phase E3 reports

## Remaining Work

None for Box API offset bugs - all structural issues resolved.

Future enhancements (non-critical):
- Periodic `grep -R '*(void**)' core/` to detect direct pointer access violations
- Enforce Box API usage via static analysis
- Document offset rationale in architecture docs

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 06:50:20 +09:00

153 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Current Task: Phase E1-CORRECT - 最下層ポインターBox実装
**Date**: 2025-11-13
**Status**: 🔧 In Progress
**Priority**: CRITICAL
---
## 🎯 Goal
Phase E1-CORRECT において、**tiny freelist next ポインタのレイアウト仕様と API を物理制約込みで厳密に統一**し、
C7/C0 特殊ケースや直接 *(void\*\*) アクセス起因の SEGV を構造的に排除する。
---
## ✅ 正式仕様(決定版)
HAKMEM_TINY_HEADER_CLASSIDX フラグ有無と size class ごとに next の格納オフセットを厳密定義する。
### 1. ヘッダ有効時 (HAKMEM_TINY_HEADER_CLASSIDX != 0)
各クラスの物理レイアウトと next オフセット:
- Class 0:
- 物理: `[1B header][7B payload]` (合計 8B)
- 制約: offset 1 に 8B pointer は入らない (1 + 8 = 9B > 8B) → 不可能
- 仕様:
- freelist 中は header を上書きして next を `base + 0` に格納
- free 中 header不要のため問題なし
- next offset: `0`
- Class 1〜6:
- 物理: `[1B header][payload >= 8B]`
- 仕様:
- header は保持
- freelist next は header 直後の `base + 1` に格納
- next offset: `1`
- Class 7:
- 大きなブロック / もともと特殊扱いだった領域
- 実装と互換性・余裕を考慮し、freelist next は `base + 0` 扱いとするのが合理的
- next offset: `0`
まとめ:
- `HAKMEM_TINY_HEADER_CLASSIDX != 0` のとき:
- Class 0,7 → `next_off = 0`
- Class 1〜6 → `next_off = 1`
### 2. ヘッダ無効時 (HAKMEM_TINY_HEADER_CLASSIDX == 0)
- 全クラス:
- header なし
- freelist next は従来通り `base + 0`
- next offset: 常に `0`
---
## 📦 Box / API 統一方針
重複・矛盾していた Box API / tiny_nextptr 実装を以下の方針で統一する。
### Authoritative Logic
単一の「next offset 計算」と「安全な load/store」を真実として定義:
- `size_t tiny_next_off(int class_idx)`:
- `#if HAKMEM_TINY_HEADER_CLASSIDX`
- `return (class_idx == 0 || class_idx == 7) ? 0 : 1;`
- `#else`
- `return 0;`
- `void* tiny_next_load(const void* base, int class_idx)`
- `void tiny_next_store(void* base, int class_idx, void* next)`
この3つを中心に全ての next アクセスを集約する。
### box/tiny_next_ptr_box.h
- `tiny_nextptr.h` をインクルード、もしくは同一ロジックを使用し、
「Box API」としての薄いラッパ/マクロを提供:
例(最終イメージ):
- `static inline void tiny_next_write(int class_idx, void* base, void* next)`
- 中で `tiny_next_store(base, class_idx, next)` を呼ぶ
- `static inline void* tiny_next_read(int class_idx, const void* base)`
- 中で `tiny_next_load(base, class_idx)` を呼ぶ
- `#define TINY_NEXT_WRITE(cls, base, next) tiny_next_write((cls), (base), (next))`
- `#define TINY_NEXT_READ(cls, base) tiny_next_read((cls), (base))`
ポイント:
- API は `class_idx``base pointer` を明示的に受け取る。
- next offset の分岐 (0 or 1) は API 内だけに閉じ込め、呼び出し元での条件分岐は禁止。
- `*(void**)` による直接アクセスは禁止grep で検出対象)。
---
## 🚫 禁止事項
- Phase E1-CORRECT 以降のコードで以下を使用することは禁止:
- `*(void**)ptr` などの直接 next 読み書き
- `class_idx == 7 ? 0 : 1` など、ローカルに next offset を決めるロジック
- `ALL classes offset 1` 前提のコメントや実装
これらは順次削除・修正対象。
---
## 🔍 現状の問題と対策
### 以前の問題点
- `tiny_nextptr.h` が「ALL classes → offset 1」として実装されていた時期があり、
- Class 0 に対して offset 1 書き込み → 即時 SEGV
- Class 7 や一部 call site での不整合も誘発
- `box/tiny_next_ptr_box.h``tiny_nextptr.h` が別仕様になり、
- どちらが正しいか不明瞭な状態で混在していた
### 対策(このドキュメントが指示すること)
1. 正式仕様を上記の通り固定Class 0,7 → 0 / Class 1〜6 → 1
2. `tiny_nextptr.h` をこの仕様に合わせて修正する。
3. `box/tiny_next_ptr_box.h``tiny_nextptr.h` ベースの Box API として整理する。
4. 全ての tiny/TLS/fastcache/refill/SLL 関連コードから、直接 offset 計算と `*(void**)` を排除し、
`tiny_next_*` / `TINY_NEXT_*` API 経由に統一する。
5. grep による監査:
- `grep -R '\*\(void\*\*\)' core/` で違反箇所検出
- 残存している場合は順次修正
---
## ✅ Success Criteria
- 10K〜100K iterations のストレステストで全サイズ (C0〜C7) SEGV 0件
- Class 0 に対する offset1 アクセスが存在しない (grep/レビューで確認)
- Class 7 の next アクセスも Box API 経由で一貫 (offset0扱い)
- すべての next アクセスパスが:
- 「仕様: next_off(class_idx)」に従う tiny_next_* 経由のみで記述されている
- 将来のリファクタ時も、この CURRENT_TASK.md を見れば
「next はどこにあり、どうアクセスすべきか」が一意に判断できる状態
---
## 📌 実装タスクまとめ(開発者向け)
- [ ] tiny_nextptr.h を上記仕様0/1 mixed: C0,7→0 / C1-6→1に修正
- [ ] box/tiny_next_ptr_box.h を tiny_nextptr.h ベースのラッパとして整理
- [ ] 既存コードから next オフセット直書きロジックを撤廃し、Box API に統一
- [ ] `*(void**)` の直接使用箇所を grep で洗い、必要なものを tiny_next_* に置換
- [ ] Release/Debug ビルド + 長時間テストで安定性確認
- [ ] ドキュメント・コメントから「ALL classes offset 1」系の誤記を除去