From d94c409f1f29ebb3490d3f541c82835559a936f1 Mon Sep 17 00:00:00 2001 From: Evrim Cicek Date: Sun, 25 Oct 2026 22:04:09 +0300 Subject: [PATCH] fix(libkernel): wait for sigtimedwait timeouts with the precise timed wait on Windows --- .../libs/prx/libkernel/System/src/Signals.cpp | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/core/libs/prx/libkernel/System/src/Signals.cpp b/core/libs/prx/libkernel/System/src/Signals.cpp index 9ea06b2e2a..25047dd7f7 100644 --- a/core/libs/prx/libkernel/System/src/Signals.cpp +++ b/core/libs/prx/libkernel/System/src/Signals.cpp @@ -5,6 +5,7 @@ #include "prx/libc/include/JumpBuffer.hpp" #include "prx/libkernel/Pthread/Posix/Common.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" +#include "prx/libkernel/Time/include/TimedWait.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -109,7 +110,7 @@ bool SignalBlocked(int guest) { struct PendingSignals { std::mutex lock; - std::condition_variable changed; + TimedWait::Condition changed; std::atomic words[4]{}; }; @@ -126,7 +127,7 @@ void MarkPending(int guest) { std::lock_guard lock(pending.lock); pending.words[SignalWord(guest)].fetch_or(SignalBit(guest), std::memory_order_relaxed); } - pending.changed.notify_all(); + pending.changed.NotifyAll(); } bool TakePending(int guest) { @@ -305,19 +306,24 @@ void DeliverUnblockedPending() { } } +std::optional SignalWaitDeadline(const KernelTimespec& timeout) { + if (timeout.tv_sec > INT32_MAX) return std::nullopt; + const std::uint64_t now = TimedWait::NowNanos(); + if (timeout.tv_sec < 0) return now; + return now + static_cast(timeout.tv_sec) * 1000000000ULL + static_cast(timeout.tv_nsec); +} + int WaitForPendingInSet(const GuestSignalSet& set, bool waitForever, const KernelTimespec* timeout, int* guest) { auto& pending = Pending(); std::unique_lock lock(pending.lock); - std::optional deadline; + const std::optional deadline = waitForever ? std::nullopt : SignalWaitDeadline(*timeout); for (;;) { if (PendingInSet(set, guest)) return 0; - if (waitForever) { - pending.changed.wait(lock); + if (!deadline) { + pending.changed.Wait(lock); continue; } - if (!deadline) deadline = std::chrono::steady_clock::now() + std::chrono::seconds(timeout->tv_sec) + - std::chrono::nanoseconds(timeout->tv_nsec); - if (pending.changed.wait_until(lock, *deadline) == std::cv_status::no_timeout) continue; + if (pending.changed.WaitUntil(lock, *deadline)) continue; return PendingInSet(set, guest) ? 0 : GuestEagain; } } @@ -336,7 +342,7 @@ void WaitForDeliverableSignal() { { std::unique_lock lock(pending.lock); if (!TakePendingUnblocked(&guest)) { - pending.changed.wait(lock); + pending.changed.Wait(lock); continue; } }