From 942b5945d1ec288c826656e2ae391aa73ebd816c Mon Sep 17 00:00:00 2001 From: Hussein Kadhim Date: Sun, 11 Oct 2026 19:58:37 +0300 Subject: [PATCH] fix(libkernel): leave the remaining time untouched when nanosleep completes FreeBSD's kern_clock_nanosleep writes the remaining time only when the sleep is cut short. A completed sleep zeroed rmtp, so nanosleep(&ts, &ts) in a polling loop slept zero time from the second call on. --- core/libs/prx/libkernel/Time/Time.cpp | 10 +++------- core/libs/tests/GuestNanosleep.cpp | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/core/libs/prx/libkernel/Time/Time.cpp b/core/libs/prx/libkernel/Time/Time.cpp index 581e81bb5..adf0e99e4 100644 --- a/core/libs/prx/libkernel/Time/Time.cpp +++ b/core/libs/prx/libkernel/Time/Time.cpp @@ -251,7 +251,7 @@ int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds) { return 0; } -static int SleepForRequest(const KernelTimespec* rqtp, KernelTimespec* rmtp) { +static int SleepForRequest(const KernelTimespec* rqtp) { constexpr int guestFault = 14; constexpr int guestInvalid = 22; if (rqtp == nullptr) return guestFault; @@ -260,20 +260,16 @@ static int SleepForRequest(const KernelTimespec* rqtp, KernelTimespec* rmtp) { CancellableSleep(static_cast(rqtp->tv_sec) * 1000000000ULL + static_cast(rqtp->tv_nsec)); } - if (rmtp != nullptr) { - rmtp->tv_sec = 0; - rmtp->tv_nsec = 0; - } return 0; } int APS5_VABI sceKernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp) { - const int error = SleepForRequest(rqtp, rmtp); + const int error = SleepForRequest(rqtp); return error == 0 ? 0 : SceKernelError(error); } int APS5_VABI nanosleep_nid_postfix(const KernelTimespec* rqtp, KernelTimespec* rmtp) { - const int error = SleepForRequest(rqtp, rmtp); + const int error = SleepForRequest(rqtp); if (error == 0) return 0; *__error_nid_postfix() = error; return -1; diff --git a/core/libs/tests/GuestNanosleep.cpp b/core/libs/tests/GuestNanosleep.cpp index db2e4ee8b..c97b6c1f1 100644 --- a/core/libs/tests/GuestNanosleep.cpp +++ b/core/libs/tests/GuestNanosleep.cpp @@ -85,6 +85,22 @@ static void SleepsForTheRequest(Nanosleep sleep) { Require(MonotonicNanos() - start >= SLEEP_NANOS - EARLY_WAKE_MARGIN_NANOS); } +static void CompletedSleepLeavesTheRemainingTimeAlone(Nanosleep sleep) { + const KernelTimespec request{0, NANOS_PER_MILLISECOND}; + KernelTimespec remaining{7, 9}; + Require(sleep(&request, &remaining) == SCE_OK); + Require(remaining.tv_sec == 7 && remaining.tv_nsec == 9); + KernelTimespec shared = request; + for (int i = 0; i < 3; ++i) { + Require(sleep(&shared, &shared) == SCE_OK); + Require(shared.tv_sec == request.tv_sec && shared.tv_nsec == request.tv_nsec); + } + const KernelTimespec invalid{0, NANOS_PER_SECOND}; + remaining = {7, 9}; + Require(sleep(&invalid, &remaining) != SCE_OK); + Require(remaining.tv_sec == 7 && remaining.tv_nsec == 9); +} + int main() { PosixRejectsInvalidRequests(nanosleep_nid_postfix); PosixRejectsInvalidRequests(_nanosleep_nid_postfix); @@ -97,4 +113,8 @@ int main() { SleepsForTheRequest(nanosleep_nid_postfix); SleepsForTheRequest(_nanosleep_nid_postfix); SleepsForTheRequest(sceKernelNanosleep); + + CompletedSleepLeavesTheRemainingTimeAlone(nanosleep_nid_postfix); + CompletedSleepLeavesTheRemainingTimeAlone(_nanosleep_nid_postfix); + CompletedSleepLeavesTheRemainingTimeAlone(sceKernelNanosleep); }