From 88e9d3bb83a8831307a5a8c317588da3995ee253 Mon Sep 17 00:00:00 2001 From: fincs Date: Wed, 29 Aug 2018 22:08:09 +0200 Subject: [PATCH] kernel/event.h: several fixes, including autoclear support --- nx/include/switch/kernel/event.h | 6 ++-- nx/source/kernel/event.c | 43 ++++++++++++++++++++++----- nx/source/nvidia/gpu/error_notifier.c | 2 +- nx/source/services/audren.c | 3 +- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/nx/include/switch/kernel/event.h b/nx/include/switch/kernel/event.h index 2e429a1a..5f311931 100644 --- a/nx/include/switch/kernel/event.h +++ b/nx/include/switch/kernel/event.h @@ -7,13 +7,13 @@ typedef struct { Handle revent; Handle wevent; + bool autoclear; } Event; -Result eventCreate(Event* t); -void eventLoadRemote(Event* t, Handle handle); +Result eventCreate(Event* t, bool autoclear); +void eventLoadRemote(Event* t, Handle handle, bool autoclear); void eventClose(Event* t); Result eventWait(Event* t, u64 timeout); Result eventFire(Event* t); Result eventClear(Event* t); - diff --git a/nx/source/kernel/event.c b/nx/source/kernel/event.c index c038e7bb..4bba26fb 100644 --- a/nx/source/kernel/event.c +++ b/nx/source/kernel/event.c @@ -1,14 +1,16 @@ // Copyright 2018 plutoo #include "types.h" #include "result.h" +#include "arm/counter.h" #include "kernel/svc.h" #include "kernel/event.h" -Result eventCreate(Event* t) +Result eventCreate(Event* t, bool autoclear) { Result rc; rc = svcCreateEvent(&t->revent, &t->wevent); + t->autoclear = autoclear; if (R_FAILED(rc)) { t->revent = INVALID_HANDLE; @@ -18,24 +20,49 @@ Result eventCreate(Event* t) return rc; } -void eventLoadRemote(Event* t, Handle handle) { +void eventLoadRemote(Event* t, Handle handle, bool autoclear) +{ t->revent = handle; + t->wevent = INVALID_HANDLE; + t->autoclear = autoclear; } Result eventWait(Event* t, u64 timeout) { Result rc; + u64 deadline = 0; - rc = svcWaitSynchronizationSingle(t->revent, timeout); + if (t->revent == INVALID_HANDLE) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (R_SUCCEEDED(rc)) { - rc = svcResetSignal(t->revent); - } + if (timeout != U64_MAX) + deadline = armGetSystemTick() + timeout * 12 / 625; // timeout: ns->ticks + + do { + do { + s64 this_timeout = -1; + if (deadline) { + this_timeout = deadline - armGetSystemTick(); + this_timeout = (this_timeout >= 0 ? this_timeout : 0) * 625 / 12; // ticks->ns + } + + rc = svcWaitSynchronizationSingle(t->revent, this_timeout); + if (deadline && (rc & 0x3FFFFF) == 0xEA01) + return rc; // timeout. + } while (R_FAILED(rc)); + + if (t->autoclear) + rc = svcResetSignal(t->revent); + } while ((rc & 0x3FFFFF) == 0xFA01); return rc; } -Result eventFire(Event* t) { +Result eventFire(Event* t) +{ + if (t->wevent == INVALID_HANDLE) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + return svcSignalEvent(t->wevent); } @@ -45,7 +72,7 @@ Result eventClear(Event* t) return svcClearEvent(t->wevent); if (t->revent != INVALID_HANDLE) - return svcClearEvent(t->revent); + return svcResetSignal(t->revent); return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); } diff --git a/nx/source/nvidia/gpu/error_notifier.c b/nx/source/nvidia/gpu/error_notifier.c index 0f952c2e..3ca4eda1 100644 --- a/nx/source/nvidia/gpu/error_notifier.c +++ b/nx/source/nvidia/gpu/error_notifier.c @@ -26,7 +26,7 @@ Result nvErrorNotifierCreate(NvErrorNotifier* t, NvGpu* parent) parent->gpu_channel.fd, NvEventId_Gpu_ErrorNotifier, &handle); if (R_SUCCEEDED(rc)) { - eventLoadRemote(&t->event, handle); + eventLoadRemote(&t->event, handle, true); rc = nvioctlChannel_SetErrorNotifier(parent->gpu_channel.fd, 1); } diff --git a/nx/source/services/audren.c b/nx/source/services/audren.c index 2597e9e6..d22d049d 100644 --- a/nx/source/services/audren.c +++ b/nx/source/services/audren.c @@ -120,7 +120,6 @@ void audrenExit(void) void audrenWaitFrame(void) { eventWait(&g_audrenEvent, U64_MAX); - eventClear(&g_audrenEvent); } Result _audrenOpenAudioRenderer(Service* audren_mgr, const AudioRendererParameter* param, u64 aruid) @@ -373,7 +372,7 @@ Result _audrenQuerySystemEvent(void) rc = resp->result; if (R_SUCCEEDED(rc)) - eventLoadRemote(&g_audrenEvent, r.Handles[0]); + eventLoadRemote(&g_audrenEvent, r.Handles[0], true); } return rc;