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 unsafe impl Send for Condvar {}
19 unsafe impl Sync for Condvar {}
21 const NEW: Condvar = Condvar {
22 condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
26 pub const fn new() -> Condvar {
30 pub unsafe fn init(&mut self) {}
32 pub unsafe fn notify_one(&self) {
33 let condvar = self.condvar.get();
34 if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
35 let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
39 "Failed to signal on condition variable"
44 pub unsafe fn notify_all(&self) {
45 let condvar = self.condvar.get();
46 if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
47 let ret = abi::condvar_signal(
48 condvar as *mut abi::condvar,
50 abi::nthreads::max_value(),
55 "Failed to broadcast on condition variable"
60 pub unsafe fn wait(&self, mutex: &Mutex) {
61 let mutex = mutex::raw(mutex);
63 (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
64 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
65 "This lock is not write-locked by this thread"
68 // Call into the kernel to wait on the condition variable.
69 let condvar = self.condvar.get();
70 let subscription = abi::subscription {
71 type_: abi::eventtype::CONDVAR,
72 union: abi::subscription_union {
73 condvar: abi::subscription_condvar {
74 condvar: condvar as *mut abi::condvar,
75 condvar_scope: abi::scope::PRIVATE,
76 lock: mutex as *mut abi::lock,
77 lock_scope: abi::scope::PRIVATE,
82 let mut event: abi::event = mem::uninitialized();
83 let mut nevents: usize = mem::uninitialized();
84 let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
88 "Failed to wait on condition variable"
93 "Failed to wait on condition variable"
97 pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
98 let mutex = mutex::raw(mutex);
100 (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
101 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
102 "This lock is not write-locked by this thread"
105 // Call into the kernel to wait on the condition variable.
106 let condvar = self.condvar.get();
107 let timeout = checked_dur2intervals(&dur)
108 .expect("overflow converting duration to nanoseconds");
109 let subscriptions = [
111 type_: abi::eventtype::CONDVAR,
112 union: abi::subscription_union {
113 condvar: abi::subscription_condvar {
114 condvar: condvar as *mut abi::condvar,
115 condvar_scope: abi::scope::PRIVATE,
116 lock: mutex as *mut abi::lock,
117 lock_scope: abi::scope::PRIVATE,
123 type_: abi::eventtype::CLOCK,
124 union: abi::subscription_union {
125 clock: abi::subscription_clock {
126 clock_id: abi::clockid::MONOTONIC,
134 let mut events: [abi::event; 2] = mem::uninitialized();
135 let mut nevents: usize = mem::uninitialized();
136 let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents);
140 "Failed to wait on condition variable"
142 for i in 0..nevents {
146 "Failed to wait on condition variable"
148 if events[i].type_ == abi::eventtype::CONDVAR {
155 pub unsafe fn destroy(&self) {
156 let condvar = self.condvar.get();
158 (*condvar).load(Ordering::Relaxed),
159 abi::CONDVAR_HAS_NO_WAITERS.0,
160 "Attempted to destroy a condition variable with blocked threads"