]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/cloudabi/condvar.rs
Permit use of mem::uninitialized via allow(deprecated)
[rust.git] / src / libstd / sys / cloudabi / condvar.rs
1 use crate::cell::UnsafeCell;
2 use crate::mem;
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;
8
9 extern "C" {
10     #[thread_local]
11     static __pthread_thread_id: abi::tid;
12 }
13
14 pub struct Condvar {
15     condvar: UnsafeCell<AtomicU32>,
16 }
17
18 unsafe impl Send for Condvar {}
19 unsafe impl Sync for Condvar {}
20
21 const NEW: Condvar = Condvar {
22     condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
23 };
24
25 impl Condvar {
26     pub const fn new() -> Condvar {
27         NEW
28     }
29
30     pub unsafe fn init(&mut self) {}
31
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);
36             assert_eq!(
37                 ret,
38                 abi::errno::SUCCESS,
39                 "Failed to signal on condition variable"
40             );
41         }
42     }
43
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,
49                 abi::scope::PRIVATE,
50                 abi::nthreads::max_value(),
51             );
52             assert_eq!(
53                 ret,
54                 abi::errno::SUCCESS,
55                 "Failed to broadcast on condition variable"
56             );
57         }
58     }
59
60     pub unsafe fn wait(&self, mutex: &Mutex) {
61         let mutex = mutex::raw(mutex);
62         assert_eq!(
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"
66         );
67
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,
78                 },
79             },
80             ..mem::zeroed()
81         };
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);
85         assert_eq!(
86             ret,
87             abi::errno::SUCCESS,
88             "Failed to wait on condition variable"
89         );
90         assert_eq!(
91             event.error,
92             abi::errno::SUCCESS,
93             "Failed to wait on condition variable"
94         );
95     }
96
97     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
98         let mutex = mutex::raw(mutex);
99         assert_eq!(
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"
103         );
104
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 = [
110             abi::subscription {
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,
118                     },
119                 },
120                 ..mem::zeroed()
121             },
122             abi::subscription {
123                 type_: abi::eventtype::CLOCK,
124                 union: abi::subscription_union {
125                     clock: abi::subscription_clock {
126                         clock_id: abi::clockid::MONOTONIC,
127                         timeout,
128                         ..mem::zeroed()
129                     },
130                 },
131                 ..mem::zeroed()
132             },
133         ];
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);
137         assert_eq!(
138             ret,
139             abi::errno::SUCCESS,
140             "Failed to wait on condition variable"
141         );
142         for i in 0..nevents {
143             assert_eq!(
144                 events[i].error,
145                 abi::errno::SUCCESS,
146                 "Failed to wait on condition variable"
147             );
148             if events[i].type_ == abi::eventtype::CONDVAR {
149                 return true;
150             }
151         }
152         false
153     }
154
155     pub unsafe fn destroy(&self) {
156         let condvar = self.condvar.get();
157         assert_eq!(
158             (*condvar).load(Ordering::Relaxed),
159             abi::CONDVAR_HAS_NO_WAITERS.0,
160             "Attempted to destroy a condition variable with blocked threads"
161         );
162     }
163 }