mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
kernel: do not release a waiter on a zero-count syncOnAddress wake (linux only) (#168)
* kernel: do not release a waiter on a zero-count syncOnAddress wake sceKernelSyncOnAddressWake with a count of 0 must release no waiters. On Linux it released exactly one. WakeLinux passes the count straight to FUTEX_WAKE, which does not treat 0 as "wake nobody": the kernel's wake loop tests `if (++ret >= nr_wake) break` after waking a waiter, so any waiter present is released before the loop can break. A standalone futex program confirms it -- FUTEX_WAKE with val = 0 returns 1, and the waiter observes its wait return 0 with the word unchanged. WakePortable already short-circuits count == 0, so the two backends of the same ABI disagreed, with only the Linux one wrong. TestWakeZeroIsNoOp in SyncOnAddressTests covers exactly this and fails on Linux without the fix (15 consecutive failures on the assertion "zero-count wake releases no waiters"); with the fix the suite passes 15 consecutive runs. * kernel: shorten zero-count futex comment --------- Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
@@ -119,6 +119,11 @@ int WaitLinux(volatile T* address, T expected, const uint32_t* timeout_micros,
|
||||
}
|
||||
|
||||
int WakeLinux(volatile void* address, int32_t count) {
|
||||
// The legacy FUTEX_WAKE path may wake one waiter when count is zero.
|
||||
if (count == 0) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
const auto result = syscall(SYS_futex, const_cast<void*>(address), FUTEX_WAKE_PRIVATE, count,
|
||||
nullptr, nullptr, 0);
|
||||
return result < 0 ? KERNEL_ERROR_EINVAL : OK;
|
||||
|
||||
Reference in New Issue
Block a user