]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/cloudabi/condvar.rs
Auto merge of #56764 - sinkuu:simpcfg_bb0, r=matthewjasper
[rust.git] / src / libstd / sys / cloudabi / condvar.rs
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.
4 //
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.
10
11 use cell::UnsafeCell;
12 use mem;
13 use sync::atomic::{AtomicU32, Ordering};
14 use sys::cloudabi::abi;
15 use sys::mutex::{self, Mutex};
16 use sys::time::checked_dur2intervals;
17 use time::Duration;
18
19 extern "C" {
20     #[thread_local]
21     static __pthread_thread_id: abi::tid;
22 }
23
24 pub struct Condvar {
25     condvar: UnsafeCell<AtomicU32>,
26 }
27
28 unsafe impl Send for Condvar {}
29 unsafe impl Sync for Condvar {}
30
31 const NEW: Condvar = Condvar {
32     condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
33 };
34
35 impl Condvar {
36     pub const fn new() -> Condvar {
37         NEW
38     }
39
40     pub unsafe fn init(&mut self) {}
41
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);
46             assert_eq!(
47                 ret,
48                 abi::errno::SUCCESS,
49                 "Failed to signal on condition variable"
50             );
51         }
52     }
53
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,
59                 abi::scope::PRIVATE,
60                 abi::nthreads::max_value(),
61             );
62             assert_eq!(
63                 ret,
64                 abi::errno::SUCCESS,
65                 "Failed to broadcast on condition variable"
66             );
67         }
68     }
69
70     pub unsafe fn wait(&self, mutex: &Mutex) {
71         let mutex = mutex::raw(mutex);
72         assert_eq!(
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"
76         );
77
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,
88                 },
89             },
90             ..mem::zeroed()
91         };
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);
95         assert_eq!(
96             ret,
97             abi::errno::SUCCESS,
98             "Failed to wait on condition variable"
99         );
100         assert_eq!(
101             event.error,
102             abi::errno::SUCCESS,
103             "Failed to wait on condition variable"
104         );
105     }
106
107     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
108         let mutex = mutex::raw(mutex);
109         assert_eq!(
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"
113         );
114
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 = [
120             abi::subscription {
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,
128                     },
129                 },
130                 ..mem::zeroed()
131             },
132             abi::subscription {
133                 type_: abi::eventtype::CLOCK,
134                 union: abi::subscription_union {
135                     clock: abi::subscription_clock {
136                         clock_id: abi::clockid::MONOTONIC,
137                         timeout,
138                         ..mem::zeroed()
139                     },
140                 },
141                 ..mem::zeroed()
142             },
143         ];
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);
147         assert_eq!(
148             ret,
149             abi::errno::SUCCESS,
150             "Failed to wait on condition variable"
151         );
152         for i in 0..nevents {
153             assert_eq!(
154                 events[i].error,
155                 abi::errno::SUCCESS,
156                 "Failed to wait on condition variable"
157             );
158             if events[i].type_ == abi::eventtype::CONDVAR {
159                 return true;
160             }
161         }
162         false
163     }
164
165     pub unsafe fn destroy(&self) {
166         let condvar = self.condvar.get();
167         assert_eq!(
168             (*condvar).load(Ordering::Relaxed),
169             abi::CONDVAR_HAS_NO_WAITERS.0,
170             "Attempted to destroy a condition variable with blocked threads"
171         );
172     }
173 }