From 000a7f05c9ca8e6ed74dd4bc0486474b99270d97 Mon Sep 17 00:00:00 2001 From: plutoo Date: Tue, 30 Jan 2018 22:39:02 +0100 Subject: [PATCH] Experimental implementation of condvars --- nx/include/switch/kernel/cond_var.h | 18 ++++++++++++++ nx/include/switch/kernel/svc.h | 2 ++ nx/source/kernel/cond_var.c | 37 +++++++++++++++++++++++++++++ nx/source/kernel/svc.s | 10 ++++++++ 4 files changed, 67 insertions(+) create mode 100644 nx/include/switch/kernel/cond_var.h create mode 100644 nx/source/kernel/cond_var.c diff --git a/nx/include/switch/kernel/cond_var.h b/nx/include/switch/kernel/cond_var.h new file mode 100644 index 00000000..8b56be2e --- /dev/null +++ b/nx/include/switch/kernel/cond_var.h @@ -0,0 +1,18 @@ +// Copyright 2018 plutoo +#include "../types.h" +#include "../kernel/mutex.h" + +typedef struct { + u32 tag; + Mutex* mutex; +} CondVar; + +void condvarInit(CondVar* c, Mutex* m); + +// When the wait-functions return, the mutex is acquired. +void condvarWaitTimeout(CondVar* c, u64 timeout); +void condvarWait(CondVar* c); + +Result condvarWake(CondVar* c, int num); +Result condvarWakeOne(CondVar* c); +Result condvarWakeAll(CondVar* c); diff --git a/nx/include/switch/kernel/svc.h b/nx/include/switch/kernel/svc.h index 159eb291..f48f5f45 100644 --- a/nx/include/switch/kernel/svc.h +++ b/nx/include/switch/kernel/svc.h @@ -52,6 +52,8 @@ Result svcWaitSynchronization(s32* index, const Handle* handles, s32 handleCount Result svcCancelSynchronization(Handle thread); Result svcArbitrateLock(u32 wait_tag, u32* tag_location, u32 self_tag); Result svcArbitrateUnlock(u32* tag_location); +Result svcWaitProcessWideKeyAtomic(u32* key, u32* tag_location, u32 self_tag, u64 timeout); +Result svcSignalProcessWideKey(u32* key, s32 num); Result svcConnectToNamedPort(Handle* session, const char* name); u64 svcGetSystemTick(void); Result svcSendSyncRequest(Handle session); diff --git a/nx/source/kernel/cond_var.c b/nx/source/kernel/cond_var.c new file mode 100644 index 00000000..e8029fa8 --- /dev/null +++ b/nx/source/kernel/cond_var.c @@ -0,0 +1,37 @@ +// Copyright 2018 plutoo +#include "types.h" +#include "result.h" +#include "kernel/svc.h" +#include "kernel/cond_var.h" +#include "../internal.h" + +void condvarInit(CondVar* c, Mutex* m) { + c->tag = 0; + c->mutex = m; +} + +void condvarWaitTimeout(CondVar* c, u64 timeout) { + Result rc; + + rc = svcWaitProcessWideKeyAtomic(&c->tag, (u32*) c->mutex, getThreadVars()->handle, timeout); + + // On timeout, we need to acquire it manually. + if (rc == 0xEA01) + mutexLock(c->mutex); +} + +void condvarWait(CondVar* c) { + return condvarWaitTimeout(c, -1); +} + +Result condvarWake(CondVar* c, int num) { + return svcSignalProcessWideKey((u32*) &c->tag, num); +} + +Result condvarWakeOne(CondVar* c) { + return condvarWake(c, 1); +} + +Result condvarWakeAll(CondVar* c) { + return condvarWake(c, -1); +} diff --git a/nx/source/kernel/svc.s b/nx/source/kernel/svc.s index 6be5ef33..7681c889 100644 --- a/nx/source/kernel/svc.s +++ b/nx/source/kernel/svc.s @@ -122,6 +122,16 @@ SVC_BEGIN svcArbitrateUnlock ret SVC_END +SVC_BEGIN svcWaitProcessWideKeyAtomic + svc 0x1c + ret +SVC_END + +SVC_BEGIN svcSignalProcessWideKey + svc 0x1d + ret +SVC_END + SVC_BEGIN svcConnectToNamedPort str x0, [sp, #-16]! svc 0x1F