Skip to main content

parking_lot/
raw_rwlock.rs

1use crate::{
2    deadlock,
3    raw_mutex::{TOKEN_HANDOFF, TOKEN_NORMAL},
4    util,
5};
6use core::{
7    cell::Cell,
8    sync::atomic::{AtomicUsize, Ordering},
9};
10use lock_api::{RawRwLock as RawRwLock_, RawRwLockUpgrade};
11use parking_lot_core::{
12    self, FilterOp, ParkResult, ParkToken, SpinWait, UnparkResult, UnparkToken,
13};
14use std::time::{Duration, Instant};
15
16// This reader-writer lock implementation is based on Boost's upgrade_mutex:
17// https://github.com/boostorg/thread/blob/fc08c1fe2840baeeee143440fba31ef9e9a813c8/include/boost/thread/v2/shared_mutex.hpp#L432
18//
19// This implementation uses 2 wait queues. The primary queue at key [addr] is
20// used for all new waiting threads. The secondary queue at key [addr + 1] is
21// used by the thread which has acquired WRITER_BIT but is waiting for the
22// remaining readers to exit the lock.
23//
24// In nonrecursive mode, readers block behind a pending writer. Recursive mode
25// admits new readers while other readers hold the lock, which can starve
26// writers.
27
28// There is at least one thread in the main queue.
29const PARKED_BIT: usize = 0b0001;
30// There is a parked thread holding WRITER_BIT. WRITER_BIT must be set.
31const WRITER_PARKED_BIT: usize = 0b0010;
32// A reader is holding an upgradable lock. The reader count must be non-zero and
33// WRITER_BIT must not be set.
34const UPGRADABLE_BIT: usize = 0b0100;
35// If the reader count is zero: a writer is currently holding an exclusive lock.
36// Otherwise: a writer is waiting for the remaining readers to exit the lock.
37const WRITER_BIT: usize = 0b1000;
38// Mask of bits used to count readers.
39const READERS_MASK: usize = !0b1111;
40// Base unit for counting readers.
41const ONE_READER: usize = 0b10000;
42
43// Token indicating what type of lock a queued thread is trying to acquire
44const TOKEN_SHARED: ParkToken = ParkToken(ONE_READER);
45const TOKEN_EXCLUSIVE: ParkToken = ParkToken(WRITER_BIT);
46const TOKEN_UPGRADABLE: ParkToken = ParkToken(ONE_READER | UPGRADABLE_BIT);
47
48/// Raw reader-writer lock type backed by the parking lot.
49///
50/// If `RECURSIVE` is `true`, readers are prioritized over writers: acquiring a
51/// read lock is guaranteed not to block unless a writer currently holds the
52/// lock. This permits recursive read locking, but may starve writers.
53pub struct RawRwLock<const RECURSIVE: bool = false> {
54    state: AtomicUsize,
55}
56
57/// Raw reader-writer lock which permits recursive read locking.
58pub type RawRwLockRecursive = RawRwLock<true>;
59
60unsafe impl<const RECURSIVE: bool> lock_api::RawRwLock for RawRwLock<RECURSIVE> {
61    const INIT: Self = Self {
62        state: AtomicUsize::new(0),
63    };
64
65    type SharedGuard = crate::GuardMarker;
66    type ExclusiveGuard = crate::GuardMarker;
67
68    #[inline]
69    fn lock_exclusive(&self) -> Self::ExclusiveGuard {
70        if self
71            .state
72            .compare_exchange_weak(0, WRITER_BIT, Ordering::Acquire, Ordering::Relaxed)
73            .is_ok()
74        {
75            self.deadlock_acquire_all();
76            Self::ExclusiveGuard::new()
77        } else {
78            self.lock_exclusive_slow(None).unwrap()
79        }
80    }
81
82    #[inline]
83    fn try_lock_exclusive(&self) -> Option<Self::ExclusiveGuard> {
84        self.state
85            .compare_exchange(0, WRITER_BIT, Ordering::Acquire, Ordering::Relaxed)
86            .ok()?;
87        self.deadlock_acquire_all();
88        Some(Self::ExclusiveGuard::new())
89    }
90
91    #[inline]
92    unsafe fn unlock_exclusive(&self, _guard: Self::ExclusiveGuard) {
93        self.deadlock_release_all();
94        let state = self.state.fetch_sub(WRITER_BIT, Ordering::Release);
95        if state & PARKED_BIT != 0 {
96            self.unlock_exclusive_or_upgradable_slow();
97        }
98    }
99
100    #[inline]
101    fn lock_shared(&self) -> Self::SharedGuard {
102        let guard = self
103            .try_lock_shared_fast()
104            .unwrap_or_else(|| self.lock_shared_slow(None).unwrap());
105        self.deadlock_acquire_secondary();
106        guard
107    }
108
109    #[inline]
110    fn try_lock_shared(&self) -> Option<Self::SharedGuard> {
111        let guard = self
112            .try_lock_shared_fast()
113            .or_else(|| self.try_lock_shared_slow())?;
114        self.deadlock_acquire_secondary();
115        Some(guard)
116    }
117
118    #[inline]
119    unsafe fn unlock_shared(&self, _guard: Self::SharedGuard) {
120        self.deadlock_release_secondary();
121        let state = self.state.fetch_sub(ONE_READER, Ordering::Release);
122        if state & (READERS_MASK | WRITER_PARKED_BIT) == (ONE_READER | WRITER_PARKED_BIT) {
123            self.unlock_shared_slow();
124        }
125    }
126
127    #[inline]
128    fn is_locked(&self) -> bool {
129        let state = self.state.load(Ordering::Relaxed);
130        state & (WRITER_BIT | READERS_MASK) != 0
131    }
132
133    #[inline]
134    fn is_locked_exclusive(&self) -> bool {
135        let state = self.state.load(Ordering::Relaxed);
136        state & (WRITER_BIT | READERS_MASK) == WRITER_BIT
137    }
138}
139
140unsafe impl<const RECURSIVE: bool> lock_api::RawRwLockFair for RawRwLock<RECURSIVE> {
141    #[inline]
142    unsafe fn unlock_shared_fair(&self, guard: Self::SharedGuard) {
143        // Shared unlocking is always fair in this implementation.
144        unsafe { self.unlock_shared(guard) };
145    }
146
147    #[inline]
148    unsafe fn unlock_exclusive_fair(&self, _guard: Self::ExclusiveGuard) {
149        self.deadlock_release_all();
150        if self
151            .state
152            .compare_exchange(WRITER_BIT, 0, Ordering::Release, Ordering::Relaxed)
153            .is_ok()
154        {
155            return;
156        }
157        self.unlock_exclusive_fair_slow();
158    }
159
160    #[inline]
161    unsafe fn bump_shared(&self, _guard: &mut Self::SharedGuard) {
162        let state = self.state.load(Ordering::Relaxed);
163        if state & WRITER_BIT != 0 && (!RECURSIVE || state & READERS_MASK == ONE_READER) {
164            unsafe { self.bump_shared_slow() };
165        }
166    }
167
168    #[inline]
169    unsafe fn bump_exclusive(&self, _guard: &mut Self::ExclusiveGuard) {
170        if self.state.load(Ordering::Relaxed) & PARKED_BIT != 0 {
171            self.bump_exclusive_slow();
172        }
173    }
174}
175
176unsafe impl<const RECURSIVE: bool> lock_api::RawRwLockDowngrade for RawRwLock<RECURSIVE> {
177    #[inline]
178    unsafe fn downgrade(&self, guard: Self::ExclusiveGuard) -> Self::SharedGuard {
179        self.deadlock_release_primary();
180        let state = self
181            .state
182            .fetch_add(ONE_READER - WRITER_BIT, Ordering::Release);
183
184        // Wake up parked shared and upgradable threads if there are any
185        if state & PARKED_BIT != 0 {
186            self.downgrade_slow();
187        }
188        guard
189    }
190}
191
192unsafe impl<const RECURSIVE: bool> lock_api::RawRwLockTimed for RawRwLock<RECURSIVE> {
193    type Duration = Duration;
194    type Instant = Instant;
195
196    #[inline]
197    fn try_lock_shared_for(&self, timeout: Self::Duration) -> Option<Self::SharedGuard> {
198        let guard = self
199            .try_lock_shared_fast()
200            .or_else(|| self.lock_shared_slow(util::to_deadline(timeout)))?;
201        self.deadlock_acquire_secondary();
202        Some(guard)
203    }
204
205    #[inline]
206    fn try_lock_shared_until(&self, timeout: Self::Instant) -> Option<Self::SharedGuard> {
207        let guard = self
208            .try_lock_shared_fast()
209            .or_else(|| self.lock_shared_slow(Some(timeout)))?;
210        self.deadlock_acquire_secondary();
211        Some(guard)
212    }
213
214    #[inline]
215    fn try_lock_exclusive_for(&self, timeout: Duration) -> Option<Self::ExclusiveGuard> {
216        if self
217            .state
218            .compare_exchange_weak(0, WRITER_BIT, Ordering::Acquire, Ordering::Relaxed)
219            .is_ok()
220        {
221            self.deadlock_acquire_all();
222            Some(Self::ExclusiveGuard::new())
223        } else {
224            self.lock_exclusive_slow(util::to_deadline(timeout))
225        }
226    }
227
228    #[inline]
229    fn try_lock_exclusive_until(&self, timeout: Instant) -> Option<Self::ExclusiveGuard> {
230        if self
231            .state
232            .compare_exchange_weak(0, WRITER_BIT, Ordering::Acquire, Ordering::Relaxed)
233            .is_ok()
234        {
235            self.deadlock_acquire_all();
236            Some(Self::ExclusiveGuard::new())
237        } else {
238            self.lock_exclusive_slow(Some(timeout))
239        }
240    }
241}
242
243unsafe impl<const RECURSIVE: bool> lock_api::RawRwLockUpgrade for RawRwLock<RECURSIVE> {
244    type UpgradableGuard = crate::GuardMarker;
245    #[inline]
246    fn lock_upgradable(&self) -> Self::UpgradableGuard {
247        let guard = self
248            .try_lock_upgradable_fast()
249            .unwrap_or_else(|| self.lock_upgradable_slow(None).unwrap());
250        self.deadlock_acquire_all();
251        guard
252    }
253
254    #[inline]
255    fn try_lock_upgradable(&self) -> Option<Self::UpgradableGuard> {
256        let guard = self
257            .try_lock_upgradable_fast()
258            .or_else(|| self.try_lock_upgradable_slow())?;
259        self.deadlock_acquire_all();
260        Some(guard)
261    }
262
263    #[inline]
264    unsafe fn unlock_upgradable(&self, _guard: Self::UpgradableGuard) {
265        self.deadlock_release_all();
266        let state = self
267            .state
268            .fetch_sub(ONE_READER | UPGRADABLE_BIT, Ordering::Release);
269        if state & PARKED_BIT != 0 {
270            self.unlock_exclusive_or_upgradable_slow();
271        }
272    }
273
274    #[inline]
275    unsafe fn upgrade(&self, guard: Self::UpgradableGuard) -> Self::ExclusiveGuard {
276        // Stop owning the reader stage before replacing it with WRITER_BIT.
277        self.deadlock_release_secondary();
278        let state = self.state.fetch_sub(
279            (ONE_READER | UPGRADABLE_BIT) - WRITER_BIT,
280            Ordering::Acquire,
281        );
282        if state & READERS_MASK != ONE_READER {
283            self.upgrade_slow(guard, None)
284                .unwrap_or_else(|_| ::core::panicking::unreachable_default_msg()unreachable!())
285        } else {
286            self.deadlock_acquire_secondary();
287            guard
288        }
289    }
290
291    #[inline]
292    unsafe fn try_upgrade(
293        &self,
294        guard: Self::UpgradableGuard,
295    ) -> Result<Self::ExclusiveGuard, Self::UpgradableGuard> {
296        if self
297            .state
298            .compare_exchange_weak(
299                ONE_READER | UPGRADABLE_BIT,
300                WRITER_BIT,
301                Ordering::Acquire,
302                Ordering::Relaxed,
303            )
304            .is_ok()
305        {
306            Ok(guard)
307        } else {
308            self.try_upgrade_slow(guard)
309        }
310    }
311}
312
313unsafe impl<const RECURSIVE: bool> lock_api::RawRwLockUpgradeFair for RawRwLock<RECURSIVE> {
314    #[inline]
315    unsafe fn unlock_upgradable_fair(&self, _guard: Self::UpgradableGuard) {
316        self.deadlock_release_all();
317        let state = self.state.load(Ordering::Relaxed);
318        #[allow(clippy::collapsible_if)]
319        if state & PARKED_BIT == 0 {
320            if self
321                .state
322                .compare_exchange_weak(
323                    state,
324                    state - (ONE_READER | UPGRADABLE_BIT),
325                    Ordering::Release,
326                    Ordering::Relaxed,
327                )
328                .is_ok()
329            {
330                return;
331            }
332        }
333        self.unlock_upgradable_fair_slow();
334    }
335
336    #[inline]
337    unsafe fn bump_upgradable(&self, _guard: &mut Self::UpgradableGuard) {
338        if self.state.load(Ordering::Relaxed) & PARKED_BIT != 0 {
339            self.bump_upgradable_slow();
340        }
341    }
342}
343
344unsafe impl<const RECURSIVE: bool> lock_api::RawRwLockUpgradeDowngrade for RawRwLock<RECURSIVE> {
345    #[inline]
346    unsafe fn downgrade_upgradable(&self, guard: Self::UpgradableGuard) -> Self::SharedGuard {
347        self.deadlock_release_primary();
348        let state = self.state.fetch_sub(UPGRADABLE_BIT, Ordering::Relaxed);
349
350        // Wake up parked upgradable threads if there are any
351        if state & PARKED_BIT != 0 {
352            self.downgrade_slow();
353        }
354        guard
355    }
356
357    #[inline]
358    unsafe fn downgrade_to_upgradable(&self, guard: Self::ExclusiveGuard) -> Self::UpgradableGuard {
359        let state = self.state.fetch_add(
360            (ONE_READER | UPGRADABLE_BIT) - WRITER_BIT,
361            Ordering::Release,
362        );
363
364        // Wake up parked shared threads if there are any
365        if state & PARKED_BIT != 0 {
366            self.downgrade_to_upgradable_slow();
367        }
368        guard
369    }
370}
371
372unsafe impl<const RECURSIVE: bool> lock_api::RawRwLockUpgradeTimed for RawRwLock<RECURSIVE> {
373    #[inline]
374    fn try_lock_upgradable_until(&self, timeout: Instant) -> Option<Self::UpgradableGuard> {
375        let guard = self
376            .try_lock_upgradable_fast()
377            .or_else(|| self.lock_upgradable_slow(Some(timeout)))?;
378        self.deadlock_acquire_all();
379        Some(guard)
380    }
381
382    #[inline]
383    fn try_lock_upgradable_for(&self, timeout: Duration) -> Option<Self::UpgradableGuard> {
384        let guard = self
385            .try_lock_upgradable_fast()
386            .or_else(|| self.lock_upgradable_slow(util::to_deadline(timeout)))?;
387        self.deadlock_acquire_all();
388        Some(guard)
389    }
390
391    #[inline]
392    unsafe fn try_upgrade_until(
393        &self,
394        guard: Self::UpgradableGuard,
395        timeout: Instant,
396    ) -> Result<Self::ExclusiveGuard, Self::UpgradableGuard> {
397        // Stop owning the reader stage before replacing it with WRITER_BIT.
398        self.deadlock_release_secondary();
399        let state = self.state.fetch_sub(
400            (ONE_READER | UPGRADABLE_BIT) - WRITER_BIT,
401            Ordering::Acquire,
402        );
403        if state & READERS_MASK == ONE_READER {
404            self.deadlock_acquire_secondary();
405            Ok(guard)
406        } else {
407            self.upgrade_slow(guard, Some(timeout))
408        }
409    }
410
411    #[inline]
412    unsafe fn try_upgrade_for(
413        &self,
414        guard: Self::UpgradableGuard,
415        timeout: Duration,
416    ) -> Result<Self::ExclusiveGuard, Self::UpgradableGuard> {
417        // Stop owning the reader stage before replacing it with WRITER_BIT.
418        self.deadlock_release_secondary();
419        let state = self.state.fetch_sub(
420            (ONE_READER | UPGRADABLE_BIT) - WRITER_BIT,
421            Ordering::Acquire,
422        );
423        if state & READERS_MASK == ONE_READER {
424            self.deadlock_acquire_secondary();
425            Ok(guard)
426        } else {
427            self.upgrade_slow(guard, util::to_deadline(timeout))
428        }
429    }
430}
431
432impl<const RECURSIVE: bool> RawRwLock<RECURSIVE> {
433    #[inline(always)]
434    fn try_lock_shared_fast(&self) -> Option<crate::GuardMarker> {
435        let state = self.state.load(Ordering::Relaxed);
436
437        // Recursive readers may skip ahead of a pending writer while another
438        // reader still holds the lock.
439        if state & WRITER_BIT != 0 && (!RECURSIVE || state & READERS_MASK == 0) {
440            return None;
441        }
442
443        let new_state = state.checked_add(ONE_READER)?;
444        self.state
445            .compare_exchange_weak(state, new_state, Ordering::Acquire, Ordering::Relaxed)
446            .ok()?;
447        Some(crate::GuardMarker::new())
448    }
449
450    #[cold]
451    fn try_lock_shared_slow(&self) -> Option<crate::GuardMarker> {
452        self.state
453            .try_update(Ordering::Acquire, Ordering::Relaxed, |state| {
454                if state & WRITER_BIT != 0 && (!RECURSIVE || state & READERS_MASK == 0) {
455                    None
456                } else {
457                    Some(
458                        state
459                            .checked_add(ONE_READER)
460                            .expect("RwLock reader count overflow"),
461                    )
462                }
463            })
464            .ok()?;
465        Some(crate::GuardMarker::new())
466    }
467
468    #[inline(always)]
469    fn try_lock_upgradable_fast(&self) -> Option<crate::GuardMarker> {
470        let state = self.state.load(Ordering::Relaxed);
471
472        // We can't grab an upgradable lock if there is already a writer or
473        // upgradable reader.
474        if state & (WRITER_BIT | UPGRADABLE_BIT) != 0 {
475            return None;
476        }
477
478        let new_state = state.checked_add(ONE_READER | UPGRADABLE_BIT)?;
479        self.state
480            .compare_exchange_weak(state, new_state, Ordering::Acquire, Ordering::Relaxed)
481            .ok()?;
482        Some(crate::GuardMarker::new())
483    }
484
485    #[cold]
486    fn try_lock_upgradable_slow(&self) -> Option<crate::GuardMarker> {
487        self.state
488            .try_update(Ordering::Acquire, Ordering::Relaxed, |state| {
489                // This mirrors the condition in try_lock_upgradable_fast.
490                if state & (WRITER_BIT | UPGRADABLE_BIT) != 0 {
491                    None
492                } else {
493                    Some(
494                        state
495                            .checked_add(ONE_READER | UPGRADABLE_BIT)
496                            .expect("RwLock reader count overflow"),
497                    )
498                }
499            })
500            .ok()?;
501        Some(crate::GuardMarker::new())
502    }
503
504    #[cold]
505    fn lock_exclusive_slow(&self, timeout: Option<Instant>) -> Option<crate::GuardMarker> {
506        let try_lock = |state: &mut usize| {
507            loop {
508                if *state & (WRITER_BIT | UPGRADABLE_BIT) != 0 {
509                    return false;
510                }
511
512                // Grab WRITER_BIT if it isn't set, even if there are parked threads.
513                match self.state.compare_exchange_weak(
514                    *state,
515                    *state | WRITER_BIT,
516                    Ordering::Acquire,
517                    Ordering::Relaxed,
518                ) {
519                    Ok(_) => return true,
520                    Err(x) => *state = x,
521                }
522            }
523        };
524
525        // Step 1: grab exclusive ownership of WRITER_BIT
526        let timed_out = !self.lock_common(timeout, TOKEN_EXCLUSIVE, try_lock, |state| {
527            state & (WRITER_BIT | UPGRADABLE_BIT) != 0
528        });
529        if timed_out {
530            return None;
531        }
532
533        // WRITER_BIT prevents new writers and upgradable readers from
534        // acquiring the lock, so it represents ownership of the primary key.
535        self.deadlock_acquire_primary();
536
537        // Step 2: wait for all remaining readers to exit the lock.
538        if !self.wait_for_readers(timeout, 0) {
539            return None;
540        }
541        self.deadlock_acquire_secondary();
542        Some(crate::GuardMarker::new())
543    }
544
545    #[cold]
546    fn unlock_exclusive_or_upgradable_slow(&self) {
547        let callback = |_, result: UnparkResult| {
548            // Ownership has already been released. Preserve any reader count
549            // and ownership bits acquired while we were accessing the queue.
550            if !result.have_more_threads {
551                self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed);
552            }
553            TOKEN_NORMAL
554        };
555        // SAFETY: `callback` does not panic or call into any function of `parking_lot`.
556        unsafe {
557            self.wake_parked_threads(0, callback);
558        }
559    }
560
561    #[cold]
562    fn unlock_exclusive_fair_slow(&self) {
563        // There are threads to unpark. Try to unpark as many as we can.
564        let callback = |mut new_state, result: UnparkResult| {
565            // If we are using a fair unlock then we should keep the
566            // rwlock locked and hand it off to the unparked threads.
567            if result.unparked_threads != 0 {
568                if result.have_more_threads {
569                    new_state |= PARKED_BIT;
570                }
571                self.state.store(new_state, Ordering::Release);
572                TOKEN_HANDOFF
573            } else {
574                // Clear the parked bit if there are no more parked threads.
575                if result.have_more_threads {
576                    self.state.store(PARKED_BIT, Ordering::Release);
577                } else {
578                    self.state.store(0, Ordering::Release);
579                }
580                TOKEN_NORMAL
581            }
582        };
583        // SAFETY: `callback` does not panic or call into any function of `parking_lot`.
584        unsafe {
585            self.wake_parked_threads(0, callback);
586        }
587    }
588
589    #[cold]
590    fn lock_shared_slow(&self, timeout: Option<Instant>) -> Option<crate::GuardMarker> {
591        let try_lock = |state: &mut usize| {
592            let mut spinwait_shared = SpinWait::new();
593            loop {
594                if *state & WRITER_BIT != 0 && (!RECURSIVE || *state & READERS_MASK == 0) {
595                    return false;
596                }
597
598                if self
599                    .state
600                    .compare_exchange_weak(
601                        *state,
602                        state
603                            .checked_add(ONE_READER)
604                            .expect("RwLock reader count overflow"),
605                        Ordering::Acquire,
606                        Ordering::Relaxed,
607                    )
608                    .is_ok()
609                {
610                    return true;
611                }
612
613                // If there is high contention on the reader count then we want
614                // to leave some time between attempts to acquire the lock to
615                // let other threads make progress.
616                spinwait_shared.spin_no_yield();
617                *state = self.state.load(Ordering::Relaxed);
618            }
619        };
620        self.lock_common(timeout, TOKEN_SHARED, try_lock, |state| {
621            state & WRITER_BIT != 0 && (!RECURSIVE || state & READERS_MASK == 0)
622        })
623        .then_some(crate::GuardMarker::new())
624    }
625
626    #[cold]
627    fn unlock_shared_slow(&self) {
628        // At this point WRITER_PARKED_BIT is set and READER_MASK is empty. We
629        // just need to wake up a potentially sleeping pending writer.
630        // Using the 2nd key at addr + 1
631        let addr = core::ptr::from_ref(self).addr() + 1;
632        let callback = |_result: UnparkResult| {
633            // Clear the WRITER_PARKED_BIT here since there can only be one
634            // parked writer thread.
635            self.state.fetch_and(!WRITER_PARKED_BIT, Ordering::Relaxed);
636            TOKEN_NORMAL
637        };
638        // SAFETY:
639        //   * `addr` is an address we control.
640        //   * `callback` does not panic or call into any function of `parking_lot`.
641        unsafe {
642            parking_lot_core::unpark_one(addr, callback);
643        }
644    }
645
646    #[cold]
647    fn lock_upgradable_slow(&self, timeout: Option<Instant>) -> Option<crate::GuardMarker> {
648        let try_lock = |state: &mut usize| {
649            let mut spinwait_shared = SpinWait::new();
650            loop {
651                if *state & (WRITER_BIT | UPGRADABLE_BIT) != 0 {
652                    return false;
653                }
654
655                if self
656                    .state
657                    .compare_exchange_weak(
658                        *state,
659                        state
660                            .checked_add(ONE_READER | UPGRADABLE_BIT)
661                            .expect("RwLock reader count overflow"),
662                        Ordering::Acquire,
663                        Ordering::Relaxed,
664                    )
665                    .is_ok()
666                {
667                    return true;
668                }
669
670                // If there is high contention on the reader count then we want
671                // to leave some time between attempts to acquire the lock to
672                // let other threads make progress.
673                spinwait_shared.spin_no_yield();
674                *state = self.state.load(Ordering::Relaxed);
675            }
676        };
677        self.lock_common(timeout, TOKEN_UPGRADABLE, try_lock, |state| {
678            state & (WRITER_BIT | UPGRADABLE_BIT) != 0
679        })
680        .then_some(crate::GuardMarker::new())
681    }
682
683    #[cold]
684    fn unlock_upgradable_fair_slow(&self) {
685        // Just release the lock if there are no parked threads.
686        let mut state = self.state.load(Ordering::Relaxed);
687        while state & PARKED_BIT == 0 {
688            match self.state.compare_exchange_weak(
689                state,
690                state - (ONE_READER | UPGRADABLE_BIT),
691                Ordering::Release,
692                Ordering::Relaxed,
693            ) {
694                Ok(_) => return,
695                Err(x) => state = x,
696            }
697        }
698
699        // There are threads to unpark. Try to unpark as many as we can.
700        let callback = |new_state, result: UnparkResult| {
701            // If we are using a fair unlock then we should keep the
702            // rwlock locked and hand it off to the unparked threads.
703            let mut state = self.state.load(Ordering::Relaxed);
704            // Fall back to normal unpark on overflow. Panicking is
705            // not allowed in parking_lot callbacks.
706            while let Some(mut new_state) =
707                (state - (ONE_READER | UPGRADABLE_BIT)).checked_add(new_state)
708            {
709                if result.have_more_threads {
710                    new_state |= PARKED_BIT;
711                } else {
712                    new_state &= !PARKED_BIT;
713                }
714                match self.state.compare_exchange_weak(
715                    state,
716                    new_state,
717                    Ordering::Release,
718                    Ordering::Relaxed,
719                ) {
720                    Ok(_) => return TOKEN_HANDOFF,
721                    Err(x) => state = x,
722                }
723            }
724
725            // Otherwise just release the upgradable lock and update PARKED_BIT.
726            loop {
727                let mut new_state = state - (ONE_READER | UPGRADABLE_BIT);
728                if result.have_more_threads {
729                    new_state |= PARKED_BIT;
730                } else {
731                    new_state &= !PARKED_BIT;
732                }
733                match self.state.compare_exchange_weak(
734                    state,
735                    new_state,
736                    Ordering::Release,
737                    Ordering::Relaxed,
738                ) {
739                    Ok(_) => return TOKEN_NORMAL,
740                    Err(x) => state = x,
741                }
742            }
743        };
744        // SAFETY: `callback` does not panic or call into any function of `parking_lot`.
745        unsafe {
746            self.wake_parked_threads(0, callback);
747        }
748    }
749
750    #[cold]
751    fn try_upgrade_slow(
752        &self,
753        guard: crate::GuardMarker,
754    ) -> Result<crate::GuardMarker, crate::GuardMarker> {
755        match self
756            .state
757            .try_update(Ordering::Acquire, Ordering::Relaxed, |state| {
758                (state & READERS_MASK == ONE_READER)
759                    .then_some(state - (ONE_READER | UPGRADABLE_BIT) + WRITER_BIT)
760            }) {
761            Ok(_) => Ok(guard),
762            Err(_) => Err(guard),
763        }
764    }
765
766    #[cold]
767    fn upgrade_slow(
768        &self,
769        guard: crate::GuardMarker,
770        timeout: Option<Instant>,
771    ) -> Result<crate::GuardMarker, crate::GuardMarker> {
772        let result = self.wait_for_readers(timeout, ONE_READER | UPGRADABLE_BIT);
773        // We either acquired exclusive access or restored the upgradable read
774        // lock after timing out. Both states own the secondary key.
775        self.deadlock_acquire_secondary();
776        if result { Ok(guard) } else { Err(guard) }
777    }
778
779    #[cold]
780    fn downgrade_slow(&self) {
781        // We only reach this point if PARKED_BIT is set.
782        let callback = |_, result: UnparkResult| {
783            // Clear the parked bit if there no more parked threads
784            if !result.have_more_threads {
785                self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed);
786            }
787            TOKEN_NORMAL
788        };
789        // SAFETY: `callback` does not panic or call into any function of `parking_lot`.
790        unsafe {
791            self.wake_parked_threads(ONE_READER, callback);
792        }
793    }
794
795    #[cold]
796    fn downgrade_to_upgradable_slow(&self) {
797        // We only reach this point if PARKED_BIT is set.
798        let callback = |_, result: UnparkResult| {
799            // Clear the parked bit if there no more parked threads
800            if !result.have_more_threads {
801                self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed);
802            }
803            TOKEN_NORMAL
804        };
805        // SAFETY: `callback` does not panic or call into any function of `parking_lot`.
806        unsafe {
807            self.wake_parked_threads(ONE_READER | UPGRADABLE_BIT, callback);
808        }
809    }
810
811    #[cold]
812    unsafe fn bump_shared_slow(&self) {
813        unsafe { self.unlock_shared(crate::GuardMarker::new()) };
814        util::abort_on_panic(|| self.lock_shared());
815    }
816
817    #[cold]
818    fn bump_exclusive_slow(&self) {
819        self.deadlock_release_all();
820        self.unlock_exclusive_fair_slow();
821        self.lock_exclusive();
822    }
823
824    #[cold]
825    fn bump_upgradable_slow(&self) {
826        self.deadlock_release_all();
827        self.unlock_upgradable_fair_slow();
828        util::abort_on_panic(|| self.lock_upgradable());
829    }
830
831    /// Common code for waking up parked threads after releasing `WRITER_BIT` or
832    /// `UPGRADABLE_BIT`.
833    ///
834    /// # Safety
835    ///
836    /// `callback` must uphold the requirements of the `callback` parameter to
837    /// `parking_lot_core::unpark_filter`: it must not unwind or call any
838    /// parking-lot function.
839    #[inline]
840    unsafe fn wake_parked_threads(
841        &self,
842        new_state: usize,
843        callback: impl FnOnce(usize, UnparkResult) -> UnparkToken,
844    ) {
845        // We must wake up at least one upgrader or writer if there is one,
846        // otherwise they may end up parked indefinitely since unlock_shared
847        // does not call wake_parked_threads.
848        let new_state = Cell::new(new_state);
849        let addr = core::ptr::from_ref(self).addr();
850        let filter = |ParkToken(token)| {
851            let s = new_state.get();
852
853            // Normal rwlocks stop after selecting a writer. Recursive rwlocks
854            // must continue scanning for readers that may be needed for
855            // forward progress.
856            if !RECURSIVE && s & WRITER_BIT != 0 {
857                return FilterOp::Stop;
858            }
859
860            // Otherwise wake *all* readers and one upgrader/writer.
861            if token & (UPGRADABLE_BIT | WRITER_BIT) != 0 && s & (UPGRADABLE_BIT | WRITER_BIT) != 0
862            {
863                // Skip writers and upgradable readers if we already have
864                // a writer/upgradable reader.
865                FilterOp::Skip
866            } else {
867                new_state.set(s + token);
868                FilterOp::Unpark
869            }
870        };
871        let callback = |result| callback(new_state.get(), result);
872        // SAFETY:
873        // * `addr` is an address we control.
874        // * `filter` does not panic or call into any function of `parking_lot`.
875        // * `callback` safety responsibility is on caller
876        unsafe { parking_lot_core::unpark_filter(addr, filter, callback) };
877    }
878
879    // Common code for waiting for readers to exit the lock after acquiring
880    // WRITER_BIT.
881    #[inline]
882    fn wait_for_readers(&self, timeout: Option<Instant>, prev_value: usize) -> bool {
883        // At this point WRITER_BIT is already set, we just need to wait for the
884        // remaining readers to exit the lock.
885        let mut spinwait = SpinWait::new();
886        let mut state = self.state.load(Ordering::Acquire);
887        while state & READERS_MASK != 0 {
888            // Spin a few times to wait for readers to exit
889            if spinwait.spin() {
890                state = self.state.load(Ordering::Acquire);
891                continue;
892            }
893
894            // Set the parked bit
895            if state & WRITER_PARKED_BIT == 0
896                && let Err(x) = self.state.compare_exchange_weak(
897                    state,
898                    state | WRITER_PARKED_BIT,
899                    Ordering::Acquire,
900                    Ordering::Acquire,
901                )
902            {
903                state = x;
904                continue;
905            }
906
907            // Park our thread until we are woken up by an unlock
908            // Using the 2nd key at addr + 1
909            let addr = core::ptr::from_ref(self).addr() + 1;
910            let validate = || {
911                let state = self.state.load(Ordering::Relaxed);
912                state & READERS_MASK != 0 && state & WRITER_PARKED_BIT != 0
913            };
914            let before_sleep = || {};
915            let timed_out = |_, was_last_thread: bool| {
916                // Clear the parked bit while holding the queue lock. There can
917                // only be one thread parked (this one).
918                if true {
    if !was_last_thread {
        ::core::panicking::panic("assertion failed: was_last_thread")
    };
};debug_assert!(was_last_thread);
919                self.state.fetch_and(!WRITER_PARKED_BIT, Ordering::Relaxed);
920            };
921            // SAFETY:
922            //   * `addr` is an address we control.
923            //   * `validate`/`timed_out` does not panic or call into any function of `parking_lot`.
924            //   * `before_sleep` does not call `park`, nor does it panic.
925            let park_result = unsafe {
926                parking_lot_core::park(
927                    addr,
928                    validate,
929                    before_sleep,
930                    timed_out,
931                    TOKEN_EXCLUSIVE,
932                    timeout,
933                )
934            };
935            match park_result {
936                // We still need to re-check the state if we are unparked
937                // since a previous writer timing-out could have allowed
938                // another reader to sneak in before we parked.
939                ParkResult::Unparked(_) | ParkResult::Invalid => {
940                    state = self.state.load(Ordering::Acquire);
941                    continue;
942                }
943
944                // Timeout expired
945                ParkResult::TimedOut => {
946                    // We need to release WRITER_BIT and revert back to
947                    // our previous value. We also wake up any threads that
948                    // might be waiting on WRITER_BIT.
949                    if prev_value == 0 {
950                        // A fresh writer no longer owns WRITER_BIT after the
951                        // rollback. An upgrading reader retains ownership of
952                        // the primary key when its upgradable lock is restored.
953                        self.deadlock_release_primary();
954                    }
955                    let state = self
956                        .state
957                        .fetch_add(prev_value.wrapping_sub(WRITER_BIT), Ordering::Relaxed);
958                    if state & PARKED_BIT != 0 {
959                        let callback = |_, result: UnparkResult| {
960                            // Clear the parked bit if there no more parked threads
961                            if !result.have_more_threads {
962                                self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed);
963                            }
964                            TOKEN_NORMAL
965                        };
966                        // SAFETY: `callback` does not panic or call any function of `parking_lot`.
967                        unsafe {
968                            self.wake_parked_threads(prev_value, callback);
969                        }
970                    }
971                    return false;
972                }
973            }
974        }
975        true
976    }
977
978    /// Common code for acquiring a lock
979    #[inline]
980    fn lock_common(
981        &self,
982        timeout: Option<Instant>,
983        token: ParkToken,
984        mut try_lock: impl FnMut(&mut usize) -> bool,
985        should_park: impl Fn(usize) -> bool,
986    ) -> bool {
987        let mut spinwait = SpinWait::new();
988        let mut state = self.state.load(Ordering::Relaxed);
989        loop {
990            // Attempt to grab the lock
991            if try_lock(&mut state) {
992                return true;
993            }
994
995            // If there are no parked threads, try spinning a few times.
996            if state & (PARKED_BIT | WRITER_PARKED_BIT) == 0 && spinwait.spin() {
997                state = self.state.load(Ordering::Relaxed);
998                continue;
999            }
1000
1001            // Set the parked bit
1002            if state & PARKED_BIT == 0
1003                && let Err(x) = self.state.compare_exchange_weak(
1004                    state,
1005                    state | PARKED_BIT,
1006                    Ordering::Relaxed,
1007                    Ordering::Relaxed,
1008                )
1009            {
1010                state = x;
1011                continue;
1012            }
1013
1014            // Park our thread until we are woken up by an unlock
1015            let addr = core::ptr::from_ref(self).addr();
1016            let validate = || {
1017                let state = self.state.load(Ordering::Relaxed);
1018                state & PARKED_BIT != 0 && should_park(state)
1019            };
1020            let before_sleep = || {};
1021            let timed_out = |_, was_last_thread| {
1022                // Clear the parked bit if we were the last parked thread
1023                if was_last_thread {
1024                    self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed);
1025                }
1026            };
1027
1028            // SAFETY:
1029            // * `addr` is an address we control.
1030            // * `validate`/`timed_out` does not panic or call into any function of `parking_lot`.
1031            // * `before_sleep` does not call `park`, nor does it panic.
1032            let park_result = unsafe {
1033                parking_lot_core::park(addr, validate, before_sleep, timed_out, token, timeout)
1034            };
1035            match park_result {
1036                // The thread that unparked us passed the lock on to us
1037                // directly without unlocking it.
1038                ParkResult::Unparked(TOKEN_HANDOFF) => return true,
1039
1040                // We were unparked normally, try acquiring the lock again
1041                ParkResult::Unparked(_) => (),
1042
1043                // The validation function failed, try locking again
1044                ParkResult::Invalid => (),
1045
1046                // Timeout expired
1047                ParkResult::TimedOut => return false,
1048            }
1049
1050            // Loop back and try locking again
1051            spinwait.reset();
1052            state = self.state.load(Ordering::Relaxed);
1053        }
1054    }
1055
1056    #[inline]
1057    fn deadlock_acquire_primary(&self) {
1058        unsafe { deadlock::acquire_resource(core::ptr::from_ref(self).addr()) };
1059    }
1060
1061    #[inline]
1062    fn deadlock_release_primary(&self) {
1063        unsafe { deadlock::release_resource(core::ptr::from_ref(self).addr()) };
1064    }
1065
1066    #[inline]
1067    fn deadlock_acquire_secondary(&self) {
1068        unsafe { deadlock::acquire_resource(core::ptr::from_ref(self).addr() + 1) };
1069    }
1070
1071    #[inline]
1072    fn deadlock_release_secondary(&self) {
1073        unsafe { deadlock::release_resource(core::ptr::from_ref(self).addr() + 1) };
1074    }
1075
1076    #[inline]
1077    fn deadlock_acquire_all(&self) {
1078        self.deadlock_acquire_primary();
1079        self.deadlock_acquire_secondary();
1080    }
1081
1082    #[inline]
1083    fn deadlock_release_all(&self) {
1084        self.deadlock_release_primary();
1085        self.deadlock_release_secondary();
1086    }
1087
1088    #[cfg(test)]
1089    pub(crate) fn has_parked_threads(&self) -> bool {
1090        self.state.load(Ordering::Relaxed) & (PARKED_BIT | WRITER_PARKED_BIT) != 0
1091    }
1092}