Merge pull request #12135 from Oscar45397/fix/libkernel-raise-short-sleep

fix(libkernel): deliver raises at the spin that ends a sleep on Windows
This commit is contained in:
Adrià authored and GitHub committed 2026-10-30 17:05:05 +01:00
commit 9304896d89
4 files changed
+95 -9

No files matched your search

+1 -1
View File
@@ -214,7 +214,7 @@
- On macOS the guest runs on a second thread and the main thread serves the main dispatch queue from its run loop: AppKit (SDL's Cocoa windows, Metal surfaces, event pumping and game controllers) only works on the main thread, and a guest never hands its thread back. The macOS entry stub of the relinker starts the guest through `Aps5StartGuest` ([MainThreadMacOs.cpp](../../../core/libs/prx/libkernel/Pthread/src/MainThreadMacOs.cpp)), on a thread with the stack size of the main thread (at least 8 MiB), and the guest ends the process with `exit`; a guest entry that returns aborts. libSceVideoOut sends its SDL calls to the main thread with `Aps5RunOnMainThread` (`OnMainThread` in [MainThread.hpp](../../../core/libs/prx/libSceVideoOut/include/MainThread.hpp)), which waits for them and rethrows their exceptions; a host program that never called `Aps5StartGuest` runs them in place
- On macOS the Rosetta main stack and the stacks of the host threads lie inside the guest arena, where a title can map fixed addresses. `Aps5StartGuest` moves the main thread onto a 16 MiB stack at `0x600000000000`, copies `argv`, `environ`, the program name and the initial block off the old stack, and releases the old stack range to the arena ([MainThreadMacOs.cpp](../../../core/libs/prx/libkernel/Pthread/src/MainThreadMacOs.cpp)). The guest thread and the other host threads still take their stacks from the system, so a title that fixes a mapping over one of those stacks fails with a host region overlap. The move is skipped when the main stack lies outside the arena, when the new stack cannot be placed outside it, and on hosts that are not x86-64
- [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) reaches a thread that waits in an alertable `TimedWait` wait through an APC. A thread blocked anywhere else, including all waits under `APS5_COARSE_TIMED_WAITS` and host waits inside the emulator, is redirected and runs the handler only when that wait returns
- [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) on Windows runs a queued delivery (an APC) in the first alertable wait of libkernel's TimedWait the target enters, or where libkernel drains APCs after releasing its address-wait or park queue lock (both are taken under a delivery deferral). Host code that holds a lock of its own across such a wait keeps it held while a waiting handler runs
- [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) on Windows runs a queued delivery (an APC) in the first alertable wait of libkernel's TimedWait the target enters, or where libkernel drains APCs after releasing its address-wait or park queue lock or after the spin that ends a sleep (each is taken under a delivery deferral). Host code that holds a lock of its own across such a wait keeps it held while a waiting handler runs
- [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) leaves the signal pending on a target thread that was created suspended and is not resumed yet, and delivers it on that thread once it is resumed, before its start routine; further raises while it is pending are merged into that one delivery. FreeBSD 11.4 libthr starts such a thread with every signal but `SIGTRAP` blocked ([`thr_create.c`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libthr/thread/thr_create.c#L177-L183)) and restores its mask only once it is resumed ([`thread_start`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libthr/thread/thr_create.c#L252-L294)), so a signal sent to it stays pending until then. The console's behaviour is unverified
- [sigaltstack](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) records each thread's alternate signal stack and reports it back, following FreeBSD's `kern_sigaltstack` (`EINVAL` for flags other than `SS_DISABLE`, `ENOMEM` below `MINSIGSTKSZ` 2048), but handlers never run on it, so `SS_ONSTACK` and `EPERM` are never reported
- [sigpending](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) reports the intersection of the process-wide pending set of `sigtimedwait` and the blocked mask of `_sigprocmask`, as FreeBSD's `sys_sigpending` intersects the pending list with `td_sigmask`, and returns -1 with `EFAULT` for a null set. PPSA99420 imports it