D465 - sceKernelWaitEventFlag blocks on the event-flag condvar rather than being absent
measured - 2026-09-02 (user-directed /loop: overnight oracle-free crunch)
sceKernelWaitEventFlag was never implemented. The
event-flag family had create, poll, set, clear and delete, but not the
blocking wait - so a guest that waits for another
thread to set an event called it against the default stub, read the
placeholder as "not ready", and called it again: 304,583 times, 91% of
PPSA04263's run, spinning where it should have parked. The spin only
became reachable once spawned threads ran at all (D464); before that the
guest never got far enough to wait on one.
The subsystem already had what a blocking wait needs - each
GuestEventFlag carries a Condvar that
event_flag_set notifies. event_flag_wait
(sync) locks the flag's bits, and while the pattern is unmet waits on
that condvar, which releases the bits lock so a setter is never shut out
and re-takes it on wake. all selects AND (every bit) over
OR (any); the mode's clear bits (0x10 all,
0x20 matched) are honoured on success; a NULL timeout waits
indefinitely and a microsecond one uses a deadline so re-checks do not
extend it. It answers as event_flag_poll does - a bad
handle, a timeout, and the matched pattern told apart - and the kernel
shim maps those to ESRCH, ETIMEDOUT and
OK-with-the-pattern-written.
Verified. PPSA04263 went from 332,914 calls to
28,343 (-304,571, exactly the spin), the
guest now parking instead of busy-looping. Blocking is correct even when
it does not advance the fault: the run still ends at the same
int 0x41 guest assert (image+0x196b91a), which
was there behind the spin all along and is a separate, deeper problem -
a guest deciding to abort on some upstream value, the same class as
PPSA21564's wall. A blocked waiter is released by the time limit ending
the process if its event is never set, so a real deadlock costs the
run's clock rather than hanging it.
Marked assumed in its knowledge entry, not because the
blocking is uncertain - it is the standard event-flag semantics - but
because the mode-bit values and the timeout error code are the
documented SCE/FreeBSD ones rather than measured on this target, and the
observed guest waits indefinitely so the timeout path is
unexercised.