Fix mutex

This commit is contained in:
flysand7 2023-08-28 01:36:46 +11:00
parent 35a760e54e
commit 7929779df6
2 changed files with 32 additions and 13 deletions

View File

@ -168,7 +168,9 @@ static _RT_Status _rt_sync_wake_one(u32 *addr, u32 *n_woken) {
if(result < 0) { if(result < 0) {
return _RT_ERROR_GENERIC; return _RT_ERROR_GENERIC;
} }
if(n_woken != NULL) {
*n_woken = (u32)result; *n_woken = (u32)result;
}
return _RT_STATUS_OK; return _RT_STATUS_OK;
} }
@ -177,6 +179,8 @@ static _RT_Status _rt_sync_wake_all(u32 *addr, u32 *n_woken) {
if(result < 0) { if(result < 0) {
return _RT_ERROR_GENERIC; return _RT_ERROR_GENERIC;
} }
if(n_woken != NULL) {
*n_woken = (u32)result; *n_woken = (u32)result;
}
return _RT_STATUS_OK; return _RT_STATUS_OK;
} }

View File

@ -1,21 +1,36 @@
#define _CIA_MUTEX_TAG_UNLOCKED 0x00000000 #define _CIA_MUTEX_FREE 0
#define _CIA_MUTEX_TAG_LOCKED 0x00000001 #define _CIA_MUTEX_LOCK 1
#define _CIA_MUTEX_CONT 2
void cia_mutex_init(Cia_Mutex *mutex) { void cia_mutex_init(Cia_Mutex *mutex) {
mutex->tag = _CIA_MUTEX_TAG_UNLOCKED; mutex->tag = _CIA_MUTEX_FREE;
} }
void cia_mutex_lock(Cia_Mutex *mutex) { void cia_mutex_lock(Cia_Mutex *mutex) {
do { u64 prev_tag;
_rt_sync_wait(&mutex->tag, _CIA_MUTEX_TAG_LOCKED, _RT_SYNC_WAIT_INFINITE); for(;;) {
} while(mutex->tag == _CIA_MUTEX_TAG_LOCKED); prev_tag = __sync_val_compare_and_swap(&mutex->tag, _CIA_MUTEX_FREE, _CIA_MUTEX_LOCK);
mutex->tag = _CIA_MUTEX_TAG_LOCKED; // We got the mutex, lets bail
if(prev_tag == _CIA_MUTEX_FREE) {
break;
}
// We should wait if:
// (1) the mutex is contested
// (2) this thread locking the mutex makes it contested
bool should_wait = 0;
should_wait |= (prev_tag == _CIA_MUTEX_CONT);
should_wait |= (__sync_val_compare_and_swap(&mutex->tag, _CIA_MUTEX_LOCK, _CIA_MUTEX_CONT) != _CIA_MUTEX_FREE);
// We wait while its contested
if(should_wait) {
_rt_sync_wait(&mutex->tag, _CIA_MUTEX_CONT, _RT_SYNC_WAIT_INFINITE);
}
}
} }
void cia_mutex_unlock(Cia_Mutex *mutex) { void cia_mutex_unlock(Cia_Mutex *mutex) {
mutex->tag = _CIA_MUTEX_TAG_UNLOCKED; // TODO: add error when we unlock a free mutex
u32 woken = 0; // TODO: support recursive muteces
_rt_sync_wake_one(&mutex->tag, &woken); mutex->tag = _CIA_MUTEX_FREE;
_rt_sync_wake_one(&mutex->tag, NULL);
} }