Skip to content

WMP card 3: land the reschedule-demand bookkeeping without the comparator pull (#1274) - #1276

Merged
drawmeanelephant merged 1 commit into
mainfrom
agent/buffy-wmp3d/wmp3-demand
Sep 14, 2026
Merged

drawmeanelephant merged 1 commit into
mainfrom
agent/buffy-wmp3d/wmp3-demand

Conversation

@drawmeanelephant

Copy link
Copy Markdown
Owner

WMP card 3: the reschedule-demand bookkeeping, without the comparator pull

Split of draft PR #1255 on request. That PR carries the whole reschedule nudge —
the 815 ms → 2.5 ms input-latency win and the defect that kills the SMP boot —
and it cannot merge until #1261 is fixed. This lands the half that changes no
scheduling at all, so something moves while the rest stays parked.

It is not a closing reference for #1252 — the card is not done, and #1261 is
still the blocker on the part that matters.

Closes #1274.

What lands

  • The coalesced reschedule request: push_home_locked (the single
    blocked→ready funnel) records that a rotation is owed; every core-0 rotation
    discharges it at the tail of tick. Four counters (resched_requested,
    resched_requests, resched_coalesced, resched_discharged).
  • Reporting on the timer and wm monitor rows.
  • Two host tests for the coalescing rule, and a live assertion on
    live-wm-pacing that the demand is non-vacuous.

What deliberately does not land

timer.nudge(), the comparator pull, nudge_ticks/nudge_target, the
period_deadline restructure, the period_tick / tick(period_tick) threading,
and #1255's latency bound.

The period_tick threading and the nudge counters were the obvious candidates
for a "safe half", and I left them out on purpose: with nothing armed,
period_tick is trivially true and those counters would be permanently zero,
so they are only "safe" because they would be dead. Shipping unwired scaffolding
for a mechanism that does not exist is not an improvement. What is left is the
one thing that is both safe and live.

Why this half is worth landing on its own

It measures the demand before anything is paid for it. resched_requests
counts wake events that found no rotation already owed — i.e. wakes for which
the 1 Hz period tick is the only thing between the woken task and running.
resched_discharged counts the rotations that served one; a discharge count
below the request count means requests are being stranded, which is a scheduler
bug rather than a pacing observation. It is #1261's timer.nudge() disabled entirely → PASS 2/2 probe made permanent and observable.

Evidence (local class-B, this tree)

live-wm-pacing            PASS 1/1
  M53 pacing OBSERVED: window_ms=28031 present_avg_ms=1274 tick_avg_ms=1001
    ptr_fan=8 lat_n=7 lat_avg_us=778716 lat_max_us=1001334 flush_n=23 flush_max_us=536
  M53 resched demand OBSERVED: requests=17 coalesced=0 discharged=17
live-wnd5-gate2-policy    PASS 2/2     <- the boot the nudge kills; unaffected here
check result
live-wm-pacing PASS 1/1
live-wnd5-gate2-policy PASS 2/2
zig build test rc=0
zig fmt --check clean
inventory-gates --check OK
coordination gate ok

The load-bearing row is the latency: 778.7 ms average, unchanged from the
786–1216 ms range card 1 measured and card 2's 815 ms. The bookkeeping moved no
scheduling. And 17 wake events in a 28 s window each owed a rotation, each
served by the next tick — which is precisely why the latency is one tick.

Honest gaps

  • coalesced=0 on this boot. The coalescing rule is pinned by the host test
    and not exercised by this workload; a wake burst is what would exercise it.
    The counter exists so that a burst shows up, not because it fired here.
  • No source-level "is it wired?" guard test. The obvious one cannot compile —
    @embedFile cannot reach outside the test binary's package path — so the
    wiring is pinned live by the gate instead: deleting the funnel call site reads
    as zero requests, deleting the discharge reads as stranded requests, and both
    fail live-wm-pacing. The comment in scheduler_test.zig says so at the point
    where the guard would have gone.

…ator pull (#1274)

Splits the parked nudge (draft PR #1255, branch box) so the half that changes
NO scheduling lands now, and the half that kills the SMP boot stays parked.

Lands: the coalesced reschedule REQUEST raised from the wake funnel
(`push_home_locked`) and DISCHARGED at the tail of every core-0 rotation, the
four counters behind it, reporting on the `timer` and `wm` monitor rows, two
host tests for the coalescing rule, and a live assertion on `live-wm-pacing`.

Does NOT land, and this is the point of the split: `timer.nudge()`, the
comparator pull, `nudge_ticks`/`nudge_target`, the `period_deadline`
restructure, the `period_tick`/`tick(period_tick)` threading, and the
`live-wm-pacing` latency bound from #1255. The parts of that commit that are
"safe" only because they would be dead (a `period_tick` that is trivially true
with nothing armed, counters that would be permanently zero) are deliberately
excluded: shipping unwired scaffolding for a mechanism that does not exist is
not an improvement.

Why this half is worth landing on its own: it measures the DEMAND the nudge
would serve, before anything is paid for it. `resched_requests` is the number
of times a task became runnable while another was executing -- i.e. the number
of wakes for which the 1 Hz period tick is the only thing standing between the
woken task and running. `resched_discharged` is how many of those the next tick
actually served; a discharge count below the request count means requests are
being stranded, which is a scheduler bug rather than a pacing observation.
This is #1261's `timer.nudge() disabled entirely -> PASS 2/2` probe made
permanent and observable.

Evidence (local class-B VZ, this tree):

  live-wm-pacing        PASS 1/1
    M53 pacing OBSERVED: window_ms=28031 present_avg_ms=1274 tick_avg_ms=1001
      ptr_fan=8 lat_n=7 lat_avg_us=778716 lat_max_us=1001334
      flush_n=23 flush_max_us=536
    M53 resched demand OBSERVED: requests=17 coalesced=0 discharged=17
  live-wnd5-gate2-policy PASS 2/2   <- the boot the nudge kills; unaffected here

The latency is the load-bearing row: 778.7 ms average is unchanged from the
786-1216 ms range card 1 measured and card 2's 815 ms, so the bookkeeping
altered no scheduling. 17 wake events in a 28 s window each owed a rotation and
each was served by the next tick -- which is exactly why the latency is one
tick.

Honest gaps: `coalesced=0` on this boot, so the coalescing rule is pinned by
the host test and NOT exercised by this workload (a wake burst is what would
exercise it). And there is no source-level "is it wired?" guard test -- the
obvious one cannot compile, because `@embedFile` cannot reach outside the test
binary's package path; the wiring is pinned live by the gate's
`resched_requests >= 1` instead. Both are noted at the point of the claim.

Host: `zig build test` rc=0; `zig fmt --check` clean;
`inventory-gates --check` OK; coordination gate ok.

Closes #1274
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

claim: WMP: land the reschedule-demand bookkeeping without pulling the comparator (the safe half of #1255)

1 participant