Synchronize eventWait and _waitLoop code

This commit is contained in:
fincs 2018-12-14 17:59:54 +01:00
parent 054b8fecdc
commit fb789b52ba
2 changed files with 31 additions and 30 deletions

View File

@ -30,30 +30,34 @@ void eventLoadRemote(Event* t, Handle handle, bool autoclear)
Result eventWait(Event* t, u64 timeout) Result eventWait(Event* t, u64 timeout)
{ {
Result rc; Result rc;
bool has_timeout = timeout != UINT64_MAX;
u64 deadline = 0; u64 deadline = 0;
if (t->revent == INVALID_HANDLE) if (t->revent == INVALID_HANDLE)
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (timeout != U64_MAX) if (has_timeout)
deadline = armGetSystemTick() + armNsToTicks(timeout); // timeout: ns->ticks deadline = armGetSystemTick() + armNsToTicks(timeout); // timeout: ns->ticks
do { do {
do { do {
s64 this_timeout = -1; u64 this_timeout = UINT64_MAX;
if (deadline) { if (has_timeout) {
this_timeout = deadline - armGetSystemTick(); s64 remaining = deadline - armGetSystemTick();
this_timeout = armTicksToNs(this_timeout >= 0 ? this_timeout : 0); // ticks->ns this_timeout = remaining > 0 ? armTicksToNs(remaining) : 0; // ticks->ns
} }
rc = svcWaitSynchronizationSingle(t->revent, this_timeout); rc = svcWaitSynchronizationSingle(t->revent, this_timeout);
if (deadline && (rc & 0x3FFFFF) == 0xEA01) if (has_timeout && R_VALUE(rc) == KERNELRESULT(TimedOut))
return rc; // timeout. return rc;
} while (R_FAILED(rc)); } while (R_VALUE(rc) == KERNELRESULT(Cancelled));
if (R_FAILED(rc))
break;
if (t->autoclear) if (t->autoclear)
rc = svcResetSignal(t->revent); rc = svcResetSignal(t->revent);
} while ((rc & 0x3FFFFF) == 0xFA01); } while (R_VALUE(rc) == KERNELRESULT(InvalidState));
return rc; return rc;
} }

View File

@ -145,39 +145,36 @@ clean_up:
return rc; 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; Result rc;
bool has_timeout = timeout != UINT64_MAX;
u64 deadline = 0;
if (has_timeout)
deadline = armGetSystemTick() + armNsToTicks(timeout); // timeout: ns->ticks
do { do {
u64 cur_tick = armGetSystemTick(); u64 this_timeout = UINT64_MAX;
rc = wait(idx_out, objects, num_objects, timeout); if (has_timeout) {
rc = R_VALUE(rc); s64 remaining = deadline - armGetSystemTick();
this_timeout = remaining > 0 ? armTicksToNs(remaining) : 0; // ticks->ns
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);
} }
}
} 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; return rc;
} }
Result waitN(s32* idx_out, Waiter* objects, size_t num_objects, u64 timeout) 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) 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);
} }