From bd73b2845b2e7cadf38c441babeeb9765896b2be Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 27 Apr 2022 15:03:48 +0100 Subject: [PATCH] Unify default `Sema` and `Atomic_Sema` behaviour --- core/sync/primitives_atomic.odin | 65 +++++++++++++++----------------- core/sync/sema_internal.odin | 42 ++------------------- 2 files changed, 34 insertions(+), 73 deletions(-) diff --git a/core/sync/primitives_atomic.odin b/core/sync/primitives_atomic.odin index 11fff4e60..22771443d 100644 --- a/core/sync/primitives_atomic.odin +++ b/core/sync/primitives_atomic.odin @@ -400,30 +400,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 + } } } @@ -431,25 +429,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 { - for s.count == 0 { - remaining := duration - time.tick_since(start) - if remaining < 0 { - return false + 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 } diff --git a/core/sync/sema_internal.odin b/core/sync/sema_internal.odin index e4a3c0bfc..5e2203c34 100644 --- a/core/sync/sema_internal.odin +++ b/core/sync/sema_internal.odin @@ -6,53 +6,19 @@ import "core:time" when #config(ODIN_SYNC_SEMA_USE_FUTEX, true) { _Sema :: struct { - count: Futex, + atomic: Atomic_Sema, } _sema_post :: proc(s: ^Sema, count := 1) { - atomic_add_explicit(&s.impl.count, Futex(count), .Release) - if count == 1 { - futex_signal(&s.impl.count) - } else { - futex_broadcast(&s.impl.count) - } + atomic_sema_post(&s.impl.atomic, count) } _sema_wait :: proc(s: ^Sema) { - for { - original_count := atomic_load_explicit(&s.impl.count, .Relaxed) - for original_count == 0 { - futex_wait(&s.impl.count, u32(original_count)) - original_count = s.impl.count - } - if original_count == atomic_compare_exchange_strong_explicit(&s.impl.count, original_count, original_count-1, .Acquire, .Acquire) { - return - } - } + atomic_sema_wait(&s.impl.atomic) } _sema_wait_with_timeout :: proc(s: ^Sema, duration: time.Duration) -> bool { - if duration <= 0 { - return false - } - for { - - original_count := atomic_load_explicit(&s.impl.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.impl.count, u32(original_count), remaining) { - return false - } - original_count = s.impl.count - } - if original_count == atomic_compare_exchange_strong_explicit(&s.impl.count, original_count, original_count-1, .Acquire, .Acquire) { - return true - } - } + return atomic_sema_wait_with_timeout(&s.impl.atomic, duration) } } else { _Sema :: struct {