[iterate-2G] db16cyc spin-hint cooperative yield: unblock title-screen 0x10a0 gate
The silph title state machine (tid13) blocked on event 0x10a0, never signaled. Root: the event's producer chain runs on the silph worker (entry 0x821C4AD0, our tid14), which was starved. tid14 shares a HW slot with a guest spinlock/ barrier participant (sub_824D1328, entry 0x824D2940) that busy-spins on the db16cyc hint `or r31,r31,r31` (encoding 0x7FFFFB78) at 0x824D140C. Under our round-robin lockstep the spinner consumed its whole block every round and starved the co-located tid14 (only 9 progress hits over 200M instr) — so the producer never reached the event-create/duplicate/signal dance the canary oracle performs (handle F80000E8 set by the submitter F8000044 via a duplicated handle). Fix (canary-faithful): recognize the db16cyc spin hint exactly as canary's InstrEmit_orx does (code 0x7FFFFB78 -> DelayExecution) and surface it as a new StepResult::Yield. The scheduler's yield_current() promotes every Ready peer on the slot past STARVE_LIMIT so begin_slot_visit picks one next round, then they reset and the spinner reclaims the slot — fair alternation, no priority inversion, pure function of slot state (deterministic). Result (lockstep, cache-persist, -n 200M): tid14 progresses past its old stall into a real wait; tid13 advances off 0x10a0 to a new event; hub/submitter re-enter their wait loops. imports 280k->592k, packets 124M->164M, swaps 1->2. draws still 0 (the splash's first draw is a further-upstream gate). Determinism preserved (two cold n50m runs byte-identical). n50m golden re-baselined (imports 90296->339766, swaps 1->2; draws unchanged 0). n2m golden unchanged (db16cyc not reached in first 2M). Tests 670/670. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2619,6 +2619,10 @@ fn worker_prologue(
|
||||
|
||||
match result {
|
||||
StepResult::Continue => {}
|
||||
StepResult::Yield => {
|
||||
// db16cyc spin-wait hint (per-instruction path): yield the slot.
|
||||
kernel.scheduler.yield_current();
|
||||
}
|
||||
StepResult::SystemCall => {
|
||||
tracing::warn!("SYSCALL at {:#010x} (hw={})", pc, hw_id);
|
||||
}
|
||||
@@ -2698,6 +2702,11 @@ fn worker_epilogue(
|
||||
|
||||
match result {
|
||||
StepResult::Continue => {}
|
||||
StepResult::Yield => {
|
||||
// db16cyc spin-wait hint: hand the slot to a Ready peer so the
|
||||
// spinner doesn't starve the co-located thread it is waiting on.
|
||||
kernel.scheduler.yield_current();
|
||||
}
|
||||
StepResult::SystemCall => {
|
||||
let last_pc = block.instrs.last().map(|i| i.addr).unwrap_or(pc_before);
|
||||
tracing::warn!("SYSCALL at {:#010x} (hw={})", last_pc, hw_id);
|
||||
@@ -3638,6 +3647,9 @@ fn dispatch_graphics_interrupts(
|
||||
isr_instrs += 1;
|
||||
match r {
|
||||
StepResult::Continue => {}
|
||||
// db16cyc inside the synchronous ISR has no slot to yield —
|
||||
// the ISR runs to completion on the borrowed context.
|
||||
StepResult::Yield => {}
|
||||
StepResult::SystemCall => {
|
||||
tracing::warn!("graphics ISR hit `sc` instruction; aborting");
|
||||
break;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"instructions": 50000003,
|
||||
"imports": 90296,
|
||||
"instructions": 50000000,
|
||||
"imports": 339766,
|
||||
"unimpl": 0,
|
||||
"draws": 0,
|
||||
"swaps": 1,
|
||||
"swaps": 2,
|
||||
"unique_render_targets": 0,
|
||||
"shader_blobs_live": 0,
|
||||
"texture_cache_entries": 0
|
||||
|
||||
Reference in New Issue
Block a user