From 7482c849fe2b54e18e89deeb2c71396863ac241b Mon Sep 17 00:00:00 2001 From: plutoo Date: Thu, 11 Jan 2018 22:25:49 +0100 Subject: [PATCH] Introducing RwLock, make hid threadsafe --- nx/include/switch.h | 1 + nx/include/switch/kernel/rwlock.h | 13 ++++ nx/source/kernel/rwlock.c | 28 +++++++ nx/source/services/hid.c | 122 ++++++++++++++++++++++++------ 4 files changed, 141 insertions(+), 23 deletions(-) create mode 100644 nx/include/switch/kernel/rwlock.h create mode 100644 nx/source/kernel/rwlock.c diff --git a/nx/include/switch.h b/nx/include/switch.h index 8d8897e6..01c01e27 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -15,6 +15,7 @@ extern "C" { #include #include #include +#include #include #include #include diff --git a/nx/include/switch/kernel/rwlock.h b/nx/include/switch/kernel/rwlock.h new file mode 100644 index 00000000..c49f6191 --- /dev/null +++ b/nx/include/switch/kernel/rwlock.h @@ -0,0 +1,13 @@ +// Copyright 2018 plutoo + +typedef struct { + RMutex r; + RMutex g; + u64 b; +} RwLock; + +void rwlockReadLock(RwLock* r); +void rwlockReadUnlock(RwLock* r); + +void rwlockWriteLock(RwLock* r); +void rwlockWriteUnlock(RwLock* r); diff --git a/nx/source/kernel/rwlock.c b/nx/source/kernel/rwlock.c new file mode 100644 index 00000000..88d61b7a --- /dev/null +++ b/nx/source/kernel/rwlock.c @@ -0,0 +1,28 @@ +// Copyright 2018 plutoo +#include + +void rwlockReadLock(RwLock* r) { + rmutexLock(&r->r); + + if (r->b++ == 0) + rmutexLock(&r->g); + + rmutexUnlock(&r->r); +} + +void rwlockReadUnlock(RwLock* r) { + rmutexLock(&r->r); + + if (r->b-- == 1) + rmutexUnlock(&r->g); + + rmutexUnlock(&r->r); +} + +void rwlockWriteLock(RwLock* r) { + rmutexLock(&r->g); +} + +void rwlockWriteUnlock(RwLock* r) { + rmutexUnlock(&r->g); +} diff --git a/nx/source/services/hid.c b/nx/source/services/hid.c index 94bc1d9e..cad3fc8b 100644 --- a/nx/source/services/hid.c +++ b/nx/source/services/hid.c @@ -18,25 +18,32 @@ static u64 g_controllerOld[10], g_controllerHeld[10], g_controllerDown[10], g_co static HIDControllerLayoutType g_controllerLayout[10]; static u64 g_touchTimestamp, g_mouseTimestamp, g_keyboardTimestamp, g_controllerTimestamps[10]; +static RwLock g_hidLock; + static Result _hidCreateAppletResource(Handle sessionhandle, Handle* handle_out, u64 AppletResourceUserId); static Result _hidGetSharedMemoryHandle(Handle sessionhandle, Handle* handle_out); -Result hidInitialize(void) { - if (g_hidServiceSession != INVALID_HANDLE) return MAKERESULT(MODULE_LIBNX, LIBNX_ALREADYINITIALIZED); +Result hidInitialize(void) +{ + if (g_hidServiceSession != INVALID_HANDLE) + return MAKERESULT(MODULE_LIBNX, LIBNX_ALREADYINITIALIZED); Result rc = 0; u64 AppletResourceUserId = 0; Handle sharedmem_handle=0; rc = appletGetAppletResourceUserId(&AppletResourceUserId); - if (R_FAILED(rc)) return rc; + if (R_FAILED(rc)) + return rc; rc = smGetService(&g_hidServiceSession, "hid"); - if (R_FAILED(rc)) return rc; + if (R_FAILED(rc)) + return rc; rc = _hidCreateAppletResource(g_hidServiceSession, &g_hidIAppletResource, AppletResourceUserId); - if (R_SUCCEEDED(rc)) rc = _hidGetSharedMemoryHandle(g_hidIAppletResource, &sharedmem_handle); + if (R_SUCCEEDED(rc)) + rc = _hidGetSharedMemoryHandle(g_hidIAppletResource, &sharedmem_handle); if (R_SUCCEEDED(rc)) { shmemLoadRemote(&g_hidSharedmem, sharedmem_handle, 0x40000, PERM_R); @@ -47,8 +54,11 @@ Result hidInitialize(void) { } if (R_FAILED(rc)) { - if (g_hidServiceSession != INVALID_HANDLE) svcCloseHandle(g_hidServiceSession); - if (g_hidIAppletResource != INVALID_HANDLE) svcCloseHandle(g_hidIAppletResource); + if (g_hidServiceSession != INVALID_HANDLE) + svcCloseHandle(g_hidServiceSession); + + if (g_hidIAppletResource != INVALID_HANDLE) + svcCloseHandle(g_hidIAppletResource); g_hidServiceSession = INVALID_HANDLE; g_hidIAppletResource = INVALID_HANDLE; @@ -61,7 +71,8 @@ Result hidInitialize(void) { void hidExit(void) { - if (g_hidServiceSession == INVALID_HANDLE) return; + if (g_hidServiceSession == INVALID_HANDLE) + return; if (g_hidServiceSession != INVALID_HANDLE) { svcCloseHandle(g_hidServiceSession); @@ -76,7 +87,10 @@ void hidExit(void) shmemClose(&g_hidSharedmem); } -void hidReset(void) { +void hidReset(void) +{ + rwlockWriteLock(&g_hidLock); + // Reset internal state memset(&g_touchEntry, 0, sizeof(HIDTouchScreenEntry)); memset(&g_mouseEntry, 0, sizeof(HIDMouseEntry)); @@ -96,6 +110,8 @@ void hidReset(void) { g_touchTimestamp = g_mouseTimestamp = g_keyboardTimestamp = 0; for (int i = 0; i < 10; i++) g_controllerTimestamps[i] = 0; + + rwlockWriteUnlock(&g_hidLock); } Handle hidGetSessionService(void) { @@ -107,15 +123,25 @@ void* hidGetSharedmemAddr(void) { } void hidSetControllerLayout(HIDControllerID id, HIDControllerLayoutType layoutType) { + rwlockWriteLock(&g_hidLock); g_controllerLayout[id] = layoutType; + rwlockWriteUnlock(&g_hidLock); } HIDControllerLayoutType hidGetControllerLayout(HIDControllerID id) { - return g_controllerLayout[id]; + rwlockReadLock(&g_hidLock); + HIDControllerLayoutType tmp = g_controllerLayout[id]; + rwlockReadUnlock(&g_hidLock); + + return tmp; } void hidScanInput(void) { - if (g_hidServiceSession == INVALID_HANDLE) return; + if (g_hidServiceSession == INVALID_HANDLE) + return; + + rwlockWriteLock(&g_hidLock); + HIDSharedMemory *sharedMem = (HIDSharedMemory*)hidGetSharedmemAddr(); g_mouseOld = g_mouseHeld; @@ -185,60 +211,110 @@ void hidScanInput(void) { g_controllerDown[i] = (~g_controllerOld[i]) & g_controllerHeld[i]; g_controllerUp[i] = g_controllerOld[i] & (~g_controllerHeld[i]); } + + rwlockWriteUnlock(&g_hidLock); } u64 hidKeysHeld(HIDControllerID id) { if (id < 0 || id > 9) return 0; - return g_controllerHeld[id]; + rwlockReadLock(&g_hidLock); + u64 tmp = g_controllerHeld[id]; + rwlockReadUnlock(&g_hidLock); + + return tmp; } u64 hidKeysDown(HIDControllerID id) { if (id < 0 || id > 9) return 0; - return g_controllerDown[id]; + rwlockReadLock(&g_hidLock); + u64 tmp = g_controllerDown[id]; + rwlockReadUnlock(&g_hidLock); + + return tmp; } u64 hidKeysUp(HIDControllerID id) { if (id < 0 || id > 9) return 0; - return g_controllerUp[id]; + rwlockReadLock(&g_hidLock); + u64 tmp = g_controllerUp[id]; + rwlockReadUnlock(&g_hidLock); + + return tmp; } u64 hidMouseButtonsHeld(void) { - return g_mouseHeld; + rwlockReadLock(&g_hidLock); + u64 tmp = g_mouseHeld; + rwlockReadUnlock(&g_hidLock); + + return tmp; } u64 hidMouseButtonsDown(void) { - return g_mouseDown; + rwlockReadLock(&g_hidLock); + u64 tmp = g_mouseDown; + rwlockReadUnlock(&g_hidLock); + + return tmp; } u64 hidMouseButtonsUp(void) { - return g_mouseUp; + rwlockReadLock(&g_hidLock); + u64 tmp = g_mouseUp; + rwlockReadUnlock(&g_hidLock); + + return tmp; } bool hidKeyboardModifierHeld(HIDKeyboardModifier modifier) { - return g_keyboardModHeld & modifier; + rwlockReadLock(&g_hidLock); + bool tmp = g_keyboardModHeld & modifier; + rwlockReadUnlock(&g_hidLock); + + return tmp; } bool hidKeyboardModifierDown(HIDKeyboardModifier modifier) { - return g_keyboardModDown & modifier; + rwlockReadLock(&g_hidLock); + bool tmp = g_keyboardModDown & modifier; + rwlockReadUnlock(&g_hidLock); + + return tmp; } bool hidKeyboardModifierUp(HIDKeyboardModifier modifier) { - return g_keyboardModUp & modifier; + rwlockReadLock(&g_hidLock); + bool tmp = g_keyboardModUp & modifier; + rwlockReadUnlock(&g_hidLock); + + return tmp; } bool hidKeyboardHeld(HIDKeyboardScancode key) { - return g_keyboardHeld[key / 32] & (1 << (key % 32)); + rwlockReadLock(&g_hidLock); + u32 tmp = g_keyboardHeld[key / 32] & (1 << (key % 32)); + rwlockReadUnlock(&g_hidLock); + + return !!tmp; } bool hidKeyboardDown(HIDKeyboardScancode key) { - return g_keyboardDown[key / 32] & (1 << (key % 32)); + rwlockReadLock(&g_hidLock); + u32 tmp = g_keyboardDown[key / 32] & (1 << (key % 32)); + rwlockReadUnlock(&g_hidLock); + + return !!tmp; } bool hidKeyboardUp(HIDKeyboardScancode key) { - return g_keyboardUp[key / 32] & (1 << (key % 32)); + rwlockReadLock(&g_hidLock); + u32 tmp = g_keyboardUp[key / 32] & (1 << (key % 32)); + rwlockReadUnlock(&g_hidLock); + + return !!tmp; } u32 hidTouchCount(void) {