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) {
return _RT_ERROR_GENERIC;
}
if(n_woken != NULL) {
*n_woken = (u32)result;
}
return _RT_STATUS_OK;
}
@ -177,6 +179,8 @@ static _RT_Status _rt_sync_wake_all(u32 *addr, u32 *n_woken) {
if(result < 0) {
return _RT_ERROR_GENERIC;
}
if(n_woken != NULL) {
*n_woken = (u32)result;
}
return _RT_STATUS_OK;
}

View File

@ -1,21 +1,36 @@
#define _CIA_MUTEX_TAG_UNLOCKED 0x00000000
#define _CIA_MUTEX_TAG_LOCKED 0x00000001
#define _CIA_MUTEX_FREE 0
#define _CIA_MUTEX_LOCK 1
#define _CIA_MUTEX_CONT 2
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) {
do {
_rt_sync_wait(&mutex->tag, _CIA_MUTEX_TAG_LOCKED, _RT_SYNC_WAIT_INFINITE);
} while(mutex->tag == _CIA_MUTEX_TAG_LOCKED);
mutex->tag = _CIA_MUTEX_TAG_LOCKED;
u64 prev_tag;
for(;;) {
prev_tag = __sync_val_compare_and_swap(&mutex->tag, _CIA_MUTEX_FREE, _CIA_MUTEX_LOCK);
// 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) {
mutex->tag = _CIA_MUTEX_TAG_UNLOCKED;
u32 woken = 0;
_rt_sync_wake_one(&mutex->tag, &woken);
// TODO: add error when we unlock a free mutex
// TODO: support recursive muteces
mutex->tag = _CIA_MUTEX_FREE;
_rt_sync_wake_one(&mutex->tag, NULL);
}