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:
parent
4be9c25519
commit
942b5945d1
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue