408. The flip completion had no reader
2026-09-04 - directed, while the Agc probe set is out for hardware
What was done
Picked the largest unimplemented call in the corpus and implemented
it. sceKernelWaitEqueue was 839 calls in
an honest run of PPSA02664 and 12,924 past the shader
wall - two orders of magnitude above anything else, and every one of
them a guest waiting for something nothing posted.
The missing half was the post, not the wait.
sceVideoOutSubmitFlip completed a flip and told nobody,
because sceVideoOutAddFlipEvent was unimplemented and the
registration that would have given the completion a reader was never
recorded. The guest registered, submitted, and then waited on work this
project had already done and never announced.
| before | after | |
|---|---|---|
sceKernelWaitEqueue, honest run |
839 | 605 |
sceKernelWaitEqueue, past the shader wall |
12,924 | 1,127 |
Frames stayed at 1, and that is the honest reading
rather than a disappointment: the guest still stops at the shader wall
in an honest run, and at the fabricated shader object's
+0x30 when a region is planted past it. The frame loop is
unblocked from the event side and still blocked from the Agc side.
Where the layout came from
sceKernelWaitEqueue is kevent(2) and the
kernel is FreeBSD-derived, so struct kevent is citable -
the strongest oracle here, and the reason this was worth doing while Agc
is out for hardware. D524 deferred delivery precisely because the layout
was unknown; it was not unknown, it was unlooked-for.
The size is still open - FreeBSD 12 appends ext[4] and
doubles it to 0x40, leaving every offset unchanged - and the guard says
so, because it is a test the rival passes too.
Two stale facts, and how they were found
D524's reasoning rested on a number that had expired: both
sync.rs and lib.rs said the title "never
waits - called zero times since the flip count stopped lying
(D516)". True when written. The title now creates
four queues, not two, and waits hundreds to thousands
of times a run. The knowledge entry carried the same expiry -
"cannot deliver one, because what a caller reads back is
unknown".
All three corrected. This is the fourth stale-fact find of the day and the pattern is consistent: they are always a number that was measured once and then reasoned from afterwards.
Guards
Seven, each watched failing, a different parameter each time:
filter/flags swapped; data and
udata swapped; posting ignoring registration and
broadcasting; the poster's udata overriding the
registration's; take draining regardless of the request;
take returning newest-first; and every handle looking like
a live queue.
What is deliberately not claimed
The guest ceasing to re-ask is consistency, not
correctness. filter is written as zero because no
lawful source here gives its value, and a real flip completion certainly
has one - a guest branching on it is taking the wrong branch right now
and will say so by where it stops. Putting the flip argument in
data is an assumption too: it is the only per-flip value
the caller supplied and the only field shaped to hold it.
Not blocked on the console
Nothing here waits on the Agc probe results, and nothing here overlaps them - this is libkernel and VideoOut. The one place the two meet is the frame loop, which needs both.