diff --git a/libctru/include/3ds/synchronization.h b/libctru/include/3ds/synchronization.h index c8703bc..05d94c6 100644 --- a/libctru/include/3ds/synchronization.h +++ b/libctru/include/3ds/synchronization.h @@ -75,6 +75,13 @@ void LightLock_Init(LightLock* lock); */ void LightLock_Lock(LightLock* lock); +/** + * @brief Attempts to lock a light lock. + * @param lock Pointer to the lock. + * @return Zero on success, non-zero on failure. + */ +int LightLock_TryLock(LightLock* lock); + /** * @brief Unlocks a light lock. * @param lock Pointer to the lock. @@ -93,6 +100,13 @@ void RecursiveLock_Init(RecursiveLock* lock); */ void RecursiveLock_Lock(RecursiveLock* lock); +/** + * @brief Attempts to lock a recursive lock. + * @param lock Pointer to the lock. + * @return Zero on success, non-zero on failure. + */ +int RecursiveLock_TryLock(RecursiveLock* lock); + /** * @brief Unlocks a recursive lock. * @param lock Pointer to the lock. diff --git a/libctru/source/synchronization.c b/libctru/source/synchronization.c index 9bc293f..d2a550c 100644 --- a/libctru/source/synchronization.c +++ b/libctru/source/synchronization.c @@ -39,6 +39,21 @@ _begin: } while (__strex(lock, -val)); } +int LightLock_TryLock(LightLock* lock) +{ + s32 val; + do + { + val = __ldrex(lock); + if (val < 0) + { + __clrex(); + return 1; // Failure + } + } while (__strex(lock, -val)); + return 0; // Success +} + void LightLock_Unlock(LightLock* lock) { s32 val; @@ -73,6 +88,19 @@ void RecursiveLock_Lock(RecursiveLock* lock) lock->counter ++; } +int RecursiveLock_TryLock(RecursiveLock* lock) +{ + u32 tag = (u32)getThreadLocalStorage(); + if (lock->thread_tag != tag) + { + if (LightLock_TryLock(&lock->lock)) + return 1; // Failure + lock->thread_tag = tag; + } + lock->counter ++; + return 0; // Success +} + void RecursiveLock_Unlock(RecursiveLock* lock) { if (!--lock->counter)