implemented mutex error checking

This commit is contained in:
RSDuck 2018-12-29 22:49:34 +01:00
parent e9cc565e92
commit 4c2102f06d
2 changed files with 23 additions and 9 deletions

View File

@ -26,8 +26,9 @@ static inline void mutexInit(Mutex* m)
/** /**
* @brief Locks a mutex. * @brief Locks a mutex.
* @param m Mutex object. * @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. * @brief Attempts to lock a mutex without waiting.
@ -39,8 +40,9 @@ bool mutexTryLock(Mutex* m);
/** /**
* @brief Unlocks a mutex. * @brief Unlocks a mutex.
* @param m Mutex object. * @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. * @brief Initializes a recursive mutex.

View File

@ -9,20 +9,21 @@ static u32 _GetTag(void) {
return getThreadVars()->handle; return getThreadVars()->handle;
} }
void mutexLock(Mutex* m) { bool mutexLock(Mutex* m) {
u32 self = _GetTag(); u32 self = _GetTag();
bool first = false;
while (1) { while (1) {
u32 cur = __sync_val_compare_and_swap((u32*)m, 0, self); u32 cur = __sync_val_compare_and_swap((u32*)m, 0, self);
if (cur == 0) { if (cur == 0) {
// We won the race! // We won the race!
return; return true;
} }
if ((cur &~ HAS_LISTENERS) == self) { if ((cur &~ HAS_LISTENERS) == self) {
// Kernel assigned it to us! // Kernel assigned it to us!
return; return !first;
} }
if (cur & HAS_LISTENERS) { if (cur & HAS_LISTENERS) {
@ -38,6 +39,8 @@ void mutexLock(Mutex* m) {
svcArbitrateLock(cur, (u32*)m, self); svcArbitrateLock(cur, (u32*)m, self);
} }
} }
first = true;
} }
} }
@ -58,11 +61,20 @@ bool mutexTryLock(Mutex* m) {
return 0; return 0;
} }
void mutexUnlock(Mutex* m) { bool mutexUnlock(Mutex* m) {
u32 old = __sync_val_compare_and_swap((u32*)m, _GetTag(), 0); u32 self = _GetTag();
u32 old = __sync_val_compare_and_swap((u32*)m, self, 0);
if (old & HAS_LISTENERS) { if ((old &~ HAS_LISTENERS) == self) {
svcArbitrateUnlock((u32*)m); if (old & HAS_LISTENERS) {
svcArbitrateUnlock((u32*)m);
}
return true;
}
else {
// The mutex doesn't belong to us
return false;
} }
} }