From fb789b52bab197994f1f0b900ca3231a7d04cc81 Mon Sep 17 00:00:00 2001 From: fincs Date: Fri, 14 Dec 2018 17:59:54 +0100 Subject: [PATCH] Synchronize eventWait and _waitLoop code --- nx/source/kernel/event.c | 22 +++++++++++++--------- nx/source/kernel/wait.c | 39 ++++++++++++++++++--------------------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/nx/source/kernel/event.c b/nx/source/kernel/event.c index 1b354001..29c378c5 100644 --- a/nx/source/kernel/event.c +++ b/nx/source/kernel/event.c @@ -30,30 +30,34 @@ void eventLoadRemote(Event* t, Handle handle, bool autoclear) Result eventWait(Event* t, u64 timeout) { Result rc; + bool has_timeout = timeout != UINT64_MAX; u64 deadline = 0; if (t->revent == INVALID_HANDLE) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (timeout != U64_MAX) + if (has_timeout) deadline = armGetSystemTick() + armNsToTicks(timeout); // timeout: ns->ticks do { do { - s64 this_timeout = -1; - if (deadline) { - this_timeout = deadline - armGetSystemTick(); - this_timeout = armTicksToNs(this_timeout >= 0 ? this_timeout : 0); // ticks->ns + u64 this_timeout = UINT64_MAX; + if (has_timeout) { + s64 remaining = deadline - armGetSystemTick(); + this_timeout = remaining > 0 ? armTicksToNs(remaining) : 0; // ticks->ns } rc = svcWaitSynchronizationSingle(t->revent, this_timeout); - if (deadline && (rc & 0x3FFFFF) == 0xEA01) - return rc; // timeout. - } while (R_FAILED(rc)); + if (has_timeout && R_VALUE(rc) == KERNELRESULT(TimedOut)) + return rc; + } while (R_VALUE(rc) == KERNELRESULT(Cancelled)); + + if (R_FAILED(rc)) + break; if (t->autoclear) rc = svcResetSignal(t->revent); - } while ((rc & 0x3FFFFF) == 0xFA01); + } while (R_VALUE(rc) == KERNELRESULT(InvalidState)); return rc; } diff --git a/nx/source/kernel/wait.c b/nx/source/kernel/wait.c index fdc7b305..bc5ac261 100644 --- a/nx/source/kernel/wait.c +++ b/nx/source/kernel/wait.c @@ -145,39 +145,36 @@ clean_up: return rc; } -static Result _waitLoop(WaitImplFunc wait, s32* idx_out, void* objects, size_t num_objects, u64 timeout) +static Result _waitLoop(s32* idx_out, void* objects, size_t num_objects, u64 timeout, WaitImplFunc waitfunc) { Result rc; + bool has_timeout = timeout != UINT64_MAX; + u64 deadline = 0; + + if (has_timeout) + deadline = armGetSystemTick() + armNsToTicks(timeout); // timeout: ns->ticks + do { - u64 cur_tick = armGetSystemTick(); - rc = wait(idx_out, objects, num_objects, timeout); - rc = R_VALUE(rc); - - if (rc == KERNELRESULT(Cancelled)) { - // On timer stop/start an interrupt is sent to listeners. - // It means the timer state has changed, and we should restart the wait. - - // Adjust timeout.. - if (timeout != -1) { - u64 time_spent = armTicksToNs(armGetSystemTick() - cur_tick); - - if (time_spent < timeout) - timeout -= time_spent; - else - rc = KERNELRESULT(TimedOut); - } + u64 this_timeout = UINT64_MAX; + if (has_timeout) { + s64 remaining = deadline - armGetSystemTick(); + this_timeout = remaining > 0 ? armTicksToNs(remaining) : 0; // ticks->ns } - } while (rc == KERNELRESULT(Cancelled)); + + rc = waitfunc(idx_out, objects, num_objects, this_timeout); + if (has_timeout && R_VALUE(rc) == KERNELRESULT(TimedOut)) + break; + } while (R_VALUE(rc) == KERNELRESULT(Cancelled)); return rc; } Result waitN(s32* idx_out, Waiter* objects, size_t num_objects, u64 timeout) { - return _waitLoop((WaitImplFunc)waitImpl, idx_out, objects, num_objects, timeout); + return _waitLoop(idx_out, objects, num_objects, timeout, (WaitImplFunc)waitImpl); } Result waitNHandle(s32* idx_out, Handle* handles, size_t num_handles, u64 timeout) { - return _waitLoop((WaitImplFunc)svcWaitSynchronization, idx_out, handles, num_handles, timeout); + return _waitLoop(idx_out, handles, num_handles, timeout, (WaitImplFunc)svcWaitSynchronization); }