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

9.4 KiB
Raw Blame History

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.