vsync.rs:
- set_state(animating, dirty) replaces set_animating. The Choreographer
callback chain re-posts while animating||dirty: gating on animating
alone let the chain die during flings (pointer inactivity >200ms) —
with EW disabled the loop then froze (measured: 30 frames in 4s,
then silence). The dirty mirror is pushed every main-loop iteration
(<=8ms stale); the 6ms poll backstop bounds chain-break damage.
- EW_ON now gates the WAKE itself: the early waker raced the
Choreographer (fires at edge+0.52ms measured) and its independent
phase caused the -4..+4ms render-phase wander. Choreographer is the
single wake source.
- MISS lines carry forensics: sw/sn (wake slot vs last rendered slot),
eage (ms since last observed vsync edge), lastage (ms since last
render) — distinguishes chain-stall / loop-stuck / guard-reject /
no-wake-iteration without a second run.
stg.rs:
- ctxsw_sample() reads /proc/self/task/<pid>/stat for voluntary/involuntary
context switches, CONDITIONAL on iteration >5ms (per-iteration procfs
reads were a measured confounder: 20-50us each, pushed phase across
the slot boundary, 10x worse drops). vsw/nvol on the IT line.
- precpu: CPU time inside Queue::present on the PRES line (pre_us >>
precpu = blocked on binder/fence/SF; pre_us ~= precpu = CPU-bound).
wgpu_30_surface.rs: EW_ON moved here (vkprobe) so vsync.rs can gate the
wake without a new crate dependency.
lib.rs: poll backstop uses the dirty state; 6ms cap during active phases.