mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 09:22:22 -07:00
Implement sync2.Recursive_Mutex using WaitOnAddress and friends on Windows
This commit is contained in:
@@ -72,52 +72,19 @@ rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
//
|
||||
// A Recursive_Mutex must not be copied after first use
|
||||
Recursive_Mutex :: struct {
|
||||
// TODO(bill): Is this implementation too lazy?
|
||||
// Can this be made to work on all OSes without construction and destruction, i.e. Zero is Initialized
|
||||
// CRITICAL_SECTION would be a perfect candidate for this on Windows but that cannot be "dumb"
|
||||
|
||||
owner: int,
|
||||
recursion: int,
|
||||
mutex: Mutex,
|
||||
impl: _Recursive_Mutex,
|
||||
}
|
||||
|
||||
recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
|
||||
tid := runtime.current_thread_id();
|
||||
if tid != m.owner {
|
||||
mutex_lock(&m.mutex);
|
||||
}
|
||||
// inside the lock
|
||||
m.owner = tid;
|
||||
m.recursion += 1;
|
||||
_recursive_mutex_lock(m);
|
||||
}
|
||||
|
||||
recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
||||
tid := runtime.current_thread_id();
|
||||
assert(tid == m.owner);
|
||||
m.recursion -= 1;
|
||||
recursion := m.recursion;
|
||||
if recursion == 0 {
|
||||
m.owner = 0;
|
||||
}
|
||||
if recursion == 0 {
|
||||
mutex_unlock(&m.mutex);
|
||||
}
|
||||
// outside the lock
|
||||
|
||||
_recursive_mutex_unlock(m);
|
||||
}
|
||||
|
||||
recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
||||
tid := runtime.current_thread_id();
|
||||
if m.owner == tid {
|
||||
return mutex_try_lock(&m.mutex);
|
||||
}
|
||||
if !mutex_try_lock(&m.mutex) {
|
||||
return false;
|
||||
}
|
||||
// inside the lock
|
||||
m.owner = tid;
|
||||
m.recursion += 1;
|
||||
return true;
|
||||
return _recursive_mutex_try_lock(m);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ package sync2
|
||||
when !#config(ODIN_SYNC_USE_PTHREADS, true) {
|
||||
|
||||
import "core:time"
|
||||
import "core:runtime"
|
||||
|
||||
_Mutex_State :: enum i32 {
|
||||
Unlocked = 0,
|
||||
@@ -160,6 +161,54 @@ _rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
}
|
||||
|
||||
|
||||
_Recursive_Mutex :: struct {
|
||||
owner: int,
|
||||
recursion: int,
|
||||
mutex: Mutex,
|
||||
}
|
||||
|
||||
_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
|
||||
tid := runtime.current_thread_id();
|
||||
if tid != m.impl.owner {
|
||||
mutex_lock(&m.impl.mutex);
|
||||
}
|
||||
// inside the lock
|
||||
m.impl.owner = tid;
|
||||
m.impl.recursion += 1;
|
||||
}
|
||||
|
||||
_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
||||
tid := runtime.current_thread_id();
|
||||
assert(tid == m.impl.owner);
|
||||
m.impl.recursion -= 1;
|
||||
recursion := m.impl.recursion;
|
||||
if recursion == 0 {
|
||||
m.impl.owner = 0;
|
||||
}
|
||||
if recursion == 0 {
|
||||
mutex_unlock(&m.impl.mutex);
|
||||
}
|
||||
// outside the lock
|
||||
|
||||
}
|
||||
|
||||
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
||||
tid := runtime.current_thread_id();
|
||||
if m.impl.owner == tid {
|
||||
return mutex_try_lock(&m.impl.mutex);
|
||||
}
|
||||
if !mutex_try_lock(&m.impl.mutex) {
|
||||
return false;
|
||||
}
|
||||
// inside the lock
|
||||
m.impl.owner = tid;
|
||||
m.impl.recursion += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Queue_Item :: struct {
|
||||
next: ^Queue_Item,
|
||||
|
||||
@@ -5,6 +5,7 @@ package sync2
|
||||
when #config(ODIN_SYNC_USE_PTHREADS, true) {
|
||||
|
||||
import "core:time"
|
||||
import "core:runtime"
|
||||
import "core:sys/unix"
|
||||
|
||||
_Mutex_State :: enum i32 {
|
||||
@@ -120,6 +121,53 @@ _rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
_Recursive_Mutex :: struct {
|
||||
owner: int,
|
||||
recursion: int,
|
||||
mutex: Mutex,
|
||||
}
|
||||
|
||||
_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
|
||||
tid := runtime.current_thread_id();
|
||||
if tid != m.impl.owner {
|
||||
mutex_lock(&m.impl.mutex);
|
||||
}
|
||||
// inside the lock
|
||||
m.impl.owner = tid;
|
||||
m.impl.recursion += 1;
|
||||
}
|
||||
|
||||
_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
||||
tid := runtime.current_thread_id();
|
||||
assert(tid == m.impl.owner);
|
||||
m.impl.recursion -= 1;
|
||||
recursion := m.impl.recursion;
|
||||
if recursion == 0 {
|
||||
m.impl.owner = 0;
|
||||
}
|
||||
if recursion == 0 {
|
||||
mutex_unlock(&m.impl.mutex);
|
||||
}
|
||||
// outside the lock
|
||||
|
||||
}
|
||||
|
||||
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
||||
tid := runtime.current_thread_id();
|
||||
if m.impl.owner == tid {
|
||||
return mutex_try_lock(&m.impl.mutex);
|
||||
}
|
||||
if !mutex_try_lock(&m.impl.mutex) {
|
||||
return false;
|
||||
}
|
||||
// inside the lock
|
||||
m.impl.owner = tid;
|
||||
m.impl.recursion += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
_Cond :: struct {
|
||||
pthread_cond: unix.pthread_cond_t,
|
||||
}
|
||||
|
||||
@@ -50,6 +50,56 @@ _rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
}
|
||||
|
||||
|
||||
_Recursive_Mutex :: struct {
|
||||
owner: u32,
|
||||
claim_count: i32,
|
||||
}
|
||||
|
||||
_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
|
||||
tid := win32.GetCurrentThreadId();
|
||||
for {
|
||||
prev_owner := atomic_cxchg_acq(&m.impl.owner, tid, 0);
|
||||
switch prev_owner {
|
||||
case 0, tid:
|
||||
m.impl.claim_count += 1;
|
||||
// inside the lock
|
||||
return;
|
||||
}
|
||||
|
||||
win32.WaitOnAddress(
|
||||
&m.impl.owner,
|
||||
&prev_owner,
|
||||
size_of(prev_owner),
|
||||
win32.INFINITE,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
||||
m.impl.claim_count -= 1;
|
||||
if m.impl.claim_count != 0 {
|
||||
return;
|
||||
}
|
||||
atomic_xchg_rel(&m.impl.owner, 0);
|
||||
win32.WakeByAddressSingle(&m.impl.owner);
|
||||
// outside the lock
|
||||
|
||||
}
|
||||
|
||||
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
||||
tid := win32.GetCurrentThreadId();
|
||||
prev_owner := atomic_cxchg_acq(&m.impl.owner, tid, 0);
|
||||
switch prev_owner {
|
||||
case 0, tid:
|
||||
m.impl.claim_count += 1;
|
||||
// inside the lock
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
_Cond :: struct {
|
||||
cond: win32.CONDITION_VARIABLE,
|
||||
|
||||
Reference in New Issue
Block a user