1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 use sync::atomic::{AtomicU32, Ordering};
14 use sys::cloudabi::abi;
15 use sys::mutex::{self, Mutex};
16 use sys::time::checked_dur2intervals;
21 static __pthread_thread_id: abi::tid;
25 condvar: UnsafeCell<AtomicU32>,
28 unsafe impl Send for Condvar {}
29 unsafe impl Sync for Condvar {}
31 const NEW: Condvar = Condvar {
32 condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
36 pub const fn new() -> Condvar {
40 pub unsafe fn init(&mut self) {}
42 pub unsafe fn notify_one(&self) {
43 let condvar = self.condvar.get();
44 if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
45 let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
49 "Failed to signal on condition variable"
54 pub unsafe fn notify_all(&self) {
55 let condvar = self.condvar.get();
56 if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
57 let ret = abi::condvar_signal(
58 condvar as *mut abi::condvar,
60 abi::nthreads::max_value(),
65 "Failed to broadcast on condition variable"
70 pub unsafe fn wait(&self, mutex: &Mutex) {
71 let mutex = mutex::raw(mutex);
73 (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
74 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
75 "This lock is not write-locked by this thread"
78 // Call into the kernel to wait on the condition variable.
79 let condvar = self.condvar.get();
80 let subscription = abi::subscription {
81 type_: abi::eventtype::CONDVAR,
82 union: abi::subscription_union {
83 condvar: abi::subscription_condvar {
84 condvar: condvar as *mut abi::condvar,
85 condvar_scope: abi::scope::PRIVATE,
86 lock: mutex as *mut abi::lock,
87 lock_scope: abi::scope::PRIVATE,
92 let mut event: abi::event = mem::uninitialized();
93 let mut nevents: usize = mem::uninitialized();
94 let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
98 "Failed to wait on condition variable"
103 "Failed to wait on condition variable"
107 pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
108 let mutex = mutex::raw(mutex);
110 (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
111 __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
112 "This lock is not write-locked by this thread"
115 // Call into the kernel to wait on the condition variable.
116 let condvar = self.condvar.get();
117 let timeout = checked_dur2intervals(&dur)
118 .expect("overflow converting duration to nanoseconds");
119 let subscriptions = [
121 type_: abi::eventtype::CONDVAR,
122 union: abi::subscription_union {
123 condvar: abi::subscription_condvar {
124 condvar: condvar as *mut abi::condvar,
125 condvar_scope: abi::scope::PRIVATE,
126 lock: mutex as *mut abi::lock,
127 lock_scope: abi::scope::PRIVATE,
133 type_: abi::eventtype::CLOCK,
134 union: abi::subscription_union {
135 clock: abi::subscription_clock {
136 clock_id: abi::clockid::MONOTONIC,
144 let mut events: [abi::event; 2] = mem::uninitialized();
145 let mut nevents: usize = mem::uninitialized();
146 let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents);
150 "Failed to wait on condition variable"
152 for i in 0..nevents {
156 "Failed to wait on condition variable"
158 if events[i].type_ == abi::eventtype::CONDVAR {
165 pub unsafe fn destroy(&self) {
166 let condvar = self.condvar.get();
168 (*condvar).load(Ordering::Relaxed),
169 abi::CONDVAR_HAS_NO_WAITERS.0,
170 "Attempted to destroy a condition variable with blocked threads"