1 use crate::cell
::UnsafeCell
;
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
;
11 static __pthread_thread_id
: abi
::tid
;
15 condvar
: UnsafeCell
<AtomicU32
>,
18 unsafe impl Send
for Condvar {}
19 unsafe impl Sync
for Condvar {}
22 Condvar { condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)) }
;
25 pub const fn new() -> Condvar
{
29 pub unsafe fn init(&mut self) {}
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");
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
,
47 assert_eq
!(ret
, abi
::errno
::SUCCESS
, "Failed to broadcast on condition variable");
51 pub unsafe fn wait(&self, mutex
: &Mutex
) {
52 let mutex
= mutex
::raw(mutex
);
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"
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
,
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");
78 event
.assume_init().error
,
80 "Failed to wait on condition variable"
84 pub unsafe fn wait_timeout(&self, mutex
: &Mutex
, dur
: Duration
) -> bool
{
85 let mutex
= mutex
::raw(mutex
);
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"
92 // Call into the kernel to wait on the condition variable.
93 let condvar
= self.condvar
.get();
95 checked_dur2intervals(&dur
).expect("overflow converting duration to nanoseconds");
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
,
110 type_
: abi
::eventtype
::CLOCK
,
111 union: abi
::subscription_union
{
112 clock
: abi
::subscription_clock
{
113 clock_id
: abi
::clockid
::MONOTONIC
,
121 let mut events
: [mem
::MaybeUninit
<abi
::event
>; 2] = [mem
::MaybeUninit
::uninit(); 2];
122 let mut nevents
: mem
::MaybeUninit
<usize> = mem
::MaybeUninit
::uninit();
124 subscriptions
.as_ptr(),
125 mem
::MaybeUninit
::first_ptr_mut(&mut events
),
127 nevents
.as_mut_ptr(),
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
{
133 events
[i
].assume_init().error
,
135 "Failed to wait on condition variable"
137 if events
[i
].assume_init().type_
== abi
::eventtype
::CONDVAR
{
144 pub unsafe fn destroy(&self) {
145 let condvar
= self.condvar
.get();
147 (*condvar
).load(Ordering
::Relaxed
),
148 abi
::CONDVAR_HAS_NO_WAITERS
.0,
149 "Attempted to destroy a condition variable with blocked threads"