Files
xenia-rs/audit-runs/phase-nonmatch-investigation/canary-tid-profiles.md
MechaCat02 ef93a4fa14 handoff: VSync/event-wedge fixes + iterate 2.A–2.BC research notes
Source changes (dormant parity infra, retained from iterate 2.AI/2.AO):
- xenia-kernel/exports.rs: nt_create_event manual_reset polarity +
  related event wiring
- xenia-gpu/mmio_region.rs: D1MODE_VBLANK_VLINE_STATUS hardcode parity

Also lands the audit-runs/ analysis notes (.md/.txt/.json digests) for the
iterate 2.x VSync/0x10e8/0x1004 wedge investigation. Raw trace dumps
(.jsonl/.gz/.csv/.stdout) and agent worktrees (.claude/) are gitignored as
regenerable local artifacts — see memory + HANDOFF for the running findings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 07:19:08 +02:00

121 lines
9.4 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.
# Canary tid-profile catalogue (Phase Non-match Investigation, 2026-05-19)
Source: `xenia-canary/build-cross/bin/Windows/Debug/canary-jitter-1.jsonl`
(4.4 GB, 18,687,353 events, 28 tids, ~90 s wallclock cold run, jitter-1 sample).
## Per-tid headline
| tid | events | role | first kind | first host_ns | thread.exit |
|----:|-------:|------|------------|--------------:|:-----------:|
| 0 | 12 | bootstrap (`schema_version`) | schema_version | 400 | - |
| 1 | 69k | system (no spawn match) | import.call | 2.160 s | - |
| 2 | 20k | NtSetEvent service (13,536 ×) | - | 1.681 s | - |
| 4 | 196k | **XAudio submitter** (26,124 × XAudioSubmitRenderDriverFrame) | - | 1.813 s | - |
| 6 | 477k | **GUEST MAIN** (Sylpheed main) | - | 0.660 s | - |
| 7 | 32 | one-shot init (CreateSymbolicLink, ExRegisterTitleTerminate) | - | 1.422 s | - |
| 8 | 60 | small worker (spawned by tid=6, entry `0x82181830`) | - | 1.426 s | - |
| 9 | 8.3k | file-IO worker (NtCreateFile/NtOpenFile/NtSetInformationFile, entry `0x8245A5D0`) | - | 1.445 s | - |
| 10 | 63k | helper (NtCreateEvent/NtCreateSemaphore + ExCreateThread × 2; entry `0x82450A28`) | - | 1.453 s | - |
| 11 | 61k | NtWaitForMultipleObjectsEx (13,564 ×), entry `0x82457EF0` | - | 1.542 s | - |
| 12 | 37k | KeWaitForSingleObject (7,380 ×), entry `0x824CD458` | - | 1.602 s | - |
| 13 | 594k | **Renderer** (12,092 × VdGetSystemCommandBuffer + VdSwap), entry `0x822F1EE0` | - | 1.671 s | - |
| 14 | **6.15 M** | **XAudio voice-mask poll** (26,126 × XAudioGetVoiceCategoryVolumeChangeMask + KeReleaseSemaphore + KeWaitForSingleObject; 941,976 × IRQL raise/lock/release/lower triplets), entry `0x824D2878` (aff=16) | - | 1.727 s | - |
| 15 | **4.78 M** | **XAudio sister** (786,872 × IRQL raise; 26,126 × KeWaitForSingleObject; light KeSetEvent), entry `0x824D2940` (aff=32) | - | 1.728 s | - |
| 16 | 1.80 M | **XMA decoder / XMACreateContext** (196,976 × RtlEnterCS, 12,072 × NtWaitForSingleObjectEx), entry `0x82178950` | - | 1.932 s | - |
| 17 | 4.1k | helper (spawns tid=18 via `0x821C4AD0`), entry `0x821748F0` | - | 1.938 s | exit @ 2.092 s, code=0 |
| 18 | 33k | helper (RtlInitAnsi, NtCreateFile, NtDuplicateObject; spawns 2× `0x822C6870`), entry `0x821C4AD0` | - | 1.959 s | exit @ 2.870 s, code=1 |
| 19,20 | 9 each | tiny short-lived threads (RtlEnterCS + NtWaitForSingleObjectEx) | - | 1.962/1.963 s | - |
| 21 | 1.00 M | **NtWaitForMultipleObjectsEx worker** (223,636 ×), entry `0x824563E0` | - | 2.103 s | - |
| 22 | 51 | tiny worker (entry `0x82170430`) | - | 2.120 s | - |
| 23 | 17 | tiny (entry `0x823DDE30`) | - | 2.144 s | - |
| 24,25 | 8 each | tiny (entry `0x823DDB50`) | - | 2.145/2.146 s | - |
| 26 | 6.7k | helper-second-call of `0x821748F0` (NtYieldExecution × 1,282), entry `0x821748F0` | - | 10.080 s | exit @ 10.280 s, code=0 |
| 27 | 36k | **sub_825070F0 worker 1** (entry `0x82506558`, ctx `0xBCE251C0`, slot 36 of dispatcher vtable) | - | 10.707 s | - |
| 28 | **3.26 M** | **sub_825070F0 worker 0** (entry `0x82506528`, ctx `0xBCE251C0`, slot 35; 1.07 M × RtlEnterCS, 530 × NtReadFile) | - | 10.707 s | - |
| 29 | 91k | **sub_825070F0 worker 2** (entry `0x82506588`, ctx `0xBCE251C0`, slot 37; 7,252 × KeWait + heavy IRQL) | - | 12.375 s | - |
| - | - | **sub_825070F0 worker 3 (`0x825065B8`) NEVER STARTED** in this 90 s window | - | - | - |
## Spawn chain (chronological)
All `thread.create` events are emitted on the parent thread (per `event_log.cc:312-326`); `parent_tid` in payload duplicates the `tid` field.
| host_ns | spawner | entry_pc | ctx_ptr | aff | stk | susp | child tid | notes |
|--------:|--------:|---------:|--------:|----:|----:|:----:|----------:|-------|
| 1.425 s | 6 | `0x82181830` | `0x828F3D08` | 0 | 131,072 | F | 8 | first guest spawn |
| 1.444 s | 6 | `0x8245A5D0` | `0x828F4838` | 0 | 65,536 | F | 9 | file IO |
| 1.453 s | 6 | `0x82450A28` | `0x828F3B68` | 0 | 262,144 | F | 10 | helper |
| 1.542 s | 10 | `0x82457EF0` | `0x828F3B08` | 0 | 65,536 | F | 11 | tid=10 spawns tid=11 |
| 1.601 s | 6 | `0x824CD458` | `0xBE56BB3C` | 4 | 32,768 | F | 12 | KeWait worker |
| 1.670 s | 6 | `0x822F1EE0` | `0xBCE24A40` | 0 | 524,288 | **T** | 13 | renderer |
| 1.726 s | 6 | `0x824D2878` | `0x00000000` | 16 | 524,288 | **T** | 14 | **XAudio (huge)** |
| 1.727 s | 6 | `0x824D2940` | `0x00000000` | 32 | 524,288 | **T** | 15 | XAudio sister |
| 1.931 s | 6 | `0x82178950` | `0x828F3EC0` | 0 | 65,536 | F | 16 | XMA decoder |
| 1.935 s | 6 | `0x821748F0` | `0xBC365620` | 0 | 524,288 | **T** | 17 | spawner of 18 |
| 1.958 s | 17 | `0x821C4AD0` | `0xBCA44B60` | 0 | 65,536 | F | 18 | tid=17 spawns tid=18 |
| 1.962 s | 18 | `0x822C6870` | `0x828F3300` | 0 | 196,608 | **T** | 19 | tid=18 spawns 19 |
| 1.962 s | 18 | `0x822C6870` | `0x828F3300` | 0 | 196,608 | **T** | 20 | tid=18 spawns 20 |
| 2.103 s | 6 | `0x824563E0` | `0x828F3E70` | 0 | 16,384 | F | 21 | NtWaitForMultipleObjectsEx worker |
| 2.120 s | 6 | `0x82170430` | `0x828F4070` | 0 | 65,536 | F | 22 | tiny |
| 2.143 s | 6 | `0x823DDE30` | `0x828F3C4C` | 0 | 65,536 | F | 23 | tiny |
| 2.144 s | 6 | `0x823DDB50` | `0x828F3C88` | 0 | 524,288 | **T** | 24 | tiny |
| 2.145 s | 6 | `0x823DDB50` | `0x828F3C88` | 0 | 524,288 | **T** | 25 | tiny |
| 10.079 s | 6 | `0x821748F0` | `0xBC366EE0` | 0 | 524,288 | **T** | 26 | repeat of earlier spawn (different ctx) |
| **10.383 s** | **6** | **`0x82506528`** | **`0xBCE251C0`** | **0** | **65,536** | **T** | **28** | **sub_825070F0 worker 0** |
| **10.383 s** | **6** | **`0x82506558`** | **`0xBCE251C0`** | **0** | **65,536** | **T** | **27** | **sub_825070F0 worker 1** |
| **10.384 s** | **6** | **`0x82506588`** | **`0xBCE251C0`** | **0** | **65,536** | **T** | **29** | **sub_825070F0 worker 2** |
| **10.384 s** | **6** | **`0x825065B8`** | **`0xBCE251C0`** | **0** | **65,536** | **T** | (none) | **sub_825070F0 worker 3 unresumed** |
The 4 final spawns are **exactly** the AUDIT-058/063-predicted `sub_825070F0` worker batch (per dossier
`xenia-rs/docs/functions/sub_825070F0.md`: worker entries `0x82506528/58/88/B8`).
## Ours's spawn behaviour (Phase W ours-postfix.jsonl)
Ours emits **10 thread.create** events vs canary's **23**. Ours stops after spawn #10 (`0x821748F0` at 1.727 s).
| host_ns | spawner | entry_pc | ctx_ptr | stk | susp |
|--------:|--------:|---------:|--------:|----:|:----:|
| 0.469 s | 1 | `0x82181830` | `0x828F3D08` | 131,072 | F |
| 0.470 s | 1 | `0x8245A5D0` | `0x828F4838` | 65,536 | F |
| 0.471 s | 1 | `0x82450A28` | `0x828F3B68` | 262,144 | F |
| 0.488 s | **5** | `0x82457EF0` | `0x828F3B08` | 65,536 | F |
| 0.495 s | 1 | `0x824CD458` | `0x42453B3C` | 32,768 | F |
| 1.413 s | 1 | `0x822F1EE0` | `0x40D0CA40` | 0 | **T** |
| 1.626 s | 1 | `0x824D2878` | `0x00000000` | 0 | **T** |
| 1.626 s | 1 | `0x824D2940` | `0x00000000` | 0 | **T** |
| 1.727 s | 1 | `0x82178950` | `0x828F3EC0` | 65,536 | F |
| 1.727 s | 1 | `0x821748F0` | `0x4024D640` | 0 | **T** |
After spawn #10, ours **never produces another `thread.create`** in the 50 M-event trace window (~3 s wallclock window per ours's faster clock). The 13 subsequent canary spawns (including the critical 4 `sub_825070F0` workers at 10.38 s) are missing.
Also note ctx-ptr divergence: ours emits `0x42453B3C` / `0x40D0CA40` / `0x4024D640` where canary emits `0xBE56BB3C` / `0xBCE24A40` / `0xBC365620` — these are the same physical RAM offset displayed with different host-side base addresses (`0xBC000000` canary mapping vs ours's `0x40000000` mapping). Not a real divergence.
## XAudio context: `0xBCE251C0`
Search count across the 4.4 GB canary jsonl: **4 occurrences**, all in the 4 `sub_825070F0` worker spawn `ctx_ptr` fields.
Same address in ours-postfix.jsonl: **0 occurrences**. Ours **never allocates the dispatcher object** that lives at this address. Per the dossier, this is the XAudio2 / `XAudio*` master-voice dispatcher object whose vtable is `0x8200A208` (slot 1 → `sub_825070F0`).
## sub_825070F0 vtable dispatch confirmation
Per `sylpheed.db`:
- `sub_825070F0` is at vtable `0x8200A208` slot 1 (anonymous class `ANON_Class_713383D7`).
- It is also at vtable `0x8200A928` slot 1 (a sibling/derived class with the same layout).
- **Zero `vptr_writes` rows** target either `0x8200A208` or `0x8200A928`.
- **Zero `xrefs`** with `target=0x8200A208` or `0x8200A928`.
- **Zero `indirect_dispatch_candidates`** mapping any `bctrl` site to these vtables.
- **Zero instructions** with operand text `200A208` or `200A928` (no lis/addi/lis/ori pair).
This confirms AUDIT-067's "the vtable is installed host-side" assessment: there is no static guest reference that materialises this vtable address. The object pointer must come from a host shim (allocator, `XAudio2*` API wrapper, etc.) or via a TOC-style load that the static analyser doesn't model.
## sub_825070F0 internals (xrefs in `[0x825070F0, 0x825073DC)`)
The function performs four nearly-identical spawn blocks at PCs `0x825071F8 / 0x82507244 / 0x82507290 / 0x825072DC`. Each block:
```
addi rN, r0, 0x82506528 (or +0x30, +0x60, +0x90) ; ref to worker entry
bl sub_824AA388 ; spawn helper (probably wraps ExCreateThread)
bne ... ; success check
... vtable bctrl chains to set up worker state ...
```
So `sub_825070F0` calls `sub_824AA388` 4 times in sequence, each with a different `ANON_Class_713383D7` slot pointer. `sub_824AA388` is the actual ExCreateThread wrapper.