aboutsummaryrefslogtreecommitdiff
path: root/core/sync
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-04-26 13:11:34 +0100
committergingerBill <bill@gingerbill.org>2022-04-26 13:11:34 +0100
commit07d1a42768cd7082622fafc2bd01216e27bed54e (patch)
tree7b5dd5b0346ba5aa35cabee84a191c430dee867d /core/sync
parentec8221cb5def171deb5bea0cf4d6a935e74e33d2 (diff)
Simplify `Atomic_Sema` implementation
Diffstat (limited to 'core/sync')
-rw-r--r--core/sync/primitives_atomic.odin67
1 files changed, 31 insertions, 36 deletions
diff --git a/core/sync/primitives_atomic.odin b/core/sync/primitives_atomic.odin
index bd32eb192..812e5ae97 100644
--- a/core/sync/primitives_atomic.odin
+++ b/core/sync/primitives_atomic.odin
@@ -325,30 +325,28 @@ atomic_cond_broadcast :: proc(c: ^Atomic_Cond) {
//
// An Atomic_Sema must not be copied after first use
Atomic_Sema :: struct {
- mutex: Atomic_Mutex,
- cond: Atomic_Cond,
- count: int,
+ count: Futex,
}
atomic_sema_post :: proc(s: ^Atomic_Sema, count := 1) {
- atomic_mutex_lock(&s.mutex)
- defer atomic_mutex_unlock(&s.mutex)
-
- s.count += count
- atomic_cond_signal(&s.cond)
+ atomic_add_explicit(&s.count, Futex(count), .Release)
+ if count == 1 {
+ futex_signal(&s.count)
+ } else {
+ futex_broadcast(&s.count)
+ }
}
atomic_sema_wait :: proc(s: ^Atomic_Sema) {
- atomic_mutex_lock(&s.mutex)
- defer atomic_mutex_unlock(&s.mutex)
-
- for s.count == 0 {
- atomic_cond_wait(&s.cond, &s.mutex)
- }
-
- s.count -= 1
- if s.count > 0 {
- atomic_cond_signal(&s.cond)
+ for {
+ original_count := atomic_load_explicit(&s.count, .Relaxed)
+ for original_count == 0 {
+ futex_wait(&s.count, u32(original_count))
+ original_count = s.count
+ }
+ if original_count == atomic_compare_exchange_strong_explicit(&s.count, original_count, original_count-1, .Acquire, .Acquire) {
+ return
+ }
}
}
@@ -356,25 +354,22 @@ atomic_sema_wait_with_timeout :: proc(s: ^Atomic_Sema, duration: time.Duration)
if duration <= 0 {
return false
}
- atomic_mutex_lock(&s.mutex)
- defer atomic_mutex_unlock(&s.mutex)
-
- start := time.tick_now()
-
- for s.count == 0 {
- remaining := duration - time.tick_since(start)
- if remaining < 0 {
- return false
+ for {
+
+ original_count := atomic_load_explicit(&s.count, .Relaxed)
+ for start := time.tick_now(); original_count == 0; /**/ {
+ remaining := duration - time.tick_since(start)
+ if remaining < 0 {
+ return false
+ }
+
+ if !futex_wait_with_timeout(&s.count, u32(original_count), remaining) {
+ return false
+ }
+ original_count = s.count
}
-
- if !atomic_cond_wait_with_timeout(&s.cond, &s.mutex, remaining) {
- return false
+ if original_count == atomic_compare_exchange_strong_explicit(&s.count, original_count, original_count-1, .Acquire, .Acquire) {
+ return true
}
}
-
- s.count -= 1
- if s.count > 0 {
- atomic_cond_signal(&s.cond)
- }
- return true
}