]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/cloudabi/condvar.rs
Add 'compiler/rustc_codegen_cranelift/' from commit '793d26047f994e23415f8f6bb5686ff2...
[rust.git] / library / std / src / 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 pub type MovableCondvar = Condvar;
19
20 unsafe impl Send for Condvar {}
21 unsafe impl Sync for Condvar {}
22
23 const NEW: Condvar =
24     Condvar { condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)) };
25
26 impl Condvar {
27     pub const fn new() -> Condvar {
28         NEW
29     }
30
31     pub unsafe fn init(&mut self) {}
32
33     pub unsafe fn notify_one(&self) {
34         let condvar = self.condvar.get();
35         if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
36             let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
37             assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
38         }
39     }
40
41     pub unsafe fn notify_all(&self) {
42         let condvar = self.condvar.get();
43         if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
44             let ret = abi::condvar_signal(
45                 condvar as *mut abi::condvar,
46                 abi::scope::PRIVATE,
47                 abi::nthreads::MAX,
48             );
49             assert_eq!(ret, abi::errno::SUCCESS, "Failed to broadcast on condition variable");
50         }
51     }
52
53     pub unsafe fn wait(&self, mutex: &Mutex) {
54         let mutex = mutex::raw(mutex);
55         assert_eq!(
56             (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
57             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
58             "This lock is not write-locked by this thread"
59         );
60
61         // Call into the kernel to wait on the condition variable.
62         let condvar = self.condvar.get();
63         let subscription = abi::subscription {
64             type_: abi::eventtype::CONDVAR,
65             union: abi::subscription_union {
66                 condvar: abi::subscription_condvar {
67                     condvar: condvar as *mut abi::condvar,
68                     condvar_scope: abi::scope::PRIVATE,
69                     lock: mutex as *mut abi::lock,
70                     lock_scope: abi::scope::PRIVATE,
71                 },
72             },
73             ..mem::zeroed()
74         };
75         let mut event: mem::MaybeUninit<abi::event> = mem::MaybeUninit::uninit();
76         let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
77         let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
78         assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
79         assert_eq!(
80             event.assume_init().error,
81             abi::errno::SUCCESS,
82             "Failed to wait on condition variable"
83         );
84     }
85
86     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
87         let mutex = mutex::raw(mutex);
88         assert_eq!(
89             (*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
90             __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
91             "This lock is not write-locked by this thread"
92         );
93
94         // Call into the kernel to wait on the condition variable.
95         let condvar = self.condvar.get();
96         let timeout =
97             checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
98         let subscriptions = [
99             abi::subscription {
100                 type_: abi::eventtype::CONDVAR,
101                 union: abi::subscription_union {
102                     condvar: abi::subscription_condvar {
103                         condvar: condvar as *mut abi::condvar,
104                         condvar_scope: abi::scope::PRIVATE,
105                         lock: mutex as *mut abi::lock,
106                         lock_scope: abi::scope::PRIVATE,
107                     },
108                 },
109                 ..mem::zeroed()
110             },
111             abi::subscription {
112                 type_: abi::eventtype::CLOCK,
113                 union: abi::subscription_union {
114                     clock: abi::subscription_clock {
115                         clock_id: abi::clockid::MONOTONIC,
116                         timeout,
117                         ..mem::zeroed()
118                     },
119                 },
120                 ..mem::zeroed()
121             },
122         ];
123         let mut events: [mem::MaybeUninit<abi::event>; 2] = [mem::MaybeUninit::uninit(); 2];
124         let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
125         let ret = abi::poll(
126             subscriptions.as_ptr(),
127             mem::MaybeUninit::first_ptr_mut(&mut events),
128             2,
129             nevents.as_mut_ptr(),
130         );
131         assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
132         let nevents = nevents.assume_init();
133         for i in 0..nevents {
134             assert_eq!(
135                 events[i].assume_init().error,
136                 abi::errno::SUCCESS,
137                 "Failed to wait on condition variable"
138             );
139             if events[i].assume_init().type_ == abi::eventtype::CONDVAR {
140                 return true;
141             }
142         }
143         false
144     }
145
146     pub unsafe fn destroy(&self) {
147         let condvar = self.condvar.get();
148         assert_eq!(
149             (*condvar).load(Ordering::Relaxed),
150             abi::CONDVAR_HAS_NO_WAITERS.0,
151             "Attempted to destroy a condition variable with blocked threads"
152         );
153     }
154 }