xref: /aosp_15_r20/external/crosvm/cros_async/src/sync/mu.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::cell::UnsafeCell;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::hint;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::mem;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::Deref;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::DerefMut;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicUsize;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::Ordering;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::thread::yield_now;
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker use super::super::sync::waiter::Kind as WaiterKind;
16*bb4ee6a4SAndroid Build Coastguard Worker use super::super::sync::waiter::Waiter;
17*bb4ee6a4SAndroid Build Coastguard Worker use super::super::sync::waiter::WaiterAdapter;
18*bb4ee6a4SAndroid Build Coastguard Worker use super::super::sync::waiter::WaiterList;
19*bb4ee6a4SAndroid Build Coastguard Worker use super::super::sync::waiter::WaitingFor;
20*bb4ee6a4SAndroid Build Coastguard Worker 
21*bb4ee6a4SAndroid Build Coastguard Worker // Set when the rwlock is exclusively locked.
22*bb4ee6a4SAndroid Build Coastguard Worker const LOCKED: usize = 1 << 0;
23*bb4ee6a4SAndroid Build Coastguard Worker // Set when there are one or more threads waiting to acquire the lock.
24*bb4ee6a4SAndroid Build Coastguard Worker const HAS_WAITERS: usize = 1 << 1;
25*bb4ee6a4SAndroid Build Coastguard Worker // Set when a thread has been woken up from the wait queue. Cleared when that thread either acquires
26*bb4ee6a4SAndroid Build Coastguard Worker // the lock or adds itself back into the wait queue. Used to prevent unnecessary wake ups when a
27*bb4ee6a4SAndroid Build Coastguard Worker // thread has been removed from the wait queue but has not gotten CPU time yet.
28*bb4ee6a4SAndroid Build Coastguard Worker const DESIGNATED_WAKER: usize = 1 << 2;
29*bb4ee6a4SAndroid Build Coastguard Worker // Used to provide exclusive access to the `waiters` field in `RwLock`. Should only be held while
30*bb4ee6a4SAndroid Build Coastguard Worker // modifying the waiter list.
31*bb4ee6a4SAndroid Build Coastguard Worker const SPINLOCK: usize = 1 << 3;
32*bb4ee6a4SAndroid Build Coastguard Worker // Set when a thread that wants an exclusive lock adds itself to the wait queue. New threads
33*bb4ee6a4SAndroid Build Coastguard Worker // attempting to acquire a shared lock will be preventing from getting it when this bit is set.
34*bb4ee6a4SAndroid Build Coastguard Worker // However, this bit is ignored once a thread has gone through the wait queue at least once.
35*bb4ee6a4SAndroid Build Coastguard Worker const WRITER_WAITING: usize = 1 << 4;
36*bb4ee6a4SAndroid Build Coastguard Worker // Set when a thread has gone through the wait queue many times but has failed to acquire the lock
37*bb4ee6a4SAndroid Build Coastguard Worker // every time it is woken up. When this bit is set, all other threads are prevented from acquiring
38*bb4ee6a4SAndroid Build Coastguard Worker // the lock until the thread that set the `LONG_WAIT` bit has acquired the lock.
39*bb4ee6a4SAndroid Build Coastguard Worker const LONG_WAIT: usize = 1 << 5;
40*bb4ee6a4SAndroid Build Coastguard Worker // The bit that is added to the rwlock state in order to acquire a shared lock. Since more than one
41*bb4ee6a4SAndroid Build Coastguard Worker // thread can acquire a shared lock, we cannot use a single bit. Instead we use all the remaining
42*bb4ee6a4SAndroid Build Coastguard Worker // bits in the state to track the number of threads that have acquired a shared lock.
43*bb4ee6a4SAndroid Build Coastguard Worker const READ_LOCK: usize = 1 << 8;
44*bb4ee6a4SAndroid Build Coastguard Worker // Mask used for checking if any threads currently hold a shared lock.
45*bb4ee6a4SAndroid Build Coastguard Worker const READ_MASK: usize = !0xff;
46*bb4ee6a4SAndroid Build Coastguard Worker 
47*bb4ee6a4SAndroid Build Coastguard Worker // The number of times the thread should just spin and attempt to re-acquire the lock.
48*bb4ee6a4SAndroid Build Coastguard Worker const SPIN_THRESHOLD: usize = 7;
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker // The number of times the thread needs to go through the wait queue before it sets the `LONG_WAIT`
51*bb4ee6a4SAndroid Build Coastguard Worker // bit and forces all other threads to wait for it to acquire the lock. This value is set relatively
52*bb4ee6a4SAndroid Build Coastguard Worker // high so that we don't lose the benefit of having running threads unless it is absolutely
53*bb4ee6a4SAndroid Build Coastguard Worker // necessary.
54*bb4ee6a4SAndroid Build Coastguard Worker const LONG_WAIT_THRESHOLD: usize = 19;
55*bb4ee6a4SAndroid Build Coastguard Worker 
56*bb4ee6a4SAndroid Build Coastguard Worker // Common methods between shared and exclusive locks.
57*bb4ee6a4SAndroid Build Coastguard Worker trait Kind {
58*bb4ee6a4SAndroid Build Coastguard Worker     // The bits that must be zero for the thread to acquire this kind of lock. If any of these bits
59*bb4ee6a4SAndroid Build Coastguard Worker     // are not zero then the thread will first spin and retry a few times before adding itself to
60*bb4ee6a4SAndroid Build Coastguard Worker     // the wait queue.
zero_to_acquire() -> usize61*bb4ee6a4SAndroid Build Coastguard Worker     fn zero_to_acquire() -> usize;
62*bb4ee6a4SAndroid Build Coastguard Worker 
63*bb4ee6a4SAndroid Build Coastguard Worker     // The bit that must be added in order to acquire this kind of lock. This should either be
64*bb4ee6a4SAndroid Build Coastguard Worker     // `LOCKED` or `READ_LOCK`.
add_to_acquire() -> usize65*bb4ee6a4SAndroid Build Coastguard Worker     fn add_to_acquire() -> usize;
66*bb4ee6a4SAndroid Build Coastguard Worker 
67*bb4ee6a4SAndroid Build Coastguard Worker     // The bits that should be set when a thread adds itself to the wait queue while waiting to
68*bb4ee6a4SAndroid Build Coastguard Worker     // acquire this kind of lock.
set_when_waiting() -> usize69*bb4ee6a4SAndroid Build Coastguard Worker     fn set_when_waiting() -> usize;
70*bb4ee6a4SAndroid Build Coastguard Worker 
71*bb4ee6a4SAndroid Build Coastguard Worker     // The bits that should be cleared when a thread acquires this kind of lock.
clear_on_acquire() -> usize72*bb4ee6a4SAndroid Build Coastguard Worker     fn clear_on_acquire() -> usize;
73*bb4ee6a4SAndroid Build Coastguard Worker 
74*bb4ee6a4SAndroid Build Coastguard Worker     // The waiter that a thread should use when waiting to acquire this kind of lock.
new_waiter(raw: &RawRwLock) -> Arc<Waiter>75*bb4ee6a4SAndroid Build Coastguard Worker     fn new_waiter(raw: &RawRwLock) -> Arc<Waiter>;
76*bb4ee6a4SAndroid Build Coastguard Worker }
77*bb4ee6a4SAndroid Build Coastguard Worker 
78*bb4ee6a4SAndroid Build Coastguard Worker // A lock type for shared read-only access to the data. More than one thread may hold this kind of
79*bb4ee6a4SAndroid Build Coastguard Worker // lock simultaneously.
80*bb4ee6a4SAndroid Build Coastguard Worker struct Shared;
81*bb4ee6a4SAndroid Build Coastguard Worker 
82*bb4ee6a4SAndroid Build Coastguard Worker impl Kind for Shared {
zero_to_acquire() -> usize83*bb4ee6a4SAndroid Build Coastguard Worker     fn zero_to_acquire() -> usize {
84*bb4ee6a4SAndroid Build Coastguard Worker         LOCKED | WRITER_WAITING | LONG_WAIT
85*bb4ee6a4SAndroid Build Coastguard Worker     }
86*bb4ee6a4SAndroid Build Coastguard Worker 
add_to_acquire() -> usize87*bb4ee6a4SAndroid Build Coastguard Worker     fn add_to_acquire() -> usize {
88*bb4ee6a4SAndroid Build Coastguard Worker         READ_LOCK
89*bb4ee6a4SAndroid Build Coastguard Worker     }
90*bb4ee6a4SAndroid Build Coastguard Worker 
set_when_waiting() -> usize91*bb4ee6a4SAndroid Build Coastguard Worker     fn set_when_waiting() -> usize {
92*bb4ee6a4SAndroid Build Coastguard Worker         0
93*bb4ee6a4SAndroid Build Coastguard Worker     }
94*bb4ee6a4SAndroid Build Coastguard Worker 
clear_on_acquire() -> usize95*bb4ee6a4SAndroid Build Coastguard Worker     fn clear_on_acquire() -> usize {
96*bb4ee6a4SAndroid Build Coastguard Worker         0
97*bb4ee6a4SAndroid Build Coastguard Worker     }
98*bb4ee6a4SAndroid Build Coastguard Worker 
new_waiter(raw: &RawRwLock) -> Arc<Waiter>99*bb4ee6a4SAndroid Build Coastguard Worker     fn new_waiter(raw: &RawRwLock) -> Arc<Waiter> {
100*bb4ee6a4SAndroid Build Coastguard Worker         Arc::new(Waiter::new(
101*bb4ee6a4SAndroid Build Coastguard Worker             WaiterKind::Shared,
102*bb4ee6a4SAndroid Build Coastguard Worker             cancel_waiter,
103*bb4ee6a4SAndroid Build Coastguard Worker             raw as *const RawRwLock as usize,
104*bb4ee6a4SAndroid Build Coastguard Worker             WaitingFor::Mutex,
105*bb4ee6a4SAndroid Build Coastguard Worker         ))
106*bb4ee6a4SAndroid Build Coastguard Worker     }
107*bb4ee6a4SAndroid Build Coastguard Worker }
108*bb4ee6a4SAndroid Build Coastguard Worker 
109*bb4ee6a4SAndroid Build Coastguard Worker // A lock type for mutually exclusive read-write access to the data. Only one thread can hold this
110*bb4ee6a4SAndroid Build Coastguard Worker // kind of lock at a time.
111*bb4ee6a4SAndroid Build Coastguard Worker struct Exclusive;
112*bb4ee6a4SAndroid Build Coastguard Worker 
113*bb4ee6a4SAndroid Build Coastguard Worker impl Kind for Exclusive {
zero_to_acquire() -> usize114*bb4ee6a4SAndroid Build Coastguard Worker     fn zero_to_acquire() -> usize {
115*bb4ee6a4SAndroid Build Coastguard Worker         LOCKED | READ_MASK | LONG_WAIT
116*bb4ee6a4SAndroid Build Coastguard Worker     }
117*bb4ee6a4SAndroid Build Coastguard Worker 
add_to_acquire() -> usize118*bb4ee6a4SAndroid Build Coastguard Worker     fn add_to_acquire() -> usize {
119*bb4ee6a4SAndroid Build Coastguard Worker         LOCKED
120*bb4ee6a4SAndroid Build Coastguard Worker     }
121*bb4ee6a4SAndroid Build Coastguard Worker 
set_when_waiting() -> usize122*bb4ee6a4SAndroid Build Coastguard Worker     fn set_when_waiting() -> usize {
123*bb4ee6a4SAndroid Build Coastguard Worker         WRITER_WAITING
124*bb4ee6a4SAndroid Build Coastguard Worker     }
125*bb4ee6a4SAndroid Build Coastguard Worker 
clear_on_acquire() -> usize126*bb4ee6a4SAndroid Build Coastguard Worker     fn clear_on_acquire() -> usize {
127*bb4ee6a4SAndroid Build Coastguard Worker         WRITER_WAITING
128*bb4ee6a4SAndroid Build Coastguard Worker     }
129*bb4ee6a4SAndroid Build Coastguard Worker 
new_waiter(raw: &RawRwLock) -> Arc<Waiter>130*bb4ee6a4SAndroid Build Coastguard Worker     fn new_waiter(raw: &RawRwLock) -> Arc<Waiter> {
131*bb4ee6a4SAndroid Build Coastguard Worker         Arc::new(Waiter::new(
132*bb4ee6a4SAndroid Build Coastguard Worker             WaiterKind::Exclusive,
133*bb4ee6a4SAndroid Build Coastguard Worker             cancel_waiter,
134*bb4ee6a4SAndroid Build Coastguard Worker             raw as *const RawRwLock as usize,
135*bb4ee6a4SAndroid Build Coastguard Worker             WaitingFor::Mutex,
136*bb4ee6a4SAndroid Build Coastguard Worker         ))
137*bb4ee6a4SAndroid Build Coastguard Worker     }
138*bb4ee6a4SAndroid Build Coastguard Worker }
139*bb4ee6a4SAndroid Build Coastguard Worker 
140*bb4ee6a4SAndroid Build Coastguard Worker // Scan `waiters` and return the ones that should be woken up. Also returns any bits that should be
141*bb4ee6a4SAndroid Build Coastguard Worker // set in the rwlock state when the current thread releases the spin lock protecting the waiter
142*bb4ee6a4SAndroid Build Coastguard Worker // list.
143*bb4ee6a4SAndroid Build Coastguard Worker //
144*bb4ee6a4SAndroid Build Coastguard Worker // If the first waiter is trying to acquire a shared lock, then all waiters in the list that are
145*bb4ee6a4SAndroid Build Coastguard Worker // waiting for a shared lock are also woken up. If any waiters waiting for an exclusive lock are
146*bb4ee6a4SAndroid Build Coastguard Worker // found when iterating through the list, then the returned `usize` contains the `WRITER_WAITING`
147*bb4ee6a4SAndroid Build Coastguard Worker // bit, which should be set when the thread releases the spin lock.
148*bb4ee6a4SAndroid Build Coastguard Worker //
149*bb4ee6a4SAndroid Build Coastguard Worker // If the first waiter is trying to acquire an exclusive lock, then only that waiter is returned and
150*bb4ee6a4SAndroid Build Coastguard Worker // no bits are set in the returned `usize`.
get_wake_list(waiters: &mut WaiterList) -> (WaiterList, usize)151*bb4ee6a4SAndroid Build Coastguard Worker fn get_wake_list(waiters: &mut WaiterList) -> (WaiterList, usize) {
152*bb4ee6a4SAndroid Build Coastguard Worker     let mut to_wake = WaiterList::new(WaiterAdapter::new());
153*bb4ee6a4SAndroid Build Coastguard Worker     let mut set_on_release = 0;
154*bb4ee6a4SAndroid Build Coastguard Worker     let mut cursor = waiters.front_mut();
155*bb4ee6a4SAndroid Build Coastguard Worker 
156*bb4ee6a4SAndroid Build Coastguard Worker     let mut waking_readers = false;
157*bb4ee6a4SAndroid Build Coastguard Worker     while let Some(w) = cursor.get() {
158*bb4ee6a4SAndroid Build Coastguard Worker         match w.kind() {
159*bb4ee6a4SAndroid Build Coastguard Worker             WaiterKind::Exclusive if !waking_readers => {
160*bb4ee6a4SAndroid Build Coastguard Worker                 // This is the first waiter and it's a writer. No need to check the other waiters.
161*bb4ee6a4SAndroid Build Coastguard Worker                 let waiter = cursor.remove().unwrap();
162*bb4ee6a4SAndroid Build Coastguard Worker                 waiter.set_waiting_for(WaitingFor::None);
163*bb4ee6a4SAndroid Build Coastguard Worker                 to_wake.push_back(waiter);
164*bb4ee6a4SAndroid Build Coastguard Worker                 break;
165*bb4ee6a4SAndroid Build Coastguard Worker             }
166*bb4ee6a4SAndroid Build Coastguard Worker 
167*bb4ee6a4SAndroid Build Coastguard Worker             WaiterKind::Shared => {
168*bb4ee6a4SAndroid Build Coastguard Worker                 // This is a reader and the first waiter in the list was not a writer so wake up all
169*bb4ee6a4SAndroid Build Coastguard Worker                 // the readers in the wait list.
170*bb4ee6a4SAndroid Build Coastguard Worker                 let waiter = cursor.remove().unwrap();
171*bb4ee6a4SAndroid Build Coastguard Worker                 waiter.set_waiting_for(WaitingFor::None);
172*bb4ee6a4SAndroid Build Coastguard Worker                 to_wake.push_back(waiter);
173*bb4ee6a4SAndroid Build Coastguard Worker                 waking_readers = true;
174*bb4ee6a4SAndroid Build Coastguard Worker             }
175*bb4ee6a4SAndroid Build Coastguard Worker 
176*bb4ee6a4SAndroid Build Coastguard Worker             WaiterKind::Exclusive => {
177*bb4ee6a4SAndroid Build Coastguard Worker                 // We found a writer while looking for more readers to wake up. Set the
178*bb4ee6a4SAndroid Build Coastguard Worker                 // `WRITER_WAITING` bit to prevent any new readers from acquiring the lock. All
179*bb4ee6a4SAndroid Build Coastguard Worker                 // readers currently in the wait list will ignore this bit since they already waited
180*bb4ee6a4SAndroid Build Coastguard Worker                 // once.
181*bb4ee6a4SAndroid Build Coastguard Worker                 set_on_release |= WRITER_WAITING;
182*bb4ee6a4SAndroid Build Coastguard Worker                 cursor.move_next();
183*bb4ee6a4SAndroid Build Coastguard Worker             }
184*bb4ee6a4SAndroid Build Coastguard Worker         }
185*bb4ee6a4SAndroid Build Coastguard Worker     }
186*bb4ee6a4SAndroid Build Coastguard Worker 
187*bb4ee6a4SAndroid Build Coastguard Worker     (to_wake, set_on_release)
188*bb4ee6a4SAndroid Build Coastguard Worker }
189*bb4ee6a4SAndroid Build Coastguard Worker 
190*bb4ee6a4SAndroid Build Coastguard Worker #[inline]
cpu_relax(iterations: usize)191*bb4ee6a4SAndroid Build Coastguard Worker fn cpu_relax(iterations: usize) {
192*bb4ee6a4SAndroid Build Coastguard Worker     for _ in 0..iterations {
193*bb4ee6a4SAndroid Build Coastguard Worker         hint::spin_loop();
194*bb4ee6a4SAndroid Build Coastguard Worker     }
195*bb4ee6a4SAndroid Build Coastguard Worker }
196*bb4ee6a4SAndroid Build Coastguard Worker 
197*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) struct RawRwLock {
198*bb4ee6a4SAndroid Build Coastguard Worker     state: AtomicUsize,
199*bb4ee6a4SAndroid Build Coastguard Worker     waiters: UnsafeCell<WaiterList>,
200*bb4ee6a4SAndroid Build Coastguard Worker }
201*bb4ee6a4SAndroid Build Coastguard Worker 
202*bb4ee6a4SAndroid Build Coastguard Worker impl RawRwLock {
new() -> RawRwLock203*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> RawRwLock {
204*bb4ee6a4SAndroid Build Coastguard Worker         RawRwLock {
205*bb4ee6a4SAndroid Build Coastguard Worker             state: AtomicUsize::new(0),
206*bb4ee6a4SAndroid Build Coastguard Worker             waiters: UnsafeCell::new(WaiterList::new(WaiterAdapter::new())),
207*bb4ee6a4SAndroid Build Coastguard Worker         }
208*bb4ee6a4SAndroid Build Coastguard Worker     }
209*bb4ee6a4SAndroid Build Coastguard Worker 
210*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
lock(&self)211*bb4ee6a4SAndroid Build Coastguard Worker     pub async fn lock(&self) {
212*bb4ee6a4SAndroid Build Coastguard Worker         match self
213*bb4ee6a4SAndroid Build Coastguard Worker             .state
214*bb4ee6a4SAndroid Build Coastguard Worker             .compare_exchange_weak(0, LOCKED, Ordering::Acquire, Ordering::Relaxed)
215*bb4ee6a4SAndroid Build Coastguard Worker         {
216*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_) => {}
217*bb4ee6a4SAndroid Build Coastguard Worker             Err(oldstate) => {
218*bb4ee6a4SAndroid Build Coastguard Worker                 // If any bits that should be zero are not zero or if we fail to acquire the lock
219*bb4ee6a4SAndroid Build Coastguard Worker                 // with a single compare_exchange then go through the slow path.
220*bb4ee6a4SAndroid Build Coastguard Worker                 if (oldstate & Exclusive::zero_to_acquire()) != 0
221*bb4ee6a4SAndroid Build Coastguard Worker                     || self
222*bb4ee6a4SAndroid Build Coastguard Worker                         .state
223*bb4ee6a4SAndroid Build Coastguard Worker                         .compare_exchange_weak(
224*bb4ee6a4SAndroid Build Coastguard Worker                             oldstate,
225*bb4ee6a4SAndroid Build Coastguard Worker                             (oldstate + Exclusive::add_to_acquire())
226*bb4ee6a4SAndroid Build Coastguard Worker                                 & !Exclusive::clear_on_acquire(),
227*bb4ee6a4SAndroid Build Coastguard Worker                             Ordering::Acquire,
228*bb4ee6a4SAndroid Build Coastguard Worker                             Ordering::Relaxed,
229*bb4ee6a4SAndroid Build Coastguard Worker                         )
230*bb4ee6a4SAndroid Build Coastguard Worker                         .is_err()
231*bb4ee6a4SAndroid Build Coastguard Worker                 {
232*bb4ee6a4SAndroid Build Coastguard Worker                     self.lock_slow::<Exclusive>(0, 0).await;
233*bb4ee6a4SAndroid Build Coastguard Worker                 }
234*bb4ee6a4SAndroid Build Coastguard Worker             }
235*bb4ee6a4SAndroid Build Coastguard Worker         }
236*bb4ee6a4SAndroid Build Coastguard Worker     }
237*bb4ee6a4SAndroid Build Coastguard Worker 
238*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
read_lock(&self)239*bb4ee6a4SAndroid Build Coastguard Worker     pub async fn read_lock(&self) {
240*bb4ee6a4SAndroid Build Coastguard Worker         match self
241*bb4ee6a4SAndroid Build Coastguard Worker             .state
242*bb4ee6a4SAndroid Build Coastguard Worker             .compare_exchange_weak(0, READ_LOCK, Ordering::Acquire, Ordering::Relaxed)
243*bb4ee6a4SAndroid Build Coastguard Worker         {
244*bb4ee6a4SAndroid Build Coastguard Worker             Ok(_) => {}
245*bb4ee6a4SAndroid Build Coastguard Worker             Err(oldstate) => {
246*bb4ee6a4SAndroid Build Coastguard Worker                 if (oldstate & Shared::zero_to_acquire()) != 0
247*bb4ee6a4SAndroid Build Coastguard Worker                     || self
248*bb4ee6a4SAndroid Build Coastguard Worker                         .state
249*bb4ee6a4SAndroid Build Coastguard Worker                         .compare_exchange_weak(
250*bb4ee6a4SAndroid Build Coastguard Worker                             oldstate,
251*bb4ee6a4SAndroid Build Coastguard Worker                             (oldstate + Shared::add_to_acquire()) & !Shared::clear_on_acquire(),
252*bb4ee6a4SAndroid Build Coastguard Worker                             Ordering::Acquire,
253*bb4ee6a4SAndroid Build Coastguard Worker                             Ordering::Relaxed,
254*bb4ee6a4SAndroid Build Coastguard Worker                         )
255*bb4ee6a4SAndroid Build Coastguard Worker                         .is_err()
256*bb4ee6a4SAndroid Build Coastguard Worker                 {
257*bb4ee6a4SAndroid Build Coastguard Worker                     self.lock_slow::<Shared>(0, 0).await;
258*bb4ee6a4SAndroid Build Coastguard Worker                 }
259*bb4ee6a4SAndroid Build Coastguard Worker             }
260*bb4ee6a4SAndroid Build Coastguard Worker         }
261*bb4ee6a4SAndroid Build Coastguard Worker     }
262*bb4ee6a4SAndroid Build Coastguard Worker 
263*bb4ee6a4SAndroid Build Coastguard Worker     // Slow path for acquiring the lock. `clear` should contain any bits that need to be cleared
264*bb4ee6a4SAndroid Build Coastguard Worker     // when the lock is acquired. Any bits set in `zero_mask` are cleared from the bits returned by
265*bb4ee6a4SAndroid Build Coastguard Worker     // `K::zero_to_acquire()`.
266*bb4ee6a4SAndroid Build Coastguard Worker     #[cold]
lock_slow<K: Kind>(&self, mut clear: usize, zero_mask: usize)267*bb4ee6a4SAndroid Build Coastguard Worker     async fn lock_slow<K: Kind>(&self, mut clear: usize, zero_mask: usize) {
268*bb4ee6a4SAndroid Build Coastguard Worker         let mut zero_to_acquire = K::zero_to_acquire() & !zero_mask;
269*bb4ee6a4SAndroid Build Coastguard Worker 
270*bb4ee6a4SAndroid Build Coastguard Worker         let mut spin_count = 0;
271*bb4ee6a4SAndroid Build Coastguard Worker         let mut wait_count = 0;
272*bb4ee6a4SAndroid Build Coastguard Worker         let mut waiter = None;
273*bb4ee6a4SAndroid Build Coastguard Worker         loop {
274*bb4ee6a4SAndroid Build Coastguard Worker             let oldstate = self.state.load(Ordering::Relaxed);
275*bb4ee6a4SAndroid Build Coastguard Worker             //  If all the bits in `zero_to_acquire` are actually zero then try to acquire the lock
276*bb4ee6a4SAndroid Build Coastguard Worker             //  directly.
277*bb4ee6a4SAndroid Build Coastguard Worker             if (oldstate & zero_to_acquire) == 0 {
278*bb4ee6a4SAndroid Build Coastguard Worker                 if self
279*bb4ee6a4SAndroid Build Coastguard Worker                     .state
280*bb4ee6a4SAndroid Build Coastguard Worker                     .compare_exchange_weak(
281*bb4ee6a4SAndroid Build Coastguard Worker                         oldstate,
282*bb4ee6a4SAndroid Build Coastguard Worker                         (oldstate + K::add_to_acquire()) & !(clear | K::clear_on_acquire()),
283*bb4ee6a4SAndroid Build Coastguard Worker                         Ordering::Acquire,
284*bb4ee6a4SAndroid Build Coastguard Worker                         Ordering::Relaxed,
285*bb4ee6a4SAndroid Build Coastguard Worker                     )
286*bb4ee6a4SAndroid Build Coastguard Worker                     .is_ok()
287*bb4ee6a4SAndroid Build Coastguard Worker                 {
288*bb4ee6a4SAndroid Build Coastguard Worker                     return;
289*bb4ee6a4SAndroid Build Coastguard Worker                 }
290*bb4ee6a4SAndroid Build Coastguard Worker             } else if (oldstate & SPINLOCK) == 0 {
291*bb4ee6a4SAndroid Build Coastguard Worker                 // The rwlock is locked and the spin lock is available.  Try to add this thread to
292*bb4ee6a4SAndroid Build Coastguard Worker                 // the waiter queue.
293*bb4ee6a4SAndroid Build Coastguard Worker                 let w = waiter.get_or_insert_with(|| K::new_waiter(self));
294*bb4ee6a4SAndroid Build Coastguard Worker                 w.reset(WaitingFor::Mutex);
295*bb4ee6a4SAndroid Build Coastguard Worker 
296*bb4ee6a4SAndroid Build Coastguard Worker                 if self
297*bb4ee6a4SAndroid Build Coastguard Worker                     .state
298*bb4ee6a4SAndroid Build Coastguard Worker                     .compare_exchange_weak(
299*bb4ee6a4SAndroid Build Coastguard Worker                         oldstate,
300*bb4ee6a4SAndroid Build Coastguard Worker                         (oldstate | SPINLOCK | HAS_WAITERS | K::set_when_waiting()) & !clear,
301*bb4ee6a4SAndroid Build Coastguard Worker                         Ordering::Acquire,
302*bb4ee6a4SAndroid Build Coastguard Worker                         Ordering::Relaxed,
303*bb4ee6a4SAndroid Build Coastguard Worker                     )
304*bb4ee6a4SAndroid Build Coastguard Worker                     .is_ok()
305*bb4ee6a4SAndroid Build Coastguard Worker                 {
306*bb4ee6a4SAndroid Build Coastguard Worker                     let mut set_on_release = 0;
307*bb4ee6a4SAndroid Build Coastguard Worker 
308*bb4ee6a4SAndroid Build Coastguard Worker                     if wait_count < LONG_WAIT_THRESHOLD {
309*bb4ee6a4SAndroid Build Coastguard Worker                         // Add the waiter to the back of the queue.
310*bb4ee6a4SAndroid Build Coastguard Worker                         // SAFETY:
311*bb4ee6a4SAndroid Build Coastguard Worker                         // Safe because we have acquired the spin lock and it provides exclusive
312*bb4ee6a4SAndroid Build Coastguard Worker                         // access to the waiter queue.
313*bb4ee6a4SAndroid Build Coastguard Worker                         unsafe { (*self.waiters.get()).push_back(w.clone()) };
314*bb4ee6a4SAndroid Build Coastguard Worker                     } else {
315*bb4ee6a4SAndroid Build Coastguard Worker                         // This waiter has gone through the queue too many times. Put it in the
316*bb4ee6a4SAndroid Build Coastguard Worker                         // front of the queue and block all other threads from acquiring the lock
317*bb4ee6a4SAndroid Build Coastguard Worker                         // until this one has acquired it at least once.
318*bb4ee6a4SAndroid Build Coastguard Worker                         // SAFETY:
319*bb4ee6a4SAndroid Build Coastguard Worker                         // Safe because we have acquired the spin lock and it provides exclusive
320*bb4ee6a4SAndroid Build Coastguard Worker                         // access to the waiter queue.
321*bb4ee6a4SAndroid Build Coastguard Worker                         unsafe { (*self.waiters.get()).push_front(w.clone()) };
322*bb4ee6a4SAndroid Build Coastguard Worker 
323*bb4ee6a4SAndroid Build Coastguard Worker                         // Set the LONG_WAIT bit to prevent all other threads from acquiring the
324*bb4ee6a4SAndroid Build Coastguard Worker                         // lock.
325*bb4ee6a4SAndroid Build Coastguard Worker                         set_on_release |= LONG_WAIT;
326*bb4ee6a4SAndroid Build Coastguard Worker 
327*bb4ee6a4SAndroid Build Coastguard Worker                         // Make sure we clear the LONG_WAIT bit when we do finally get the lock.
328*bb4ee6a4SAndroid Build Coastguard Worker                         clear |= LONG_WAIT;
329*bb4ee6a4SAndroid Build Coastguard Worker 
330*bb4ee6a4SAndroid Build Coastguard Worker                         // Since we set the LONG_WAIT bit we shouldn't allow that bit to prevent us
331*bb4ee6a4SAndroid Build Coastguard Worker                         // from acquiring the lock.
332*bb4ee6a4SAndroid Build Coastguard Worker                         zero_to_acquire &= !LONG_WAIT;
333*bb4ee6a4SAndroid Build Coastguard Worker                     }
334*bb4ee6a4SAndroid Build Coastguard Worker 
335*bb4ee6a4SAndroid Build Coastguard Worker                     // Release the spin lock.
336*bb4ee6a4SAndroid Build Coastguard Worker                     let mut state = oldstate;
337*bb4ee6a4SAndroid Build Coastguard Worker                     loop {
338*bb4ee6a4SAndroid Build Coastguard Worker                         match self.state.compare_exchange_weak(
339*bb4ee6a4SAndroid Build Coastguard Worker                             state,
340*bb4ee6a4SAndroid Build Coastguard Worker                             (state | set_on_release) & !SPINLOCK,
341*bb4ee6a4SAndroid Build Coastguard Worker                             Ordering::Release,
342*bb4ee6a4SAndroid Build Coastguard Worker                             Ordering::Relaxed,
343*bb4ee6a4SAndroid Build Coastguard Worker                         ) {
344*bb4ee6a4SAndroid Build Coastguard Worker                             Ok(_) => break,
345*bb4ee6a4SAndroid Build Coastguard Worker                             Err(w) => state = w,
346*bb4ee6a4SAndroid Build Coastguard Worker                         }
347*bb4ee6a4SAndroid Build Coastguard Worker                     }
348*bb4ee6a4SAndroid Build Coastguard Worker 
349*bb4ee6a4SAndroid Build Coastguard Worker                     // Now wait until we are woken.
350*bb4ee6a4SAndroid Build Coastguard Worker                     w.wait().await;
351*bb4ee6a4SAndroid Build Coastguard Worker 
352*bb4ee6a4SAndroid Build Coastguard Worker                     // The `DESIGNATED_WAKER` bit gets set when this thread is woken up by the
353*bb4ee6a4SAndroid Build Coastguard Worker                     // thread that originally held the lock. While this bit is set, no other waiters
354*bb4ee6a4SAndroid Build Coastguard Worker                     // will be woken up so it's important to clear it the next time we try to
355*bb4ee6a4SAndroid Build Coastguard Worker                     // acquire the main lock or the spin lock.
356*bb4ee6a4SAndroid Build Coastguard Worker                     clear |= DESIGNATED_WAKER;
357*bb4ee6a4SAndroid Build Coastguard Worker 
358*bb4ee6a4SAndroid Build Coastguard Worker                     // Now that the thread has waited once, we no longer care if there is a writer
359*bb4ee6a4SAndroid Build Coastguard Worker                     // waiting. Only the limits of mutual exclusion can prevent us from acquiring
360*bb4ee6a4SAndroid Build Coastguard Worker                     // the lock.
361*bb4ee6a4SAndroid Build Coastguard Worker                     zero_to_acquire &= !WRITER_WAITING;
362*bb4ee6a4SAndroid Build Coastguard Worker 
363*bb4ee6a4SAndroid Build Coastguard Worker                     // Reset the spin count since we just went through the wait queue.
364*bb4ee6a4SAndroid Build Coastguard Worker                     spin_count = 0;
365*bb4ee6a4SAndroid Build Coastguard Worker 
366*bb4ee6a4SAndroid Build Coastguard Worker                     // Increment the wait count since we went through the wait queue.
367*bb4ee6a4SAndroid Build Coastguard Worker                     wait_count += 1;
368*bb4ee6a4SAndroid Build Coastguard Worker 
369*bb4ee6a4SAndroid Build Coastguard Worker                     // Skip the `cpu_relax` below.
370*bb4ee6a4SAndroid Build Coastguard Worker                     continue;
371*bb4ee6a4SAndroid Build Coastguard Worker                 }
372*bb4ee6a4SAndroid Build Coastguard Worker             }
373*bb4ee6a4SAndroid Build Coastguard Worker 
374*bb4ee6a4SAndroid Build Coastguard Worker             // Both the lock and the spin lock are held by one or more other threads. First, we'll
375*bb4ee6a4SAndroid Build Coastguard Worker             // spin a few times in case we can acquire the lock or the spin lock. If that fails then
376*bb4ee6a4SAndroid Build Coastguard Worker             // we yield because we might be preventing the threads that do hold the 2 locks from
377*bb4ee6a4SAndroid Build Coastguard Worker             // getting cpu time.
378*bb4ee6a4SAndroid Build Coastguard Worker             if spin_count < SPIN_THRESHOLD {
379*bb4ee6a4SAndroid Build Coastguard Worker                 cpu_relax(1 << spin_count);
380*bb4ee6a4SAndroid Build Coastguard Worker                 spin_count += 1;
381*bb4ee6a4SAndroid Build Coastguard Worker             } else {
382*bb4ee6a4SAndroid Build Coastguard Worker                 yield_now();
383*bb4ee6a4SAndroid Build Coastguard Worker             }
384*bb4ee6a4SAndroid Build Coastguard Worker         }
385*bb4ee6a4SAndroid Build Coastguard Worker     }
386*bb4ee6a4SAndroid Build Coastguard Worker 
387*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
unlock(&self)388*bb4ee6a4SAndroid Build Coastguard Worker     pub fn unlock(&self) {
389*bb4ee6a4SAndroid Build Coastguard Worker         // Fast path, if possible. We can directly clear the locked bit since we have exclusive
390*bb4ee6a4SAndroid Build Coastguard Worker         // access to the rwlock.
391*bb4ee6a4SAndroid Build Coastguard Worker         let oldstate = self.state.fetch_sub(LOCKED, Ordering::Release);
392*bb4ee6a4SAndroid Build Coastguard Worker 
393*bb4ee6a4SAndroid Build Coastguard Worker         // Panic if we just tried to unlock a rwlock that wasn't held by this thread. This shouldn't
394*bb4ee6a4SAndroid Build Coastguard Worker         // really be possible since `unlock` is not a public method.
395*bb4ee6a4SAndroid Build Coastguard Worker         debug_assert_eq!(
396*bb4ee6a4SAndroid Build Coastguard Worker             oldstate & READ_MASK,
397*bb4ee6a4SAndroid Build Coastguard Worker             0,
398*bb4ee6a4SAndroid Build Coastguard Worker             "`unlock` called on rwlock held in read-mode"
399*bb4ee6a4SAndroid Build Coastguard Worker         );
400*bb4ee6a4SAndroid Build Coastguard Worker         debug_assert_ne!(
401*bb4ee6a4SAndroid Build Coastguard Worker             oldstate & LOCKED,
402*bb4ee6a4SAndroid Build Coastguard Worker             0,
403*bb4ee6a4SAndroid Build Coastguard Worker             "`unlock` called on rwlock not held in write-mode"
404*bb4ee6a4SAndroid Build Coastguard Worker         );
405*bb4ee6a4SAndroid Build Coastguard Worker 
406*bb4ee6a4SAndroid Build Coastguard Worker         if (oldstate & HAS_WAITERS) != 0 && (oldstate & DESIGNATED_WAKER) == 0 {
407*bb4ee6a4SAndroid Build Coastguard Worker             // The oldstate has waiters but no designated waker has been chosen yet.
408*bb4ee6a4SAndroid Build Coastguard Worker             self.unlock_slow();
409*bb4ee6a4SAndroid Build Coastguard Worker         }
410*bb4ee6a4SAndroid Build Coastguard Worker     }
411*bb4ee6a4SAndroid Build Coastguard Worker 
412*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
read_unlock(&self)413*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read_unlock(&self) {
414*bb4ee6a4SAndroid Build Coastguard Worker         // Fast path, if possible. We can directly subtract the READ_LOCK bit since we had
415*bb4ee6a4SAndroid Build Coastguard Worker         // previously added it.
416*bb4ee6a4SAndroid Build Coastguard Worker         let oldstate = self.state.fetch_sub(READ_LOCK, Ordering::Release);
417*bb4ee6a4SAndroid Build Coastguard Worker 
418*bb4ee6a4SAndroid Build Coastguard Worker         debug_assert_eq!(
419*bb4ee6a4SAndroid Build Coastguard Worker             oldstate & LOCKED,
420*bb4ee6a4SAndroid Build Coastguard Worker             0,
421*bb4ee6a4SAndroid Build Coastguard Worker             "`read_unlock` called on rwlock held in write-mode"
422*bb4ee6a4SAndroid Build Coastguard Worker         );
423*bb4ee6a4SAndroid Build Coastguard Worker         debug_assert_ne!(
424*bb4ee6a4SAndroid Build Coastguard Worker             oldstate & READ_MASK,
425*bb4ee6a4SAndroid Build Coastguard Worker             0,
426*bb4ee6a4SAndroid Build Coastguard Worker             "`read_unlock` called on rwlock not held in read-mode"
427*bb4ee6a4SAndroid Build Coastguard Worker         );
428*bb4ee6a4SAndroid Build Coastguard Worker 
429*bb4ee6a4SAndroid Build Coastguard Worker         if (oldstate & HAS_WAITERS) != 0
430*bb4ee6a4SAndroid Build Coastguard Worker             && (oldstate & DESIGNATED_WAKER) == 0
431*bb4ee6a4SAndroid Build Coastguard Worker             && (oldstate & READ_MASK) == READ_LOCK
432*bb4ee6a4SAndroid Build Coastguard Worker         {
433*bb4ee6a4SAndroid Build Coastguard Worker             // There are waiters, no designated waker has been chosen yet, and the last reader is
434*bb4ee6a4SAndroid Build Coastguard Worker             // unlocking so we have to take the slow path.
435*bb4ee6a4SAndroid Build Coastguard Worker             self.unlock_slow();
436*bb4ee6a4SAndroid Build Coastguard Worker         }
437*bb4ee6a4SAndroid Build Coastguard Worker     }
438*bb4ee6a4SAndroid Build Coastguard Worker 
439*bb4ee6a4SAndroid Build Coastguard Worker     #[cold]
unlock_slow(&self)440*bb4ee6a4SAndroid Build Coastguard Worker     fn unlock_slow(&self) {
441*bb4ee6a4SAndroid Build Coastguard Worker         let mut spin_count = 0;
442*bb4ee6a4SAndroid Build Coastguard Worker 
443*bb4ee6a4SAndroid Build Coastguard Worker         loop {
444*bb4ee6a4SAndroid Build Coastguard Worker             let oldstate = self.state.load(Ordering::Relaxed);
445*bb4ee6a4SAndroid Build Coastguard Worker             if (oldstate & HAS_WAITERS) == 0 || (oldstate & DESIGNATED_WAKER) != 0 {
446*bb4ee6a4SAndroid Build Coastguard Worker                 // No more waiters or a designated waker has been chosen. Nothing left for us to do.
447*bb4ee6a4SAndroid Build Coastguard Worker                 return;
448*bb4ee6a4SAndroid Build Coastguard Worker             } else if (oldstate & SPINLOCK) == 0 {
449*bb4ee6a4SAndroid Build Coastguard Worker                 // The spin lock is not held by another thread. Try to acquire it. Also set the
450*bb4ee6a4SAndroid Build Coastguard Worker                 // `DESIGNATED_WAKER` bit since we are likely going to wake up one or more threads.
451*bb4ee6a4SAndroid Build Coastguard Worker                 if self
452*bb4ee6a4SAndroid Build Coastguard Worker                     .state
453*bb4ee6a4SAndroid Build Coastguard Worker                     .compare_exchange_weak(
454*bb4ee6a4SAndroid Build Coastguard Worker                         oldstate,
455*bb4ee6a4SAndroid Build Coastguard Worker                         oldstate | SPINLOCK | DESIGNATED_WAKER,
456*bb4ee6a4SAndroid Build Coastguard Worker                         Ordering::Acquire,
457*bb4ee6a4SAndroid Build Coastguard Worker                         Ordering::Relaxed,
458*bb4ee6a4SAndroid Build Coastguard Worker                     )
459*bb4ee6a4SAndroid Build Coastguard Worker                     .is_ok()
460*bb4ee6a4SAndroid Build Coastguard Worker                 {
461*bb4ee6a4SAndroid Build Coastguard Worker                     // Acquired the spinlock. Try to wake a waiter. We may also end up wanting to
462*bb4ee6a4SAndroid Build Coastguard Worker                     // clear the HAS_WAITER and DESIGNATED_WAKER bits so start collecting the bits
463*bb4ee6a4SAndroid Build Coastguard Worker                     // to be cleared.
464*bb4ee6a4SAndroid Build Coastguard Worker                     let mut clear = SPINLOCK;
465*bb4ee6a4SAndroid Build Coastguard Worker 
466*bb4ee6a4SAndroid Build Coastguard Worker                     // SAFETY:
467*bb4ee6a4SAndroid Build Coastguard Worker                     // Safe because the spinlock guarantees exclusive access to the waiter list and
468*bb4ee6a4SAndroid Build Coastguard Worker                     // the reference does not escape this function.
469*bb4ee6a4SAndroid Build Coastguard Worker                     let waiters = unsafe { &mut *self.waiters.get() };
470*bb4ee6a4SAndroid Build Coastguard Worker                     let (wake_list, set_on_release) = get_wake_list(waiters);
471*bb4ee6a4SAndroid Build Coastguard Worker 
472*bb4ee6a4SAndroid Build Coastguard Worker                     // If the waiter list is now empty, clear the HAS_WAITERS bit.
473*bb4ee6a4SAndroid Build Coastguard Worker                     if waiters.is_empty() {
474*bb4ee6a4SAndroid Build Coastguard Worker                         clear |= HAS_WAITERS;
475*bb4ee6a4SAndroid Build Coastguard Worker                     }
476*bb4ee6a4SAndroid Build Coastguard Worker 
477*bb4ee6a4SAndroid Build Coastguard Worker                     if wake_list.is_empty() {
478*bb4ee6a4SAndroid Build Coastguard Worker                         // Since we are not going to wake any waiters clear the DESIGNATED_WAKER bit
479*bb4ee6a4SAndroid Build Coastguard Worker                         // that we set when we acquired the spin lock.
480*bb4ee6a4SAndroid Build Coastguard Worker                         clear |= DESIGNATED_WAKER;
481*bb4ee6a4SAndroid Build Coastguard Worker                     }
482*bb4ee6a4SAndroid Build Coastguard Worker 
483*bb4ee6a4SAndroid Build Coastguard Worker                     // Release the spin lock and clear any other bits as necessary. Also, set any
484*bb4ee6a4SAndroid Build Coastguard Worker                     // bits returned by `get_wake_list`. For now, this is just the `WRITER_WAITING`
485*bb4ee6a4SAndroid Build Coastguard Worker                     // bit, which needs to be set when we are waking up a bunch of readers and there
486*bb4ee6a4SAndroid Build Coastguard Worker                     // are still writers in the wait queue. This will prevent any readers that
487*bb4ee6a4SAndroid Build Coastguard Worker                     // aren't in `wake_list` from acquiring the read lock.
488*bb4ee6a4SAndroid Build Coastguard Worker                     let mut state = oldstate;
489*bb4ee6a4SAndroid Build Coastguard Worker                     loop {
490*bb4ee6a4SAndroid Build Coastguard Worker                         match self.state.compare_exchange_weak(
491*bb4ee6a4SAndroid Build Coastguard Worker                             state,
492*bb4ee6a4SAndroid Build Coastguard Worker                             (state | set_on_release) & !clear,
493*bb4ee6a4SAndroid Build Coastguard Worker                             Ordering::Release,
494*bb4ee6a4SAndroid Build Coastguard Worker                             Ordering::Relaxed,
495*bb4ee6a4SAndroid Build Coastguard Worker                         ) {
496*bb4ee6a4SAndroid Build Coastguard Worker                             Ok(_) => break,
497*bb4ee6a4SAndroid Build Coastguard Worker                             Err(w) => state = w,
498*bb4ee6a4SAndroid Build Coastguard Worker                         }
499*bb4ee6a4SAndroid Build Coastguard Worker                     }
500*bb4ee6a4SAndroid Build Coastguard Worker 
501*bb4ee6a4SAndroid Build Coastguard Worker                     // Now wake the waiters, if any.
502*bb4ee6a4SAndroid Build Coastguard Worker                     for w in wake_list {
503*bb4ee6a4SAndroid Build Coastguard Worker                         w.wake();
504*bb4ee6a4SAndroid Build Coastguard Worker                     }
505*bb4ee6a4SAndroid Build Coastguard Worker 
506*bb4ee6a4SAndroid Build Coastguard Worker                     // We're done.
507*bb4ee6a4SAndroid Build Coastguard Worker                     return;
508*bb4ee6a4SAndroid Build Coastguard Worker                 }
509*bb4ee6a4SAndroid Build Coastguard Worker             }
510*bb4ee6a4SAndroid Build Coastguard Worker 
511*bb4ee6a4SAndroid Build Coastguard Worker             // Spin and try again.  It's ok to block here as we have already released the lock.
512*bb4ee6a4SAndroid Build Coastguard Worker             if spin_count < SPIN_THRESHOLD {
513*bb4ee6a4SAndroid Build Coastguard Worker                 cpu_relax(1 << spin_count);
514*bb4ee6a4SAndroid Build Coastguard Worker                 spin_count += 1;
515*bb4ee6a4SAndroid Build Coastguard Worker             } else {
516*bb4ee6a4SAndroid Build Coastguard Worker                 yield_now();
517*bb4ee6a4SAndroid Build Coastguard Worker             }
518*bb4ee6a4SAndroid Build Coastguard Worker         }
519*bb4ee6a4SAndroid Build Coastguard Worker     }
520*bb4ee6a4SAndroid Build Coastguard Worker 
cancel_waiter(&self, waiter: &Waiter, wake_next: bool)521*bb4ee6a4SAndroid Build Coastguard Worker     fn cancel_waiter(&self, waiter: &Waiter, wake_next: bool) {
522*bb4ee6a4SAndroid Build Coastguard Worker         let mut oldstate = self.state.load(Ordering::Relaxed);
523*bb4ee6a4SAndroid Build Coastguard Worker         while oldstate & SPINLOCK != 0
524*bb4ee6a4SAndroid Build Coastguard Worker             || self
525*bb4ee6a4SAndroid Build Coastguard Worker                 .state
526*bb4ee6a4SAndroid Build Coastguard Worker                 .compare_exchange_weak(
527*bb4ee6a4SAndroid Build Coastguard Worker                     oldstate,
528*bb4ee6a4SAndroid Build Coastguard Worker                     oldstate | SPINLOCK,
529*bb4ee6a4SAndroid Build Coastguard Worker                     Ordering::Acquire,
530*bb4ee6a4SAndroid Build Coastguard Worker                     Ordering::Relaxed,
531*bb4ee6a4SAndroid Build Coastguard Worker                 )
532*bb4ee6a4SAndroid Build Coastguard Worker                 .is_err()
533*bb4ee6a4SAndroid Build Coastguard Worker         {
534*bb4ee6a4SAndroid Build Coastguard Worker             hint::spin_loop();
535*bb4ee6a4SAndroid Build Coastguard Worker             oldstate = self.state.load(Ordering::Relaxed);
536*bb4ee6a4SAndroid Build Coastguard Worker         }
537*bb4ee6a4SAndroid Build Coastguard Worker 
538*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
539*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the spin lock provides exclusive access and the reference does not escape
540*bb4ee6a4SAndroid Build Coastguard Worker         // this function.
541*bb4ee6a4SAndroid Build Coastguard Worker         let waiters = unsafe { &mut *self.waiters.get() };
542*bb4ee6a4SAndroid Build Coastguard Worker 
543*bb4ee6a4SAndroid Build Coastguard Worker         let mut clear = SPINLOCK;
544*bb4ee6a4SAndroid Build Coastguard Worker 
545*bb4ee6a4SAndroid Build Coastguard Worker         // If we are about to remove the first waiter in the wait list, then clear the LONG_WAIT
546*bb4ee6a4SAndroid Build Coastguard Worker         // bit. Also clear the bit if we are going to be waking some other waiters. In this case the
547*bb4ee6a4SAndroid Build Coastguard Worker         // waiter that set the bit may have already been removed from the waiter list (and could be
548*bb4ee6a4SAndroid Build Coastguard Worker         // the one that is currently being dropped). If it is still in the waiter list then clearing
549*bb4ee6a4SAndroid Build Coastguard Worker         // this bit may starve it for one more iteration through the lock_slow() loop, whereas not
550*bb4ee6a4SAndroid Build Coastguard Worker         // clearing this bit could cause a deadlock if the waiter that set it is the one that is
551*bb4ee6a4SAndroid Build Coastguard Worker         // being dropped.
552*bb4ee6a4SAndroid Build Coastguard Worker         if wake_next
553*bb4ee6a4SAndroid Build Coastguard Worker             || waiters
554*bb4ee6a4SAndroid Build Coastguard Worker                 .front()
555*bb4ee6a4SAndroid Build Coastguard Worker                 .get()
556*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|front| std::ptr::eq(front, waiter))
557*bb4ee6a4SAndroid Build Coastguard Worker                 .unwrap_or(false)
558*bb4ee6a4SAndroid Build Coastguard Worker         {
559*bb4ee6a4SAndroid Build Coastguard Worker             clear |= LONG_WAIT;
560*bb4ee6a4SAndroid Build Coastguard Worker         }
561*bb4ee6a4SAndroid Build Coastguard Worker 
562*bb4ee6a4SAndroid Build Coastguard Worker         let waiting_for = waiter.is_waiting_for();
563*bb4ee6a4SAndroid Build Coastguard Worker 
564*bb4ee6a4SAndroid Build Coastguard Worker         // Don't drop the old waiter while holding the spin lock.
565*bb4ee6a4SAndroid Build Coastguard Worker         let old_waiter = if waiter.is_linked() && waiting_for == WaitingFor::Mutex {
566*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
567*bb4ee6a4SAndroid Build Coastguard Worker             // We know that the waiter is still linked and is waiting for the rwlock, which
568*bb4ee6a4SAndroid Build Coastguard Worker             // guarantees that it is still linked into `self.waiters`.
569*bb4ee6a4SAndroid Build Coastguard Worker             let mut cursor = unsafe { waiters.cursor_mut_from_ptr(waiter as *const Waiter) };
570*bb4ee6a4SAndroid Build Coastguard Worker             cursor.remove()
571*bb4ee6a4SAndroid Build Coastguard Worker         } else {
572*bb4ee6a4SAndroid Build Coastguard Worker             None
573*bb4ee6a4SAndroid Build Coastguard Worker         };
574*bb4ee6a4SAndroid Build Coastguard Worker 
575*bb4ee6a4SAndroid Build Coastguard Worker         let (wake_list, set_on_release) = if wake_next || waiting_for == WaitingFor::None {
576*bb4ee6a4SAndroid Build Coastguard Worker             // Either the waiter was already woken or it's been removed from the rwlock's waiter
577*bb4ee6a4SAndroid Build Coastguard Worker             // list and is going to be woken. Either way, we need to wake up another thread.
578*bb4ee6a4SAndroid Build Coastguard Worker             get_wake_list(waiters)
579*bb4ee6a4SAndroid Build Coastguard Worker         } else {
580*bb4ee6a4SAndroid Build Coastguard Worker             (WaiterList::new(WaiterAdapter::new()), 0)
581*bb4ee6a4SAndroid Build Coastguard Worker         };
582*bb4ee6a4SAndroid Build Coastguard Worker 
583*bb4ee6a4SAndroid Build Coastguard Worker         if waiters.is_empty() {
584*bb4ee6a4SAndroid Build Coastguard Worker             clear |= HAS_WAITERS;
585*bb4ee6a4SAndroid Build Coastguard Worker         }
586*bb4ee6a4SAndroid Build Coastguard Worker 
587*bb4ee6a4SAndroid Build Coastguard Worker         if wake_list.is_empty() {
588*bb4ee6a4SAndroid Build Coastguard Worker             // We're not waking any other threads so clear the DESIGNATED_WAKER bit. In the worst
589*bb4ee6a4SAndroid Build Coastguard Worker             // case this leads to an additional thread being woken up but we risk a deadlock if we
590*bb4ee6a4SAndroid Build Coastguard Worker             // don't clear it.
591*bb4ee6a4SAndroid Build Coastguard Worker             clear |= DESIGNATED_WAKER;
592*bb4ee6a4SAndroid Build Coastguard Worker         }
593*bb4ee6a4SAndroid Build Coastguard Worker 
594*bb4ee6a4SAndroid Build Coastguard Worker         if let WaiterKind::Exclusive = waiter.kind() {
595*bb4ee6a4SAndroid Build Coastguard Worker             // The waiter being dropped is a writer so clear the writer waiting bit for now. If we
596*bb4ee6a4SAndroid Build Coastguard Worker             // found more writers in the list while fetching waiters to wake up then this bit will
597*bb4ee6a4SAndroid Build Coastguard Worker             // be set again via `set_on_release`.
598*bb4ee6a4SAndroid Build Coastguard Worker             clear |= WRITER_WAITING;
599*bb4ee6a4SAndroid Build Coastguard Worker         }
600*bb4ee6a4SAndroid Build Coastguard Worker 
601*bb4ee6a4SAndroid Build Coastguard Worker         while self
602*bb4ee6a4SAndroid Build Coastguard Worker             .state
603*bb4ee6a4SAndroid Build Coastguard Worker             .compare_exchange_weak(
604*bb4ee6a4SAndroid Build Coastguard Worker                 oldstate,
605*bb4ee6a4SAndroid Build Coastguard Worker                 (oldstate & !clear) | set_on_release,
606*bb4ee6a4SAndroid Build Coastguard Worker                 Ordering::Release,
607*bb4ee6a4SAndroid Build Coastguard Worker                 Ordering::Relaxed,
608*bb4ee6a4SAndroid Build Coastguard Worker             )
609*bb4ee6a4SAndroid Build Coastguard Worker             .is_err()
610*bb4ee6a4SAndroid Build Coastguard Worker         {
611*bb4ee6a4SAndroid Build Coastguard Worker             hint::spin_loop();
612*bb4ee6a4SAndroid Build Coastguard Worker             oldstate = self.state.load(Ordering::Relaxed);
613*bb4ee6a4SAndroid Build Coastguard Worker         }
614*bb4ee6a4SAndroid Build Coastguard Worker 
615*bb4ee6a4SAndroid Build Coastguard Worker         for w in wake_list {
616*bb4ee6a4SAndroid Build Coastguard Worker             w.wake();
617*bb4ee6a4SAndroid Build Coastguard Worker         }
618*bb4ee6a4SAndroid Build Coastguard Worker 
619*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(old_waiter);
620*bb4ee6a4SAndroid Build Coastguard Worker     }
621*bb4ee6a4SAndroid Build Coastguard Worker }
622*bb4ee6a4SAndroid Build Coastguard Worker 
623*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/315998194): Add safety comment
624*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)]
625*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Send for RawRwLock {}
626*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/315998194): Add safety comment
627*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)]
628*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Sync for RawRwLock {}
629*bb4ee6a4SAndroid Build Coastguard Worker 
cancel_waiter(raw: usize, waiter: &Waiter, wake_next: bool)630*bb4ee6a4SAndroid Build Coastguard Worker fn cancel_waiter(raw: usize, waiter: &Waiter, wake_next: bool) {
631*bb4ee6a4SAndroid Build Coastguard Worker     let raw_rwlock = raw as *const RawRwLock;
632*bb4ee6a4SAndroid Build Coastguard Worker 
633*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY:
634*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because the thread that owns the waiter that is being canceled must also own a reference
635*bb4ee6a4SAndroid Build Coastguard Worker     // to the rwlock, which ensures that this pointer is valid.
636*bb4ee6a4SAndroid Build Coastguard Worker     unsafe { (*raw_rwlock).cancel_waiter(waiter, wake_next) }
637*bb4ee6a4SAndroid Build Coastguard Worker }
638*bb4ee6a4SAndroid Build Coastguard Worker 
639*bb4ee6a4SAndroid Build Coastguard Worker /// A high-level primitive that provides safe, mutable access to a shared resource.
640*bb4ee6a4SAndroid Build Coastguard Worker ///
641*bb4ee6a4SAndroid Build Coastguard Worker /// `RwLock` safely provides both shared, immutable access (via `read_lock()`) as well as exclusive,
642*bb4ee6a4SAndroid Build Coastguard Worker /// mutable access (via `lock()`) to an underlying resource asynchronously while ensuring fairness
643*bb4ee6a4SAndroid Build Coastguard Worker /// with no loss of performance. If you don't need `read_lock()` nor fairness, try upstream
644*bb4ee6a4SAndroid Build Coastguard Worker /// `futures::lock::Mutex` instead.
645*bb4ee6a4SAndroid Build Coastguard Worker ///
646*bb4ee6a4SAndroid Build Coastguard Worker /// # Poisoning
647*bb4ee6a4SAndroid Build Coastguard Worker ///
648*bb4ee6a4SAndroid Build Coastguard Worker /// `RwLock` does not support lock poisoning so if a thread panics while holding the lock, the
649*bb4ee6a4SAndroid Build Coastguard Worker /// poisoned data will be accessible by other threads in your program. If you need to guarantee that
650*bb4ee6a4SAndroid Build Coastguard Worker /// other threads cannot access poisoned data then you may wish to wrap this `RwLock` inside another
651*bb4ee6a4SAndroid Build Coastguard Worker /// type that provides the poisoning feature. See the implementation of `std::sync::Mutex` for an
652*bb4ee6a4SAndroid Build Coastguard Worker /// example of this. Note `futures::lock::Mutex` does not support poisoning either.
653*bb4ee6a4SAndroid Build Coastguard Worker ///
654*bb4ee6a4SAndroid Build Coastguard Worker ///
655*bb4ee6a4SAndroid Build Coastguard Worker /// # Fairness
656*bb4ee6a4SAndroid Build Coastguard Worker ///
657*bb4ee6a4SAndroid Build Coastguard Worker /// This `RwLock` implementation does not guarantee that threads will acquire the lock in the same
658*bb4ee6a4SAndroid Build Coastguard Worker /// order that they call `lock()` or `read_lock()`. However it will attempt to prevent long-term
659*bb4ee6a4SAndroid Build Coastguard Worker /// starvation: if a thread repeatedly fails to acquire the lock beyond a threshold then all other
660*bb4ee6a4SAndroid Build Coastguard Worker /// threads will fail to acquire the lock until the starved thread has acquired it. Note, on the
661*bb4ee6a4SAndroid Build Coastguard Worker /// other hand, `futures::lock::Mutex` does not guarantee fairness.
662*bb4ee6a4SAndroid Build Coastguard Worker ///
663*bb4ee6a4SAndroid Build Coastguard Worker /// Similarly, this `RwLock` will attempt to balance reader and writer threads: once there is a
664*bb4ee6a4SAndroid Build Coastguard Worker /// writer thread waiting to acquire the lock no new reader threads will be allowed to acquire it.
665*bb4ee6a4SAndroid Build Coastguard Worker /// However, any reader threads that were already waiting will still be allowed to acquire it.
666*bb4ee6a4SAndroid Build Coastguard Worker ///
667*bb4ee6a4SAndroid Build Coastguard Worker /// # Examples
668*bb4ee6a4SAndroid Build Coastguard Worker ///
669*bb4ee6a4SAndroid Build Coastguard Worker /// ```edition2018
670*bb4ee6a4SAndroid Build Coastguard Worker /// use std::sync::Arc;
671*bb4ee6a4SAndroid Build Coastguard Worker /// use std::thread;
672*bb4ee6a4SAndroid Build Coastguard Worker /// use std::sync::mpsc::channel;
673*bb4ee6a4SAndroid Build Coastguard Worker ///
674*bb4ee6a4SAndroid Build Coastguard Worker /// use cros_async::{block_on, sync::RwLock};
675*bb4ee6a4SAndroid Build Coastguard Worker ///
676*bb4ee6a4SAndroid Build Coastguard Worker /// const N: usize = 10;
677*bb4ee6a4SAndroid Build Coastguard Worker ///
678*bb4ee6a4SAndroid Build Coastguard Worker /// // Spawn a few threads to increment a shared variable (non-atomically), and
679*bb4ee6a4SAndroid Build Coastguard Worker /// // let the main thread know once all increments are done.
680*bb4ee6a4SAndroid Build Coastguard Worker /// //
681*bb4ee6a4SAndroid Build Coastguard Worker /// // Here we're using an Arc to share memory among threads, and the data inside
682*bb4ee6a4SAndroid Build Coastguard Worker /// // the Arc is protected with a rwlock.
683*bb4ee6a4SAndroid Build Coastguard Worker /// let data = Arc::new(RwLock::new(0));
684*bb4ee6a4SAndroid Build Coastguard Worker ///
685*bb4ee6a4SAndroid Build Coastguard Worker /// let (tx, rx) = channel();
686*bb4ee6a4SAndroid Build Coastguard Worker /// for _ in 0..N {
687*bb4ee6a4SAndroid Build Coastguard Worker ///     let (data, tx) = (Arc::clone(&data), tx.clone());
688*bb4ee6a4SAndroid Build Coastguard Worker ///     thread::spawn(move || {
689*bb4ee6a4SAndroid Build Coastguard Worker ///         // The shared state can only be accessed once the lock is held.
690*bb4ee6a4SAndroid Build Coastguard Worker ///         // Our non-atomic increment is safe because we're the only thread
691*bb4ee6a4SAndroid Build Coastguard Worker ///         // which can access the shared state when the lock is held.
692*bb4ee6a4SAndroid Build Coastguard Worker ///         let mut data = block_on(data.lock());
693*bb4ee6a4SAndroid Build Coastguard Worker ///         *data += 1;
694*bb4ee6a4SAndroid Build Coastguard Worker ///         if *data == N {
695*bb4ee6a4SAndroid Build Coastguard Worker ///             tx.send(()).unwrap();
696*bb4ee6a4SAndroid Build Coastguard Worker ///         }
697*bb4ee6a4SAndroid Build Coastguard Worker ///         // the lock is unlocked here when `data` goes out of scope.
698*bb4ee6a4SAndroid Build Coastguard Worker ///     });
699*bb4ee6a4SAndroid Build Coastguard Worker /// }
700*bb4ee6a4SAndroid Build Coastguard Worker ///
701*bb4ee6a4SAndroid Build Coastguard Worker /// rx.recv().unwrap();
702*bb4ee6a4SAndroid Build Coastguard Worker /// ```
703*bb4ee6a4SAndroid Build Coastguard Worker #[repr(align(128))]
704*bb4ee6a4SAndroid Build Coastguard Worker pub struct RwLock<T: ?Sized> {
705*bb4ee6a4SAndroid Build Coastguard Worker     raw: RawRwLock,
706*bb4ee6a4SAndroid Build Coastguard Worker     value: UnsafeCell<T>,
707*bb4ee6a4SAndroid Build Coastguard Worker }
708*bb4ee6a4SAndroid Build Coastguard Worker 
709*bb4ee6a4SAndroid Build Coastguard Worker impl<T> RwLock<T> {
710*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a new, unlocked `RwLock` ready for use.
new(v: T) -> RwLock<T>711*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(v: T) -> RwLock<T> {
712*bb4ee6a4SAndroid Build Coastguard Worker         RwLock {
713*bb4ee6a4SAndroid Build Coastguard Worker             raw: RawRwLock::new(),
714*bb4ee6a4SAndroid Build Coastguard Worker             value: UnsafeCell::new(v),
715*bb4ee6a4SAndroid Build Coastguard Worker         }
716*bb4ee6a4SAndroid Build Coastguard Worker     }
717*bb4ee6a4SAndroid Build Coastguard Worker 
718*bb4ee6a4SAndroid Build Coastguard Worker     /// Consume the `RwLock` and return the contained value. This method does not perform any
719*bb4ee6a4SAndroid Build Coastguard Worker     /// locking as the compiler will guarantee that there are no other references to `self` and the
720*bb4ee6a4SAndroid Build Coastguard Worker     /// caller owns the `RwLock`.
into_inner(self) -> T721*bb4ee6a4SAndroid Build Coastguard Worker     pub fn into_inner(self) -> T {
722*bb4ee6a4SAndroid Build Coastguard Worker         // Don't need to acquire the lock because the compiler guarantees that there are
723*bb4ee6a4SAndroid Build Coastguard Worker         // no references to `self`.
724*bb4ee6a4SAndroid Build Coastguard Worker         self.value.into_inner()
725*bb4ee6a4SAndroid Build Coastguard Worker     }
726*bb4ee6a4SAndroid Build Coastguard Worker }
727*bb4ee6a4SAndroid Build Coastguard Worker 
728*bb4ee6a4SAndroid Build Coastguard Worker impl<T: ?Sized> RwLock<T> {
729*bb4ee6a4SAndroid Build Coastguard Worker     /// Acquires exclusive, mutable access to the resource protected by the `RwLock`, blocking the
730*bb4ee6a4SAndroid Build Coastguard Worker     /// current thread until it is able to do so. Upon returning, the current thread will be the
731*bb4ee6a4SAndroid Build Coastguard Worker     /// only thread with access to the resource. The `RwLock` will be released when the returned
732*bb4ee6a4SAndroid Build Coastguard Worker     /// `RwLockWriteGuard` is dropped.
733*bb4ee6a4SAndroid Build Coastguard Worker     ///
734*bb4ee6a4SAndroid Build Coastguard Worker     /// Calling `lock()` while holding a `RwLockWriteGuard` or a `RwLockReadGuard` will cause a
735*bb4ee6a4SAndroid Build Coastguard Worker     /// deadlock.
736*bb4ee6a4SAndroid Build Coastguard Worker     ///
737*bb4ee6a4SAndroid Build Coastguard Worker     /// Callers that are not in an async context may wish to use the `block_on` method to block the
738*bb4ee6a4SAndroid Build Coastguard Worker     /// thread until the `RwLock` is acquired.
739*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
lock(&self) -> RwLockWriteGuard<'_, T>740*bb4ee6a4SAndroid Build Coastguard Worker     pub async fn lock(&self) -> RwLockWriteGuard<'_, T> {
741*bb4ee6a4SAndroid Build Coastguard Worker         self.raw.lock().await;
742*bb4ee6a4SAndroid Build Coastguard Worker 
743*bb4ee6a4SAndroid Build Coastguard Worker         RwLockWriteGuard {
744*bb4ee6a4SAndroid Build Coastguard Worker             mu: self,
745*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
746*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we have exclusive access to `self.value`.
747*bb4ee6a4SAndroid Build Coastguard Worker             value: unsafe { &mut *self.value.get() },
748*bb4ee6a4SAndroid Build Coastguard Worker         }
749*bb4ee6a4SAndroid Build Coastguard Worker     }
750*bb4ee6a4SAndroid Build Coastguard Worker 
751*bb4ee6a4SAndroid Build Coastguard Worker     /// Acquires shared, immutable access to the resource protected by the `RwLock`, blocking the
752*bb4ee6a4SAndroid Build Coastguard Worker     /// current thread until it is able to do so. Upon returning there may be other threads that
753*bb4ee6a4SAndroid Build Coastguard Worker     /// also have immutable access to the resource but there will not be any threads that have
754*bb4ee6a4SAndroid Build Coastguard Worker     /// mutable access to the resource. When the returned `RwLockReadGuard` is dropped the thread
755*bb4ee6a4SAndroid Build Coastguard Worker     /// releases its access to the resource.
756*bb4ee6a4SAndroid Build Coastguard Worker     ///
757*bb4ee6a4SAndroid Build Coastguard Worker     /// Calling `read_lock()` while holding a `RwLockReadGuard` may deadlock. Calling `read_lock()`
758*bb4ee6a4SAndroid Build Coastguard Worker     /// while holding a `RwLockWriteGuard` will deadlock.
759*bb4ee6a4SAndroid Build Coastguard Worker     ///
760*bb4ee6a4SAndroid Build Coastguard Worker     /// Callers that are not in an async context may wish to use the `block_on` method to block the
761*bb4ee6a4SAndroid Build Coastguard Worker     /// thread until the `RwLock` is acquired.
762*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
read_lock(&self) -> RwLockReadGuard<'_, T>763*bb4ee6a4SAndroid Build Coastguard Worker     pub async fn read_lock(&self) -> RwLockReadGuard<'_, T> {
764*bb4ee6a4SAndroid Build Coastguard Worker         self.raw.read_lock().await;
765*bb4ee6a4SAndroid Build Coastguard Worker 
766*bb4ee6a4SAndroid Build Coastguard Worker         RwLockReadGuard {
767*bb4ee6a4SAndroid Build Coastguard Worker             mu: self,
768*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
769*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we have shared read-only access to `self.value`.
770*bb4ee6a4SAndroid Build Coastguard Worker             value: unsafe { &*self.value.get() },
771*bb4ee6a4SAndroid Build Coastguard Worker         }
772*bb4ee6a4SAndroid Build Coastguard Worker     }
773*bb4ee6a4SAndroid Build Coastguard Worker 
774*bb4ee6a4SAndroid Build Coastguard Worker     // Called from `Condvar::wait` when the thread wants to reacquire the lock.
775*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
lock_from_cv(&self) -> RwLockWriteGuard<'_, T>776*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) async fn lock_from_cv(&self) -> RwLockWriteGuard<'_, T> {
777*bb4ee6a4SAndroid Build Coastguard Worker         self.raw.lock_slow::<Exclusive>(DESIGNATED_WAKER, 0).await;
778*bb4ee6a4SAndroid Build Coastguard Worker 
779*bb4ee6a4SAndroid Build Coastguard Worker         RwLockWriteGuard {
780*bb4ee6a4SAndroid Build Coastguard Worker             mu: self,
781*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
782*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we have exclusive access to `self.value`.
783*bb4ee6a4SAndroid Build Coastguard Worker             value: unsafe { &mut *self.value.get() },
784*bb4ee6a4SAndroid Build Coastguard Worker         }
785*bb4ee6a4SAndroid Build Coastguard Worker     }
786*bb4ee6a4SAndroid Build Coastguard Worker 
787*bb4ee6a4SAndroid Build Coastguard Worker     // Like `lock_from_cv` but for acquiring a shared lock.
788*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
read_lock_from_cv(&self) -> RwLockReadGuard<'_, T>789*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) async fn read_lock_from_cv(&self) -> RwLockReadGuard<'_, T> {
790*bb4ee6a4SAndroid Build Coastguard Worker         // Threads that have waited in the Condvar's waiter list don't have to care if there is a
791*bb4ee6a4SAndroid Build Coastguard Worker         // writer waiting since they have already waited once.
792*bb4ee6a4SAndroid Build Coastguard Worker         self.raw
793*bb4ee6a4SAndroid Build Coastguard Worker             .lock_slow::<Shared>(DESIGNATED_WAKER, WRITER_WAITING)
794*bb4ee6a4SAndroid Build Coastguard Worker             .await;
795*bb4ee6a4SAndroid Build Coastguard Worker 
796*bb4ee6a4SAndroid Build Coastguard Worker         RwLockReadGuard {
797*bb4ee6a4SAndroid Build Coastguard Worker             mu: self,
798*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
799*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we have exclusive access to `self.value`.
800*bb4ee6a4SAndroid Build Coastguard Worker             value: unsafe { &*self.value.get() },
801*bb4ee6a4SAndroid Build Coastguard Worker         }
802*bb4ee6a4SAndroid Build Coastguard Worker     }
803*bb4ee6a4SAndroid Build Coastguard Worker 
804*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
unlock(&self)805*bb4ee6a4SAndroid Build Coastguard Worker     fn unlock(&self) {
806*bb4ee6a4SAndroid Build Coastguard Worker         self.raw.unlock();
807*bb4ee6a4SAndroid Build Coastguard Worker     }
808*bb4ee6a4SAndroid Build Coastguard Worker 
809*bb4ee6a4SAndroid Build Coastguard Worker     #[inline]
read_unlock(&self)810*bb4ee6a4SAndroid Build Coastguard Worker     fn read_unlock(&self) {
811*bb4ee6a4SAndroid Build Coastguard Worker         self.raw.read_unlock();
812*bb4ee6a4SAndroid Build Coastguard Worker     }
813*bb4ee6a4SAndroid Build Coastguard Worker 
get_mut(&mut self) -> &mut T814*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_mut(&mut self) -> &mut T {
815*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
816*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the compiler statically guarantees that are no other references to `self`.
817*bb4ee6a4SAndroid Build Coastguard Worker         // This is also why we don't need to acquire the lock first.
818*bb4ee6a4SAndroid Build Coastguard Worker         unsafe { &mut *self.value.get() }
819*bb4ee6a4SAndroid Build Coastguard Worker     }
820*bb4ee6a4SAndroid Build Coastguard Worker }
821*bb4ee6a4SAndroid Build Coastguard Worker 
822*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/315998194): Add safety comment
823*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)]
824*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl<T: ?Sized + Send> Send for RwLock<T> {}
825*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/315998194): Add safety comment
826*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::undocumented_unsafe_blocks)]
827*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl<T: ?Sized + Send> Sync for RwLock<T> {}
828*bb4ee6a4SAndroid Build Coastguard Worker 
829*bb4ee6a4SAndroid Build Coastguard Worker impl<T: Default> Default for RwLock<T> {
default() -> Self830*bb4ee6a4SAndroid Build Coastguard Worker     fn default() -> Self {
831*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(Default::default())
832*bb4ee6a4SAndroid Build Coastguard Worker     }
833*bb4ee6a4SAndroid Build Coastguard Worker }
834*bb4ee6a4SAndroid Build Coastguard Worker 
835*bb4ee6a4SAndroid Build Coastguard Worker impl<T> From<T> for RwLock<T> {
from(source: T) -> Self836*bb4ee6a4SAndroid Build Coastguard Worker     fn from(source: T) -> Self {
837*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(source)
838*bb4ee6a4SAndroid Build Coastguard Worker     }
839*bb4ee6a4SAndroid Build Coastguard Worker }
840*bb4ee6a4SAndroid Build Coastguard Worker 
841*bb4ee6a4SAndroid Build Coastguard Worker /// An RAII implementation of a "scoped exclusive lock" for a `RwLock`. When this structure is
842*bb4ee6a4SAndroid Build Coastguard Worker /// dropped, the lock will be released. The resource protected by the `RwLock` can be accessed via
843*bb4ee6a4SAndroid Build Coastguard Worker /// the `Deref` and `DerefMut` implementations of this structure.
844*bb4ee6a4SAndroid Build Coastguard Worker pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
845*bb4ee6a4SAndroid Build Coastguard Worker     mu: &'a RwLock<T>,
846*bb4ee6a4SAndroid Build Coastguard Worker     value: &'a mut T,
847*bb4ee6a4SAndroid Build Coastguard Worker }
848*bb4ee6a4SAndroid Build Coastguard Worker 
849*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
into_inner(self) -> &'a RwLock<T>850*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) fn into_inner(self) -> &'a RwLock<T> {
851*bb4ee6a4SAndroid Build Coastguard Worker         self.mu
852*bb4ee6a4SAndroid Build Coastguard Worker     }
853*bb4ee6a4SAndroid Build Coastguard Worker 
as_raw_rwlock(&self) -> &RawRwLock854*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) fn as_raw_rwlock(&self) -> &RawRwLock {
855*bb4ee6a4SAndroid Build Coastguard Worker         &self.mu.raw
856*bb4ee6a4SAndroid Build Coastguard Worker     }
857*bb4ee6a4SAndroid Build Coastguard Worker }
858*bb4ee6a4SAndroid Build Coastguard Worker 
859*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> {
860*bb4ee6a4SAndroid Build Coastguard Worker     type Target = T;
861*bb4ee6a4SAndroid Build Coastguard Worker 
deref(&self) -> &Self::Target862*bb4ee6a4SAndroid Build Coastguard Worker     fn deref(&self) -> &Self::Target {
863*bb4ee6a4SAndroid Build Coastguard Worker         self.value
864*bb4ee6a4SAndroid Build Coastguard Worker     }
865*bb4ee6a4SAndroid Build Coastguard Worker }
866*bb4ee6a4SAndroid Build Coastguard Worker 
867*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: ?Sized> DerefMut for RwLockWriteGuard<'a, T> {
deref_mut(&mut self) -> &mut Self::Target868*bb4ee6a4SAndroid Build Coastguard Worker     fn deref_mut(&mut self) -> &mut Self::Target {
869*bb4ee6a4SAndroid Build Coastguard Worker         self.value
870*bb4ee6a4SAndroid Build Coastguard Worker     }
871*bb4ee6a4SAndroid Build Coastguard Worker }
872*bb4ee6a4SAndroid Build Coastguard Worker 
873*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
drop(&mut self)874*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
875*bb4ee6a4SAndroid Build Coastguard Worker         self.mu.unlock()
876*bb4ee6a4SAndroid Build Coastguard Worker     }
877*bb4ee6a4SAndroid Build Coastguard Worker }
878*bb4ee6a4SAndroid Build Coastguard Worker 
879*bb4ee6a4SAndroid Build Coastguard Worker /// An RAII implementation of a "scoped shared lock" for a `RwLock`. When this structure is dropped,
880*bb4ee6a4SAndroid Build Coastguard Worker /// the lock will be released. The resource protected by the `RwLock` can be accessed via the
881*bb4ee6a4SAndroid Build Coastguard Worker /// `Deref` implementation of this structure.
882*bb4ee6a4SAndroid Build Coastguard Worker pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
883*bb4ee6a4SAndroid Build Coastguard Worker     mu: &'a RwLock<T>,
884*bb4ee6a4SAndroid Build Coastguard Worker     value: &'a T,
885*bb4ee6a4SAndroid Build Coastguard Worker }
886*bb4ee6a4SAndroid Build Coastguard Worker 
887*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: ?Sized> RwLockReadGuard<'a, T> {
into_inner(self) -> &'a RwLock<T>888*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) fn into_inner(self) -> &'a RwLock<T> {
889*bb4ee6a4SAndroid Build Coastguard Worker         self.mu
890*bb4ee6a4SAndroid Build Coastguard Worker     }
891*bb4ee6a4SAndroid Build Coastguard Worker 
as_raw_rwlock(&self) -> &RawRwLock892*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) fn as_raw_rwlock(&self) -> &RawRwLock {
893*bb4ee6a4SAndroid Build Coastguard Worker         &self.mu.raw
894*bb4ee6a4SAndroid Build Coastguard Worker     }
895*bb4ee6a4SAndroid Build Coastguard Worker }
896*bb4ee6a4SAndroid Build Coastguard Worker 
897*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> {
898*bb4ee6a4SAndroid Build Coastguard Worker     type Target = T;
899*bb4ee6a4SAndroid Build Coastguard Worker 
deref(&self) -> &Self::Target900*bb4ee6a4SAndroid Build Coastguard Worker     fn deref(&self) -> &Self::Target {
901*bb4ee6a4SAndroid Build Coastguard Worker         self.value
902*bb4ee6a4SAndroid Build Coastguard Worker     }
903*bb4ee6a4SAndroid Build Coastguard Worker }
904*bb4ee6a4SAndroid Build Coastguard Worker 
905*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> {
drop(&mut self)906*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
907*bb4ee6a4SAndroid Build Coastguard Worker         self.mu.read_unlock()
908*bb4ee6a4SAndroid Build Coastguard Worker     }
909*bb4ee6a4SAndroid Build Coastguard Worker }
910*bb4ee6a4SAndroid Build Coastguard Worker 
911*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/194338842): Fix tests for windows
912*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
913*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
914*bb4ee6a4SAndroid Build Coastguard Worker mod test {
915*bb4ee6a4SAndroid Build Coastguard Worker     use std::future::Future;
916*bb4ee6a4SAndroid Build Coastguard Worker     use std::mem;
917*bb4ee6a4SAndroid Build Coastguard Worker     use std::pin::Pin;
918*bb4ee6a4SAndroid Build Coastguard Worker     use std::rc::Rc;
919*bb4ee6a4SAndroid Build Coastguard Worker     use std::sync::atomic::AtomicUsize;
920*bb4ee6a4SAndroid Build Coastguard Worker     use std::sync::atomic::Ordering;
921*bb4ee6a4SAndroid Build Coastguard Worker     use std::sync::mpsc::channel;
922*bb4ee6a4SAndroid Build Coastguard Worker     use std::sync::mpsc::Sender;
923*bb4ee6a4SAndroid Build Coastguard Worker     use std::sync::Arc;
924*bb4ee6a4SAndroid Build Coastguard Worker     use std::task::Context;
925*bb4ee6a4SAndroid Build Coastguard Worker     use std::task::Poll;
926*bb4ee6a4SAndroid Build Coastguard Worker     use std::task::Waker;
927*bb4ee6a4SAndroid Build Coastguard Worker     use std::thread;
928*bb4ee6a4SAndroid Build Coastguard Worker     use std::time::Duration;
929*bb4ee6a4SAndroid Build Coastguard Worker 
930*bb4ee6a4SAndroid Build Coastguard Worker     use futures::channel::oneshot;
931*bb4ee6a4SAndroid Build Coastguard Worker     use futures::pending;
932*bb4ee6a4SAndroid Build Coastguard Worker     use futures::select;
933*bb4ee6a4SAndroid Build Coastguard Worker     use futures::task::waker_ref;
934*bb4ee6a4SAndroid Build Coastguard Worker     use futures::task::ArcWake;
935*bb4ee6a4SAndroid Build Coastguard Worker     use futures::FutureExt;
936*bb4ee6a4SAndroid Build Coastguard Worker     use futures_executor::LocalPool;
937*bb4ee6a4SAndroid Build Coastguard Worker     use futures_executor::ThreadPool;
938*bb4ee6a4SAndroid Build Coastguard Worker     use futures_util::task::LocalSpawnExt;
939*bb4ee6a4SAndroid Build Coastguard Worker 
940*bb4ee6a4SAndroid Build Coastguard Worker     use super::super::super::block_on;
941*bb4ee6a4SAndroid Build Coastguard Worker     use super::super::super::sync::Condvar;
942*bb4ee6a4SAndroid Build Coastguard Worker     use super::super::super::sync::SpinLock;
943*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
944*bb4ee6a4SAndroid Build Coastguard Worker 
945*bb4ee6a4SAndroid Build Coastguard Worker     #[derive(Debug, Eq, PartialEq)]
946*bb4ee6a4SAndroid Build Coastguard Worker     struct NonCopy(u32);
947*bb4ee6a4SAndroid Build Coastguard Worker 
948*bb4ee6a4SAndroid Build Coastguard Worker     // Dummy waker used when we want to manually drive futures.
949*bb4ee6a4SAndroid Build Coastguard Worker     struct TestWaker;
950*bb4ee6a4SAndroid Build Coastguard Worker     impl ArcWake for TestWaker {
wake_by_ref(_arc_self: &Arc<Self>)951*bb4ee6a4SAndroid Build Coastguard Worker         fn wake_by_ref(_arc_self: &Arc<Self>) {}
952*bb4ee6a4SAndroid Build Coastguard Worker     }
953*bb4ee6a4SAndroid Build Coastguard Worker 
954*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
it_works()955*bb4ee6a4SAndroid Build Coastguard Worker     fn it_works() {
956*bb4ee6a4SAndroid Build Coastguard Worker         let mu = RwLock::new(NonCopy(13));
957*bb4ee6a4SAndroid Build Coastguard Worker 
958*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.lock()), NonCopy(13));
959*bb4ee6a4SAndroid Build Coastguard Worker     }
960*bb4ee6a4SAndroid Build Coastguard Worker 
961*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
smoke()962*bb4ee6a4SAndroid Build Coastguard Worker     fn smoke() {
963*bb4ee6a4SAndroid Build Coastguard Worker         let mu = RwLock::new(NonCopy(7));
964*bb4ee6a4SAndroid Build Coastguard Worker 
965*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(block_on(mu.lock()));
966*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(block_on(mu.lock()));
967*bb4ee6a4SAndroid Build Coastguard Worker     }
968*bb4ee6a4SAndroid Build Coastguard Worker 
969*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
rw_smoke()970*bb4ee6a4SAndroid Build Coastguard Worker     fn rw_smoke() {
971*bb4ee6a4SAndroid Build Coastguard Worker         let mu = RwLock::new(NonCopy(7));
972*bb4ee6a4SAndroid Build Coastguard Worker 
973*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(block_on(mu.lock()));
974*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(block_on(mu.read_lock()));
975*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop((block_on(mu.read_lock()), block_on(mu.read_lock())));
976*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(block_on(mu.lock()));
977*bb4ee6a4SAndroid Build Coastguard Worker     }
978*bb4ee6a4SAndroid Build Coastguard Worker 
979*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
async_smoke()980*bb4ee6a4SAndroid Build Coastguard Worker     fn async_smoke() {
981*bb4ee6a4SAndroid Build Coastguard Worker         async fn lock(mu: Rc<RwLock<NonCopy>>) {
982*bb4ee6a4SAndroid Build Coastguard Worker             mu.lock().await;
983*bb4ee6a4SAndroid Build Coastguard Worker         }
984*bb4ee6a4SAndroid Build Coastguard Worker 
985*bb4ee6a4SAndroid Build Coastguard Worker         async fn read_lock(mu: Rc<RwLock<NonCopy>>) {
986*bb4ee6a4SAndroid Build Coastguard Worker             mu.read_lock().await;
987*bb4ee6a4SAndroid Build Coastguard Worker         }
988*bb4ee6a4SAndroid Build Coastguard Worker 
989*bb4ee6a4SAndroid Build Coastguard Worker         async fn double_read_lock(mu: Rc<RwLock<NonCopy>>) {
990*bb4ee6a4SAndroid Build Coastguard Worker             let first = mu.read_lock().await;
991*bb4ee6a4SAndroid Build Coastguard Worker             mu.read_lock().await;
992*bb4ee6a4SAndroid Build Coastguard Worker 
993*bb4ee6a4SAndroid Build Coastguard Worker             // Make sure first lives past the second read lock.
994*bb4ee6a4SAndroid Build Coastguard Worker             first.as_raw_rwlock();
995*bb4ee6a4SAndroid Build Coastguard Worker         }
996*bb4ee6a4SAndroid Build Coastguard Worker 
997*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Rc::new(RwLock::new(NonCopy(7)));
998*bb4ee6a4SAndroid Build Coastguard Worker 
999*bb4ee6a4SAndroid Build Coastguard Worker         let mut ex = LocalPool::new();
1000*bb4ee6a4SAndroid Build Coastguard Worker         let spawner = ex.spawner();
1001*bb4ee6a4SAndroid Build Coastguard Worker 
1002*bb4ee6a4SAndroid Build Coastguard Worker         spawner
1003*bb4ee6a4SAndroid Build Coastguard Worker             .spawn_local(lock(Rc::clone(&mu)))
1004*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to spawn future");
1005*bb4ee6a4SAndroid Build Coastguard Worker         spawner
1006*bb4ee6a4SAndroid Build Coastguard Worker             .spawn_local(read_lock(Rc::clone(&mu)))
1007*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to spawn future");
1008*bb4ee6a4SAndroid Build Coastguard Worker         spawner
1009*bb4ee6a4SAndroid Build Coastguard Worker             .spawn_local(double_read_lock(Rc::clone(&mu)))
1010*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to spawn future");
1011*bb4ee6a4SAndroid Build Coastguard Worker         spawner
1012*bb4ee6a4SAndroid Build Coastguard Worker             .spawn_local(lock(Rc::clone(&mu)))
1013*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to spawn future");
1014*bb4ee6a4SAndroid Build Coastguard Worker 
1015*bb4ee6a4SAndroid Build Coastguard Worker         ex.run();
1016*bb4ee6a4SAndroid Build Coastguard Worker     }
1017*bb4ee6a4SAndroid Build Coastguard Worker 
1018*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
send()1019*bb4ee6a4SAndroid Build Coastguard Worker     fn send() {
1020*bb4ee6a4SAndroid Build Coastguard Worker         let mu = RwLock::new(NonCopy(19));
1021*bb4ee6a4SAndroid Build Coastguard Worker 
1022*bb4ee6a4SAndroid Build Coastguard Worker         thread::spawn(move || {
1023*bb4ee6a4SAndroid Build Coastguard Worker             let value = block_on(mu.lock());
1024*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(*value, NonCopy(19));
1025*bb4ee6a4SAndroid Build Coastguard Worker         })
1026*bb4ee6a4SAndroid Build Coastguard Worker         .join()
1027*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
1028*bb4ee6a4SAndroid Build Coastguard Worker     }
1029*bb4ee6a4SAndroid Build Coastguard Worker 
1030*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
arc_nested()1031*bb4ee6a4SAndroid Build Coastguard Worker     fn arc_nested() {
1032*bb4ee6a4SAndroid Build Coastguard Worker         // Tests nested rwlocks and access to underlying data.
1033*bb4ee6a4SAndroid Build Coastguard Worker         let mu = RwLock::new(1);
1034*bb4ee6a4SAndroid Build Coastguard Worker         let arc = Arc::new(RwLock::new(mu));
1035*bb4ee6a4SAndroid Build Coastguard Worker         thread::spawn(move || {
1036*bb4ee6a4SAndroid Build Coastguard Worker             let nested = block_on(arc.lock());
1037*bb4ee6a4SAndroid Build Coastguard Worker             let lock2 = block_on(nested.lock());
1038*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(*lock2, 1);
1039*bb4ee6a4SAndroid Build Coastguard Worker         })
1040*bb4ee6a4SAndroid Build Coastguard Worker         .join()
1041*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
1042*bb4ee6a4SAndroid Build Coastguard Worker     }
1043*bb4ee6a4SAndroid Build Coastguard Worker 
1044*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
arc_access_in_unwind()1045*bb4ee6a4SAndroid Build Coastguard Worker     fn arc_access_in_unwind() {
1046*bb4ee6a4SAndroid Build Coastguard Worker         let arc = Arc::new(RwLock::new(1));
1047*bb4ee6a4SAndroid Build Coastguard Worker         let arc2 = arc.clone();
1048*bb4ee6a4SAndroid Build Coastguard Worker         thread::spawn(move || {
1049*bb4ee6a4SAndroid Build Coastguard Worker             struct Unwinder {
1050*bb4ee6a4SAndroid Build Coastguard Worker                 i: Arc<RwLock<i32>>,
1051*bb4ee6a4SAndroid Build Coastguard Worker             }
1052*bb4ee6a4SAndroid Build Coastguard Worker             impl Drop for Unwinder {
1053*bb4ee6a4SAndroid Build Coastguard Worker                 fn drop(&mut self) {
1054*bb4ee6a4SAndroid Build Coastguard Worker                     *block_on(self.i.lock()) += 1;
1055*bb4ee6a4SAndroid Build Coastguard Worker                 }
1056*bb4ee6a4SAndroid Build Coastguard Worker             }
1057*bb4ee6a4SAndroid Build Coastguard Worker             let _u = Unwinder { i: arc2 };
1058*bb4ee6a4SAndroid Build Coastguard Worker             panic!();
1059*bb4ee6a4SAndroid Build Coastguard Worker         })
1060*bb4ee6a4SAndroid Build Coastguard Worker         .join()
1061*bb4ee6a4SAndroid Build Coastguard Worker         .expect_err("thread did not panic");
1062*bb4ee6a4SAndroid Build Coastguard Worker         let lock = block_on(arc.lock());
1063*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*lock, 2);
1064*bb4ee6a4SAndroid Build Coastguard Worker     }
1065*bb4ee6a4SAndroid Build Coastguard Worker 
1066*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
unsized_value()1067*bb4ee6a4SAndroid Build Coastguard Worker     fn unsized_value() {
1068*bb4ee6a4SAndroid Build Coastguard Worker         let rwlock: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
1069*bb4ee6a4SAndroid Build Coastguard Worker         {
1070*bb4ee6a4SAndroid Build Coastguard Worker             let b = &mut *block_on(rwlock.lock());
1071*bb4ee6a4SAndroid Build Coastguard Worker             b[0] = 4;
1072*bb4ee6a4SAndroid Build Coastguard Worker             b[2] = 5;
1073*bb4ee6a4SAndroid Build Coastguard Worker         }
1074*bb4ee6a4SAndroid Build Coastguard Worker         let expected: &[i32] = &[4, 2, 5];
1075*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&*block_on(rwlock.lock()), expected);
1076*bb4ee6a4SAndroid Build Coastguard Worker     }
1077*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
high_contention()1078*bb4ee6a4SAndroid Build Coastguard Worker     fn high_contention() {
1079*bb4ee6a4SAndroid Build Coastguard Worker         const THREADS: usize = 17;
1080*bb4ee6a4SAndroid Build Coastguard Worker         const ITERATIONS: usize = 103;
1081*bb4ee6a4SAndroid Build Coastguard Worker 
1082*bb4ee6a4SAndroid Build Coastguard Worker         let mut threads = Vec::with_capacity(THREADS);
1083*bb4ee6a4SAndroid Build Coastguard Worker 
1084*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0usize));
1085*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..THREADS {
1086*bb4ee6a4SAndroid Build Coastguard Worker             let mu2 = mu.clone();
1087*bb4ee6a4SAndroid Build Coastguard Worker             threads.push(thread::spawn(move || {
1088*bb4ee6a4SAndroid Build Coastguard Worker                 for _ in 0..ITERATIONS {
1089*bb4ee6a4SAndroid Build Coastguard Worker                     *block_on(mu2.lock()) += 1;
1090*bb4ee6a4SAndroid Build Coastguard Worker                 }
1091*bb4ee6a4SAndroid Build Coastguard Worker             }));
1092*bb4ee6a4SAndroid Build Coastguard Worker         }
1093*bb4ee6a4SAndroid Build Coastguard Worker 
1094*bb4ee6a4SAndroid Build Coastguard Worker         for t in threads.into_iter() {
1095*bb4ee6a4SAndroid Build Coastguard Worker             t.join().unwrap();
1096*bb4ee6a4SAndroid Build Coastguard Worker         }
1097*bb4ee6a4SAndroid Build Coastguard Worker 
1098*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.read_lock()), THREADS * ITERATIONS);
1099*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1100*bb4ee6a4SAndroid Build Coastguard Worker     }
1101*bb4ee6a4SAndroid Build Coastguard Worker 
1102*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
high_contention_with_cancel()1103*bb4ee6a4SAndroid Build Coastguard Worker     fn high_contention_with_cancel() {
1104*bb4ee6a4SAndroid Build Coastguard Worker         const TASKS: usize = 17;
1105*bb4ee6a4SAndroid Build Coastguard Worker         const ITERATIONS: usize = 103;
1106*bb4ee6a4SAndroid Build Coastguard Worker 
1107*bb4ee6a4SAndroid Build Coastguard Worker         async fn increment(mu: Arc<RwLock<usize>>, alt_mu: Arc<RwLock<usize>>, tx: Sender<()>) {
1108*bb4ee6a4SAndroid Build Coastguard Worker             for _ in 0..ITERATIONS {
1109*bb4ee6a4SAndroid Build Coastguard Worker                 select! {
1110*bb4ee6a4SAndroid Build Coastguard Worker                     mut count = mu.lock().fuse() => *count += 1,
1111*bb4ee6a4SAndroid Build Coastguard Worker                     mut count = alt_mu.lock().fuse() => *count += 1,
1112*bb4ee6a4SAndroid Build Coastguard Worker                 }
1113*bb4ee6a4SAndroid Build Coastguard Worker             }
1114*bb4ee6a4SAndroid Build Coastguard Worker             tx.send(()).expect("Failed to send completion signal");
1115*bb4ee6a4SAndroid Build Coastguard Worker         }
1116*bb4ee6a4SAndroid Build Coastguard Worker 
1117*bb4ee6a4SAndroid Build Coastguard Worker         let ex = ThreadPool::new().expect("Failed to create ThreadPool");
1118*bb4ee6a4SAndroid Build Coastguard Worker 
1119*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0usize));
1120*bb4ee6a4SAndroid Build Coastguard Worker         let alt_mu = Arc::new(RwLock::new(0usize));
1121*bb4ee6a4SAndroid Build Coastguard Worker 
1122*bb4ee6a4SAndroid Build Coastguard Worker         let (tx, rx) = channel();
1123*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..TASKS {
1124*bb4ee6a4SAndroid Build Coastguard Worker             ex.spawn_ok(increment(Arc::clone(&mu), Arc::clone(&alt_mu), tx.clone()));
1125*bb4ee6a4SAndroid Build Coastguard Worker         }
1126*bb4ee6a4SAndroid Build Coastguard Worker 
1127*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..TASKS {
1128*bb4ee6a4SAndroid Build Coastguard Worker             if let Err(e) = rx.recv_timeout(Duration::from_secs(10)) {
1129*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("Error while waiting for threads to complete: {}", e);
1130*bb4ee6a4SAndroid Build Coastguard Worker             }
1131*bb4ee6a4SAndroid Build Coastguard Worker         }
1132*bb4ee6a4SAndroid Build Coastguard Worker 
1133*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1134*bb4ee6a4SAndroid Build Coastguard Worker             *block_on(mu.read_lock()) + *block_on(alt_mu.read_lock()),
1135*bb4ee6a4SAndroid Build Coastguard Worker             TASKS * ITERATIONS
1136*bb4ee6a4SAndroid Build Coastguard Worker         );
1137*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1138*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(alt_mu.raw.state.load(Ordering::Relaxed), 0);
1139*bb4ee6a4SAndroid Build Coastguard Worker     }
1140*bb4ee6a4SAndroid Build Coastguard Worker 
1141*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
single_thread_async()1142*bb4ee6a4SAndroid Build Coastguard Worker     fn single_thread_async() {
1143*bb4ee6a4SAndroid Build Coastguard Worker         const TASKS: usize = 17;
1144*bb4ee6a4SAndroid Build Coastguard Worker         const ITERATIONS: usize = 103;
1145*bb4ee6a4SAndroid Build Coastguard Worker 
1146*bb4ee6a4SAndroid Build Coastguard Worker         // Async closures are unstable.
1147*bb4ee6a4SAndroid Build Coastguard Worker         async fn increment(mu: Rc<RwLock<usize>>) {
1148*bb4ee6a4SAndroid Build Coastguard Worker             for _ in 0..ITERATIONS {
1149*bb4ee6a4SAndroid Build Coastguard Worker                 *mu.lock().await += 1;
1150*bb4ee6a4SAndroid Build Coastguard Worker             }
1151*bb4ee6a4SAndroid Build Coastguard Worker         }
1152*bb4ee6a4SAndroid Build Coastguard Worker 
1153*bb4ee6a4SAndroid Build Coastguard Worker         let mut ex = LocalPool::new();
1154*bb4ee6a4SAndroid Build Coastguard Worker         let spawner = ex.spawner();
1155*bb4ee6a4SAndroid Build Coastguard Worker 
1156*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Rc::new(RwLock::new(0usize));
1157*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..TASKS {
1158*bb4ee6a4SAndroid Build Coastguard Worker             spawner
1159*bb4ee6a4SAndroid Build Coastguard Worker                 .spawn_local(increment(Rc::clone(&mu)))
1160*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("Failed to spawn task");
1161*bb4ee6a4SAndroid Build Coastguard Worker         }
1162*bb4ee6a4SAndroid Build Coastguard Worker 
1163*bb4ee6a4SAndroid Build Coastguard Worker         ex.run();
1164*bb4ee6a4SAndroid Build Coastguard Worker 
1165*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.read_lock()), TASKS * ITERATIONS);
1166*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1167*bb4ee6a4SAndroid Build Coastguard Worker     }
1168*bb4ee6a4SAndroid Build Coastguard Worker 
1169*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
multi_thread_async()1170*bb4ee6a4SAndroid Build Coastguard Worker     fn multi_thread_async() {
1171*bb4ee6a4SAndroid Build Coastguard Worker         const TASKS: usize = 17;
1172*bb4ee6a4SAndroid Build Coastguard Worker         const ITERATIONS: usize = 103;
1173*bb4ee6a4SAndroid Build Coastguard Worker 
1174*bb4ee6a4SAndroid Build Coastguard Worker         // Async closures are unstable.
1175*bb4ee6a4SAndroid Build Coastguard Worker         async fn increment(mu: Arc<RwLock<usize>>, tx: Sender<()>) {
1176*bb4ee6a4SAndroid Build Coastguard Worker             for _ in 0..ITERATIONS {
1177*bb4ee6a4SAndroid Build Coastguard Worker                 *mu.lock().await += 1;
1178*bb4ee6a4SAndroid Build Coastguard Worker             }
1179*bb4ee6a4SAndroid Build Coastguard Worker             tx.send(()).expect("Failed to send completion signal");
1180*bb4ee6a4SAndroid Build Coastguard Worker         }
1181*bb4ee6a4SAndroid Build Coastguard Worker 
1182*bb4ee6a4SAndroid Build Coastguard Worker         let ex = ThreadPool::new().expect("Failed to create ThreadPool");
1183*bb4ee6a4SAndroid Build Coastguard Worker 
1184*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0usize));
1185*bb4ee6a4SAndroid Build Coastguard Worker         let (tx, rx) = channel();
1186*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..TASKS {
1187*bb4ee6a4SAndroid Build Coastguard Worker             ex.spawn_ok(increment(Arc::clone(&mu), tx.clone()));
1188*bb4ee6a4SAndroid Build Coastguard Worker         }
1189*bb4ee6a4SAndroid Build Coastguard Worker 
1190*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..TASKS {
1191*bb4ee6a4SAndroid Build Coastguard Worker             rx.recv_timeout(Duration::from_secs(5))
1192*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("Failed to receive completion signal");
1193*bb4ee6a4SAndroid Build Coastguard Worker         }
1194*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.read_lock()), TASKS * ITERATIONS);
1195*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1196*bb4ee6a4SAndroid Build Coastguard Worker     }
1197*bb4ee6a4SAndroid Build Coastguard Worker 
1198*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
get_mut()1199*bb4ee6a4SAndroid Build Coastguard Worker     fn get_mut() {
1200*bb4ee6a4SAndroid Build Coastguard Worker         let mut mu = RwLock::new(NonCopy(13));
1201*bb4ee6a4SAndroid Build Coastguard Worker         *mu.get_mut() = NonCopy(17);
1202*bb4ee6a4SAndroid Build Coastguard Worker 
1203*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.into_inner(), NonCopy(17));
1204*bb4ee6a4SAndroid Build Coastguard Worker     }
1205*bb4ee6a4SAndroid Build Coastguard Worker 
1206*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
into_inner()1207*bb4ee6a4SAndroid Build Coastguard Worker     fn into_inner() {
1208*bb4ee6a4SAndroid Build Coastguard Worker         let mu = RwLock::new(NonCopy(29));
1209*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.into_inner(), NonCopy(29));
1210*bb4ee6a4SAndroid Build Coastguard Worker     }
1211*bb4ee6a4SAndroid Build Coastguard Worker 
1212*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
into_inner_drop()1213*bb4ee6a4SAndroid Build Coastguard Worker     fn into_inner_drop() {
1214*bb4ee6a4SAndroid Build Coastguard Worker         struct NeedsDrop(Arc<AtomicUsize>);
1215*bb4ee6a4SAndroid Build Coastguard Worker         impl Drop for NeedsDrop {
1216*bb4ee6a4SAndroid Build Coastguard Worker             fn drop(&mut self) {
1217*bb4ee6a4SAndroid Build Coastguard Worker                 self.0.fetch_add(1, Ordering::AcqRel);
1218*bb4ee6a4SAndroid Build Coastguard Worker             }
1219*bb4ee6a4SAndroid Build Coastguard Worker         }
1220*bb4ee6a4SAndroid Build Coastguard Worker 
1221*bb4ee6a4SAndroid Build Coastguard Worker         let value = Arc::new(AtomicUsize::new(0));
1222*bb4ee6a4SAndroid Build Coastguard Worker         let needs_drop = RwLock::new(NeedsDrop(value.clone()));
1223*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(value.load(Ordering::Acquire), 0);
1224*bb4ee6a4SAndroid Build Coastguard Worker 
1225*bb4ee6a4SAndroid Build Coastguard Worker         {
1226*bb4ee6a4SAndroid Build Coastguard Worker             let inner = needs_drop.into_inner();
1227*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(inner.0.load(Ordering::Acquire), 0);
1228*bb4ee6a4SAndroid Build Coastguard Worker         }
1229*bb4ee6a4SAndroid Build Coastguard Worker 
1230*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(value.load(Ordering::Acquire), 1);
1231*bb4ee6a4SAndroid Build Coastguard Worker     }
1232*bb4ee6a4SAndroid Build Coastguard Worker 
1233*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
rw_arc()1234*bb4ee6a4SAndroid Build Coastguard Worker     fn rw_arc() {
1235*bb4ee6a4SAndroid Build Coastguard Worker         const THREADS: isize = 7;
1236*bb4ee6a4SAndroid Build Coastguard Worker         const ITERATIONS: isize = 13;
1237*bb4ee6a4SAndroid Build Coastguard Worker 
1238*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0isize));
1239*bb4ee6a4SAndroid Build Coastguard Worker         let mu2 = mu.clone();
1240*bb4ee6a4SAndroid Build Coastguard Worker 
1241*bb4ee6a4SAndroid Build Coastguard Worker         let (tx, rx) = channel();
1242*bb4ee6a4SAndroid Build Coastguard Worker         thread::spawn(move || {
1243*bb4ee6a4SAndroid Build Coastguard Worker             let mut guard = block_on(mu2.lock());
1244*bb4ee6a4SAndroid Build Coastguard Worker             for _ in 0..ITERATIONS {
1245*bb4ee6a4SAndroid Build Coastguard Worker                 let tmp = *guard;
1246*bb4ee6a4SAndroid Build Coastguard Worker                 *guard = -1;
1247*bb4ee6a4SAndroid Build Coastguard Worker                 thread::yield_now();
1248*bb4ee6a4SAndroid Build Coastguard Worker                 *guard = tmp + 1;
1249*bb4ee6a4SAndroid Build Coastguard Worker             }
1250*bb4ee6a4SAndroid Build Coastguard Worker             tx.send(()).unwrap();
1251*bb4ee6a4SAndroid Build Coastguard Worker         });
1252*bb4ee6a4SAndroid Build Coastguard Worker 
1253*bb4ee6a4SAndroid Build Coastguard Worker         let mut readers = Vec::with_capacity(10);
1254*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..THREADS {
1255*bb4ee6a4SAndroid Build Coastguard Worker             let mu3 = mu.clone();
1256*bb4ee6a4SAndroid Build Coastguard Worker             let handle = thread::spawn(move || {
1257*bb4ee6a4SAndroid Build Coastguard Worker                 let guard = block_on(mu3.read_lock());
1258*bb4ee6a4SAndroid Build Coastguard Worker                 assert!(*guard >= 0);
1259*bb4ee6a4SAndroid Build Coastguard Worker             });
1260*bb4ee6a4SAndroid Build Coastguard Worker 
1261*bb4ee6a4SAndroid Build Coastguard Worker             readers.push(handle);
1262*bb4ee6a4SAndroid Build Coastguard Worker         }
1263*bb4ee6a4SAndroid Build Coastguard Worker 
1264*bb4ee6a4SAndroid Build Coastguard Worker         // Wait for the readers to finish their checks.
1265*bb4ee6a4SAndroid Build Coastguard Worker         for r in readers {
1266*bb4ee6a4SAndroid Build Coastguard Worker             r.join().expect("One or more readers saw a negative value");
1267*bb4ee6a4SAndroid Build Coastguard Worker         }
1268*bb4ee6a4SAndroid Build Coastguard Worker 
1269*bb4ee6a4SAndroid Build Coastguard Worker         // Wait for the writer to finish.
1270*bb4ee6a4SAndroid Build Coastguard Worker         rx.recv_timeout(Duration::from_secs(5)).unwrap();
1271*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.read_lock()), ITERATIONS);
1272*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1273*bb4ee6a4SAndroid Build Coastguard Worker     }
1274*bb4ee6a4SAndroid Build Coastguard Worker 
1275*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
rw_single_thread_async()1276*bb4ee6a4SAndroid Build Coastguard Worker     fn rw_single_thread_async() {
1277*bb4ee6a4SAndroid Build Coastguard Worker         // A Future that returns `Poll::pending` the first time it is polled and `Poll::Ready` every
1278*bb4ee6a4SAndroid Build Coastguard Worker         // time after that.
1279*bb4ee6a4SAndroid Build Coastguard Worker         struct TestFuture {
1280*bb4ee6a4SAndroid Build Coastguard Worker             polled: bool,
1281*bb4ee6a4SAndroid Build Coastguard Worker             waker: Arc<SpinLock<Option<Waker>>>,
1282*bb4ee6a4SAndroid Build Coastguard Worker         }
1283*bb4ee6a4SAndroid Build Coastguard Worker 
1284*bb4ee6a4SAndroid Build Coastguard Worker         impl Future for TestFuture {
1285*bb4ee6a4SAndroid Build Coastguard Worker             type Output = ();
1286*bb4ee6a4SAndroid Build Coastguard Worker 
1287*bb4ee6a4SAndroid Build Coastguard Worker             fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
1288*bb4ee6a4SAndroid Build Coastguard Worker                 if self.polled {
1289*bb4ee6a4SAndroid Build Coastguard Worker                     Poll::Ready(())
1290*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
1291*bb4ee6a4SAndroid Build Coastguard Worker                     self.polled = true;
1292*bb4ee6a4SAndroid Build Coastguard Worker                     *self.waker.lock() = Some(cx.waker().clone());
1293*bb4ee6a4SAndroid Build Coastguard Worker                     Poll::Pending
1294*bb4ee6a4SAndroid Build Coastguard Worker                 }
1295*bb4ee6a4SAndroid Build Coastguard Worker             }
1296*bb4ee6a4SAndroid Build Coastguard Worker         }
1297*bb4ee6a4SAndroid Build Coastguard Worker 
1298*bb4ee6a4SAndroid Build Coastguard Worker         fn wake_future(waker: Arc<SpinLock<Option<Waker>>>) {
1299*bb4ee6a4SAndroid Build Coastguard Worker             loop {
1300*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(w) = waker.lock().take() {
1301*bb4ee6a4SAndroid Build Coastguard Worker                     w.wake();
1302*bb4ee6a4SAndroid Build Coastguard Worker                     return;
1303*bb4ee6a4SAndroid Build Coastguard Worker                 }
1304*bb4ee6a4SAndroid Build Coastguard Worker 
1305*bb4ee6a4SAndroid Build Coastguard Worker                 // This sleep cannot be moved into an else branch because we would end up holding
1306*bb4ee6a4SAndroid Build Coastguard Worker                 // the lock while sleeping due to rust's drop ordering rules.
1307*bb4ee6a4SAndroid Build Coastguard Worker                 thread::sleep(Duration::from_millis(10));
1308*bb4ee6a4SAndroid Build Coastguard Worker             }
1309*bb4ee6a4SAndroid Build Coastguard Worker         }
1310*bb4ee6a4SAndroid Build Coastguard Worker 
1311*bb4ee6a4SAndroid Build Coastguard Worker         async fn writer(mu: Rc<RwLock<isize>>) {
1312*bb4ee6a4SAndroid Build Coastguard Worker             let mut guard = mu.lock().await;
1313*bb4ee6a4SAndroid Build Coastguard Worker             for _ in 0..ITERATIONS {
1314*bb4ee6a4SAndroid Build Coastguard Worker                 let tmp = *guard;
1315*bb4ee6a4SAndroid Build Coastguard Worker                 *guard = -1;
1316*bb4ee6a4SAndroid Build Coastguard Worker                 let waker = Arc::new(SpinLock::new(None));
1317*bb4ee6a4SAndroid Build Coastguard Worker                 let waker2 = Arc::clone(&waker);
1318*bb4ee6a4SAndroid Build Coastguard Worker                 thread::spawn(move || wake_future(waker2));
1319*bb4ee6a4SAndroid Build Coastguard Worker                 let fut = TestFuture {
1320*bb4ee6a4SAndroid Build Coastguard Worker                     polled: false,
1321*bb4ee6a4SAndroid Build Coastguard Worker                     waker,
1322*bb4ee6a4SAndroid Build Coastguard Worker                 };
1323*bb4ee6a4SAndroid Build Coastguard Worker                 fut.await;
1324*bb4ee6a4SAndroid Build Coastguard Worker                 *guard = tmp + 1;
1325*bb4ee6a4SAndroid Build Coastguard Worker             }
1326*bb4ee6a4SAndroid Build Coastguard Worker         }
1327*bb4ee6a4SAndroid Build Coastguard Worker 
1328*bb4ee6a4SAndroid Build Coastguard Worker         async fn reader(mu: Rc<RwLock<isize>>) {
1329*bb4ee6a4SAndroid Build Coastguard Worker             let guard = mu.read_lock().await;
1330*bb4ee6a4SAndroid Build Coastguard Worker             assert!(*guard >= 0);
1331*bb4ee6a4SAndroid Build Coastguard Worker         }
1332*bb4ee6a4SAndroid Build Coastguard Worker 
1333*bb4ee6a4SAndroid Build Coastguard Worker         const TASKS: isize = 7;
1334*bb4ee6a4SAndroid Build Coastguard Worker         const ITERATIONS: isize = 13;
1335*bb4ee6a4SAndroid Build Coastguard Worker 
1336*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Rc::new(RwLock::new(0isize));
1337*bb4ee6a4SAndroid Build Coastguard Worker         let mut ex = LocalPool::new();
1338*bb4ee6a4SAndroid Build Coastguard Worker         let spawner = ex.spawner();
1339*bb4ee6a4SAndroid Build Coastguard Worker 
1340*bb4ee6a4SAndroid Build Coastguard Worker         spawner
1341*bb4ee6a4SAndroid Build Coastguard Worker             .spawn_local(writer(Rc::clone(&mu)))
1342*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to spawn writer");
1343*bb4ee6a4SAndroid Build Coastguard Worker 
1344*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..TASKS {
1345*bb4ee6a4SAndroid Build Coastguard Worker             spawner
1346*bb4ee6a4SAndroid Build Coastguard Worker                 .spawn_local(reader(Rc::clone(&mu)))
1347*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("Failed to spawn reader");
1348*bb4ee6a4SAndroid Build Coastguard Worker         }
1349*bb4ee6a4SAndroid Build Coastguard Worker 
1350*bb4ee6a4SAndroid Build Coastguard Worker         ex.run();
1351*bb4ee6a4SAndroid Build Coastguard Worker 
1352*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.read_lock()), ITERATIONS);
1353*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1354*bb4ee6a4SAndroid Build Coastguard Worker     }
1355*bb4ee6a4SAndroid Build Coastguard Worker 
1356*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
rw_multi_thread_async()1357*bb4ee6a4SAndroid Build Coastguard Worker     fn rw_multi_thread_async() {
1358*bb4ee6a4SAndroid Build Coastguard Worker         async fn writer(mu: Arc<RwLock<isize>>, tx: Sender<()>) {
1359*bb4ee6a4SAndroid Build Coastguard Worker             let mut guard = mu.lock().await;
1360*bb4ee6a4SAndroid Build Coastguard Worker             for _ in 0..ITERATIONS {
1361*bb4ee6a4SAndroid Build Coastguard Worker                 let tmp = *guard;
1362*bb4ee6a4SAndroid Build Coastguard Worker                 *guard = -1;
1363*bb4ee6a4SAndroid Build Coastguard Worker                 thread::yield_now();
1364*bb4ee6a4SAndroid Build Coastguard Worker                 *guard = tmp + 1;
1365*bb4ee6a4SAndroid Build Coastguard Worker             }
1366*bb4ee6a4SAndroid Build Coastguard Worker 
1367*bb4ee6a4SAndroid Build Coastguard Worker             mem::drop(guard);
1368*bb4ee6a4SAndroid Build Coastguard Worker             tx.send(()).unwrap();
1369*bb4ee6a4SAndroid Build Coastguard Worker         }
1370*bb4ee6a4SAndroid Build Coastguard Worker 
1371*bb4ee6a4SAndroid Build Coastguard Worker         async fn reader(mu: Arc<RwLock<isize>>, tx: Sender<()>) {
1372*bb4ee6a4SAndroid Build Coastguard Worker             let guard = mu.read_lock().await;
1373*bb4ee6a4SAndroid Build Coastguard Worker             assert!(*guard >= 0);
1374*bb4ee6a4SAndroid Build Coastguard Worker 
1375*bb4ee6a4SAndroid Build Coastguard Worker             mem::drop(guard);
1376*bb4ee6a4SAndroid Build Coastguard Worker             tx.send(()).expect("Failed to send completion message");
1377*bb4ee6a4SAndroid Build Coastguard Worker         }
1378*bb4ee6a4SAndroid Build Coastguard Worker 
1379*bb4ee6a4SAndroid Build Coastguard Worker         const TASKS: isize = 7;
1380*bb4ee6a4SAndroid Build Coastguard Worker         const ITERATIONS: isize = 13;
1381*bb4ee6a4SAndroid Build Coastguard Worker 
1382*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0isize));
1383*bb4ee6a4SAndroid Build Coastguard Worker         let ex = ThreadPool::new().expect("Failed to create ThreadPool");
1384*bb4ee6a4SAndroid Build Coastguard Worker 
1385*bb4ee6a4SAndroid Build Coastguard Worker         let (txw, rxw) = channel();
1386*bb4ee6a4SAndroid Build Coastguard Worker         ex.spawn_ok(writer(Arc::clone(&mu), txw));
1387*bb4ee6a4SAndroid Build Coastguard Worker 
1388*bb4ee6a4SAndroid Build Coastguard Worker         let (txr, rxr) = channel();
1389*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..TASKS {
1390*bb4ee6a4SAndroid Build Coastguard Worker             ex.spawn_ok(reader(Arc::clone(&mu), txr.clone()));
1391*bb4ee6a4SAndroid Build Coastguard Worker         }
1392*bb4ee6a4SAndroid Build Coastguard Worker 
1393*bb4ee6a4SAndroid Build Coastguard Worker         // Wait for the readers to finish their checks.
1394*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..TASKS {
1395*bb4ee6a4SAndroid Build Coastguard Worker             rxr.recv_timeout(Duration::from_secs(5))
1396*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("Failed to receive completion message from reader");
1397*bb4ee6a4SAndroid Build Coastguard Worker         }
1398*bb4ee6a4SAndroid Build Coastguard Worker 
1399*bb4ee6a4SAndroid Build Coastguard Worker         // Wait for the writer to finish.
1400*bb4ee6a4SAndroid Build Coastguard Worker         rxw.recv_timeout(Duration::from_secs(5))
1401*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to receive completion message from writer");
1402*bb4ee6a4SAndroid Build Coastguard Worker 
1403*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.read_lock()), ITERATIONS);
1404*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1405*bb4ee6a4SAndroid Build Coastguard Worker     }
1406*bb4ee6a4SAndroid Build Coastguard Worker 
1407*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
wake_all_readers()1408*bb4ee6a4SAndroid Build Coastguard Worker     fn wake_all_readers() {
1409*bb4ee6a4SAndroid Build Coastguard Worker         async fn read(mu: Arc<RwLock<()>>) {
1410*bb4ee6a4SAndroid Build Coastguard Worker             let g = mu.read_lock().await;
1411*bb4ee6a4SAndroid Build Coastguard Worker             pending!();
1412*bb4ee6a4SAndroid Build Coastguard Worker             mem::drop(g);
1413*bb4ee6a4SAndroid Build Coastguard Worker         }
1414*bb4ee6a4SAndroid Build Coastguard Worker 
1415*bb4ee6a4SAndroid Build Coastguard Worker         async fn write(mu: Arc<RwLock<()>>) {
1416*bb4ee6a4SAndroid Build Coastguard Worker             mu.lock().await;
1417*bb4ee6a4SAndroid Build Coastguard Worker         }
1418*bb4ee6a4SAndroid Build Coastguard Worker 
1419*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(()));
1420*bb4ee6a4SAndroid Build Coastguard Worker         let mut futures: [Pin<Box<dyn Future<Output = ()>>>; 5] = [
1421*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone())),
1422*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone())),
1423*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone())),
1424*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(write(mu.clone())),
1425*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone())),
1426*bb4ee6a4SAndroid Build Coastguard Worker         ];
1427*bb4ee6a4SAndroid Build Coastguard Worker         const NUM_READERS: usize = 4;
1428*bb4ee6a4SAndroid Build Coastguard Worker 
1429*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1430*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1431*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1432*bb4ee6a4SAndroid Build Coastguard Worker 
1433*bb4ee6a4SAndroid Build Coastguard Worker         // Acquire the lock so that the futures cannot get it.
1434*bb4ee6a4SAndroid Build Coastguard Worker         let g = block_on(mu.lock());
1435*bb4ee6a4SAndroid Build Coastguard Worker 
1436*bb4ee6a4SAndroid Build Coastguard Worker         for r in &mut futures {
1437*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = r.as_mut().poll(&mut cx) {
1438*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("future unexpectedly ready");
1439*bb4ee6a4SAndroid Build Coastguard Worker             }
1440*bb4ee6a4SAndroid Build Coastguard Worker         }
1441*bb4ee6a4SAndroid Build Coastguard Worker 
1442*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1443*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & HAS_WAITERS,
1444*bb4ee6a4SAndroid Build Coastguard Worker             HAS_WAITERS
1445*bb4ee6a4SAndroid Build Coastguard Worker         );
1446*bb4ee6a4SAndroid Build Coastguard Worker 
1447*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1448*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & WRITER_WAITING,
1449*bb4ee6a4SAndroid Build Coastguard Worker             WRITER_WAITING
1450*bb4ee6a4SAndroid Build Coastguard Worker         );
1451*bb4ee6a4SAndroid Build Coastguard Worker 
1452*bb4ee6a4SAndroid Build Coastguard Worker         // Drop the lock. This should allow all readers to make progress. Since they already waited
1453*bb4ee6a4SAndroid Build Coastguard Worker         // once they should ignore the WRITER_WAITING bit that is currently set.
1454*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(g);
1455*bb4ee6a4SAndroid Build Coastguard Worker         for r in &mut futures {
1456*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = r.as_mut().poll(&mut cx) {
1457*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("future unexpectedly ready");
1458*bb4ee6a4SAndroid Build Coastguard Worker             }
1459*bb4ee6a4SAndroid Build Coastguard Worker         }
1460*bb4ee6a4SAndroid Build Coastguard Worker 
1461*bb4ee6a4SAndroid Build Coastguard Worker         // Check that all readers were able to acquire the lock.
1462*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1463*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & READ_MASK,
1464*bb4ee6a4SAndroid Build Coastguard Worker             READ_LOCK * NUM_READERS
1465*bb4ee6a4SAndroid Build Coastguard Worker         );
1466*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1467*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & WRITER_WAITING,
1468*bb4ee6a4SAndroid Build Coastguard Worker             WRITER_WAITING
1469*bb4ee6a4SAndroid Build Coastguard Worker         );
1470*bb4ee6a4SAndroid Build Coastguard Worker 
1471*bb4ee6a4SAndroid Build Coastguard Worker         let mut needs_poll = None;
1472*bb4ee6a4SAndroid Build Coastguard Worker 
1473*bb4ee6a4SAndroid Build Coastguard Worker         // All the readers can now finish but the writer needs to be polled again.
1474*bb4ee6a4SAndroid Build Coastguard Worker         for (i, r) in futures.iter_mut().enumerate() {
1475*bb4ee6a4SAndroid Build Coastguard Worker             match r.as_mut().poll(&mut cx) {
1476*bb4ee6a4SAndroid Build Coastguard Worker                 Poll::Ready(()) => {}
1477*bb4ee6a4SAndroid Build Coastguard Worker                 Poll::Pending => {
1478*bb4ee6a4SAndroid Build Coastguard Worker                     if needs_poll.is_some() {
1479*bb4ee6a4SAndroid Build Coastguard Worker                         panic!("More than one future unable to complete");
1480*bb4ee6a4SAndroid Build Coastguard Worker                     }
1481*bb4ee6a4SAndroid Build Coastguard Worker                     needs_poll = Some(i);
1482*bb4ee6a4SAndroid Build Coastguard Worker                 }
1483*bb4ee6a4SAndroid Build Coastguard Worker             }
1484*bb4ee6a4SAndroid Build Coastguard Worker         }
1485*bb4ee6a4SAndroid Build Coastguard Worker 
1486*bb4ee6a4SAndroid Build Coastguard Worker         if futures[needs_poll.expect("Writer unexpectedly able to complete")]
1487*bb4ee6a4SAndroid Build Coastguard Worker             .as_mut()
1488*bb4ee6a4SAndroid Build Coastguard Worker             .poll(&mut cx)
1489*bb4ee6a4SAndroid Build Coastguard Worker             .is_pending()
1490*bb4ee6a4SAndroid Build Coastguard Worker         {
1491*bb4ee6a4SAndroid Build Coastguard Worker             panic!("Writer unable to complete");
1492*bb4ee6a4SAndroid Build Coastguard Worker         }
1493*bb4ee6a4SAndroid Build Coastguard Worker 
1494*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1495*bb4ee6a4SAndroid Build Coastguard Worker     }
1496*bb4ee6a4SAndroid Build Coastguard Worker 
1497*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
long_wait()1498*bb4ee6a4SAndroid Build Coastguard Worker     fn long_wait() {
1499*bb4ee6a4SAndroid Build Coastguard Worker         async fn tight_loop(mu: Arc<RwLock<bool>>) {
1500*bb4ee6a4SAndroid Build Coastguard Worker             loop {
1501*bb4ee6a4SAndroid Build Coastguard Worker                 let ready = mu.lock().await;
1502*bb4ee6a4SAndroid Build Coastguard Worker                 if *ready {
1503*bb4ee6a4SAndroid Build Coastguard Worker                     break;
1504*bb4ee6a4SAndroid Build Coastguard Worker                 }
1505*bb4ee6a4SAndroid Build Coastguard Worker                 pending!();
1506*bb4ee6a4SAndroid Build Coastguard Worker             }
1507*bb4ee6a4SAndroid Build Coastguard Worker         }
1508*bb4ee6a4SAndroid Build Coastguard Worker 
1509*bb4ee6a4SAndroid Build Coastguard Worker         async fn mark_ready(mu: Arc<RwLock<bool>>) {
1510*bb4ee6a4SAndroid Build Coastguard Worker             *mu.lock().await = true;
1511*bb4ee6a4SAndroid Build Coastguard Worker         }
1512*bb4ee6a4SAndroid Build Coastguard Worker 
1513*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(false));
1514*bb4ee6a4SAndroid Build Coastguard Worker         let mut tl = Box::pin(tight_loop(mu.clone()));
1515*bb4ee6a4SAndroid Build Coastguard Worker         let mut mark = Box::pin(mark_ready(mu.clone()));
1516*bb4ee6a4SAndroid Build Coastguard Worker 
1517*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1518*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1519*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1520*bb4ee6a4SAndroid Build Coastguard Worker 
1521*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..=LONG_WAIT_THRESHOLD {
1522*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = tl.as_mut().poll(&mut cx) {
1523*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("tight_loop unexpectedly ready");
1524*bb4ee6a4SAndroid Build Coastguard Worker             }
1525*bb4ee6a4SAndroid Build Coastguard Worker 
1526*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = mark.as_mut().poll(&mut cx) {
1527*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("mark_ready unexpectedly ready");
1528*bb4ee6a4SAndroid Build Coastguard Worker             }
1529*bb4ee6a4SAndroid Build Coastguard Worker         }
1530*bb4ee6a4SAndroid Build Coastguard Worker 
1531*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1532*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed),
1533*bb4ee6a4SAndroid Build Coastguard Worker             LOCKED | HAS_WAITERS | WRITER_WAITING | LONG_WAIT
1534*bb4ee6a4SAndroid Build Coastguard Worker         );
1535*bb4ee6a4SAndroid Build Coastguard Worker 
1536*bb4ee6a4SAndroid Build Coastguard Worker         // This time the tight loop will fail to acquire the lock.
1537*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = tl.as_mut().poll(&mut cx) {
1538*bb4ee6a4SAndroid Build Coastguard Worker             panic!("tight_loop unexpectedly ready");
1539*bb4ee6a4SAndroid Build Coastguard Worker         }
1540*bb4ee6a4SAndroid Build Coastguard Worker 
1541*bb4ee6a4SAndroid Build Coastguard Worker         // Which will finally allow the mark_ready function to make progress.
1542*bb4ee6a4SAndroid Build Coastguard Worker         if mark.as_mut().poll(&mut cx).is_pending() {
1543*bb4ee6a4SAndroid Build Coastguard Worker             panic!("mark_ready not able to make progress");
1544*bb4ee6a4SAndroid Build Coastguard Worker         }
1545*bb4ee6a4SAndroid Build Coastguard Worker 
1546*bb4ee6a4SAndroid Build Coastguard Worker         // Now the tight loop will finish.
1547*bb4ee6a4SAndroid Build Coastguard Worker         if tl.as_mut().poll(&mut cx).is_pending() {
1548*bb4ee6a4SAndroid Build Coastguard Worker             panic!("tight_loop not able to finish");
1549*bb4ee6a4SAndroid Build Coastguard Worker         }
1550*bb4ee6a4SAndroid Build Coastguard Worker 
1551*bb4ee6a4SAndroid Build Coastguard Worker         assert!(*block_on(mu.lock()));
1552*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1553*bb4ee6a4SAndroid Build Coastguard Worker     }
1554*bb4ee6a4SAndroid Build Coastguard Worker 
1555*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
cancel_long_wait_before_wake()1556*bb4ee6a4SAndroid Build Coastguard Worker     fn cancel_long_wait_before_wake() {
1557*bb4ee6a4SAndroid Build Coastguard Worker         async fn tight_loop(mu: Arc<RwLock<bool>>) {
1558*bb4ee6a4SAndroid Build Coastguard Worker             loop {
1559*bb4ee6a4SAndroid Build Coastguard Worker                 let ready = mu.lock().await;
1560*bb4ee6a4SAndroid Build Coastguard Worker                 if *ready {
1561*bb4ee6a4SAndroid Build Coastguard Worker                     break;
1562*bb4ee6a4SAndroid Build Coastguard Worker                 }
1563*bb4ee6a4SAndroid Build Coastguard Worker                 pending!();
1564*bb4ee6a4SAndroid Build Coastguard Worker             }
1565*bb4ee6a4SAndroid Build Coastguard Worker         }
1566*bb4ee6a4SAndroid Build Coastguard Worker 
1567*bb4ee6a4SAndroid Build Coastguard Worker         async fn mark_ready(mu: Arc<RwLock<bool>>) {
1568*bb4ee6a4SAndroid Build Coastguard Worker             *mu.lock().await = true;
1569*bb4ee6a4SAndroid Build Coastguard Worker         }
1570*bb4ee6a4SAndroid Build Coastguard Worker 
1571*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(false));
1572*bb4ee6a4SAndroid Build Coastguard Worker         let mut tl = Box::pin(tight_loop(mu.clone()));
1573*bb4ee6a4SAndroid Build Coastguard Worker         let mut mark = Box::pin(mark_ready(mu.clone()));
1574*bb4ee6a4SAndroid Build Coastguard Worker 
1575*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1576*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1577*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1578*bb4ee6a4SAndroid Build Coastguard Worker 
1579*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..=LONG_WAIT_THRESHOLD {
1580*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = tl.as_mut().poll(&mut cx) {
1581*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("tight_loop unexpectedly ready");
1582*bb4ee6a4SAndroid Build Coastguard Worker             }
1583*bb4ee6a4SAndroid Build Coastguard Worker 
1584*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = mark.as_mut().poll(&mut cx) {
1585*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("mark_ready unexpectedly ready");
1586*bb4ee6a4SAndroid Build Coastguard Worker             }
1587*bb4ee6a4SAndroid Build Coastguard Worker         }
1588*bb4ee6a4SAndroid Build Coastguard Worker 
1589*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1590*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed),
1591*bb4ee6a4SAndroid Build Coastguard Worker             LOCKED | HAS_WAITERS | WRITER_WAITING | LONG_WAIT
1592*bb4ee6a4SAndroid Build Coastguard Worker         );
1593*bb4ee6a4SAndroid Build Coastguard Worker 
1594*bb4ee6a4SAndroid Build Coastguard Worker         // Now drop the mark_ready future, which should clear the LONG_WAIT bit.
1595*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(mark);
1596*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), LOCKED);
1597*bb4ee6a4SAndroid Build Coastguard Worker 
1598*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(tl);
1599*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1600*bb4ee6a4SAndroid Build Coastguard Worker     }
1601*bb4ee6a4SAndroid Build Coastguard Worker 
1602*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
cancel_long_wait_after_wake()1603*bb4ee6a4SAndroid Build Coastguard Worker     fn cancel_long_wait_after_wake() {
1604*bb4ee6a4SAndroid Build Coastguard Worker         async fn tight_loop(mu: Arc<RwLock<bool>>) {
1605*bb4ee6a4SAndroid Build Coastguard Worker             loop {
1606*bb4ee6a4SAndroid Build Coastguard Worker                 let ready = mu.lock().await;
1607*bb4ee6a4SAndroid Build Coastguard Worker                 if *ready {
1608*bb4ee6a4SAndroid Build Coastguard Worker                     break;
1609*bb4ee6a4SAndroid Build Coastguard Worker                 }
1610*bb4ee6a4SAndroid Build Coastguard Worker                 pending!();
1611*bb4ee6a4SAndroid Build Coastguard Worker             }
1612*bb4ee6a4SAndroid Build Coastguard Worker         }
1613*bb4ee6a4SAndroid Build Coastguard Worker 
1614*bb4ee6a4SAndroid Build Coastguard Worker         async fn mark_ready(mu: Arc<RwLock<bool>>) {
1615*bb4ee6a4SAndroid Build Coastguard Worker             *mu.lock().await = true;
1616*bb4ee6a4SAndroid Build Coastguard Worker         }
1617*bb4ee6a4SAndroid Build Coastguard Worker 
1618*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(false));
1619*bb4ee6a4SAndroid Build Coastguard Worker         let mut tl = Box::pin(tight_loop(mu.clone()));
1620*bb4ee6a4SAndroid Build Coastguard Worker         let mut mark = Box::pin(mark_ready(mu.clone()));
1621*bb4ee6a4SAndroid Build Coastguard Worker 
1622*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1623*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1624*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1625*bb4ee6a4SAndroid Build Coastguard Worker 
1626*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..=LONG_WAIT_THRESHOLD {
1627*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = tl.as_mut().poll(&mut cx) {
1628*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("tight_loop unexpectedly ready");
1629*bb4ee6a4SAndroid Build Coastguard Worker             }
1630*bb4ee6a4SAndroid Build Coastguard Worker 
1631*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = mark.as_mut().poll(&mut cx) {
1632*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("mark_ready unexpectedly ready");
1633*bb4ee6a4SAndroid Build Coastguard Worker             }
1634*bb4ee6a4SAndroid Build Coastguard Worker         }
1635*bb4ee6a4SAndroid Build Coastguard Worker 
1636*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1637*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed),
1638*bb4ee6a4SAndroid Build Coastguard Worker             LOCKED | HAS_WAITERS | WRITER_WAITING | LONG_WAIT
1639*bb4ee6a4SAndroid Build Coastguard Worker         );
1640*bb4ee6a4SAndroid Build Coastguard Worker 
1641*bb4ee6a4SAndroid Build Coastguard Worker         // This time the tight loop will fail to acquire the lock.
1642*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = tl.as_mut().poll(&mut cx) {
1643*bb4ee6a4SAndroid Build Coastguard Worker             panic!("tight_loop unexpectedly ready");
1644*bb4ee6a4SAndroid Build Coastguard Worker         }
1645*bb4ee6a4SAndroid Build Coastguard Worker 
1646*bb4ee6a4SAndroid Build Coastguard Worker         // Now drop the mark_ready future, which should clear the LONG_WAIT bit.
1647*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(mark);
1648*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed) & LONG_WAIT, 0);
1649*bb4ee6a4SAndroid Build Coastguard Worker 
1650*bb4ee6a4SAndroid Build Coastguard Worker         // Since the lock is not held, we should be able to spawn a future to set the ready flag.
1651*bb4ee6a4SAndroid Build Coastguard Worker         block_on(mark_ready(mu.clone()));
1652*bb4ee6a4SAndroid Build Coastguard Worker 
1653*bb4ee6a4SAndroid Build Coastguard Worker         // Now the tight loop will finish.
1654*bb4ee6a4SAndroid Build Coastguard Worker         if tl.as_mut().poll(&mut cx).is_pending() {
1655*bb4ee6a4SAndroid Build Coastguard Worker             panic!("tight_loop not able to finish");
1656*bb4ee6a4SAndroid Build Coastguard Worker         }
1657*bb4ee6a4SAndroid Build Coastguard Worker 
1658*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1659*bb4ee6a4SAndroid Build Coastguard Worker     }
1660*bb4ee6a4SAndroid Build Coastguard Worker 
1661*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
designated_waker()1662*bb4ee6a4SAndroid Build Coastguard Worker     fn designated_waker() {
1663*bb4ee6a4SAndroid Build Coastguard Worker         async fn inc(mu: Arc<RwLock<usize>>) {
1664*bb4ee6a4SAndroid Build Coastguard Worker             *mu.lock().await += 1;
1665*bb4ee6a4SAndroid Build Coastguard Worker         }
1666*bb4ee6a4SAndroid Build Coastguard Worker 
1667*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0));
1668*bb4ee6a4SAndroid Build Coastguard Worker 
1669*bb4ee6a4SAndroid Build Coastguard Worker         let mut futures = [
1670*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(inc(mu.clone())),
1671*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(inc(mu.clone())),
1672*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(inc(mu.clone())),
1673*bb4ee6a4SAndroid Build Coastguard Worker         ];
1674*bb4ee6a4SAndroid Build Coastguard Worker 
1675*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1676*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1677*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1678*bb4ee6a4SAndroid Build Coastguard Worker 
1679*bb4ee6a4SAndroid Build Coastguard Worker         let count = block_on(mu.lock());
1680*bb4ee6a4SAndroid Build Coastguard Worker 
1681*bb4ee6a4SAndroid Build Coastguard Worker         // Poll 2 futures. Since neither will be able to acquire the lock, they should get added to
1682*bb4ee6a4SAndroid Build Coastguard Worker         // the waiter list.
1683*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = futures[0].as_mut().poll(&mut cx) {
1684*bb4ee6a4SAndroid Build Coastguard Worker             panic!("future unexpectedly ready");
1685*bb4ee6a4SAndroid Build Coastguard Worker         }
1686*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = futures[1].as_mut().poll(&mut cx) {
1687*bb4ee6a4SAndroid Build Coastguard Worker             panic!("future unexpectedly ready");
1688*bb4ee6a4SAndroid Build Coastguard Worker         }
1689*bb4ee6a4SAndroid Build Coastguard Worker 
1690*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1691*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed),
1692*bb4ee6a4SAndroid Build Coastguard Worker             LOCKED | HAS_WAITERS | WRITER_WAITING,
1693*bb4ee6a4SAndroid Build Coastguard Worker         );
1694*bb4ee6a4SAndroid Build Coastguard Worker 
1695*bb4ee6a4SAndroid Build Coastguard Worker         // Now drop the lock. This should set the DESIGNATED_WAKER bit and wake up the first future
1696*bb4ee6a4SAndroid Build Coastguard Worker         // in the wait list.
1697*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(count);
1698*bb4ee6a4SAndroid Build Coastguard Worker 
1699*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1700*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed),
1701*bb4ee6a4SAndroid Build Coastguard Worker             DESIGNATED_WAKER | HAS_WAITERS | WRITER_WAITING,
1702*bb4ee6a4SAndroid Build Coastguard Worker         );
1703*bb4ee6a4SAndroid Build Coastguard Worker 
1704*bb4ee6a4SAndroid Build Coastguard Worker         // Now poll the third future.  It should be able to acquire the lock immediately.
1705*bb4ee6a4SAndroid Build Coastguard Worker         if futures[2].as_mut().poll(&mut cx).is_pending() {
1706*bb4ee6a4SAndroid Build Coastguard Worker             panic!("future unable to complete");
1707*bb4ee6a4SAndroid Build Coastguard Worker         }
1708*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.lock()), 1);
1709*bb4ee6a4SAndroid Build Coastguard Worker 
1710*bb4ee6a4SAndroid Build Coastguard Worker         // There should still be a waiter in the wait list and the DESIGNATED_WAKER bit should still
1711*bb4ee6a4SAndroid Build Coastguard Worker         // be set.
1712*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1713*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & DESIGNATED_WAKER,
1714*bb4ee6a4SAndroid Build Coastguard Worker             DESIGNATED_WAKER
1715*bb4ee6a4SAndroid Build Coastguard Worker         );
1716*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1717*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & HAS_WAITERS,
1718*bb4ee6a4SAndroid Build Coastguard Worker             HAS_WAITERS
1719*bb4ee6a4SAndroid Build Coastguard Worker         );
1720*bb4ee6a4SAndroid Build Coastguard Worker 
1721*bb4ee6a4SAndroid Build Coastguard Worker         // Now let the future that was woken up run.
1722*bb4ee6a4SAndroid Build Coastguard Worker         if futures[0].as_mut().poll(&mut cx).is_pending() {
1723*bb4ee6a4SAndroid Build Coastguard Worker             panic!("future unable to complete");
1724*bb4ee6a4SAndroid Build Coastguard Worker         }
1725*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.lock()), 2);
1726*bb4ee6a4SAndroid Build Coastguard Worker 
1727*bb4ee6a4SAndroid Build Coastguard Worker         if futures[1].as_mut().poll(&mut cx).is_pending() {
1728*bb4ee6a4SAndroid Build Coastguard Worker             panic!("future unable to complete");
1729*bb4ee6a4SAndroid Build Coastguard Worker         }
1730*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.lock()), 3);
1731*bb4ee6a4SAndroid Build Coastguard Worker 
1732*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1733*bb4ee6a4SAndroid Build Coastguard Worker     }
1734*bb4ee6a4SAndroid Build Coastguard Worker 
1735*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
cancel_designated_waker()1736*bb4ee6a4SAndroid Build Coastguard Worker     fn cancel_designated_waker() {
1737*bb4ee6a4SAndroid Build Coastguard Worker         async fn inc(mu: Arc<RwLock<usize>>) {
1738*bb4ee6a4SAndroid Build Coastguard Worker             *mu.lock().await += 1;
1739*bb4ee6a4SAndroid Build Coastguard Worker         }
1740*bb4ee6a4SAndroid Build Coastguard Worker 
1741*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0));
1742*bb4ee6a4SAndroid Build Coastguard Worker 
1743*bb4ee6a4SAndroid Build Coastguard Worker         let mut fut = Box::pin(inc(mu.clone()));
1744*bb4ee6a4SAndroid Build Coastguard Worker 
1745*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1746*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1747*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1748*bb4ee6a4SAndroid Build Coastguard Worker 
1749*bb4ee6a4SAndroid Build Coastguard Worker         let count = block_on(mu.lock());
1750*bb4ee6a4SAndroid Build Coastguard Worker 
1751*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = fut.as_mut().poll(&mut cx) {
1752*bb4ee6a4SAndroid Build Coastguard Worker             panic!("Future unexpectedly ready when lock is held");
1753*bb4ee6a4SAndroid Build Coastguard Worker         }
1754*bb4ee6a4SAndroid Build Coastguard Worker 
1755*bb4ee6a4SAndroid Build Coastguard Worker         // Drop the lock.  This will wake up the future.
1756*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(count);
1757*bb4ee6a4SAndroid Build Coastguard Worker 
1758*bb4ee6a4SAndroid Build Coastguard Worker         // Now drop the future without polling. This should clear all the state in the rwlock.
1759*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(fut);
1760*bb4ee6a4SAndroid Build Coastguard Worker 
1761*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1762*bb4ee6a4SAndroid Build Coastguard Worker     }
1763*bb4ee6a4SAndroid Build Coastguard Worker 
1764*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
cancel_before_wake()1765*bb4ee6a4SAndroid Build Coastguard Worker     fn cancel_before_wake() {
1766*bb4ee6a4SAndroid Build Coastguard Worker         async fn inc(mu: Arc<RwLock<usize>>) {
1767*bb4ee6a4SAndroid Build Coastguard Worker             *mu.lock().await += 1;
1768*bb4ee6a4SAndroid Build Coastguard Worker         }
1769*bb4ee6a4SAndroid Build Coastguard Worker 
1770*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0));
1771*bb4ee6a4SAndroid Build Coastguard Worker 
1772*bb4ee6a4SAndroid Build Coastguard Worker         let mut fut1 = Box::pin(inc(mu.clone()));
1773*bb4ee6a4SAndroid Build Coastguard Worker 
1774*bb4ee6a4SAndroid Build Coastguard Worker         let mut fut2 = Box::pin(inc(mu.clone()));
1775*bb4ee6a4SAndroid Build Coastguard Worker 
1776*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1777*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1778*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1779*bb4ee6a4SAndroid Build Coastguard Worker 
1780*bb4ee6a4SAndroid Build Coastguard Worker         // First acquire the lock.
1781*bb4ee6a4SAndroid Build Coastguard Worker         let count = block_on(mu.lock());
1782*bb4ee6a4SAndroid Build Coastguard Worker 
1783*bb4ee6a4SAndroid Build Coastguard Worker         // Now poll the futures. Since the lock is acquired they will both get queued in the waiter
1784*bb4ee6a4SAndroid Build Coastguard Worker         // list.
1785*bb4ee6a4SAndroid Build Coastguard Worker         match fut1.as_mut().poll(&mut cx) {
1786*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Pending => {}
1787*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Ready(()) => panic!("Future is unexpectedly ready"),
1788*bb4ee6a4SAndroid Build Coastguard Worker         }
1789*bb4ee6a4SAndroid Build Coastguard Worker 
1790*bb4ee6a4SAndroid Build Coastguard Worker         match fut2.as_mut().poll(&mut cx) {
1791*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Pending => {}
1792*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Ready(()) => panic!("Future is unexpectedly ready"),
1793*bb4ee6a4SAndroid Build Coastguard Worker         }
1794*bb4ee6a4SAndroid Build Coastguard Worker 
1795*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1796*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & WRITER_WAITING,
1797*bb4ee6a4SAndroid Build Coastguard Worker             WRITER_WAITING
1798*bb4ee6a4SAndroid Build Coastguard Worker         );
1799*bb4ee6a4SAndroid Build Coastguard Worker 
1800*bb4ee6a4SAndroid Build Coastguard Worker         // Drop fut1.  This should remove it from the waiter list but shouldn't wake fut2.
1801*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(fut1);
1802*bb4ee6a4SAndroid Build Coastguard Worker 
1803*bb4ee6a4SAndroid Build Coastguard Worker         // There should be no designated waker.
1804*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed) & DESIGNATED_WAKER, 0);
1805*bb4ee6a4SAndroid Build Coastguard Worker 
1806*bb4ee6a4SAndroid Build Coastguard Worker         // Since the waiter was a writer, we should clear the WRITER_WAITING bit.
1807*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed) & WRITER_WAITING, 0);
1808*bb4ee6a4SAndroid Build Coastguard Worker 
1809*bb4ee6a4SAndroid Build Coastguard Worker         match fut2.as_mut().poll(&mut cx) {
1810*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Pending => {}
1811*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Ready(()) => panic!("Future is unexpectedly ready"),
1812*bb4ee6a4SAndroid Build Coastguard Worker         }
1813*bb4ee6a4SAndroid Build Coastguard Worker 
1814*bb4ee6a4SAndroid Build Coastguard Worker         // Now drop the lock.  This should mark fut2 as ready to make progress.
1815*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(count);
1816*bb4ee6a4SAndroid Build Coastguard Worker 
1817*bb4ee6a4SAndroid Build Coastguard Worker         match fut2.as_mut().poll(&mut cx) {
1818*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Pending => panic!("Future is not ready to make progress"),
1819*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Ready(()) => {}
1820*bb4ee6a4SAndroid Build Coastguard Worker         }
1821*bb4ee6a4SAndroid Build Coastguard Worker 
1822*bb4ee6a4SAndroid Build Coastguard Worker         // Verify that we only incremented the count once.
1823*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.lock()), 1);
1824*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1825*bb4ee6a4SAndroid Build Coastguard Worker     }
1826*bb4ee6a4SAndroid Build Coastguard Worker 
1827*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
cancel_after_wake()1828*bb4ee6a4SAndroid Build Coastguard Worker     fn cancel_after_wake() {
1829*bb4ee6a4SAndroid Build Coastguard Worker         async fn inc(mu: Arc<RwLock<usize>>) {
1830*bb4ee6a4SAndroid Build Coastguard Worker             *mu.lock().await += 1;
1831*bb4ee6a4SAndroid Build Coastguard Worker         }
1832*bb4ee6a4SAndroid Build Coastguard Worker 
1833*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0));
1834*bb4ee6a4SAndroid Build Coastguard Worker 
1835*bb4ee6a4SAndroid Build Coastguard Worker         let mut fut1 = Box::pin(inc(mu.clone()));
1836*bb4ee6a4SAndroid Build Coastguard Worker 
1837*bb4ee6a4SAndroid Build Coastguard Worker         let mut fut2 = Box::pin(inc(mu.clone()));
1838*bb4ee6a4SAndroid Build Coastguard Worker 
1839*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1840*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1841*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1842*bb4ee6a4SAndroid Build Coastguard Worker 
1843*bb4ee6a4SAndroid Build Coastguard Worker         // First acquire the lock.
1844*bb4ee6a4SAndroid Build Coastguard Worker         let count = block_on(mu.lock());
1845*bb4ee6a4SAndroid Build Coastguard Worker 
1846*bb4ee6a4SAndroid Build Coastguard Worker         // Now poll the futures. Since the lock is acquired they will both get queued in the waiter
1847*bb4ee6a4SAndroid Build Coastguard Worker         // list.
1848*bb4ee6a4SAndroid Build Coastguard Worker         match fut1.as_mut().poll(&mut cx) {
1849*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Pending => {}
1850*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Ready(()) => panic!("Future is unexpectedly ready"),
1851*bb4ee6a4SAndroid Build Coastguard Worker         }
1852*bb4ee6a4SAndroid Build Coastguard Worker 
1853*bb4ee6a4SAndroid Build Coastguard Worker         match fut2.as_mut().poll(&mut cx) {
1854*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Pending => {}
1855*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Ready(()) => panic!("Future is unexpectedly ready"),
1856*bb4ee6a4SAndroid Build Coastguard Worker         }
1857*bb4ee6a4SAndroid Build Coastguard Worker 
1858*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1859*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & WRITER_WAITING,
1860*bb4ee6a4SAndroid Build Coastguard Worker             WRITER_WAITING
1861*bb4ee6a4SAndroid Build Coastguard Worker         );
1862*bb4ee6a4SAndroid Build Coastguard Worker 
1863*bb4ee6a4SAndroid Build Coastguard Worker         // Drop the lock.  This should mark fut1 as ready to make progress.
1864*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(count);
1865*bb4ee6a4SAndroid Build Coastguard Worker 
1866*bb4ee6a4SAndroid Build Coastguard Worker         // Now drop fut1.  This should make fut2 ready to make progress.
1867*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(fut1);
1868*bb4ee6a4SAndroid Build Coastguard Worker 
1869*bb4ee6a4SAndroid Build Coastguard Worker         // Since there was still another waiter in the list we shouldn't have cleared the
1870*bb4ee6a4SAndroid Build Coastguard Worker         // DESIGNATED_WAKER bit.
1871*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1872*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & DESIGNATED_WAKER,
1873*bb4ee6a4SAndroid Build Coastguard Worker             DESIGNATED_WAKER
1874*bb4ee6a4SAndroid Build Coastguard Worker         );
1875*bb4ee6a4SAndroid Build Coastguard Worker 
1876*bb4ee6a4SAndroid Build Coastguard Worker         // Since the waiter was a writer, we should clear the WRITER_WAITING bit.
1877*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed) & WRITER_WAITING, 0);
1878*bb4ee6a4SAndroid Build Coastguard Worker 
1879*bb4ee6a4SAndroid Build Coastguard Worker         match fut2.as_mut().poll(&mut cx) {
1880*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Pending => panic!("Future is not ready to make progress"),
1881*bb4ee6a4SAndroid Build Coastguard Worker             Poll::Ready(()) => {}
1882*bb4ee6a4SAndroid Build Coastguard Worker         }
1883*bb4ee6a4SAndroid Build Coastguard Worker 
1884*bb4ee6a4SAndroid Build Coastguard Worker         // Verify that we only incremented the count once.
1885*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.lock()), 1);
1886*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1887*bb4ee6a4SAndroid Build Coastguard Worker     }
1888*bb4ee6a4SAndroid Build Coastguard Worker 
1889*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
timeout()1890*bb4ee6a4SAndroid Build Coastguard Worker     fn timeout() {
1891*bb4ee6a4SAndroid Build Coastguard Worker         async fn timed_lock(timer: oneshot::Receiver<()>, mu: Arc<RwLock<()>>) {
1892*bb4ee6a4SAndroid Build Coastguard Worker             select! {
1893*bb4ee6a4SAndroid Build Coastguard Worker                 res = timer.fuse() => {
1894*bb4ee6a4SAndroid Build Coastguard Worker                     match res {
1895*bb4ee6a4SAndroid Build Coastguard Worker                         Ok(()) => {},
1896*bb4ee6a4SAndroid Build Coastguard Worker                         Err(e) => panic!("Timer unexpectedly canceled: {}", e),
1897*bb4ee6a4SAndroid Build Coastguard Worker                     }
1898*bb4ee6a4SAndroid Build Coastguard Worker                 }
1899*bb4ee6a4SAndroid Build Coastguard Worker                 _ = mu.lock().fuse() => panic!("Successfuly acquired lock"),
1900*bb4ee6a4SAndroid Build Coastguard Worker             }
1901*bb4ee6a4SAndroid Build Coastguard Worker         }
1902*bb4ee6a4SAndroid Build Coastguard Worker 
1903*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(()));
1904*bb4ee6a4SAndroid Build Coastguard Worker         let (tx, rx) = oneshot::channel();
1905*bb4ee6a4SAndroid Build Coastguard Worker 
1906*bb4ee6a4SAndroid Build Coastguard Worker         let mut timeout = Box::pin(timed_lock(rx, mu.clone()));
1907*bb4ee6a4SAndroid Build Coastguard Worker 
1908*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1909*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1910*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1911*bb4ee6a4SAndroid Build Coastguard Worker 
1912*bb4ee6a4SAndroid Build Coastguard Worker         // Acquire the lock.
1913*bb4ee6a4SAndroid Build Coastguard Worker         let g = block_on(mu.lock());
1914*bb4ee6a4SAndroid Build Coastguard Worker 
1915*bb4ee6a4SAndroid Build Coastguard Worker         // Poll the future.
1916*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = timeout.as_mut().poll(&mut cx) {
1917*bb4ee6a4SAndroid Build Coastguard Worker             panic!("timed_lock unexpectedly ready");
1918*bb4ee6a4SAndroid Build Coastguard Worker         }
1919*bb4ee6a4SAndroid Build Coastguard Worker 
1920*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1921*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & HAS_WAITERS,
1922*bb4ee6a4SAndroid Build Coastguard Worker             HAS_WAITERS
1923*bb4ee6a4SAndroid Build Coastguard Worker         );
1924*bb4ee6a4SAndroid Build Coastguard Worker 
1925*bb4ee6a4SAndroid Build Coastguard Worker         // Signal the channel, which should cancel the lock.
1926*bb4ee6a4SAndroid Build Coastguard Worker         tx.send(()).expect("Failed to send wakeup");
1927*bb4ee6a4SAndroid Build Coastguard Worker 
1928*bb4ee6a4SAndroid Build Coastguard Worker         // Now the future should have completed without acquiring the lock.
1929*bb4ee6a4SAndroid Build Coastguard Worker         if timeout.as_mut().poll(&mut cx).is_pending() {
1930*bb4ee6a4SAndroid Build Coastguard Worker             panic!("timed_lock not ready after timeout");
1931*bb4ee6a4SAndroid Build Coastguard Worker         }
1932*bb4ee6a4SAndroid Build Coastguard Worker 
1933*bb4ee6a4SAndroid Build Coastguard Worker         // The rwlock state should not show any waiters.
1934*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed) & HAS_WAITERS, 0);
1935*bb4ee6a4SAndroid Build Coastguard Worker 
1936*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(g);
1937*bb4ee6a4SAndroid Build Coastguard Worker 
1938*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
1939*bb4ee6a4SAndroid Build Coastguard Worker     }
1940*bb4ee6a4SAndroid Build Coastguard Worker 
1941*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
writer_waiting()1942*bb4ee6a4SAndroid Build Coastguard Worker     fn writer_waiting() {
1943*bb4ee6a4SAndroid Build Coastguard Worker         async fn read_zero(mu: Arc<RwLock<usize>>) {
1944*bb4ee6a4SAndroid Build Coastguard Worker             let val = mu.read_lock().await;
1945*bb4ee6a4SAndroid Build Coastguard Worker             pending!();
1946*bb4ee6a4SAndroid Build Coastguard Worker 
1947*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(*val, 0);
1948*bb4ee6a4SAndroid Build Coastguard Worker         }
1949*bb4ee6a4SAndroid Build Coastguard Worker 
1950*bb4ee6a4SAndroid Build Coastguard Worker         async fn inc(mu: Arc<RwLock<usize>>) {
1951*bb4ee6a4SAndroid Build Coastguard Worker             *mu.lock().await += 1;
1952*bb4ee6a4SAndroid Build Coastguard Worker         }
1953*bb4ee6a4SAndroid Build Coastguard Worker 
1954*bb4ee6a4SAndroid Build Coastguard Worker         async fn read_one(mu: Arc<RwLock<usize>>) {
1955*bb4ee6a4SAndroid Build Coastguard Worker             let val = mu.read_lock().await;
1956*bb4ee6a4SAndroid Build Coastguard Worker 
1957*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(*val, 1);
1958*bb4ee6a4SAndroid Build Coastguard Worker         }
1959*bb4ee6a4SAndroid Build Coastguard Worker 
1960*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0));
1961*bb4ee6a4SAndroid Build Coastguard Worker 
1962*bb4ee6a4SAndroid Build Coastguard Worker         let mut r1 = Box::pin(read_zero(mu.clone()));
1963*bb4ee6a4SAndroid Build Coastguard Worker         let mut r2 = Box::pin(read_zero(mu.clone()));
1964*bb4ee6a4SAndroid Build Coastguard Worker 
1965*bb4ee6a4SAndroid Build Coastguard Worker         let mut w = Box::pin(inc(mu.clone()));
1966*bb4ee6a4SAndroid Build Coastguard Worker         let mut r3 = Box::pin(read_one(mu.clone()));
1967*bb4ee6a4SAndroid Build Coastguard Worker 
1968*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
1969*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
1970*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
1971*bb4ee6a4SAndroid Build Coastguard Worker 
1972*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = r1.as_mut().poll(&mut cx) {
1973*bb4ee6a4SAndroid Build Coastguard Worker             panic!("read_zero unexpectedly ready");
1974*bb4ee6a4SAndroid Build Coastguard Worker         }
1975*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = r2.as_mut().poll(&mut cx) {
1976*bb4ee6a4SAndroid Build Coastguard Worker             panic!("read_zero unexpectedly ready");
1977*bb4ee6a4SAndroid Build Coastguard Worker         }
1978*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1979*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & READ_MASK,
1980*bb4ee6a4SAndroid Build Coastguard Worker             2 * READ_LOCK
1981*bb4ee6a4SAndroid Build Coastguard Worker         );
1982*bb4ee6a4SAndroid Build Coastguard Worker 
1983*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = w.as_mut().poll(&mut cx) {
1984*bb4ee6a4SAndroid Build Coastguard Worker             panic!("inc unexpectedly ready");
1985*bb4ee6a4SAndroid Build Coastguard Worker         }
1986*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1987*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & WRITER_WAITING,
1988*bb4ee6a4SAndroid Build Coastguard Worker             WRITER_WAITING
1989*bb4ee6a4SAndroid Build Coastguard Worker         );
1990*bb4ee6a4SAndroid Build Coastguard Worker 
1991*bb4ee6a4SAndroid Build Coastguard Worker         // The WRITER_WAITING bit should prevent the next reader from acquiring the lock.
1992*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = r3.as_mut().poll(&mut cx) {
1993*bb4ee6a4SAndroid Build Coastguard Worker             panic!("read_one unexpectedly ready");
1994*bb4ee6a4SAndroid Build Coastguard Worker         }
1995*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
1996*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & READ_MASK,
1997*bb4ee6a4SAndroid Build Coastguard Worker             2 * READ_LOCK
1998*bb4ee6a4SAndroid Build Coastguard Worker         );
1999*bb4ee6a4SAndroid Build Coastguard Worker 
2000*bb4ee6a4SAndroid Build Coastguard Worker         if r1.as_mut().poll(&mut cx).is_pending() {
2001*bb4ee6a4SAndroid Build Coastguard Worker             panic!("read_zero unable to complete");
2002*bb4ee6a4SAndroid Build Coastguard Worker         }
2003*bb4ee6a4SAndroid Build Coastguard Worker         if r2.as_mut().poll(&mut cx).is_pending() {
2004*bb4ee6a4SAndroid Build Coastguard Worker             panic!("read_zero unable to complete");
2005*bb4ee6a4SAndroid Build Coastguard Worker         }
2006*bb4ee6a4SAndroid Build Coastguard Worker         if w.as_mut().poll(&mut cx).is_pending() {
2007*bb4ee6a4SAndroid Build Coastguard Worker             panic!("inc unable to complete");
2008*bb4ee6a4SAndroid Build Coastguard Worker         }
2009*bb4ee6a4SAndroid Build Coastguard Worker         if r3.as_mut().poll(&mut cx).is_pending() {
2010*bb4ee6a4SAndroid Build Coastguard Worker             panic!("read_one unable to complete");
2011*bb4ee6a4SAndroid Build Coastguard Worker         }
2012*bb4ee6a4SAndroid Build Coastguard Worker 
2013*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
2014*bb4ee6a4SAndroid Build Coastguard Worker     }
2015*bb4ee6a4SAndroid Build Coastguard Worker 
2016*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
notify_one()2017*bb4ee6a4SAndroid Build Coastguard Worker     fn notify_one() {
2018*bb4ee6a4SAndroid Build Coastguard Worker         async fn read(mu: Arc<RwLock<usize>>, cv: Arc<Condvar>) {
2019*bb4ee6a4SAndroid Build Coastguard Worker             let mut count = mu.read_lock().await;
2020*bb4ee6a4SAndroid Build Coastguard Worker             while *count == 0 {
2021*bb4ee6a4SAndroid Build Coastguard Worker                 count = cv.wait_read(count).await;
2022*bb4ee6a4SAndroid Build Coastguard Worker             }
2023*bb4ee6a4SAndroid Build Coastguard Worker         }
2024*bb4ee6a4SAndroid Build Coastguard Worker 
2025*bb4ee6a4SAndroid Build Coastguard Worker         async fn write(mu: Arc<RwLock<usize>>, cv: Arc<Condvar>) {
2026*bb4ee6a4SAndroid Build Coastguard Worker             let mut count = mu.lock().await;
2027*bb4ee6a4SAndroid Build Coastguard Worker             while *count == 0 {
2028*bb4ee6a4SAndroid Build Coastguard Worker                 count = cv.wait(count).await;
2029*bb4ee6a4SAndroid Build Coastguard Worker             }
2030*bb4ee6a4SAndroid Build Coastguard Worker 
2031*bb4ee6a4SAndroid Build Coastguard Worker             *count -= 1;
2032*bb4ee6a4SAndroid Build Coastguard Worker         }
2033*bb4ee6a4SAndroid Build Coastguard Worker 
2034*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0));
2035*bb4ee6a4SAndroid Build Coastguard Worker         let cv = Arc::new(Condvar::new());
2036*bb4ee6a4SAndroid Build Coastguard Worker 
2037*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
2038*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
2039*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
2040*bb4ee6a4SAndroid Build Coastguard Worker 
2041*bb4ee6a4SAndroid Build Coastguard Worker         let mut readers = [
2042*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2043*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2044*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2045*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2046*bb4ee6a4SAndroid Build Coastguard Worker         ];
2047*bb4ee6a4SAndroid Build Coastguard Worker         let mut writer = Box::pin(write(mu.clone(), cv.clone()));
2048*bb4ee6a4SAndroid Build Coastguard Worker 
2049*bb4ee6a4SAndroid Build Coastguard Worker         for r in &mut readers {
2050*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = r.as_mut().poll(&mut cx) {
2051*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("reader unexpectedly ready");
2052*bb4ee6a4SAndroid Build Coastguard Worker             }
2053*bb4ee6a4SAndroid Build Coastguard Worker         }
2054*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = writer.as_mut().poll(&mut cx) {
2055*bb4ee6a4SAndroid Build Coastguard Worker             panic!("writer unexpectedly ready");
2056*bb4ee6a4SAndroid Build Coastguard Worker         }
2057*bb4ee6a4SAndroid Build Coastguard Worker 
2058*bb4ee6a4SAndroid Build Coastguard Worker         let mut count = block_on(mu.lock());
2059*bb4ee6a4SAndroid Build Coastguard Worker         *count = 1;
2060*bb4ee6a4SAndroid Build Coastguard Worker 
2061*bb4ee6a4SAndroid Build Coastguard Worker         // This should wake all readers + one writer.
2062*bb4ee6a4SAndroid Build Coastguard Worker         cv.notify_one();
2063*bb4ee6a4SAndroid Build Coastguard Worker 
2064*bb4ee6a4SAndroid Build Coastguard Worker         // Poll the readers and the writer so they add themselves to the rwlock's waiter list.
2065*bb4ee6a4SAndroid Build Coastguard Worker         for r in &mut readers {
2066*bb4ee6a4SAndroid Build Coastguard Worker             if r.as_mut().poll(&mut cx).is_ready() {
2067*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("reader unexpectedly ready");
2068*bb4ee6a4SAndroid Build Coastguard Worker             }
2069*bb4ee6a4SAndroid Build Coastguard Worker         }
2070*bb4ee6a4SAndroid Build Coastguard Worker 
2071*bb4ee6a4SAndroid Build Coastguard Worker         if writer.as_mut().poll(&mut cx).is_ready() {
2072*bb4ee6a4SAndroid Build Coastguard Worker             panic!("writer unexpectedly ready");
2073*bb4ee6a4SAndroid Build Coastguard Worker         }
2074*bb4ee6a4SAndroid Build Coastguard Worker 
2075*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2076*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & HAS_WAITERS,
2077*bb4ee6a4SAndroid Build Coastguard Worker             HAS_WAITERS
2078*bb4ee6a4SAndroid Build Coastguard Worker         );
2079*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2080*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & WRITER_WAITING,
2081*bb4ee6a4SAndroid Build Coastguard Worker             WRITER_WAITING
2082*bb4ee6a4SAndroid Build Coastguard Worker         );
2083*bb4ee6a4SAndroid Build Coastguard Worker 
2084*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(count);
2085*bb4ee6a4SAndroid Build Coastguard Worker 
2086*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2087*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & (HAS_WAITERS | WRITER_WAITING),
2088*bb4ee6a4SAndroid Build Coastguard Worker             HAS_WAITERS | WRITER_WAITING
2089*bb4ee6a4SAndroid Build Coastguard Worker         );
2090*bb4ee6a4SAndroid Build Coastguard Worker 
2091*bb4ee6a4SAndroid Build Coastguard Worker         for r in &mut readers {
2092*bb4ee6a4SAndroid Build Coastguard Worker             if r.as_mut().poll(&mut cx).is_pending() {
2093*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("reader unable to complete");
2094*bb4ee6a4SAndroid Build Coastguard Worker             }
2095*bb4ee6a4SAndroid Build Coastguard Worker         }
2096*bb4ee6a4SAndroid Build Coastguard Worker 
2097*bb4ee6a4SAndroid Build Coastguard Worker         if writer.as_mut().poll(&mut cx).is_pending() {
2098*bb4ee6a4SAndroid Build Coastguard Worker             panic!("writer unable to complete");
2099*bb4ee6a4SAndroid Build Coastguard Worker         }
2100*bb4ee6a4SAndroid Build Coastguard Worker 
2101*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.read_lock()), 0);
2102*bb4ee6a4SAndroid Build Coastguard Worker     }
2103*bb4ee6a4SAndroid Build Coastguard Worker 
2104*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
notify_when_unlocked()2105*bb4ee6a4SAndroid Build Coastguard Worker     fn notify_when_unlocked() {
2106*bb4ee6a4SAndroid Build Coastguard Worker         async fn dec(mu: Arc<RwLock<usize>>, cv: Arc<Condvar>) {
2107*bb4ee6a4SAndroid Build Coastguard Worker             let mut count = mu.lock().await;
2108*bb4ee6a4SAndroid Build Coastguard Worker 
2109*bb4ee6a4SAndroid Build Coastguard Worker             while *count == 0 {
2110*bb4ee6a4SAndroid Build Coastguard Worker                 count = cv.wait(count).await;
2111*bb4ee6a4SAndroid Build Coastguard Worker             }
2112*bb4ee6a4SAndroid Build Coastguard Worker 
2113*bb4ee6a4SAndroid Build Coastguard Worker             *count -= 1;
2114*bb4ee6a4SAndroid Build Coastguard Worker         }
2115*bb4ee6a4SAndroid Build Coastguard Worker 
2116*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0));
2117*bb4ee6a4SAndroid Build Coastguard Worker         let cv = Arc::new(Condvar::new());
2118*bb4ee6a4SAndroid Build Coastguard Worker 
2119*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
2120*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
2121*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
2122*bb4ee6a4SAndroid Build Coastguard Worker 
2123*bb4ee6a4SAndroid Build Coastguard Worker         let mut futures = [
2124*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(dec(mu.clone(), cv.clone())),
2125*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(dec(mu.clone(), cv.clone())),
2126*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(dec(mu.clone(), cv.clone())),
2127*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(dec(mu.clone(), cv.clone())),
2128*bb4ee6a4SAndroid Build Coastguard Worker         ];
2129*bb4ee6a4SAndroid Build Coastguard Worker 
2130*bb4ee6a4SAndroid Build Coastguard Worker         for f in &mut futures {
2131*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = f.as_mut().poll(&mut cx) {
2132*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("future unexpectedly ready");
2133*bb4ee6a4SAndroid Build Coastguard Worker             }
2134*bb4ee6a4SAndroid Build Coastguard Worker         }
2135*bb4ee6a4SAndroid Build Coastguard Worker 
2136*bb4ee6a4SAndroid Build Coastguard Worker         *block_on(mu.lock()) = futures.len();
2137*bb4ee6a4SAndroid Build Coastguard Worker         cv.notify_all();
2138*bb4ee6a4SAndroid Build Coastguard Worker 
2139*bb4ee6a4SAndroid Build Coastguard Worker         // Since we haven't polled `futures` yet, the rwlock should not have any waiters.
2140*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed) & HAS_WAITERS, 0);
2141*bb4ee6a4SAndroid Build Coastguard Worker 
2142*bb4ee6a4SAndroid Build Coastguard Worker         for f in &mut futures {
2143*bb4ee6a4SAndroid Build Coastguard Worker             if f.as_mut().poll(&mut cx).is_pending() {
2144*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("future unexpectedly ready");
2145*bb4ee6a4SAndroid Build Coastguard Worker             }
2146*bb4ee6a4SAndroid Build Coastguard Worker         }
2147*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
2148*bb4ee6a4SAndroid Build Coastguard Worker     }
2149*bb4ee6a4SAndroid Build Coastguard Worker 
2150*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
notify_reader_writer()2151*bb4ee6a4SAndroid Build Coastguard Worker     fn notify_reader_writer() {
2152*bb4ee6a4SAndroid Build Coastguard Worker         async fn read(mu: Arc<RwLock<usize>>, cv: Arc<Condvar>) {
2153*bb4ee6a4SAndroid Build Coastguard Worker             let mut count = mu.read_lock().await;
2154*bb4ee6a4SAndroid Build Coastguard Worker             while *count == 0 {
2155*bb4ee6a4SAndroid Build Coastguard Worker                 count = cv.wait_read(count).await;
2156*bb4ee6a4SAndroid Build Coastguard Worker             }
2157*bb4ee6a4SAndroid Build Coastguard Worker 
2158*bb4ee6a4SAndroid Build Coastguard Worker             // Yield once while holding the read lock, which should prevent the writer from waking
2159*bb4ee6a4SAndroid Build Coastguard Worker             // up.
2160*bb4ee6a4SAndroid Build Coastguard Worker             pending!();
2161*bb4ee6a4SAndroid Build Coastguard Worker         }
2162*bb4ee6a4SAndroid Build Coastguard Worker 
2163*bb4ee6a4SAndroid Build Coastguard Worker         async fn write(mu: Arc<RwLock<usize>>, cv: Arc<Condvar>) {
2164*bb4ee6a4SAndroid Build Coastguard Worker             let mut count = mu.lock().await;
2165*bb4ee6a4SAndroid Build Coastguard Worker             while *count == 0 {
2166*bb4ee6a4SAndroid Build Coastguard Worker                 count = cv.wait(count).await;
2167*bb4ee6a4SAndroid Build Coastguard Worker             }
2168*bb4ee6a4SAndroid Build Coastguard Worker 
2169*bb4ee6a4SAndroid Build Coastguard Worker             *count -= 1;
2170*bb4ee6a4SAndroid Build Coastguard Worker         }
2171*bb4ee6a4SAndroid Build Coastguard Worker 
2172*bb4ee6a4SAndroid Build Coastguard Worker         async fn lock(mu: Arc<RwLock<usize>>) {
2173*bb4ee6a4SAndroid Build Coastguard Worker             mem::drop(mu.lock().await);
2174*bb4ee6a4SAndroid Build Coastguard Worker         }
2175*bb4ee6a4SAndroid Build Coastguard Worker 
2176*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0));
2177*bb4ee6a4SAndroid Build Coastguard Worker         let cv = Arc::new(Condvar::new());
2178*bb4ee6a4SAndroid Build Coastguard Worker 
2179*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
2180*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
2181*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
2182*bb4ee6a4SAndroid Build Coastguard Worker 
2183*bb4ee6a4SAndroid Build Coastguard Worker         let mut futures: [Pin<Box<dyn Future<Output = ()>>>; 5] = [
2184*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2185*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2186*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2187*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(write(mu.clone(), cv.clone())),
2188*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2189*bb4ee6a4SAndroid Build Coastguard Worker         ];
2190*bb4ee6a4SAndroid Build Coastguard Worker         const NUM_READERS: usize = 4;
2191*bb4ee6a4SAndroid Build Coastguard Worker 
2192*bb4ee6a4SAndroid Build Coastguard Worker         let mut l = Box::pin(lock(mu.clone()));
2193*bb4ee6a4SAndroid Build Coastguard Worker 
2194*bb4ee6a4SAndroid Build Coastguard Worker         for f in &mut futures {
2195*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = f.as_mut().poll(&mut cx) {
2196*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("future unexpectedly ready");
2197*bb4ee6a4SAndroid Build Coastguard Worker             }
2198*bb4ee6a4SAndroid Build Coastguard Worker         }
2199*bb4ee6a4SAndroid Build Coastguard Worker 
2200*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
2201*bb4ee6a4SAndroid Build Coastguard Worker 
2202*bb4ee6a4SAndroid Build Coastguard Worker         let mut count = block_on(mu.lock());
2203*bb4ee6a4SAndroid Build Coastguard Worker         *count = 1;
2204*bb4ee6a4SAndroid Build Coastguard Worker 
2205*bb4ee6a4SAndroid Build Coastguard Worker         // Now poll the lock function. Since the lock is held by us, it will get queued on the
2206*bb4ee6a4SAndroid Build Coastguard Worker         // waiter list.
2207*bb4ee6a4SAndroid Build Coastguard Worker         if let Poll::Ready(()) = l.as_mut().poll(&mut cx) {
2208*bb4ee6a4SAndroid Build Coastguard Worker             panic!("lock() unexpectedly ready");
2209*bb4ee6a4SAndroid Build Coastguard Worker         }
2210*bb4ee6a4SAndroid Build Coastguard Worker 
2211*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2212*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & (HAS_WAITERS | WRITER_WAITING),
2213*bb4ee6a4SAndroid Build Coastguard Worker             HAS_WAITERS | WRITER_WAITING
2214*bb4ee6a4SAndroid Build Coastguard Worker         );
2215*bb4ee6a4SAndroid Build Coastguard Worker 
2216*bb4ee6a4SAndroid Build Coastguard Worker         // Wake up waiters while holding the lock.
2217*bb4ee6a4SAndroid Build Coastguard Worker         cv.notify_all();
2218*bb4ee6a4SAndroid Build Coastguard Worker 
2219*bb4ee6a4SAndroid Build Coastguard Worker         // Drop the lock.  This should wake up the lock function.
2220*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(count);
2221*bb4ee6a4SAndroid Build Coastguard Worker 
2222*bb4ee6a4SAndroid Build Coastguard Worker         if l.as_mut().poll(&mut cx).is_pending() {
2223*bb4ee6a4SAndroid Build Coastguard Worker             panic!("lock() unable to complete");
2224*bb4ee6a4SAndroid Build Coastguard Worker         }
2225*bb4ee6a4SAndroid Build Coastguard Worker 
2226*bb4ee6a4SAndroid Build Coastguard Worker         // Since we haven't polled `futures` yet, the rwlock state should now be empty.
2227*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
2228*bb4ee6a4SAndroid Build Coastguard Worker 
2229*bb4ee6a4SAndroid Build Coastguard Worker         // Poll everything again. The readers should be able to make progress (but not complete) but
2230*bb4ee6a4SAndroid Build Coastguard Worker         // the writer should be blocked.
2231*bb4ee6a4SAndroid Build Coastguard Worker         for f in &mut futures {
2232*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = f.as_mut().poll(&mut cx) {
2233*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("future unexpectedly ready");
2234*bb4ee6a4SAndroid Build Coastguard Worker             }
2235*bb4ee6a4SAndroid Build Coastguard Worker         }
2236*bb4ee6a4SAndroid Build Coastguard Worker 
2237*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2238*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & READ_MASK,
2239*bb4ee6a4SAndroid Build Coastguard Worker             READ_LOCK * NUM_READERS
2240*bb4ee6a4SAndroid Build Coastguard Worker         );
2241*bb4ee6a4SAndroid Build Coastguard Worker 
2242*bb4ee6a4SAndroid Build Coastguard Worker         // All the readers can now finish but the writer needs to be polled again.
2243*bb4ee6a4SAndroid Build Coastguard Worker         let mut needs_poll = None;
2244*bb4ee6a4SAndroid Build Coastguard Worker         for (i, r) in futures.iter_mut().enumerate() {
2245*bb4ee6a4SAndroid Build Coastguard Worker             match r.as_mut().poll(&mut cx) {
2246*bb4ee6a4SAndroid Build Coastguard Worker                 Poll::Ready(()) => {}
2247*bb4ee6a4SAndroid Build Coastguard Worker                 Poll::Pending => {
2248*bb4ee6a4SAndroid Build Coastguard Worker                     if needs_poll.is_some() {
2249*bb4ee6a4SAndroid Build Coastguard Worker                         panic!("More than one future unable to complete");
2250*bb4ee6a4SAndroid Build Coastguard Worker                     }
2251*bb4ee6a4SAndroid Build Coastguard Worker                     needs_poll = Some(i);
2252*bb4ee6a4SAndroid Build Coastguard Worker                 }
2253*bb4ee6a4SAndroid Build Coastguard Worker             }
2254*bb4ee6a4SAndroid Build Coastguard Worker         }
2255*bb4ee6a4SAndroid Build Coastguard Worker 
2256*bb4ee6a4SAndroid Build Coastguard Worker         if futures[needs_poll.expect("Writer unexpectedly able to complete")]
2257*bb4ee6a4SAndroid Build Coastguard Worker             .as_mut()
2258*bb4ee6a4SAndroid Build Coastguard Worker             .poll(&mut cx)
2259*bb4ee6a4SAndroid Build Coastguard Worker             .is_pending()
2260*bb4ee6a4SAndroid Build Coastguard Worker         {
2261*bb4ee6a4SAndroid Build Coastguard Worker             panic!("Writer unable to complete");
2262*bb4ee6a4SAndroid Build Coastguard Worker         }
2263*bb4ee6a4SAndroid Build Coastguard Worker 
2264*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*block_on(mu.lock()), 0);
2265*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
2266*bb4ee6a4SAndroid Build Coastguard Worker     }
2267*bb4ee6a4SAndroid Build Coastguard Worker 
2268*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
notify_readers_with_read_lock()2269*bb4ee6a4SAndroid Build Coastguard Worker     fn notify_readers_with_read_lock() {
2270*bb4ee6a4SAndroid Build Coastguard Worker         async fn read(mu: Arc<RwLock<usize>>, cv: Arc<Condvar>) {
2271*bb4ee6a4SAndroid Build Coastguard Worker             let mut count = mu.read_lock().await;
2272*bb4ee6a4SAndroid Build Coastguard Worker             while *count == 0 {
2273*bb4ee6a4SAndroid Build Coastguard Worker                 count = cv.wait_read(count).await;
2274*bb4ee6a4SAndroid Build Coastguard Worker             }
2275*bb4ee6a4SAndroid Build Coastguard Worker 
2276*bb4ee6a4SAndroid Build Coastguard Worker             // Yield once while holding the read lock.
2277*bb4ee6a4SAndroid Build Coastguard Worker             pending!();
2278*bb4ee6a4SAndroid Build Coastguard Worker         }
2279*bb4ee6a4SAndroid Build Coastguard Worker 
2280*bb4ee6a4SAndroid Build Coastguard Worker         let mu = Arc::new(RwLock::new(0));
2281*bb4ee6a4SAndroid Build Coastguard Worker         let cv = Arc::new(Condvar::new());
2282*bb4ee6a4SAndroid Build Coastguard Worker 
2283*bb4ee6a4SAndroid Build Coastguard Worker         let arc_waker = Arc::new(TestWaker);
2284*bb4ee6a4SAndroid Build Coastguard Worker         let waker = waker_ref(&arc_waker);
2285*bb4ee6a4SAndroid Build Coastguard Worker         let mut cx = Context::from_waker(&waker);
2286*bb4ee6a4SAndroid Build Coastguard Worker 
2287*bb4ee6a4SAndroid Build Coastguard Worker         let mut futures = [
2288*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2289*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2290*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2291*bb4ee6a4SAndroid Build Coastguard Worker             Box::pin(read(mu.clone(), cv.clone())),
2292*bb4ee6a4SAndroid Build Coastguard Worker         ];
2293*bb4ee6a4SAndroid Build Coastguard Worker 
2294*bb4ee6a4SAndroid Build Coastguard Worker         for f in &mut futures {
2295*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = f.as_mut().poll(&mut cx) {
2296*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("future unexpectedly ready");
2297*bb4ee6a4SAndroid Build Coastguard Worker             }
2298*bb4ee6a4SAndroid Build Coastguard Worker         }
2299*bb4ee6a4SAndroid Build Coastguard Worker 
2300*bb4ee6a4SAndroid Build Coastguard Worker         // Increment the count and then grab a read lock.
2301*bb4ee6a4SAndroid Build Coastguard Worker         *block_on(mu.lock()) = 1;
2302*bb4ee6a4SAndroid Build Coastguard Worker 
2303*bb4ee6a4SAndroid Build Coastguard Worker         let g = block_on(mu.read_lock());
2304*bb4ee6a4SAndroid Build Coastguard Worker 
2305*bb4ee6a4SAndroid Build Coastguard Worker         // Notify the condvar while holding the read lock. This should wake up all the waiters.
2306*bb4ee6a4SAndroid Build Coastguard Worker         cv.notify_all();
2307*bb4ee6a4SAndroid Build Coastguard Worker 
2308*bb4ee6a4SAndroid Build Coastguard Worker         // Since the lock is held in shared mode, all the readers should immediately be able to
2309*bb4ee6a4SAndroid Build Coastguard Worker         // acquire the read lock.
2310*bb4ee6a4SAndroid Build Coastguard Worker         for f in &mut futures {
2311*bb4ee6a4SAndroid Build Coastguard Worker             if let Poll::Ready(()) = f.as_mut().poll(&mut cx) {
2312*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("future unexpectedly ready");
2313*bb4ee6a4SAndroid Build Coastguard Worker             }
2314*bb4ee6a4SAndroid Build Coastguard Worker         }
2315*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed) & HAS_WAITERS, 0);
2316*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
2317*bb4ee6a4SAndroid Build Coastguard Worker             mu.raw.state.load(Ordering::Relaxed) & READ_MASK,
2318*bb4ee6a4SAndroid Build Coastguard Worker             READ_LOCK * (futures.len() + 1)
2319*bb4ee6a4SAndroid Build Coastguard Worker         );
2320*bb4ee6a4SAndroid Build Coastguard Worker 
2321*bb4ee6a4SAndroid Build Coastguard Worker         mem::drop(g);
2322*bb4ee6a4SAndroid Build Coastguard Worker 
2323*bb4ee6a4SAndroid Build Coastguard Worker         for f in &mut futures {
2324*bb4ee6a4SAndroid Build Coastguard Worker             if f.as_mut().poll(&mut cx).is_pending() {
2325*bb4ee6a4SAndroid Build Coastguard Worker                 panic!("future unable to complete");
2326*bb4ee6a4SAndroid Build Coastguard Worker             }
2327*bb4ee6a4SAndroid Build Coastguard Worker         }
2328*bb4ee6a4SAndroid Build Coastguard Worker 
2329*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(mu.raw.state.load(Ordering::Relaxed), 0);
2330*bb4ee6a4SAndroid Build Coastguard Worker     }
2331*bb4ee6a4SAndroid Build Coastguard Worker }
2332