Files
xenia-rs/audit-runs/phase-c7-XamTaskCloseHandle/broad-impact.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

3.0 KiB

Phase C+7 XamTaskCloseHandle — broad-impact summary

Per-chain first-divergence map (pre vs post)

chain pre-fix (C+7 keSetEvent) post-fix category
tid=6 → 1 (main) 102158 XamTaskCloseHandle rv=0 vs 1 102164 KeResetEvent rv=0 vs 1 ADVANCED (+6)
tid=4 → 11 — (no divergence in 9-event window) unchanged
tid=7 → 2 — (no divergence in 29-event window) unchanged
tid=12 → 7 2 KeWaitForSingleObject rv=0 vs 258 2 (same) persisted
tid=14 → 9 39 RtlEnterCS vs XAudio 39 (same) persisted
tid=15 → 10 unchanged
  • Resolved: 1 (XamTaskCloseHandle at 102158)
  • Advanced: 1 (main chain progressed +6 events)
  • Persisted: 2 (KeWait=258 on tid=12→7, XAudio on tid=14→9)
  • NEW: 0 (the new tid=6→1 divergence at idx 102164 is KeResetEvent — same class as KeSetEvent already known to be deferred per C+7 memo)

XamTaskCloseHandle call-site verification

Only 1 invocation appears within the 50M Phase A window in both engines:

# tid (c→o) idx canary rv pre-fix ours rv post-fix ours rv match?
1 6→1 102158 1 0 1 YES

Both engines emit the same 3-event sequence (import.call, kernel.call, kernel.return) at idx 102156-102158 in their respective tids.

Handle-table state delta

Pre-fix: XamTaskCloseHandle(handle) was a no-op (stub_success) — handle remained in state.objects with refcount unchanged. Subsequent reuse of the handle value would have aliased to the same Thread object indefinitely.

Post-fix: xam_task_close_handle decrements the per-handle refcount and drops the object when it hits 0, mirroring canary's ObjectTable::ReleaseHandle. No leaks; no double-frees (the function short-circuits to return 0 on unknown handle, matching canary's X_STATUS_INVALID_HANDLE branch).

Reading-error class

No new class. C+7's #28 (canary source-of-truth) was re-applied as discipline — and this time the framing held (C+6½'s "calls NtClose, returns 1" claim was accurate). Confirms #28 as a routine check, not a one-off lesson.

Deferred-item interaction check

NONE triggered. Heap region (C+2), clock (Stage 2), audio host-pump, KeSetEvent semantics — all untouched.

Cascade outcome

  • A=framing verified: DONE
  • B=fix landed: DONE (~158 LOC, 1 file, scope held)
  • C=main chain advances: DONE (+6)
  • D=clean re-validation: DONE (all gates pass)
  • E=no escalation needed: DONE

Next target (Phase C+8)

Main chain (tid=6 → tid=1) at idx 102164: KeResetEvent return_value=0 vs 1.

Per C+7's memo:

ke_reset_event left as-is (also returns prior, would mismatch canary's hardcoded return 1 in XEvent::Reset if exercised, but KeResetEvent does not appear in any current Phase A first-divergence — defer).

Defer is now consumed; KeResetEvent has surfaced. Same fix pattern as C+7 KeSetEvent: read canary's XEvent::Reset body, mirror it, add unit tests. ~10-20 LOC body fix.