1 use crate::cell::UnsafeCell;
3 use crate::sync::atomic::{AtomicU32, Ordering};
4 use crate::sys::cloudabi::abi;
5 use crate::sys::mutex::{self, Mutex};
6 use crate::sys::time::checked_dur2intervals;
7 use crate::time::Duration;
11 static __pthread_thread_id: abi::tid;
15 condvar: UnsafeCell<AtomicU32>,
18 pub type MovableCondvar = Condvar;
20 unsafe impl Send for Condvar {}
21 unsafe impl Sync for Condvar {}
24 Condvar { condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)) };
27 pub const fn new() -> Condvar {
31 pub unsafe fn init(&mut self) {}
33 pub unsafe fn notify_one(&self) {
34 let condvar = self.condvar.get();
35 if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
36 let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
37 assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
41 pub unsafe fn notify_all(&self) {
42 let condvar = self.condvar.get();
43 if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
44 let ret = abi::condvar_signal(
45 condvar as *mut abi::condvar,
49 assert_eq!(ret, abi::errno::SUCCESS, "Failed to broadcast on condition variable");
53 pub unsafe fn wait(&self, mutex: &Mutex) {
54 let mutex = mutex::raw(mutex);
56 (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
57 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
58 "This lock is not write-locked by this thread"
61 // Call into the kernel to wait on the condition variable.
62 let condvar = self.condvar.get();
63 let subscription = abi::subscription {
64 type_: abi::eventtype::CONDVAR,
65 union: abi::subscription_union {
66 condvar: abi::subscription_condvar {
67 condvar: condvar as *mut abi::condvar,
68 condvar_scope: abi::scope::PRIVATE,
69 lock: mutex as *mut abi::lock,
70 lock_scope: abi::scope::PRIVATE,
75 let mut event: mem::MaybeUninit<abi::event> = mem::MaybeUninit::uninit();
76 let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
77 let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
78 assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
80 event.assume_init().error,
82 "Failed to wait on condition variable"
86 pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
87 let mutex = mutex::raw(mutex);
89 (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
90 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
91 "This lock is not write-locked by this thread"
94 // Call into the kernel to wait on the condition variable.
95 let condvar = self.condvar.get();
97 checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
100 type_: abi::eventtype::CONDVAR,
101 union: abi::subscription_union {
102 condvar: abi::subscription_condvar {
103 condvar: condvar as *mut abi::condvar,
104 condvar_scope: abi::scope::PRIVATE,
105 lock: mutex as *mut abi::lock,
106 lock_scope: abi::scope::PRIVATE,
112 type_: abi::eventtype::CLOCK,
113 union: abi::subscription_union {
114 clock: abi::subscription_clock {
115 clock_id: abi::clockid::MONOTONIC,
123 let mut events: [mem::MaybeUninit<abi::event>; 2] = [mem::MaybeUninit::uninit(); 2];
124 let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
126 subscriptions.as_ptr(),
127 mem::MaybeUninit::first_ptr_mut(&mut events),
129 nevents.as_mut_ptr(),
131 assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
132 let nevents = nevents.assume_init();
133 for i in 0..nevents {
135 events[i].assume_init().error,
137 "Failed to wait on condition variable"
139 if events[i].assume_init().type_ == abi::eventtype::CONDVAR {
146 pub unsafe fn destroy(&self) {
147 let condvar = self.condvar.get();
149 (*condvar).load(Ordering::Relaxed),
150 abi::CONDVAR_HAS_NO_WAITERS.0,
151 "Attempted to destroy a condition variable with blocked threads"