# C7 (1024B) TLS SLL Corruption Root Cause Analysis ## 症状 **修正後も依然として発生**: - Class 7 (1024B)でTLS SLL破壊が継続 - `tiny_nextptr.h` line 45を `return 1u` に修正済み(C7もoffset=1) - 破壊がClass 6からClass 7に移動(修正の効果はあるが根本解決せず) **観察事項**: ``` [TLS_SLL_POP_INVALID] cls=7 head=0x5d dropped count=1 [TLS_SLL_POP_INVALID] cls=7 last_push=0x7815fa801003 ← 奇数アドレス! [TLS_SLL_POP_INVALID] cls=7 head=0xfd dropped count=2 [TLS_SLL_POP_INVALID] cls=7 last_push=0x7815f99a0801 ← 奇数アドレス! ``` 1. headに無効な小さい値(0x5d, 0xfd等)が入る 2. `last_push`アドレスが奇数(0x...03, 0x...01等) ## アーキテクチャ確認 ### Allocation Path(正常) **tiny_alloc_fast.inc.h**: - `tiny_alloc_fast_pop()` returns `base` (SuperSlab block start) - `HAK_RET_ALLOC(7, base)`: ```c *(uint8_t*)(base) = 0xa7; // Write header at base[0] return (void*)((uint8_t*)(base) + 1); // Return user = base + 1 ``` - User receives: `ptr = base + 1` ### Free Path(ここに問題がある可能性) **tiny_free_fast_v2.inc.h** (line 106-144): ```c int class_idx = tiny_region_id_read_header(ptr); // Read from ptr-1 = base ✓ void* base = (char*)ptr - 1; // base = user - 1 ✓ ``` **tls_sll_box.h** (line 117, 235-238): ```c static inline bool tls_sll_push(int class_idx, void* ptr, uint32_t capacity) { // ptr parameter = base (from caller) ... PTR_NEXT_WRITE("tls_push", class_idx, ptr, 0, g_tls_sll[class_idx].head); g_tls_sll[class_idx].head = ptr; ... s_tls_sll_last_push[class_idx] = ptr; // ← Should store base } ``` **tiny_next_ptr_box.h** (line 39): ```c static inline void tiny_next_write(int class_idx, void *base, void *next_value) { tiny_next_store(base, class_idx, next_value); } ``` **tiny_nextptr.h** (line 44-45, 69-80): ```c static inline size_t tiny_next_off(int class_idx) { return (class_idx == 0) ? 0u : 1u; // C7 → offset = 1 ✓ } static inline void tiny_next_store(void* base, int class_idx, void* next) { size_t off = tiny_next_off(class_idx); // C7 → off = 1 if (off == 0) { *(void**)base = next; return; } // off == 1: C7はここを通る uint8_t* p = (uint8_t*)base + off; // p = base + 1 = user pointer! memcpy(p, &next, sizeof(void*)); // Write next at user pointer } ``` ### 期待される動作(C7 freelist中) Memory layout(C7 freelist中): ``` Address: base base+1 base+9 base+2048 ┌────┬──────────────┬───────────────┬──────────┐ Content: │ ?? │ next (8B) │ (unused) │ │ └────┴──────────────┴───────────────┴──────────┘ header ← ここにnextを格納(offset=1) ``` - `base`: headerの位置(freelist中は破壊されてもOK - C0と同じ) - `base + 1`: next pointerを格納(user dataの先頭8バイトを使用) ### 問題の仮説 **仮説1: header restoration logic** `tls_sll_box.h` line 176: ```c if (class_idx != 0 && class_idx != 7) { // C7はここに入らない → header restorationしない ... } ``` C7はC0と同様に「freelist中はheaderを潰す」設計だが、`tiny_nextptr.h`では: - C0: `offset = 0` → base[0]からnextを書く(header潰す)✓ - C7: `offset = 1` → base[1]からnextを書く(header保持)❌ **矛盾!** **これが根本原因**: C7は「headerを潰す」前提(offset=0)だが、現在は「headerを保持」(offset=1)になっている。 ## 修正案 ### Option A: C7もoffset=0に戻す(元の設計に従う) **tiny_nextptr.h** line 44-45を修正: ```c static inline size_t tiny_next_off(int class_idx) { // Class 0, 7: offset 0 (freelist時はheader潰す) // Class 1-6: offset 1 (header保持) return (class_idx == 0 || class_idx == 7) ? 0u : 1u; } ``` **理由**: - C7 (2048B total) = [1B header] + [2047B payload] - Next pointer (8B)はheader位置から書く → payload = 2047B確保 - Header restorationは allocation時に行う(HAK_RET_ALLOC) ### Option B: C7もheader保持(現在のoffset=1を維持し、restoration追加) **tls_sll_box.h** line 176を修正: ```c if (class_idx != 0) { // C7も含める // All header classes (C1-C7) restore header during push ... } ``` **理由**: - 統一性:全header classes (C1-C7)でheader保持 - Payload: 2047B → 2039B (8B next pointer) ## 推奨: Option A **根拠**: 1. **Design Consistency**: C0とC7は「headerを犠牲にしてpayload最大化」という同じ設計思想 2. **Memory Efficiency**: 2047B payload維持(8B節約) 3. **Performance**: Header restoration不要(1命令削減) 4. **Code Simplicity**: 既存のC0 logicを再利用 ## 実装手順 1. `core/tiny_nextptr.h` line 44-45を修正 2. Build & test with C7 (1024B) allocations 3. Verify no TLS_SLL_POP_INVALID errors 4. Verify `last_push` addresses are even (base pointers) ## 期待される結果 修正後: ``` # 100K iterations, no errors Throughput = 25-30M ops/s (current: 1.5M ops/s with corruption) ```