Fix memory ordering on mutex acquire

This commit is contained in:
flysand7 2023-09-10 18:12:17 +11:00
parent dc2ec9eb13
commit 362460ac9c
3 changed files with 8 additions and 9 deletions

View File

@ -30,7 +30,7 @@ struct _LD_Thread_Block {
/* +0x10 */ _Atomic(u32) thread_behaviour; /* One of the CIA_THREAD_BEHAVIOR_* constants */ /* +0x10 */ _Atomic(u32) thread_behaviour; /* One of the CIA_THREAD_BEHAVIOR_* constants */
/* +0x14 */ _Atomic(i32) thread_finished; /* +0x14 */ _Atomic(i32) thread_finished;
/* +0x18 */ u32 pad0; /* +0x18 */ u32 pad0;
/* +0x1c */ i32 exit_code; /* +0x1c */ _Atomic(i32) exit_code;
/* +0x20 */ u64 pad1; /* +0x20 */ u64 pad1;
/* +0x28 */ u64 stack_canary; /* +0x28 */ u64 stack_canary;
}; };

View File

@ -65,7 +65,7 @@ void _rt_thread_finish(int exit_code) {
} }
// If main thread set this thread to be joined, we signal it that we're done here // If main thread set this thread to be joined, we signal it that we're done here
if(thread_behaviour == _LD_THREAD_BEHAVIOUR_JOIN) { if(thread_behaviour == _LD_THREAD_BEHAVIOUR_JOIN) {
tcb->exit_code = exit_code; atomic_store_explicit(&tcb->exit_code, exit_code, memory_order_relaxed);
atomic_store_explicit(&tcb->thread_finished, 1, memory_order_release); atomic_store_explicit(&tcb->thread_finished, 1, memory_order_release);
syscall(SYS_futex, &tcb->thread_finished, FUTEX_WAKE, 0, NULL, 0, 0); syscall(SYS_futex, &tcb->thread_finished, FUTEX_WAKE, 0, NULL, 0, 0);
sys_exit(exit_code); sys_exit(exit_code);
@ -86,7 +86,7 @@ static _RT_Status _rt_thread_join(_RT_Thread *thread, int *out_exit_code) {
syscall(SYS_futex, &tcb->thread_finished, FUTEX_WAIT, 0, NULL, 0, 0); syscall(SYS_futex, &tcb->thread_finished, FUTEX_WAIT, 0, NULL, 0, 0);
} }
// Set the exit code // Set the exit code
*out_exit_code = tcb->exit_code; *out_exit_code = atomic_load_explicit(&tcb->exit_code, memory_order_acquire);
return _RT_STATUS_OK; return _RT_STATUS_OK;
} }

View File

@ -10,20 +10,21 @@ void cia_mutex_init(Cia_Mutex *mutex) {
void cia_mutex_lock(Cia_Mutex *mutex) { void cia_mutex_lock(Cia_Mutex *mutex) {
u32 p_tag; u32 p_tag;
for(;;) { for(;;) {
//p_tag = __sync_val_compare_and_swap(&mutex->tag, _CIA_MUTEX_FREE, _CIA_MUTEX_LOCK);
p_tag = _CIA_MUTEX_FREE; p_tag = _CIA_MUTEX_FREE;
atomic_compare_exchange_strong_explicit( atomic_compare_exchange_strong_explicit(
&mutex->tag &mutex->tag
, &p_tag , &p_tag
, _CIA_MUTEX_LOCK , _CIA_MUTEX_LOCK
, memory_order_relaxed , memory_order_acquire
, memory_order_relaxed , memory_order_relaxed
); );
// We got the mutex, lets bail // We got the mutex, lets bail
if(p_tag == _CIA_MUTEX_FREE) { if(p_tag == _CIA_MUTEX_FREE) {
break; break;
} }
#if 0 #if 1
_rt_sync_wait(&mutex->tag, _CIA_MUTEX_LOCK, _RT_SYNC_WAIT_INFINITE);
#else
// We should wait if: // We should wait if:
// (1) the mutex is contested // (1) the mutex is contested
// (2) // (2)
@ -34,8 +35,6 @@ void cia_mutex_lock(Cia_Mutex *mutex) {
if(should_wait) { if(should_wait) {
_rt_sync_wait(&mutex->tag, _CIA_MUTEX_CONT, _RT_SYNC_WAIT_INFINITE); _rt_sync_wait(&mutex->tag, _CIA_MUTEX_CONT, _RT_SYNC_WAIT_INFINITE);
} }
#else
_rt_sync_wait(&mutex->tag, _CIA_MUTEX_LOCK, _RT_SYNC_WAIT_INFINITE);
#endif #endif
} }
} }
@ -43,6 +42,6 @@ void cia_mutex_lock(Cia_Mutex *mutex) {
void cia_mutex_unlock(Cia_Mutex *mutex) { void cia_mutex_unlock(Cia_Mutex *mutex) {
// TODO: add error when we unlock a free mutex // TODO: add error when we unlock a free mutex
// TODO: support recursive muteces // TODO: support recursive muteces
atomic_store_explicit(&mutex->tag, _CIA_MUTEX_FREE, memory_order_relaxed); atomic_store_explicit(&mutex->tag, _CIA_MUTEX_FREE, memory_order_release);
_rt_sync_wake_one(&mutex->tag, NULL); _rt_sync_wake_one(&mutex->tag, NULL);
} }