aboutsummaryrefslogtreecommitdiff
path: root/core/sync
diff options
context:
space:
mode:
authorKarl Zylinski <karl@zylinski.se>2024-09-17 19:36:17 +0200
committerKarl Zylinski <karl@zylinski.se>2024-09-17 19:36:17 +0200
commit093ade050445b3e348177e30fb1fc9d726f7b289 (patch)
tree5122cfefa5fefbab9d27d5d8adacd8739eeeb5de /core/sync
parent3d7b92426081cd9f3197b13f7384a52dbac5379a (diff)
parent6ef779cd5c8260b2e6979e676d28489fd53dd599 (diff)
Merge branch 'master' into file-tags-without-comments
Diffstat (limited to 'core/sync')
-rw-r--r--core/sync/chan/chan.odin83
-rw-r--r--core/sync/extended.odin75
-rw-r--r--core/sync/futex_darwin.odin25
-rw-r--r--core/sync/futex_freebsd.odin8
-rw-r--r--core/sync/futex_linux.odin8
-rw-r--r--core/sync/futex_netbsd.odin8
-rw-r--r--core/sync/futex_openbsd.odin8
-rw-r--r--core/sync/futex_wasm.odin8
-rw-r--r--core/sync/primitives.odin20
-rw-r--r--core/sync/primitives_atomic.odin4
10 files changed, 121 insertions, 126 deletions
diff --git a/core/sync/chan/chan.odin b/core/sync/chan/chan.odin
index 53a3bff4b..c470d15f3 100644
--- a/core/sync/chan/chan.odin
+++ b/core/sync/chan/chan.odin
@@ -22,19 +22,17 @@ Raw_Chan :: struct {
allocator: runtime.Allocator,
allocation_size: int,
msg_size: u16,
- closed: b16, // atomic
+ closed: b16, // guarded by `mutex`
mutex: sync.Mutex,
r_cond: sync.Cond,
w_cond: sync.Cond,
- r_waiting: int, // atomic
- w_waiting: int, // atomic
+ r_waiting: int, // guarded by `mutex`
+ w_waiting: int, // guarded by `mutex`
// Buffered
queue: ^Raw_Queue,
// Unbuffered
- r_mutex: sync.Mutex,
- w_mutex: sync.Mutex,
unbuffered_data: rawptr,
}
@@ -164,27 +162,30 @@ send_raw :: proc "contextless" (c: ^Raw_Chan, msg_in: rawptr) -> (ok: bool) {
}
if c.queue != nil { // buffered
sync.guard(&c.mutex)
- for c.queue.len == c.queue.cap {
- sync.atomic_add(&c.w_waiting, 1)
+ for !c.closed && c.queue.len == c.queue.cap {
+ c.w_waiting += 1
sync.wait(&c.w_cond, &c.mutex)
- sync.atomic_sub(&c.w_waiting, 1)
+ c.w_waiting -= 1
+ }
+
+ if c.closed {
+ return false
}
ok = raw_queue_push(c.queue, msg_in)
- if sync.atomic_load(&c.r_waiting) > 0 {
+ if c.r_waiting > 0 {
sync.signal(&c.r_cond)
}
} else if c.unbuffered_data != nil { // unbuffered
- sync.guard(&c.w_mutex)
sync.guard(&c.mutex)
- if sync.atomic_load(&c.closed) {
+ if c.closed {
return false
}
mem.copy(c.unbuffered_data, msg_in, int(c.msg_size))
- sync.atomic_add(&c.w_waiting, 1)
- if sync.atomic_load(&c.r_waiting) > 0 {
+ c.w_waiting += 1
+ if c.r_waiting > 0 {
sync.signal(&c.r_cond)
}
sync.wait(&c.w_cond, &c.mutex)
@@ -201,13 +202,13 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) {
if c.queue != nil { // buffered
sync.guard(&c.mutex)
for c.queue.len == 0 {
- if sync.atomic_load(&c.closed) {
+ if c.closed {
return
}
- sync.atomic_add(&c.r_waiting, 1)
+ c.r_waiting += 1
sync.wait(&c.r_cond, &c.mutex)
- sync.atomic_sub(&c.r_waiting, 1)
+ c.r_waiting -= 1
}
msg := raw_queue_pop(c.queue)
@@ -215,27 +216,26 @@ recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> (ok: bool) {
mem.copy(msg_out, msg, int(c.msg_size))
}
- if sync.atomic_load(&c.w_waiting) > 0 {
+ if c.w_waiting > 0 {
sync.signal(&c.w_cond)
}
ok = true
} else if c.unbuffered_data != nil { // unbuffered
- sync.guard(&c.r_mutex)
sync.guard(&c.mutex)
- for !sync.atomic_load(&c.closed) &&
- sync.atomic_load(&c.w_waiting) == 0 {
- sync.atomic_add(&c.r_waiting, 1)
+ for !c.closed &&
+ c.w_waiting == 0 {
+ c.r_waiting += 1
sync.wait(&c.r_cond, &c.mutex)
- sync.atomic_sub(&c.r_waiting, 1)
+ c.r_waiting -= 1
}
- if sync.atomic_load(&c.closed) {
+ if c.closed {
return
}
mem.copy(msg_out, c.unbuffered_data, int(c.msg_size))
- sync.atomic_sub(&c.w_waiting, 1)
+ c.w_waiting -= 1
sync.signal(&c.w_cond)
ok = true
@@ -255,21 +255,24 @@ try_send_raw :: proc "contextless" (c: ^Raw_Chan, msg_in: rawptr) -> (ok: bool)
return false
}
+ if c.closed {
+ return false
+ }
+
ok = raw_queue_push(c.queue, msg_in)
- if sync.atomic_load(&c.r_waiting) > 0 {
+ if c.r_waiting > 0 {
sync.signal(&c.r_cond)
}
} else if c.unbuffered_data != nil { // unbuffered
- sync.guard(&c.w_mutex)
sync.guard(&c.mutex)
- if sync.atomic_load(&c.closed) {
+ if c.closed {
return false
}
mem.copy(c.unbuffered_data, msg_in, int(c.msg_size))
- sync.atomic_add(&c.w_waiting, 1)
- if sync.atomic_load(&c.r_waiting) > 0 {
+ c.w_waiting += 1
+ if c.r_waiting > 0 {
sync.signal(&c.r_cond)
}
sync.wait(&c.w_cond, &c.mutex)
@@ -294,21 +297,19 @@ try_recv_raw :: proc "contextless" (c: ^Raw_Chan, msg_out: rawptr) -> bool {
mem.copy(msg_out, msg, int(c.msg_size))
}
- if sync.atomic_load(&c.w_waiting) > 0 {
+ if c.w_waiting > 0 {
sync.signal(&c.w_cond)
}
return true
} else if c.unbuffered_data != nil { // unbuffered
- sync.guard(&c.r_mutex)
sync.guard(&c.mutex)
- if sync.atomic_load(&c.closed) ||
- sync.atomic_load(&c.w_waiting) == 0 {
+ if c.closed || c.w_waiting == 0 {
return false
}
mem.copy(msg_out, c.unbuffered_data, int(c.msg_size))
- sync.atomic_sub(&c.w_waiting, 1)
+ c.w_waiting -= 1
sync.signal(&c.w_cond)
return true
@@ -351,10 +352,10 @@ close :: proc "contextless" (c: ^Raw_Chan) -> bool {
return false
}
sync.guard(&c.mutex)
- if sync.atomic_load(&c.closed) {
+ if c.closed {
return false
}
- sync.atomic_store(&c.closed, true)
+ c.closed = true
sync.broadcast(&c.r_cond)
sync.broadcast(&c.w_cond)
return true
@@ -366,7 +367,7 @@ is_closed :: proc "contextless" (c: ^Raw_Chan) -> bool {
return true
}
sync.guard(&c.mutex)
- return bool(sync.atomic_load(&c.closed))
+ return bool(c.closed)
}
@@ -423,9 +424,9 @@ raw_queue_pop :: proc "contextless" (q: ^Raw_Queue) -> (data: rawptr) {
can_recv :: proc "contextless" (c: ^Raw_Chan) -> bool {
sync.guard(&c.mutex)
if is_buffered(c) {
- return len(c) > 0
+ return c.queue.len > 0
}
- return sync.atomic_load(&c.w_waiting) > 0
+ return c.w_waiting > 0
}
@@ -435,7 +436,7 @@ can_send :: proc "contextless" (c: ^Raw_Chan) -> bool {
if is_buffered(c) {
return c.queue.len < c.queue.cap
}
- return sync.atomic_load(&c.r_waiting) > 0
+ return c.w_waiting == 0
}
@@ -484,4 +485,4 @@ select_raw :: proc "odin" (recvs: []^Raw_Chan, sends: []^Raw_Chan, send_msgs: []
ok = send_raw(sends[sel.idx], send_msgs[sel.idx])
}
return
-} \ No newline at end of file
+}
diff --git a/core/sync/extended.odin b/core/sync/extended.odin
index b446fefa0..30b1b2770 100644
--- a/core/sync/extended.odin
+++ b/core/sync/extended.odin
@@ -8,7 +8,7 @@ _ :: vg
Wait group.
Wait group is a synchronization primitive used by the waiting thread to wait,
-until a all working threads finish work.
+until all working threads finish work.
The waiting thread first sets the number of working threads it will expect to
wait for using `wait_group_add` call, and start waiting using `wait_group_wait`
@@ -35,7 +35,7 @@ Wait_Group :: struct #no_copy {
/*
Increment an internal counter of a wait group.
-This procedure atomicaly increments a number to the specified wait group's
+This procedure atomically increments a number to the specified wait group's
internal counter by a specified amount. This operation can be done on any
thread.
*/
@@ -48,12 +48,12 @@ wait_group_add :: proc "contextless" (wg: ^Wait_Group, delta: int) {
atomic_add(&wg.counter, delta)
if wg.counter < 0 {
- _panic("sync.Wait_Group negative counter")
+ panic_contextless("sync.Wait_Group negative counter")
}
if wg.counter == 0 {
cond_broadcast(&wg.cond)
if wg.counter != 0 {
- _panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
+ panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
}
}
}
@@ -81,7 +81,7 @@ wait_group_wait :: proc "contextless" (wg: ^Wait_Group) {
if wg.counter != 0 {
cond_wait(&wg.cond, &wg.mutex)
if wg.counter != 0 {
- _panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
+ panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
}
}
}
@@ -105,7 +105,7 @@ wait_group_wait_with_timeout :: proc "contextless" (wg: ^Wait_Group, duration: t
return false
}
if wg.counter != 0 {
- _panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
+ panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
}
}
return true
@@ -121,7 +121,7 @@ When `barrier_wait` procedure is called by any thread, that thread will block
the execution, until all threads associated with the barrier reach the same
point of execution and also call `barrier_wait`.
-when barrier is initialized, a `thread_count` parameter is passed, signifying
+When a barrier is initialized, a `thread_count` parameter is passed, signifying
the amount of participant threads of the barrier. The barrier also keeps track
of an internal atomic counter. When a thread calls `barrier_wait`, the internal
counter is incremented. When the internal counter reaches `thread_count`, it is
@@ -208,7 +208,7 @@ Represents a thread synchronization primitive that, when signalled, releases one
single waiting thread and then resets automatically to a state where it can be
signalled again.
-When a thread calls `auto_reset_event_wait`, it's execution will be blocked,
+When a thread calls `auto_reset_event_wait`, its execution will be blocked,
until the event is signalled by another thread. The call to
`auto_reset_event_signal` wakes up exactly one thread waiting for the event.
*/
@@ -228,15 +228,15 @@ thread.
*/
auto_reset_event_signal :: proc "contextless" (e: ^Auto_Reset_Event) {
old_status := atomic_load_explicit(&e.status, .Relaxed)
+ new_status := old_status + 1 if old_status < 1 else 1
for {
- new_status := old_status + 1 if old_status < 1 else 1
if _, ok := atomic_compare_exchange_weak_explicit(&e.status, old_status, new_status, .Release, .Relaxed); ok {
break
}
-
- if old_status < 0 {
- sema_post(&e.sema)
- }
+ cpu_relax()
+ }
+ if old_status < 0 {
+ sema_post(&e.sema)
}
}
@@ -297,7 +297,7 @@ waiting to acquire the lock, exactly one of those threads is unblocked and
allowed into the critical section.
*/
ticket_mutex_unlock :: #force_inline proc "contextless" (m: ^Ticket_Mutex) {
- atomic_add_explicit(&m.serving, 1, .Relaxed)
+ atomic_add_explicit(&m.serving, 1, .Release)
}
/*
@@ -331,8 +331,8 @@ Benaphore.
A benaphore is a combination of an atomic variable and a semaphore that can
improve locking efficiency in a no-contention system. Acquiring a benaphore
-lock doesn't call into an internal semaphore, if no other thread in a middle of
-a critical section.
+lock doesn't call into an internal semaphore, if no other thread is in the
+middle of a critical section.
Once a lock on a benaphore is acquired by a thread, no other thread is allowed
into any critical sections, associted with the same benaphore, until the lock
@@ -355,7 +355,7 @@ from entering any critical sections associated with the same benaphore, until
until the lock is released.
*/
benaphore_lock :: proc "contextless" (b: ^Benaphore) {
- if atomic_add_explicit(&b.counter, 1, .Acquire) > 1 {
+ if atomic_add_explicit(&b.counter, 1, .Acquire) > 0 {
sema_wait(&b.sema)
}
}
@@ -381,10 +381,10 @@ Release a lock on a benaphore.
This procedure releases a lock on the specified benaphore. If any of the threads
are waiting on the lock, exactly one thread is allowed into a critical section
-associated with the same banaphore.
+associated with the same benaphore.
*/
benaphore_unlock :: proc "contextless" (b: ^Benaphore) {
- if atomic_sub_explicit(&b.counter, 1, .Release) > 0 {
+ if atomic_sub_explicit(&b.counter, 1, .Release) > 1 {
sema_post(&b.sema)
}
}
@@ -418,8 +418,8 @@ benaphore_guard :: proc "contextless" (m: ^Benaphore) -> bool {
/*
Recursive benaphore.
-Recurisve benaphore is just like a plain benaphore, except it allows reentrancy
-into the critical section.
+A recursive benaphore is just like a plain benaphore, except it allows
+reentrancy into the critical section.
When a lock is acquired on a benaphore, all other threads attempting to
acquire a lock on the same benaphore will be blocked from any critical sections,
@@ -449,13 +449,15 @@ recursive benaphore, until the lock is released.
*/
recursive_benaphore_lock :: proc "contextless" (b: ^Recursive_Benaphore) {
tid := current_thread_id()
- if atomic_add_explicit(&b.counter, 1, .Acquire) > 1 {
- if tid != b.owner {
- sema_wait(&b.sema)
+ check_owner: if tid != atomic_load_explicit(&b.owner, .Acquire) {
+ atomic_add_explicit(&b.counter, 1, .Relaxed)
+ if _, ok := atomic_compare_exchange_strong_explicit(&b.owner, 0, tid, .Release, .Relaxed); ok {
+ break check_owner
}
+ sema_wait(&b.sema)
+ atomic_store_explicit(&b.owner, tid, .Release)
}
// inside the lock
- b.owner = tid
b.recursion += 1
}
@@ -472,15 +474,14 @@ benaphore, until the lock is released.
*/
recursive_benaphore_try_lock :: proc "contextless" (b: ^Recursive_Benaphore) -> bool {
tid := current_thread_id()
- if b.owner == tid {
- atomic_add_explicit(&b.counter, 1, .Acquire)
- }
-
- if v, _ := atomic_compare_exchange_strong_explicit(&b.counter, 0, 1, .Acquire, .Acquire); v != 0 {
+ check_owner: if tid != atomic_load_explicit(&b.owner, .Acquire) {
+ if _, ok := atomic_compare_exchange_strong_explicit(&b.owner, 0, tid, .Release, .Relaxed); ok {
+ atomic_add_explicit(&b.counter, 1, .Relaxed)
+ break check_owner
+ }
return false
}
// inside the lock
- b.owner = tid
b.recursion += 1
return true
}
@@ -494,14 +495,14 @@ for other threads for entering.
*/
recursive_benaphore_unlock :: proc "contextless" (b: ^Recursive_Benaphore) {
tid := current_thread_id()
- _assert(tid == b.owner, "tid != b.owner")
+ assert_contextless(tid == atomic_load_explicit(&b.owner, .Relaxed), "tid != b.owner")
b.recursion -= 1
recursion := b.recursion
+
if recursion == 0 {
- b.owner = 0
- }
- if atomic_sub_explicit(&b.counter, 1, .Release) > 0 {
- if recursion == 0 {
+ if atomic_sub_explicit(&b.counter, 1, .Relaxed) == 1 {
+ atomic_store_explicit(&b.owner, 0, .Release)
+ } else {
sema_post(&b.sema)
}
}
@@ -740,4 +741,4 @@ Make event available.
one_shot_event_signal :: proc "contextless" (e: ^One_Shot_Event) {
atomic_store_explicit(&e.state, 1, .Release)
futex_broadcast(&e.state)
-} \ No newline at end of file
+}
diff --git a/core/sync/futex_darwin.odin b/core/sync/futex_darwin.odin
index 5b5f53c20..10ff7bfbb 100644
--- a/core/sync/futex_darwin.odin
+++ b/core/sync/futex_darwin.odin
@@ -12,6 +12,8 @@ foreign System {
// __ulock_wait is not available on 10.15
// See https://github.com/odin-lang/Odin/issues/1959
__ulock_wait :: proc "c" (operation: u32, addr: rawptr, value: u64, timeout_us: u32) -> c.int ---
+ // >= MacOS 11.
+ __ulock_wait2 :: proc "c" (operation: u32, addr: rawptr, value: u64, timeout_ns: u64, value2: u64) -> c.int ---
__ulock_wake :: proc "c" (operation: u32, addr: rawptr, wake_value: u64) -> c.int ---
}
@@ -48,22 +50,29 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, durati
case -ETIMEDOUT:
return false
case:
- _panic("darwin.os_sync_wait_on_address_with_timeout failure")
+ panic_contextless("darwin.os_sync_wait_on_address_with_timeout failure")
}
} else {
- timeout_ns := u32(duration)
- s := __ulock_wait(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO, f, u64(expected), timeout_ns)
+ when darwin.ULOCK_WAIT_2_AVAILABLE {
+ timeout_ns := u64(duration)
+ s := __ulock_wait2(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO, f, u64(expected), timeout_ns, 0)
+ } else {
+ timeout_us := u32(duration / time.Microsecond)
+ s := __ulock_wait(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO, f, u64(expected), timeout_us)
+ }
+
if s >= 0 {
return true
}
+
switch s {
case EINTR, EFAULT:
return true
case ETIMEDOUT:
return false
case:
- _panic("futex_wait failure")
+ panic_contextless("futex_wait failure")
}
return true
@@ -83,7 +92,7 @@ _futex_signal :: proc "contextless" (f: ^Futex) {
case -ENOENT:
return
case:
- _panic("darwin.os_sync_wake_by_address_any failure")
+ panic_contextless("darwin.os_sync_wake_by_address_any failure")
}
}
} else {
@@ -99,7 +108,7 @@ _futex_signal :: proc "contextless" (f: ^Futex) {
case ENOENT:
return
case:
- _panic("futex_wake_single failure")
+ panic_contextless("futex_wake_single failure")
}
}
@@ -119,7 +128,7 @@ _futex_broadcast :: proc "contextless" (f: ^Futex) {
case -ENOENT:
return
case:
- _panic("darwin.os_sync_wake_by_address_all failure")
+ panic_contextless("darwin.os_sync_wake_by_address_all failure")
}
}
} else {
@@ -135,7 +144,7 @@ _futex_broadcast :: proc "contextless" (f: ^Futex) {
case ENOENT:
return
case:
- _panic("futex_wake_all failure")
+ panic_contextless("futex_wake_all failure")
}
}
diff --git a/core/sync/futex_freebsd.odin b/core/sync/futex_freebsd.odin
index 4fbb33ee0..e3f95b146 100644
--- a/core/sync/futex_freebsd.odin
+++ b/core/sync/futex_freebsd.odin
@@ -21,7 +21,7 @@ _futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool {
continue
}
- _panic("_futex_wait failure")
+ panic_contextless("_futex_wait failure")
}
unreachable()
@@ -44,14 +44,14 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, durati
return false
}
- _panic("_futex_wait_with_timeout failure")
+ panic_contextless("_futex_wait_with_timeout failure")
}
_futex_signal :: proc "contextless" (f: ^Futex) {
errno := freebsd._umtx_op(f, .WAKE, 1, nil, nil)
if errno != nil {
- _panic("_futex_signal failure")
+ panic_contextless("_futex_signal failure")
}
}
@@ -59,6 +59,6 @@ _futex_broadcast :: proc "contextless" (f: ^Futex) {
errno := freebsd._umtx_op(f, .WAKE, cast(c.ulong)max(i32), nil, nil)
if errno != nil {
- _panic("_futex_broadcast failure")
+ panic_contextless("_futex_broadcast failure")
}
}
diff --git a/core/sync/futex_linux.odin b/core/sync/futex_linux.odin
index 846a82486..52143880b 100644
--- a/core/sync/futex_linux.odin
+++ b/core/sync/futex_linux.odin
@@ -15,7 +15,7 @@ _futex_wait :: proc "contextless" (futex: ^Futex, expected: u32) -> bool {
return true
case:
// TODO(flysand): More descriptive panic messages based on the vlaue of `errno`
- _panic("futex_wait failure")
+ panic_contextless("futex_wait failure")
}
}
@@ -34,7 +34,7 @@ _futex_wait_with_timeout :: proc "contextless" (futex: ^Futex, expected: u32, du
case .NONE, .EINTR, .EAGAIN:
return true
case:
- _panic("futex_wait_with_timeout failure")
+ panic_contextless("futex_wait_with_timeout failure")
}
}
@@ -44,7 +44,7 @@ _futex_signal :: proc "contextless" (futex: ^Futex) {
case .NONE:
return
case:
- _panic("futex_wake_single failure")
+ panic_contextless("futex_wake_single failure")
}
}
@@ -57,6 +57,6 @@ _futex_broadcast :: proc "contextless" (futex: ^Futex) {
case .NONE:
return
case:
- _panic("_futex_wake_all failure")
+ panic_contextless("_futex_wake_all failure")
}
}
diff --git a/core/sync/futex_netbsd.odin b/core/sync/futex_netbsd.odin
index b98346434..e49b25b02 100644
--- a/core/sync/futex_netbsd.odin
+++ b/core/sync/futex_netbsd.odin
@@ -35,7 +35,7 @@ _futex_wait :: proc "contextless" (futex: ^Futex, expected: u32) -> bool {
case EINTR, EAGAIN:
return true
case:
- _panic("futex_wait failure")
+ panic_contextless("futex_wait failure")
}
}
return true
@@ -55,7 +55,7 @@ _futex_wait_with_timeout :: proc "contextless" (futex: ^Futex, expected: u32, du
case ETIMEDOUT:
return false
case:
- _panic("futex_wait_with_timeout failure")
+ panic_contextless("futex_wait_with_timeout failure")
}
}
return true
@@ -63,12 +63,12 @@ _futex_wait_with_timeout :: proc "contextless" (futex: ^Futex, expected: u32, du
_futex_signal :: proc "contextless" (futex: ^Futex) {
if _, ok := intrinsics.syscall_bsd(unix.SYS___futex, uintptr(futex), FUTEX_WAKE_PRIVATE, 1, 0, 0, 0); !ok {
- _panic("futex_wake_single failure")
+ panic_contextless("futex_wake_single failure")
}
}
_futex_broadcast :: proc "contextless" (futex: ^Futex) {
if _, ok := intrinsics.syscall_bsd(unix.SYS___futex, uintptr(futex), FUTEX_WAKE_PRIVATE, uintptr(max(i32)), 0, 0, 0); !ok {
- _panic("_futex_wake_all failure")
+ panic_contextless("_futex_wake_all failure")
}
}
diff --git a/core/sync/futex_openbsd.odin b/core/sync/futex_openbsd.odin
index 83055b950..7d3cc8578 100644
--- a/core/sync/futex_openbsd.odin
+++ b/core/sync/futex_openbsd.odin
@@ -36,7 +36,7 @@ _futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool {
return false
}
- _panic("futex_wait failure")
+ panic_contextless("futex_wait failure")
}
_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool {
@@ -62,14 +62,14 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, durati
return false
}
- _panic("futex_wait_with_timeout failure")
+ panic_contextless("futex_wait_with_timeout failure")
}
_futex_signal :: proc "contextless" (f: ^Futex) {
res := _unix_futex(f, FUTEX_WAKE_PRIVATE, 1, nil)
if res == -1 {
- _panic("futex_wake_single failure")
+ panic_contextless("futex_wake_single failure")
}
}
@@ -77,6 +77,6 @@ _futex_broadcast :: proc "contextless" (f: ^Futex) {
res := _unix_futex(f, FUTEX_WAKE_PRIVATE, u32(max(i32)), nil)
if res == -1 {
- _panic("_futex_wake_all failure")
+ panic_contextless("_futex_wake_all failure")
}
}
diff --git a/core/sync/futex_wasm.odin b/core/sync/futex_wasm.odin
index 013c425e8..0f9659a02 100644
--- a/core/sync/futex_wasm.odin
+++ b/core/sync/futex_wasm.odin
@@ -10,7 +10,7 @@ import "core:time"
_futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool {
when !intrinsics.has_target_feature("atomics") {
- _panic("usage of `core:sync` requires the `-target-feature:\"atomics\"` or a `-microarch` that supports it")
+ panic_contextless("usage of `core:sync` requires the `-target-feature:\"atomics\"` or a `-microarch` that supports it")
} else {
s := intrinsics.wasm_memory_atomic_wait32((^u32)(f), expected, -1)
return s != 0
@@ -19,7 +19,7 @@ _futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool {
_futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool {
when !intrinsics.has_target_feature("atomics") {
- _panic("usage of `core:sync` requires the `-target-feature:\"atomics\"` or a `-microarch` that supports it")
+ panic_contextless("usage of `core:sync` requires the `-target-feature:\"atomics\"` or a `-microarch` that supports it")
} else {
s := intrinsics.wasm_memory_atomic_wait32((^u32)(f), expected, i64(duration))
return s != 0
@@ -28,7 +28,7 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, durati
_futex_signal :: proc "contextless" (f: ^Futex) {
when !intrinsics.has_target_feature("atomics") {
- _panic("usage of `core:sync` requires the `-target-feature:\"atomics\"` or a `-microarch` that supports it")
+ panic_contextless("usage of `core:sync` requires the `-target-feature:\"atomics\"` or a `-microarch` that supports it")
} else {
loop: for {
s := intrinsics.wasm_memory_atomic_notify32((^u32)(f), 1)
@@ -41,7 +41,7 @@ _futex_signal :: proc "contextless" (f: ^Futex) {
_futex_broadcast :: proc "contextless" (f: ^Futex) {
when !intrinsics.has_target_feature("atomics") {
- _panic("usage of `core:sync` requires the `-target-feature:\"atomics\"` or a `-microarch` that supports it")
+ panic_contextless("usage of `core:sync` requires the `-target-feature:\"atomics\"` or a `-microarch` that supports it")
} else {
loop: for {
s := intrinsics.wasm_memory_atomic_notify32((^u32)(f), ~u32(0))
diff --git a/core/sync/primitives.odin b/core/sync/primitives.odin
index a22824481..f091de045 100644
--- a/core/sync/primitives.odin
+++ b/core/sync/primitives.odin
@@ -1,6 +1,5 @@
package sync
-import "base:runtime"
import "core:time"
/*
@@ -390,7 +389,7 @@ recursive_mutex_guard :: proc "contextless" (m: ^Recursive_Mutex) -> bool {
A condition variable.
`Cond` implements a condition variable, a rendezvous point for threads waiting
-for signalling the occurence of an event. Condition variables are used on
+for signalling the occurence of an event. Condition variables are used in
conjuction with mutexes to provide a shared access to one or more shared
variable.
@@ -560,7 +559,7 @@ futex_wait :: proc "contextless" (f: ^Futex, expected: u32) {
return
}
ok := _futex_wait(f, expected)
- _assert(ok, "futex_wait failure")
+ assert_contextless(ok, "futex_wait failure")
}
/*
@@ -597,18 +596,3 @@ Wake up multiple threads waiting on a futex.
futex_broadcast :: proc "contextless" (f: ^Futex) {
_futex_broadcast(f)
}
-
-
-@(private)
-_assert :: proc "contextless" (cond: bool, msg: string) {
- if !cond {
- _panic(msg)
- }
-}
-
-@(private)
-_panic :: proc "contextless" (msg: string) -> ! {
- runtime.print_string(msg)
- runtime.print_byte('\n')
- runtime.trap()
-}
diff --git a/core/sync/primitives_atomic.odin b/core/sync/primitives_atomic.odin
index 1d8e423db..3c4324eb7 100644
--- a/core/sync/primitives_atomic.odin
+++ b/core/sync/primitives_atomic.odin
@@ -240,7 +240,7 @@ atomic_recursive_mutex_lock :: proc "contextless" (m: ^Atomic_Recursive_Mutex) {
atomic_recursive_mutex_unlock :: proc "contextless" (m: ^Atomic_Recursive_Mutex) {
tid := current_thread_id()
- _assert(tid == m.owner, "tid != m.owner")
+ assert_contextless(tid == m.owner, "tid != m.owner")
m.recursion -= 1
recursion := m.recursion
if recursion == 0 {
@@ -361,7 +361,7 @@ atomic_sema_wait_with_timeout :: proc "contextless" (s: ^Atomic_Sema, duration:
if !futex_wait_with_timeout(&s.count, u32(original_count), remaining) {
return false
}
- original_count = s.count
+ original_count = atomic_load_explicit(&s.count, .Relaxed)
}
if original_count == atomic_compare_exchange_strong_explicit(&s.count, original_count, original_count-1, .Acquire, .Acquire) {
return true