fix(xam): XAMBUG-PRODUCER-001 — XamTaskSchedule spawns a real guest thread

Replaces the no-op stub at xam.rs:204 with a canary-faithful
implementation mirroring xenia-canary/src/xenia/kernel/xam/xam_task.cc:43-80.
Allocates a ThreadImage, allocates a KernelObject::Thread handle, and
routes through Scheduler::spawn with entry=callback and
start_context=message_ptr (canary's third positional XThread ctor arg).
Stack size = max(0x4000, page-aligned 0x10_0000).

Producer-hypothesis outcome (500M --trace-handles-focus run): the call
site at 0x824a9a10 is never reached during this boot horizon, so
XamTaskSchedule cannot be the missing producer for the 3 parked
Event/Manual handles (0x1004, 0x100c, 0x15e4). The fix still lands —
the stub was a real correctness bug that would manifest the moment
the boot advances past the current deadlock. Next candidate per
audit-findings.md: XAudioRegisterRenderDriverClient.

- Workspace tests: 561 → 562 green (new test
  xam::tests::xam_task_schedule_spawns_real_thread).
- --stable-digest -n 100M: instructions=100000002 unchanged from
  baseline; lockstep determinism preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-03 18:32:40 +02:00
parent b54aa48d10
commit 691404e36e
2 changed files with 193 additions and 5 deletions

View File

@@ -3974,3 +3974,50 @@ likely producer-class candidates for next session:
4. **GPUBUG-FETCH-PATCH-001**: re-enable the PM4_TYPE0
fetch-constant patch via a side-channel (GpuCommand variant)
when draws actually start firing — relevant for bloom/blur N+1.
## Producer-hunt session 2026-05-03
### XAMBUG-PRODUCER-001 — XamTaskSchedule was a no-op stub
**Status:** fixed. Hypothesis falsified for the parked-waiter set.
**Site:** `crates/xenia-kernel/src/xam.rs:204` (pre-fix).
**Canary parity:** `xenia-canary/src/xenia/kernel/xam/xam_task.cc:43-80`.
The pre-fix stub allocated a handle, logged it, and returned
`STATUS_SUCCESS` — it never spawned a thread. Replaced with a
canary-faithful implementation: allocates a `ThreadImage`, allocates
a `KernelObject::Thread` handle, and routes through
`Scheduler::spawn` with `entry=callback`, `start_context=message_ptr`
(canary's third positional `XThread` arg). Stack sized as
`max(0x4000, page-aligned 0x10_0000)`.
**Verification:**
- Unit test `xam::tests::xam_task_schedule_spawns_real_thread`
confirms the spawned thread's `pc == callback` and `gpr[3] == message_ptr`.
- Workspace tests: 561 → 562 green.
- `--stable-digest -n 100M` lockstep: `instructions=100000002`
unchanged from baseline (interpreter determinism preserved).
- `--trace-handles-focus=0x1004,0x100c,0x15e4 -n 500M`: no
`kernel.calls{name=XamTaskSchedule}` counter appears — the call
site at `0x824a9a10` is **never reached** within 500M
instructions. Boot stalls earlier on the parked handles.
**Outcome:** the 3 focus handles still show
`signal_attempts=0 (primary=0, ghost=0)` after 500M instructions.
The XAM-task hypothesis is therefore **falsified for this run** —
XamTaskSchedule cannot be the missing producer for these specific
handles, because Sylpheed's only call site to it isn't reached
before the deadlock.
The fix lands regardless: the stub was a real correctness bug that
will manifest the moment the call site is reached (post-deadlock-resolution).
### Recommended next producer candidate
`XAudioRegisterRenderDriverClient` (currently a one-shot stub, called
once per the metric counter). Audio buffer-complete callbacks are a
known signal source on Xbox 360 audio engines; the stub may be
hiding the producer for one of the 3 handles. If that lead is also
falsified, escalate to file I/O completion (`signal_io_completion_event`
already real but possibly mis-routed) or Timer DPC delivery.