diff --git a/core/libs/prx/libc/src/Threads.cpp b/core/libs/prx/libc/src/Threads.cpp index b1d85f9fafe0..a5cc18181298 100644 --- a/core/libs/prx/libc/src/Threads.cpp +++ b/core/libs/prx/libc/src/Threads.cpp @@ -246,7 +246,8 @@ int APS5_VABI _Cnd_timedwait_nid_postfix(void** conditionHandle, void** mutexHan bool timeout = false; try { const auto deadlineTime = std::chrono::system_clock::time_point( - std::chrono::seconds(deadline.tv_sec) + std::chrono::nanoseconds(deadline.tv_nsec)); + std::chrono::seconds(deadline.tv_sec) + + std::chrono::ceil(std::chrono::nanoseconds(deadline.tv_nsec))); timeout = (condition->native.wait_until(lock, deadlineTime) == std::cv_status::timeout); } catch (const std::system_error&) { lock.release(); diff --git a/core/libs/tests/GuestLibcCndTimedWait.cpp b/core/libs/tests/GuestLibcCndTimedWait.cpp index 07bb8719c35a..467d2e6ed51e 100644 --- a/core/libs/tests/GuestLibcCndTimedWait.cpp +++ b/core/libs/tests/GuestLibcCndTimedWait.cpp @@ -99,6 +99,26 @@ int main() { } signaler.join(); + constexpr std::int64_t farSeconds = 10000000000; + const Xtime farTime{farSeconds, 999999999}; + constexpr auto clockSeconds = std::chrono::duration_cast(std::chrono::system_clock::duration::max()).count(); + if (farSeconds < clockSeconds) { + bool farReady = false; + std::thread farSignaler([&] { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + Require(_Mtx_lock_nid_postfix(&mutex) == success); + farReady = true; + Require(_Cnd_broadcast_nid_postfix(&condition) == success); + Require(_Mtx_unlock_nid_postfix(&mutex) == success); + }); + while (!farReady) { + Require(_Cnd_timedwait_nid_postfix(&condition, &mutex, &farTime) == success); + } + farSignaler.join(); + } else { + RequireThrows([&] { _Cnd_timedwait_nid_postfix(&condition, &mutex, &farTime); }); + } + Require(_Mtx_unlock_nid_postfix(&mutex) == success); RequireThrows([&] { _Cnd_timedwait_nid_postfix(&condition, &mutex, nullptr); }); const Xtime overflowCarryTime{std::numeric_limits::max(), 1000000000};