From 4c2102f06d09c6fd1088ecebad13fec40eac134b Mon Sep 17 00:00:00 2001 From: RSDuck Date: Sat, 29 Dec 2018 22:49:34 +0100 Subject: [PATCH] implemented mutex error checking --- nx/include/switch/kernel/mutex.h | 6 ++++-- nx/source/kernel/mutex.c | 26 +++++++++++++++++++------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/nx/include/switch/kernel/mutex.h b/nx/include/switch/kernel/mutex.h index fe6ca3a3..579c721f 100644 --- a/nx/include/switch/kernel/mutex.h +++ b/nx/include/switch/kernel/mutex.h @@ -26,8 +26,9 @@ static inline void mutexInit(Mutex* m) /** * @brief Locks a mutex. * @param m Mutex object. + * @return 0 if the mutex is already owned by this thread, and 1 if it was sucessfully acquired. */ -void mutexLock(Mutex* m); +bool mutexLock(Mutex* m); /** * @brief Attempts to lock a mutex without waiting. @@ -39,8 +40,9 @@ bool mutexTryLock(Mutex* m); /** * @brief Unlocks a mutex. * @param m Mutex object. + * @return 1 if the mutex was released, and 0 if the mutex does not belong to this thread. */ -void mutexUnlock(Mutex* m); +bool mutexUnlock(Mutex* m); /** * @brief Initializes a recursive mutex. diff --git a/nx/source/kernel/mutex.c b/nx/source/kernel/mutex.c index f7fd8c59..c0add7b2 100644 --- a/nx/source/kernel/mutex.c +++ b/nx/source/kernel/mutex.c @@ -9,20 +9,21 @@ static u32 _GetTag(void) { return getThreadVars()->handle; } -void mutexLock(Mutex* m) { +bool mutexLock(Mutex* m) { u32 self = _GetTag(); + bool first = false; while (1) { u32 cur = __sync_val_compare_and_swap((u32*)m, 0, self); if (cur == 0) { // We won the race! - return; + return true; } if ((cur &~ HAS_LISTENERS) == self) { // Kernel assigned it to us! - return; + return !first; } if (cur & HAS_LISTENERS) { @@ -38,6 +39,8 @@ void mutexLock(Mutex* m) { svcArbitrateLock(cur, (u32*)m, self); } } + + first = true; } } @@ -58,11 +61,20 @@ bool mutexTryLock(Mutex* m) { return 0; } -void mutexUnlock(Mutex* m) { - u32 old = __sync_val_compare_and_swap((u32*)m, _GetTag(), 0); +bool mutexUnlock(Mutex* m) { + u32 self = _GetTag(); + u32 old = __sync_val_compare_and_swap((u32*)m, self, 0); - if (old & HAS_LISTENERS) { - svcArbitrateUnlock((u32*)m); + if ((old &~ HAS_LISTENERS) == self) { + if (old & HAS_LISTENERS) { + svcArbitrateUnlock((u32*)m); + } + + return true; + } + else { + // The mutex doesn't belong to us + return false; } }