Introducing RwLock, make hid threadsafe

This commit is contained in:
plutoo 2018-01-11 22:25:49 +01:00
parent bf89c7526e
commit 7482c849fe
4 changed files with 141 additions and 23 deletions

View File

@ -15,6 +15,7 @@ extern "C" {
#include <switch/kernel/tmem.h> #include <switch/kernel/tmem.h>
#include <switch/kernel/shmem.h> #include <switch/kernel/shmem.h>
#include <switch/kernel/mutex.h> #include <switch/kernel/mutex.h>
#include <switch/kernel/rwlock.h>
#include <switch/kernel/thread.h> #include <switch/kernel/thread.h>
#include <switch/kernel/virtmem.h> #include <switch/kernel/virtmem.h>
#include <switch/kernel/detect.h> #include <switch/kernel/detect.h>

View File

@ -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);

28
nx/source/kernel/rwlock.c Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2018 plutoo
#include <switch.h>
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);
}

View File

@ -18,25 +18,32 @@ static u64 g_controllerOld[10], g_controllerHeld[10], g_controllerDown[10], g_co
static HIDControllerLayoutType g_controllerLayout[10]; static HIDControllerLayoutType g_controllerLayout[10];
static u64 g_touchTimestamp, g_mouseTimestamp, g_keyboardTimestamp, g_controllerTimestamps[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 _hidCreateAppletResource(Handle sessionhandle, Handle* handle_out, u64 AppletResourceUserId);
static Result _hidGetSharedMemoryHandle(Handle sessionhandle, Handle* handle_out); static Result _hidGetSharedMemoryHandle(Handle sessionhandle, Handle* handle_out);
Result hidInitialize(void) { Result hidInitialize(void)
if (g_hidServiceSession != INVALID_HANDLE) return MAKERESULT(MODULE_LIBNX, LIBNX_ALREADYINITIALIZED); {
if (g_hidServiceSession != INVALID_HANDLE)
return MAKERESULT(MODULE_LIBNX, LIBNX_ALREADYINITIALIZED);
Result rc = 0; Result rc = 0;
u64 AppletResourceUserId = 0; u64 AppletResourceUserId = 0;
Handle sharedmem_handle=0; Handle sharedmem_handle=0;
rc = appletGetAppletResourceUserId(&AppletResourceUserId); rc = appletGetAppletResourceUserId(&AppletResourceUserId);
if (R_FAILED(rc)) return rc; if (R_FAILED(rc))
return rc;
rc = smGetService(&g_hidServiceSession, "hid"); rc = smGetService(&g_hidServiceSession, "hid");
if (R_FAILED(rc)) return rc; if (R_FAILED(rc))
return rc;
rc = _hidCreateAppletResource(g_hidServiceSession, &g_hidIAppletResource, AppletResourceUserId); 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)) { if (R_SUCCEEDED(rc)) {
shmemLoadRemote(&g_hidSharedmem, sharedmem_handle, 0x40000, PERM_R); shmemLoadRemote(&g_hidSharedmem, sharedmem_handle, 0x40000, PERM_R);
@ -47,8 +54,11 @@ Result hidInitialize(void) {
} }
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
if (g_hidServiceSession != INVALID_HANDLE) svcCloseHandle(g_hidServiceSession); if (g_hidServiceSession != INVALID_HANDLE)
if (g_hidIAppletResource != INVALID_HANDLE) svcCloseHandle(g_hidIAppletResource); svcCloseHandle(g_hidServiceSession);
if (g_hidIAppletResource != INVALID_HANDLE)
svcCloseHandle(g_hidIAppletResource);
g_hidServiceSession = INVALID_HANDLE; g_hidServiceSession = INVALID_HANDLE;
g_hidIAppletResource = INVALID_HANDLE; g_hidIAppletResource = INVALID_HANDLE;
@ -61,7 +71,8 @@ Result hidInitialize(void) {
void hidExit(void) void hidExit(void)
{ {
if (g_hidServiceSession == INVALID_HANDLE) return; if (g_hidServiceSession == INVALID_HANDLE)
return;
if (g_hidServiceSession != INVALID_HANDLE) { if (g_hidServiceSession != INVALID_HANDLE) {
svcCloseHandle(g_hidServiceSession); svcCloseHandle(g_hidServiceSession);
@ -76,7 +87,10 @@ void hidExit(void)
shmemClose(&g_hidSharedmem); shmemClose(&g_hidSharedmem);
} }
void hidReset(void) { void hidReset(void)
{
rwlockWriteLock(&g_hidLock);
// Reset internal state // Reset internal state
memset(&g_touchEntry, 0, sizeof(HIDTouchScreenEntry)); memset(&g_touchEntry, 0, sizeof(HIDTouchScreenEntry));
memset(&g_mouseEntry, 0, sizeof(HIDMouseEntry)); memset(&g_mouseEntry, 0, sizeof(HIDMouseEntry));
@ -96,6 +110,8 @@ void hidReset(void) {
g_touchTimestamp = g_mouseTimestamp = g_keyboardTimestamp = 0; g_touchTimestamp = g_mouseTimestamp = g_keyboardTimestamp = 0;
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
g_controllerTimestamps[i] = 0; g_controllerTimestamps[i] = 0;
rwlockWriteUnlock(&g_hidLock);
} }
Handle hidGetSessionService(void) { Handle hidGetSessionService(void) {
@ -107,15 +123,25 @@ void* hidGetSharedmemAddr(void) {
} }
void hidSetControllerLayout(HIDControllerID id, HIDControllerLayoutType layoutType) { void hidSetControllerLayout(HIDControllerID id, HIDControllerLayoutType layoutType) {
rwlockWriteLock(&g_hidLock);
g_controllerLayout[id] = layoutType; g_controllerLayout[id] = layoutType;
rwlockWriteUnlock(&g_hidLock);
} }
HIDControllerLayoutType hidGetControllerLayout(HIDControllerID id) { HIDControllerLayoutType hidGetControllerLayout(HIDControllerID id) {
return g_controllerLayout[id]; rwlockReadLock(&g_hidLock);
HIDControllerLayoutType tmp = g_controllerLayout[id];
rwlockReadUnlock(&g_hidLock);
return tmp;
} }
void hidScanInput(void) { void hidScanInput(void) {
if (g_hidServiceSession == INVALID_HANDLE) return; if (g_hidServiceSession == INVALID_HANDLE)
return;
rwlockWriteLock(&g_hidLock);
HIDSharedMemory *sharedMem = (HIDSharedMemory*)hidGetSharedmemAddr(); HIDSharedMemory *sharedMem = (HIDSharedMemory*)hidGetSharedmemAddr();
g_mouseOld = g_mouseHeld; g_mouseOld = g_mouseHeld;
@ -185,60 +211,110 @@ void hidScanInput(void) {
g_controllerDown[i] = (~g_controllerOld[i]) & g_controllerHeld[i]; g_controllerDown[i] = (~g_controllerOld[i]) & g_controllerHeld[i];
g_controllerUp[i] = g_controllerOld[i] & (~g_controllerHeld[i]); g_controllerUp[i] = g_controllerOld[i] & (~g_controllerHeld[i]);
} }
rwlockWriteUnlock(&g_hidLock);
} }
u64 hidKeysHeld(HIDControllerID id) { u64 hidKeysHeld(HIDControllerID id) {
if (id < 0 || id > 9) return 0; 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) { u64 hidKeysDown(HIDControllerID id) {
if (id < 0 || id > 9) return 0; 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) { u64 hidKeysUp(HIDControllerID id) {
if (id < 0 || id > 9) return 0; 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) { u64 hidMouseButtonsHeld(void) {
return g_mouseHeld; rwlockReadLock(&g_hidLock);
u64 tmp = g_mouseHeld;
rwlockReadUnlock(&g_hidLock);
return tmp;
} }
u64 hidMouseButtonsDown(void) { u64 hidMouseButtonsDown(void) {
return g_mouseDown; rwlockReadLock(&g_hidLock);
u64 tmp = g_mouseDown;
rwlockReadUnlock(&g_hidLock);
return tmp;
} }
u64 hidMouseButtonsUp(void) { u64 hidMouseButtonsUp(void) {
return g_mouseUp; rwlockReadLock(&g_hidLock);
u64 tmp = g_mouseUp;
rwlockReadUnlock(&g_hidLock);
return tmp;
} }
bool hidKeyboardModifierHeld(HIDKeyboardModifier modifier) { 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) { 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) { 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) { 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) { 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) { 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) { u32 hidTouchCount(void) {