2 use crate::sync::atomic::{AtomicU32, Ordering};
3 use crate::sys::cloudabi::abi;
4 use crate::sys::mutex::{self, Mutex};
5 use crate::sys::time::checked_dur2intervals;
6 use crate::time::Duration;
10 static __pthread_thread_id: abi::tid;
17 pub type MovableCondvar = Condvar;
19 unsafe impl Send for Condvar {}
20 unsafe impl Sync for Condvar {}
23 pub const fn new() -> Condvar {
24 Condvar { condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0) }
27 pub unsafe fn init(&mut self) {}
29 pub unsafe fn notify_one(&self) {
30 if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
31 let ret = abi::condvar_signal(
32 &self.condvar as *const AtomicU32 as *mut abi::condvar,
36 assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
40 pub unsafe fn notify_all(&self) {
41 if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
42 let ret = abi::condvar_signal(
43 &self.condvar as *const AtomicU32 as *mut abi::condvar,
47 assert_eq!(ret, abi::errno::SUCCESS, "Failed to broadcast on condition variable");
51 pub unsafe fn wait(&self, mutex: &Mutex) {
52 let mutex = mutex::raw(mutex);
54 mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
55 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
56 "This lock is not write-locked by this thread"
59 // Call into the kernel to wait on the condition variable.
60 let subscription = abi::subscription {
61 type_: abi::eventtype::CONDVAR,
62 union: abi::subscription_union {
63 condvar: abi::subscription_condvar {
64 condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
65 condvar_scope: abi::scope::PRIVATE,
66 lock: mutex as *const AtomicU32 as *mut abi::lock,
67 lock_scope: abi::scope::PRIVATE,
72 let mut event: mem::MaybeUninit<abi::event> = mem::MaybeUninit::uninit();
73 let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
74 let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
75 assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
77 event.assume_init().error,
79 "Failed to wait on condition variable"
83 pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
84 let mutex = mutex::raw(mutex);
86 mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
87 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
88 "This lock is not write-locked by this thread"
91 // Call into the kernel to wait on the condition variable.
93 checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
96 type_: abi::eventtype::CONDVAR,
97 union: abi::subscription_union {
98 condvar: abi::subscription_condvar {
99 condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
100 condvar_scope: abi::scope::PRIVATE,
101 lock: mutex as *const AtomicU32 as *mut abi::lock,
102 lock_scope: abi::scope::PRIVATE,
108 type_: abi::eventtype::CLOCK,
109 union: abi::subscription_union {
110 clock: abi::subscription_clock {
111 clock_id: abi::clockid::MONOTONIC,
119 let mut events: [mem::MaybeUninit<abi::event>; 2] = [mem::MaybeUninit::uninit(); 2];
120 let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
122 subscriptions.as_ptr(),
123 mem::MaybeUninit::slice_as_mut_ptr(&mut events),
125 nevents.as_mut_ptr(),
127 assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
128 let nevents = nevents.assume_init();
129 for i in 0..nevents {
131 events[i].assume_init().error,
133 "Failed to wait on condition variable"
135 if events[i].assume_init().type_ == abi::eventtype::CONDVAR {
142 pub unsafe fn destroy(&self) {
144 self.condvar.load(Ordering::Relaxed),
145 abi::CONDVAR_HAS_NO_WAITERS.0,
146 "Attempted to destroy a condition variable with blocked threads"