DRAFT / BLOCKED (#1261): WMP card 3 reschedule nudge — 815 ms -> 2.5 ms, blocked by a silent VM death on the WM dui path - #1255
drawmeanelephant wants to merge 1 commit into
Conversation
… by an SMP starvation defect Parked WIP, not a merge candidate. This is the card-3 (#1252) reschedule nudge as it stood when it measured 815 ms -> 2.5 ms average input-to-present on live-wm-pacing, kept on a branch so the finding stays reproducible rather than living only in an issue comment. Mechanism: the wake funnel (push_home_locked) raises a coalesced reschedule request; scheduler.request_resched_for(id) pulls core 0's comparator forward ~2 ms via timer.nudge so the SAME IRQ rotation a period tick uses serves the owed preemption. timer.handle() now reports whether the PPI was the 1 Hz period boundary and scheduler.tick(period_tick) gates on_tick (tick_count, sleepers, app timers, WM pacing, CPU accounting) on it, so a nudge does not advance the wall clock and every 1 Hz assumption keeps its meaning. Why it is not shipped: an extra core-0 context switch starves the SMP NOTEPAD boot (live-wnd5-gate2-policy, PASS 3/3 on main -> FAIL 0/4, ending in VZVirtualMachine.State.error with heartbeats exact and the WM still presenting). Seven probes bisect it; the win and the breakage are the same mechanism, and every variant that keeps the win breaks the boot. Full table and defect list are on issue #1252. Known defects in THIS revision: timer.arm() still writes the shared period_deadline global from every core (core 1 clobbers core 0's deadline); the targeted-handoff / in-tick-arm discrimination is not here. Refs #1252
6701c1d to
bc89e9c
Compare
Verification record (this is the comment that was promised hours ago and never landed)Re-verified the branch head The PR was one merge away from closing the card it says it doesn't closeLine 4 of the original body read:
GitHub's closing-keyword parser matches the literal substring Fixed by rewording the sentence; Also corrected while I was in there:
What is unchanged and still true
The reproduction is pinned by the branch, not by this PR staying open: The blocker's diagnosis, correctedInstrumented boots on the nudge tree (local class-B, on
Full measurements, including the two defects I found in my own instrument, are on #1261. |
Split landed: the pull-free half is #1276This PR is now explicitly two halves, and the safe half has its own home. Landed separately as #1276 ( Live evidence from that tree, both gates local class-B: The latency row is the one that matters for this PR: 778.7 ms average, unchanged from card 1's 786–1216 ms range and card 2's 815 ms, while 17 wakes in a 28 s window each owed a rotation and each was served by the next tick. That is the What stayed here, deliberately: So this PR is unchanged in substance and still the reproduction it says it is. Its remaining content is the comparator pull and the 815 → 2.5 ms measurement, blocked on #1261. The delay between the two halves is now measurable in the open rather than asserted: #1274 counts the demand, and this PR is the thing that would serve it. |
DRAFT / WIP — parked, not a merge candidate
Reproduction artifact for #1252 (WMP card 3, the reschedule nudge). It is not
a closing reference for that card and is not intended to merge as-is.
Read this first: the branch head is knowingly red on
live-wnd5-gate2-policy(PASS 3/3onmain→FAIL 0/4). That is thefinding, not an oversight — see below.
The result this branch exists to reproduce
Same
live-wm-pacingspec, running the latency bound the fix earned:main(card 2, #1250)live-sb6-perf-payoff(the 1 Hz determinism gate) was green throughout, so the"repair every 1 Hz assumption" half of the card genuinely holds.
Mechanism
The wake funnel (
push_home_locked) raises a coalesced reschedule request;scheduler.request_resched_for(id)pulls core 0's comparator forward ~2 msvia
timer.nudge(), so the same IRQ rotation a period tick uses serves the owedpreemption. A nudge is deliberately not a second:
timer.handle()nowreturns whether the PPI was the 1 Hz period boundary, and
scheduler.tick(period_tick)gateson_tick(tick_count, sleepers, app timers,WM pacing, CPU accounting) on it — so
sys_sleep(1),heartbeat_every, SB6'sone-tick-per-frame determinism and CPU-limit accounting keep their 1 Hz meaning.
Why it is not shipped — seven probes
live-wnd5-gate2-policy(WND + NOTEPAD,duiorientation chords) goes fromPASS 3/3onmaintoFAIL 0/4. The guest does not fault — no[EXC] parking:, heartbeats exact — the WM keeps presenting while the shellstops completing
duicommands, and the boot dies inVZVirtualMachine.State.error(state=3).Corrected (see the status note above and #1261): "starvation" was the wrong
word for it. The staging backlog is survivable — 489,187 lines over 120 s with a
healthy guest — and the fatal event is the WM
duipath itself, which ends theVM without taking a synchronous exception the kernel can report. The seven-probe
table below still stands; only the name of the blocker was wrong.
timer.nudge()disabled entirelyon_tickThe last row is decisive: suppressing the wakes that arrive inside the tick's
own beat (
wm_server.on_tick, the WM's kind-18 delivery) fixes the boot andtakes
resched_requestsfrom 32 to 1 — it removes exactly the handoffs thatproduced the 2.5 ms. The win and the breakage are the same mechanism, and no
subset keeps one without the other.
Two traps for the next attempt
Both look like progress.
6/7 purely because the target was being cleared before delivery — it was a
nudge with no rotation, measuring 807 ms.
the period tick, so a rotation-based discharge cleared the handoff the same
beat had just armed — visible as
handoff_attempts=1out ofnudge_served=16.Defects specific to this revision
timer.arm()still writes the sharedperiod_deadlineglobal from everycore, so core 1 clobbers core 0's deadline. (Fixed on the abandoned working
tree; not in this commit.)
Evidence
zig build test— 172/172 steps, 3441/3441 tests passed;zig buildrc=0;zig fmt --checkclean;inventory-gates --checkOK.just verify-vz).History note
This branch was refreshed: it previously carried two raw
git stashcommits(
On agent/buffy/wmp3-resched-nudge: …/index on …) pushed straight from astash, and a stale
docs/gate-fleet-inventory.mdline that would have revertedmain. It is now one commit on top of currentmain, with the inventoryre-rendered rather than reverted.