From bb93bf34ec88c5fe8dac5b1ba5ee3ecc52b50ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kr=C3=BCger?= <45282134+UweKrueger@users.noreply.github.com> Date: Wed, 12 Aug 2020 03:45:09 +0200 Subject: [PATCH] sync/semaphores: use dispatch semaphores on MacOS (#6110) --- vlib/builtin/cfns.c.v | 7 ++++ vlib/sync/channels.v | 10 ++---- vlib/sync/sync_nix.c.v | 77 +++++++++++------------------------------- 3 files changed, 28 insertions(+), 66 deletions(-) diff --git a/vlib/builtin/cfns.c.v b/vlib/builtin/cfns.c.v index 0777cbe5f9..3fc4e35dbf 100644 --- a/vlib/builtin/cfns.c.v +++ b/vlib/builtin/cfns.c.v @@ -437,6 +437,13 @@ fn C.sem_trywait(voidptr) int fn C.sem_timedwait(voidptr, voidptr) int fn C.sem_destroy(voidptr) int +// MacOS semaphore functions +fn C.dispatch_semaphore_create(i64) voidptr +fn C.dispatch_semaphore_signal(voidptr) i64 +fn C.dispatch_semaphore_wait(voidptr, u64) i64 +fn C.dispatch_time(u64, i64) u64 +fn C.dispatch_release(voidptr) + fn C.read(fd int, buf voidptr, count size_t) int fn C.write(fd int, buf voidptr, count size_t) int fn C.close(fd int) int diff --git a/vlib/sync/channels.v b/vlib/sync/channels.v index e9d5bf19ad..9ca291ccb1 100644 --- a/vlib/sync/channels.v +++ b/vlib/sync/channels.v @@ -174,10 +174,7 @@ fn (mut ch Channel) try_push_priv(src voidptr, no_block bool) TransactionState { if C.atomic_load_u16(&ch.closed) != 0 { return .closed } - mut spinloops_sem_, spinloops_ := if no_block { spinloops, spinloops_sem } else { 1, 1 } - $if macos { - spinloops_sem_ = 1 - } + spinloops_sem_, spinloops_ := if no_block { spinloops, spinloops_sem } else { 1, 1 } mut have_swapped := false for { mut got_sem := false @@ -333,10 +330,7 @@ pub fn (mut ch Channel) try_pop(dest voidptr) TransactionState { } fn (mut ch Channel) try_pop_priv(dest voidptr, no_block bool) TransactionState { - mut spinloops_sem_, spinloops_ := if no_block { spinloops, spinloops_sem } else { 1, 1 } - $if macos { - spinloops_sem_ = 1 - } + spinloops_sem_, spinloops_ := if no_block { spinloops, spinloops_sem } else { 1, 1 } mut have_swapped := false mut write_in_progress := false for { diff --git a/vlib/sync/sync_nix.c.v b/vlib/sync/sync_nix.c.v index 67df5a5c5b..dc4386ac0a 100644 --- a/vlib/sync/sync_nix.c.v +++ b/vlib/sync/sync_nix.c.v @@ -6,7 +6,11 @@ module sync import time #flag -lpthread -#include +$if macos { + #include +} $else { + #include +} // [init_with=new_mutex] // TODO: implement support for this struct attribute, and disallow Mutex{} from outside the sync.new_mutex() function. [ref_only] @@ -26,14 +30,10 @@ struct RwMutexAttr { /* MacOSX has no unnamed semaphores and no `timed_wait()` at all so we emulate the behaviour with other devices */ -[ref_only] -struct MacOSX_Semaphore { - mtx C.pthread_mutex_t - cond C.pthread_cond_t - attr C.pthread_condattr_t -mut: - count u32 -} +// [ref_only] +// struct MacOSX_Semaphore { +// sem C.dispatch_semaphore_t +// } [ref_only] struct PosixSemaphore { @@ -42,7 +42,7 @@ struct PosixSemaphore { pub struct Semaphore { mut: - sem voidptr // since the above does not work, yet + sem voidptr } pub fn new_mutex() &Mutex { @@ -98,12 +98,8 @@ pub fn new_semaphore() Semaphore { pub fn new_semaphore_init(n u32) Semaphore { $if macos { s := Semaphore{ - sem: &MacOSX_Semaphore{count: n} + sem: C.dispatch_semaphore_create(n) } - C.pthread_mutex_init(&&MacOSX_Semaphore(s.sem).mtx, C.NULL) - C.pthread_condattr_init(&&MacOSX_Semaphore(s.sem).attr) - C.pthread_condattr_setpshared(&&MacOSX_Semaphore(s.sem).attr, C.PTHREAD_PROCESS_PRIVATE) - C.pthread_cond_init(&&MacOSX_Semaphore(s.sem).cond, &&MacOSX_Semaphore(s.sem).attr) return s } $else { s := Semaphore{ @@ -116,10 +112,7 @@ pub fn new_semaphore_init(n u32) Semaphore { pub fn (s Semaphore) post() { $if macos { - C.pthread_mutex_lock(&&MacOSX_Semaphore(s.sem).mtx) - (&MacOSX_Semaphore(s.sem)).count++ - C.pthread_cond_signal(&&MacOSX_Semaphore(s.sem).cond) - C.pthread_mutex_unlock(&&MacOSX_Semaphore(s.sem).mtx) + C.dispatch_semaphore_signal(s.sem) } $else { unsafe { C.sem_post(&&PosixSemaphore(s.sem).sem) } } @@ -127,12 +120,7 @@ pub fn (s Semaphore) post() { pub fn (s Semaphore) wait() { $if macos { - C.pthread_mutex_lock(&&MacOSX_Semaphore(s.sem).mtx) - for &MacOSX_Semaphore(s.sem).count == 0 { - C.pthread_cond_wait(&&MacOSX_Semaphore(s.sem).cond, &&MacOSX_Semaphore(s.sem).mtx) - } - (&MacOSX_Semaphore(s.sem)).count-- - C.pthread_mutex_unlock(&&MacOSX_Semaphore(s.sem).mtx) + C.dispatch_semaphore_wait(s.sem, C.DISPATCH_TIME_FOREVER) } $else { unsafe { C.sem_wait(&&PosixSemaphore(s.sem).sem) } } @@ -140,53 +128,26 @@ pub fn (s Semaphore) wait() { pub fn (s Semaphore) try_wait() bool { $if macos { - t_spec := time.zero_timespec() - C.pthread_mutex_lock(&&MacOSX_Semaphore(s.sem).mtx) - for &MacOSX_Semaphore(s.sem).count == 0 { - res := C.pthread_cond_timedwait(&&MacOSX_Semaphore(s.sem).cond, &&MacOSX_Semaphore(s.sem).mtx, &t_spec) - if res == C.ETIMEDOUT { - break - } - } - mut res := false - if &MacOSX_Semaphore(s.sem).count > 0 { // success - (&MacOSX_Semaphore(s.sem)).count-- - res = true - } - C.pthread_mutex_unlock(&&MacOSX_Semaphore(s.sem).mtx) - return res + return C.dispatch_semaphore_wait(s.sem, C.DISPATCH_TIME_NOW) == 0 } $else { return unsafe { C.sem_trywait(&&PosixSemaphore(s.sem).sem) == 0 } } } pub fn (s Semaphore) timed_wait(timeout time.Duration) bool { - t_spec := timeout.timespec() $if macos { - C.pthread_mutex_lock(&&MacOSX_Semaphore(s.sem).mtx) - for &MacOSX_Semaphore(s.sem).count == 0 { - res := C.pthread_cond_timedwait(&&MacOSX_Semaphore(s.sem).cond, &&MacOSX_Semaphore(s.sem).mtx, &t_spec) - if res == C.ETIMEDOUT { - break - } - } - mut res := false - if &MacOSX_Semaphore(s.sem).count > 0 { // success - (&MacOSX_Semaphore(s.sem)).count-- - res = true - } - C.pthread_mutex_unlock(&&MacOSX_Semaphore(s.sem).mtx) - return res + return C.dispatch_semaphore_wait(s.sem, C.dispatch_time(C.DISPATCH_TIME_NOW, i64(timeout))) == 0 } $else { + t_spec := timeout.timespec() return unsafe { C.sem_timedwait(&&PosixSemaphore(s.sem).sem, &t_spec) == 0 } } } pub fn (s Semaphore) destroy() bool { $if macos { - return C.pthread_cond_destroy(&&MacOSX_Semaphore(s.sem).cond) == 0 && - C.pthread_condattr_destroy(&&MacOSX_Semaphore(s.sem).attr) == 0 && - C.pthread_mutex_destroy(&&MacOSX_Semaphore(s.sem).mtx) == 0 + for s.try_wait() {} + C.dispatch_release(s.sem) + return true } $else { return unsafe { C.sem_destroy(&&PosixSemaphore(s.sem).sem) == 0 } }