diff --git a/nx/include/switch/kernel/mutex.h b/nx/include/switch/kernel/mutex.h index bdad14af..73fbc1e5 100644 --- a/nx/include/switch/kernel/mutex.h +++ b/nx/include/switch/kernel/mutex.h @@ -29,6 +29,13 @@ static inline void mutexInit(Mutex* m) */ void mutexLock(Mutex* m); +/** + * @brief Attempts to lock a mutex without waiting. + * @param m Mutex object. + * @return 1 if the mutex has been acquired successfully, and 0 on contention. + */ +u32 mutexTryLock(Mutex* m); + /** * @brief Unlocks a mutex. * @param m Mutex object. @@ -53,6 +60,13 @@ static inline void rmutexInit(RMutex* m) */ void rmutexLock(RMutex* m); +/** + * @brief Attempts to lock a recursive mutex without waiting. + * @param m Recursive mutex object. + * @return 1 if the mutex has been acquired successfully, and 0 on contention. + */ +u32 rmutexTryLock(RMutex* m); + /** * @brief Unlocks a recursive mutex. * @param m Recursive mutex object. diff --git a/nx/source/kernel/mutex.c b/nx/source/kernel/mutex.c index 95c22719..5213e926 100644 --- a/nx/source/kernel/mutex.c +++ b/nx/source/kernel/mutex.c @@ -41,6 +41,23 @@ void mutexLock(Mutex* m) { } } +u32 mutexTryLock(Mutex* m) { + u32 self = _GetTag(); + u32 cur = __sync_val_compare_and_swap((u32*)m, 0, self); + + if (cur == 0) { + // We won the race! + return 1; + } + + if ((cur &~ HAS_LISTENERS) == self) { + // Kernel assigned it to us! + return 1; + } + + return 0; +} + void mutexUnlock(Mutex* m) { u32 old = __sync_lock_test_and_set((u32*)m, 0); @@ -58,6 +75,18 @@ void rmutexLock(RMutex* m) { m->counter++; } +u32 rmutexTryLock(RMutex* m) { + if (m->thread_tag != _GetTag()) { + if (!mutexTryLock(&m->lock)) { + return 0; + } + m->thread_tag = _GetTag(); + } + + m->counter++; + return 1; +} + void rmutexUnlock(RMutex* m) { if (--m->counter == 0) { m->thread_tag = 0;