diff options
Diffstat (limited to 'library/std/src/sys/hermit/condvar.rs')
| -rw-r--r-- | library/std/src/sys/hermit/condvar.rs | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/library/std/src/sys/hermit/condvar.rs b/library/std/src/sys/hermit/condvar.rs new file mode 100644 index 00000000000..52c8c3b17e8 --- /dev/null +++ b/library/std/src/sys/hermit/condvar.rs @@ -0,0 +1,64 @@ +use crate::ffi::c_void; +use crate::ptr; +use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +use crate::sys::hermit::abi; +use crate::sys::mutex::Mutex; +use crate::time::Duration; + +// The implementation is inspired by Andrew D. Birrell's paper +// "Implementing Condition Variables with Semaphores" + +pub struct Condvar { + counter: AtomicUsize, + sem1: *const c_void, + sem2: *const c_void, +} + +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() } + } + + pub unsafe fn init(&mut self) { + let _ = abi::sem_init(&mut self.sem1 as *mut *const c_void, 0); + let _ = abi::sem_init(&mut self.sem2 as *mut *const c_void, 0); + } + + pub unsafe fn notify_one(&self) { + if self.counter.load(SeqCst) > 0 { + self.counter.fetch_sub(1, SeqCst); + abi::sem_post(self.sem1); + abi::sem_timedwait(self.sem2, 0); + } + } + + pub unsafe fn notify_all(&self) { + let counter = self.counter.swap(0, SeqCst); + for _ in 0..counter { + abi::sem_post(self.sem1); + } + for _ in 0..counter { + abi::sem_timedwait(self.sem2, 0); + } + } + + pub unsafe fn wait(&self, mutex: &Mutex) { + self.counter.fetch_add(1, SeqCst); + mutex.unlock(); + abi::sem_timedwait(self.sem1, 0); + abi::sem_post(self.sem2); + mutex.lock(); + } + + pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + panic!("wait_timeout not supported on hermit"); + } + + pub unsafe fn destroy(&self) { + let _ = abi::sem_destroy(self.sem1); + let _ = abi::sem_destroy(self.sem2); + } +} |
