Repository navigation
fix(libkernel): defer raises while a thread holds the address-wait lock on Windows - #5756
Merged
oneandonlydean merged 1 commit intoOct 14, 2026
Conversation
10 tasks done
oneandonlydean
force-pushed
the
fix/raise-address-lock-1488
branch
from
October 14, 2026 09:43
cb270d5 to
ba231e9
Compare
oneandonlydean
force-pushed
the
fix/raise-address-lock-1488
branch
from
October 14, 2026 10:03
ba231e9 to
5281378
Compare
oneandonlydean
marked this pull request as ready for review
October 14, 2026 10:38
Open
Merged
12 tasks done
imellag
added a commit
to imellag/AnyPS5
that referenced
this pull request
Oct 24, 2026
…ck on Linux and macOS On Linux and macOS, sceKernelRaiseException runs the guest handler in the target's SIGUSR1 handler wherever the thread was interrupted. A thread interrupted while it held the address-wait lock of sceKernelSyncOnAddressWait, sceKernelSyncOnAddressWake or _umtx_op ran the handler with the lock held, so a handler that waits, as a stop-the-world collector's does, blocked every other thread that waits on or wakes an address. boykopovar#5756 fixed this on Windows. The address-wait lock is now taken under DeliveryDeferral on every host. On POSIX the deferral is a count per thread: while it is raised the SIGUSR1 handler only records the signal, and DeliverDeferred sends it to the thread again once the lock is released. An address waiter waits on its own semaphore (sem_t, a dispatch semaphore on macOS) with the lock released and the deferral lifted, so a raise reaches a thread that waits for an address without a timeout. The address-lock phases of guest_raise_exception now run on every host, with a new phase that raises at a thread in an unbounded address wait.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes #1488. On Windows,
sceKernelRaiseExceptionredirects a thread wherever it was stopped. A thread stopped insidesceKernelSyncOnAddressWake,sceKernelSyncOnAddressWaitor_umtx_opwhile it held the address-wait lock ran the handler with the lock held, so a handler that waits, as a stop-the-world GC handler does, blocked every other thread that waits on or wakes an address. After #1562, LeandroLP23's reproducer in #1488 still blocked 35 of 300 rounds, all insidesceKernelSyncOnAddressWake.The address-wait lock is now taken under the
DeliveryDeferralthat the guest mutex park queues already use (#5429): while it is held the thread's wait count is raised, so a raise queues an APC instead of redirecting the thread. The APC runs in the condition wait, where the lock is released, or after the lock is released on the way out of the call, before it returns to the guest. Nothing is delivered from inside the unlock or between the condition's enqueue and its wait (the points raised in the #4888 review).DeliveryDeferralandDeliverDeferredmove fromTimedWait.cppintoTimedWait.hppfor this.Linux is unchanged: delivery there runs in the target's SIGUSR1 handler and the debt entry for it stays. Other emulator locks can take the same deferral when a case shows up. The Windows
sceKernelRaiseExceptionentry indocs/dev/debt/libkernel.mdnow names the deferred locks.Tested
guest_raise_exception: a guest thread loops onsceKernelSyncOnAddressWake, or on a 20 µssceKernelSyncOnAddressWait; for 100 rounds each the test raises at it, holds the handler, and requires a wake on another address from another thread to return within 500 ms.guest_raise_exceptionpasses on Windows). Test without the fix:guest_raise_exceptionfails on Windows in run 38543474956 (completed failure).ctestexceptagc_driver*: 724 of 724 (6 VideoOut tests skipped, no display). The new phases are Windows only.tools/check_conventions.pyandtools/check_test_registration.pypass.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)