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>
This commit is contained in:
102
audit-runs/phase-c15a-schema-wiring/audit.md
Normal file
102
audit-runs/phase-c15a-schema-wiring/audit.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Phase C+15-α Schema-Wiring Audit (2026-05-14)
|
||||
|
||||
## Phase 1 — Wired/unwired matrix (pre-session)
|
||||
|
||||
| Kind | Canary emits? | Ours emits? | Status (pre) | Priority |
|
||||
|---------------------|---------------|-------------|---------------|----------|
|
||||
| `schema_version` | yes | yes | wired | — |
|
||||
| `import.call` | yes | yes | wired | — |
|
||||
| `kernel.call` | yes | yes | wired (+C+10) | — |
|
||||
| `kernel.return` | yes | yes | wired | — |
|
||||
| `handle.create` | declared | declared | **stubbed** | HIGH |
|
||||
| `handle.destroy` | declared | declared | **stubbed** | HIGH |
|
||||
| `thread.create` | declared | declared | **stubbed** | HIGH |
|
||||
| `thread.exit` | declared | declared | **stubbed** | HIGH |
|
||||
| `wait.begin` | declared | declared | **stubbed** | HIGH |
|
||||
| `wait.end` | declared | declared | **stubbed** | HIGH |
|
||||
| `thread.suspend` | declared | not in API | unwired | LOW |
|
||||
| `thread.resume` | declared | not in API | unwired | LOW |
|
||||
| `vfs.open` | declared | not in API | redundant? | MEDIUM |
|
||||
| `vfs.read` | declared | not in API | high-vol | LOW |
|
||||
| `vfs.close` | declared | not in API | redundant? | MEDIUM |
|
||||
| `mem.write` | declared | not in API | opt-in | LOW |
|
||||
|
||||
## Phase 2/3 — Kinds wired this session
|
||||
|
||||
Wired symmetrically in both engines (cvar-gated default-off):
|
||||
|
||||
- **`handle.create`** — emitted from `KernelState::alloc_handle_for` (ours) /
|
||||
`ObjectTable::AddHandle` (canary). 39+ call sites covered via centralized hook.
|
||||
- **`handle.destroy`** — emitted from `nt_close` + `xam_task_close_handle` (ours) /
|
||||
`ObjectTable::RemoveHandle` (canary).
|
||||
- **`thread.create`** — emitted from `ex_create_thread` (ours) / `ExCreateThread`
|
||||
in `xboxkrnl_threading.cc` (canary). After spawn succeeds.
|
||||
- **`thread.exit`** — emitted from `ex_terminate_thread` (ours) / `XThread::Exit`
|
||||
(canary). Canary's `XThread::Exit` covers both explicit `ExTerminateThread`
|
||||
and implicit thread-entry returns.
|
||||
- **`wait.begin`** — emitted from `nt_wait_for_single_object_ex` +
|
||||
`ke_wait_for_single_object` (ours) / `xeKeWaitForSingleObject` +
|
||||
`NtWaitForSingleObjectEx` (canary).
|
||||
|
||||
Deferred (v1.2):
|
||||
|
||||
- **`wait.end`** — design challenge: wait can park the guest thread, and the
|
||||
wake-status path differs between engines. Sync outcome status is already
|
||||
captured in the immediately-following `kernel.return`. Async wake outcome
|
||||
surfaced in subsequent events.
|
||||
- **`thread.suspend` / `thread.resume`** — low-frequency; defer until needed.
|
||||
- **`vfs.*`** — redundant with `kernel.call` for Nt*File. Skip per schema-v1
|
||||
audit recommendation.
|
||||
- **`mem.write`** — opt-in only (separate cvar); high-volume.
|
||||
|
||||
## Code summary
|
||||
|
||||
### Ours (~140 LOC)
|
||||
|
||||
- `crates/xenia-kernel/src/event_log.rs` — registry + auto helpers
|
||||
(`register_handle_semantic_id`, `lookup_handle_semantic_id`,
|
||||
`forget_handle_semantic_id`, `emit_handle_create_auto`,
|
||||
`emit_handle_destroy_auto`). +85 LOC.
|
||||
- `crates/xenia-kernel/src/objects.rs` — `KernelObject::schema_object_type()`.
|
||||
+14 LOC.
|
||||
- `crates/xenia-kernel/src/state.rs` — `alloc_handle_for` emit hook. +24 LOC.
|
||||
- `crates/xenia-kernel/src/exports.rs` — `nt_close` destroy emit,
|
||||
`ex_create_thread` thread.create emit, `ex_terminate_thread` thread.exit emit,
|
||||
`nt_wait_for_single_object_ex` + `ke_wait_for_single_object` wait.begin emits,
|
||||
+ `decode_timeout_ns` helper. +85 LOC.
|
||||
- `crates/xenia-kernel/src/xam.rs` — `xam_task_close_handle` destroy emit. +14 LOC.
|
||||
|
||||
### Canary (~130 LOC)
|
||||
|
||||
- `src/xenia/kernel/event_log.h` — registry API (`RegisterHandleSemanticId`,
|
||||
`LookupHandleSemanticId`, `ForgetHandleSemanticId`, `EmitHandleCreateAuto`,
|
||||
`EmitHandleDestroyAuto`). +20 LOC.
|
||||
- `src/xenia/kernel/event_log.cc` — per-tid counter map (was per-host-thread
|
||||
`thread_local`; produced duplicate `tid_event_idx` for tid=0 across host
|
||||
threads — a bug in the pre-session implementation), `CurrentTid` non-asserting
|
||||
via new `XThread::TryGetCurrentThread`, registry helpers, auto-emit wrappers.
|
||||
+60 LOC net.
|
||||
- `src/xenia/kernel/xthread.h` + `xthread.cc` — `TryGetCurrentThread` accessor
|
||||
+ `XThread::Exit` thread.exit emit. +12 LOC.
|
||||
- `src/xenia/kernel/util/object_table.cc` — `AddHandle`/`RemoveHandle` hooks
|
||||
+ `SchemaObjectType` mapping. +35 LOC.
|
||||
- `src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc` — `ExCreateThread`
|
||||
thread.create emit, `xeKeWaitForSingleObject` + `NtWaitForSingleObjectEx`
|
||||
wait.begin emits. +30 LOC.
|
||||
|
||||
### Diff tool
|
||||
|
||||
- `tools/diff-events/diff_events.py` — `SKIP_PAYLOAD_FIELDS_BY_KIND` now skips
|
||||
`handle_semantic_id` (cross-engine `creating_tid` differs, so SIDs are
|
||||
engine-local), `parent_tid`, `handles_semantic_ids`, `woken_by_semantic_id`.
|
||||
+6 LOC.
|
||||
|
||||
## Bug found and fixed this session
|
||||
|
||||
**Pre-session bug**: canary's `t_tid_event_idx` was a host-thread-local global,
|
||||
not a tid-keyed counter. When `AddHandle` runs from multiple host threads with
|
||||
tid==0 (boot init + early XThread bootstrap before guest tid is assigned), each
|
||||
host thread had its own counter starting at 0, producing duplicate
|
||||
`tid_event_idx` values within the tid=0 stream. The diff tool rejected the
|
||||
file with "events out of order at index 8". Fixed by replacing the thread_local
|
||||
with a tid-keyed `std::unordered_map` + mutex (matches ours's design).
|
||||
Reference in New Issue
Block a user