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.
This commit is contained in:
Hussein Kadhim 2026-10-11 19:58:37 +03:00 committed by MarcZX100
parent 4be9c25519
commit 942b5945d1
2 changed files with 23 additions and 7 deletions

View File

@ -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<std::uint64_t>(rqtp->tv_sec) * 1000000000ULL +
static_cast<std::uint64_t>(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;

View File

@ -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);
}