mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-20 16:36:46 +00:00
Update sync2 to just use atomic intrinsics rather than the parapoly wrappers
This commit is contained in:
@@ -4,7 +4,6 @@ package sync2
|
||||
|
||||
when !#config(ODIN_SYNC_USE_PTHREADS, false) {
|
||||
|
||||
import "intrinsics"
|
||||
import "core:time"
|
||||
|
||||
_Mutex_State :: enum i32 {
|
||||
@@ -17,13 +16,13 @@ _Mutex :: struct {
|
||||
}
|
||||
|
||||
_mutex_lock :: proc(m: ^Mutex) {
|
||||
if intrinsics.atomic_xchg_rel(&m.impl.state, .Unlocked) != .Unlocked {
|
||||
if atomic_xchg_rel(&m.impl.state, .Unlocked) != .Unlocked {
|
||||
_mutex_unlock_slow(m);
|
||||
}
|
||||
}
|
||||
|
||||
_mutex_unlock :: proc(m: ^Mutex) {
|
||||
switch intrinsics.atomic_xchg_rel(&m.impl.state, .Unlocked) {
|
||||
switch atomic_xchg_rel(&m.impl.state, .Unlocked) {
|
||||
case .Unlocked:
|
||||
unreachable();
|
||||
case .Locked:
|
||||
@@ -34,7 +33,7 @@ _mutex_unlock :: proc(m: ^Mutex) {
|
||||
}
|
||||
|
||||
_mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
_, ok := intrinsics.atomic_cxchg_acq(&m.impl.state, .Unlocked, .Locked);
|
||||
_, ok := atomic_cxchg_acq(&m.impl.state, .Unlocked, .Locked);
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ _mutex_lock_slow :: proc(m: ^Mutex, curr_state: _Mutex_State) {
|
||||
new_state := curr_state; // Make a copy of it
|
||||
|
||||
spin_lock: for spin in 0..<i32(100) {
|
||||
state, ok := intrinsics.atomic_cxchgweak_acq(&m.impl.state, .Unlocked, new_state);
|
||||
state, ok := atomic_cxchgweak_acq(&m.impl.state, .Unlocked, new_state);
|
||||
if ok {
|
||||
return;
|
||||
}
|
||||
@@ -54,17 +53,17 @@ _mutex_lock_slow :: proc(m: ^Mutex, curr_state: _Mutex_State) {
|
||||
}
|
||||
|
||||
for i := min(spin+1, 32); i > 0; i -= 1 {
|
||||
intrinsics.cpu_relax();
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
if intrinsics.atomic_xchg_acq(&m.impl.state, .Waiting) == .Unlocked {
|
||||
if atomic_xchg_acq(&m.impl.state, .Waiting) == .Unlocked {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(bill): Use a Futex here for Linux to improve performance and error handling
|
||||
intrinsics.cpu_relax();
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,25 +90,25 @@ _RW_Mutex :: struct {
|
||||
}
|
||||
|
||||
_rw_mutex_lock :: proc(rw: ^RW_Mutex) {
|
||||
_ = intrinsics.atomic_add(&rw.impl.state, RW_Mutex_State_Writer);
|
||||
_ = atomic_add(&rw.impl.state, RW_Mutex_State_Writer);
|
||||
mutex_lock(&rw.impl.mutex);
|
||||
|
||||
state := intrinsics.atomic_or(&rw.impl.state, RW_Mutex_State_Writer);
|
||||
state := atomic_or(&rw.impl.state, RW_Mutex_State_Writer);
|
||||
if state & RW_Mutex_State_Reader_Mask != 0 {
|
||||
sema_wait(&rw.impl.sema);
|
||||
}
|
||||
}
|
||||
|
||||
_rw_mutex_unlock :: proc(rw: ^RW_Mutex) {
|
||||
_ = intrinsics.atomic_and(&rw.impl.state, ~RW_Mutex_State_Is_Writing);
|
||||
_ = atomic_and(&rw.impl.state, ~RW_Mutex_State_Is_Writing);
|
||||
mutex_unlock(&rw.impl.mutex);
|
||||
}
|
||||
|
||||
_rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
if mutex_try_lock(&rw.impl.mutex) {
|
||||
state := intrinsics.atomic_load(&rw.impl.state);
|
||||
state := atomic_load(&rw.impl.state);
|
||||
if state & RW_Mutex_State_Reader_Mask == 0 {
|
||||
_ = intrinsics.atomic_or(&rw.impl.state, RW_Mutex_State_Is_Writing);
|
||||
_ = atomic_or(&rw.impl.state, RW_Mutex_State_Is_Writing);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -119,22 +118,22 @@ _rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
}
|
||||
|
||||
_rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) {
|
||||
state := intrinsics.atomic_load(&rw.impl.state);
|
||||
state := atomic_load(&rw.impl.state);
|
||||
for state & (RW_Mutex_State_Is_Writing|RW_Mutex_State_Writer_Mask) == 0 {
|
||||
ok: bool;
|
||||
state, ok = intrinsics.atomic_cxchgweak(&rw.impl.state, state, state + RW_Mutex_State_Reader);
|
||||
state, ok = atomic_cxchgweak(&rw.impl.state, state, state + RW_Mutex_State_Reader);
|
||||
if ok {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&rw.impl.mutex);
|
||||
_ = intrinsics.atomic_add(&rw.impl.state, RW_Mutex_State_Reader);
|
||||
_ = atomic_add(&rw.impl.state, RW_Mutex_State_Reader);
|
||||
mutex_unlock(&rw.impl.mutex);
|
||||
}
|
||||
|
||||
_rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) {
|
||||
state := intrinsics.atomic_sub(&rw.impl.state, RW_Mutex_State_Reader);
|
||||
state := atomic_sub(&rw.impl.state, RW_Mutex_State_Reader);
|
||||
|
||||
if (state & RW_Mutex_State_Reader_Mask == RW_Mutex_State_Reader) &&
|
||||
(state & RW_Mutex_State_Is_Writing != 0) {
|
||||
@@ -143,15 +142,15 @@ _rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) {
|
||||
}
|
||||
|
||||
_rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||
state := intrinsics.atomic_load(&rw.impl.state);
|
||||
state := atomic_load(&rw.impl.state);
|
||||
if state & (RW_Mutex_State_Is_Writing|RW_Mutex_State_Writer_Mask) == 0 {
|
||||
_, ok := intrinsics.atomic_cxchg(&rw.impl.state, state, state + RW_Mutex_State_Reader);
|
||||
_, ok := atomic_cxchg(&rw.impl.state, state, state + RW_Mutex_State_Reader);
|
||||
if ok {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if mutex_try_lock(&rw.impl.mutex) {
|
||||
_ = intrinsics.atomic_add(&rw.impl.state, RW_Mutex_State_Reader);
|
||||
_ = atomic_add(&rw.impl.state, RW_Mutex_State_Reader);
|
||||
mutex_unlock(&rw.impl.mutex);
|
||||
return true;
|
||||
}
|
||||
@@ -167,13 +166,13 @@ Queue_Item :: struct {
|
||||
}
|
||||
|
||||
queue_item_wait :: proc(item: ^Queue_Item) {
|
||||
for intrinsics.atomic_load_acq(&item.futex) == 0 {
|
||||
for atomic_load_acq(&item.futex) == 0 {
|
||||
// TODO(bill): Use a Futex here for Linux to improve performance and error handling
|
||||
intrinsics.cpu_relax();
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
queue_item_signal :: proc(item: ^Queue_Item) {
|
||||
intrinsics.atomic_store_rel(&item.futex, 1);
|
||||
atomic_store_rel(&item.futex, 1);
|
||||
// TODO(bill): Use a Futex here for Linux to improve performance and error handling
|
||||
}
|
||||
|
||||
@@ -191,7 +190,7 @@ _cond_wait :: proc(c: ^Cond, m: ^Mutex) {
|
||||
waiter.next = c.impl.queue_head;
|
||||
c.impl.queue_head = waiter;
|
||||
|
||||
intrinsics.atomic_store(&c.impl.pending, true);
|
||||
atomic_store(&c.impl.pending, true);
|
||||
mutex_unlock(&c.impl.queue_mutex);
|
||||
|
||||
mutex_unlock(m);
|
||||
@@ -205,7 +204,7 @@ _cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, timeout: time.Duration) ->
|
||||
}
|
||||
|
||||
_cond_signal :: proc(c: ^Cond) {
|
||||
if !intrinsics.atomic_load(&c.impl.pending) {
|
||||
if !atomic_load(&c.impl.pending) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -214,7 +213,7 @@ _cond_signal :: proc(c: ^Cond) {
|
||||
if c.impl.queue_head != nil {
|
||||
c.impl.queue_head = c.impl.queue_head.next;
|
||||
}
|
||||
intrinsics.atomic_store(&c.impl.pending, c.impl.queue_head != nil);
|
||||
atomic_store(&c.impl.pending, c.impl.queue_head != nil);
|
||||
mutex_unlock(&c.impl.queue_mutex);
|
||||
|
||||
if waiter != nil {
|
||||
@@ -223,11 +222,11 @@ _cond_signal :: proc(c: ^Cond) {
|
||||
}
|
||||
|
||||
_cond_broadcast :: proc(c: ^Cond) {
|
||||
if !intrinsics.atomic_load(&c.impl.pending) {
|
||||
if !atomic_load(&c.impl.pending) {
|
||||
return;
|
||||
}
|
||||
|
||||
intrinsics.atomic_store(&c.impl.pending, false);
|
||||
atomic_store(&c.impl.pending, false);
|
||||
|
||||
mutex_lock(&c.impl.queue_mutex);
|
||||
waiters := c.impl.queue_head;
|
||||
|
||||
Reference in New Issue
Block a user