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