Skip to main content

ax_task/sync/
rt_rwlock.rs

1//! PREEMPT_RT reader/writer spin locks.
2
3use core::{
4    fmt,
5    ops::{Deref, DerefMut},
6};
7
8use super::{
9    RawRwSemaphore, RtCriticalGuard, RwSemaphore, RwSemaphoreReadGuard, RwSemaphoreWriteGuard,
10};
11
12/// A preemptible RT reader/writer lock with a single-writer PI gate.
13///
14/// Readers already holding the lock cannot receive a writer's donation.
15/// Each successful guard pins migration but leaves hardware IRQs enabled.
16pub struct SpinRwLock<T: ?Sized> {
17    lock: RwSemaphore<T>,
18}
19
20/// Shared RT lock ownership, bound to the acquiring task.
21#[must_use]
22pub struct SpinRwLockReadGuard<'a, T: ?Sized> {
23    migration: Option<RtCriticalGuard>,
24    owner: RwSemaphoreReadGuard<'a, T>,
25}
26
27/// Exclusive RT lock ownership, bound to the acquiring task.
28#[must_use]
29pub struct SpinRwLockWriteGuard<'a, T: ?Sized> {
30    migration: Option<RtCriticalGuard>,
31    owner: RwSemaphoreWriteGuard<'a, T>,
32}
33
34impl<T> SpinRwLock<T> {
35    /// Creates an unlocked RT read/write lock.
36    pub const fn new(value: T) -> Self {
37        Self {
38            lock: RwSemaphore::const_new(RawRwSemaphore::with_wait_state(true), value),
39        }
40    }
41    /// Returns the protected value through exclusive object ownership.
42    pub fn into_inner(self) -> T {
43        self.lock.into_inner()
44    }
45}
46
47impl<T: ?Sized> SpinRwLock<T> {
48    /// Acquires shared access in preemptible task context.
49    pub fn read(&self) -> SpinRwLockReadGuard<'_, T> {
50        crate::thread::current::validate_rt_lock_context()
51            .expect("RT rwlock requires task context");
52        let owner = self.lock.read();
53        let migration = RtCriticalGuard::new().expect("RT reader migration pin");
54        SpinRwLockReadGuard {
55            migration: Some(migration),
56            owner,
57        }
58    }
59    /// Acquires exclusive access, waiting for existing readers to finish.
60    pub fn write(&self) -> SpinRwLockWriteGuard<'_, T> {
61        crate::thread::current::validate_rt_lock_context()
62            .expect("RT rwlock requires task context");
63        let owner = self.lock.write();
64        let migration = RtCriticalGuard::new().expect("RT writer migration pin");
65        SpinRwLockWriteGuard {
66            migration: Some(migration),
67            owner,
68        }
69    }
70    /// Attempts shared access without sleeping.
71    pub fn try_read(&self) -> Option<SpinRwLockReadGuard<'_, T>> {
72        crate::thread::current::validate_rt_lock_context().ok()?;
73        let owner = self.lock.try_read()?;
74        let migration = RtCriticalGuard::new().expect("RT reader migration pin");
75        Some(SpinRwLockReadGuard {
76            migration: Some(migration),
77            owner,
78        })
79    }
80    /// Attempts exclusive access without sleeping.
81    pub fn try_write(&self) -> Option<SpinRwLockWriteGuard<'_, T>> {
82        crate::thread::current::validate_rt_lock_context().ok()?;
83        let owner = self.lock.try_write()?;
84        let migration = RtCriticalGuard::new().expect("RT writer migration pin");
85        Some(SpinRwLockWriteGuard {
86            migration: Some(migration),
87            owner,
88        })
89    }
90    /// RT IRQ-save spelling; hardware IRQ state remains unchanged.
91    pub fn read_irqsave(&self) -> SpinRwLockReadGuard<'_, T> {
92        self.read()
93    }
94    /// RT IRQ-save spelling; hardware IRQ state remains unchanged.
95    pub fn write_irqsave(&self) -> SpinRwLockWriteGuard<'_, T> {
96        self.write()
97    }
98    /// RT IRQ-save spelling; hardware IRQ state remains unchanged.
99    pub fn try_read_irqsave(&self) -> Option<SpinRwLockReadGuard<'_, T>> {
100        self.try_read()
101    }
102    /// RT IRQ-save spelling; hardware IRQ state remains unchanged.
103    pub fn try_write_irqsave(&self) -> Option<SpinRwLockWriteGuard<'_, T>> {
104        self.try_write()
105    }
106    /// Returns exclusive access without locking.
107    pub fn get_mut(&mut self) -> &mut T {
108        self.lock.get_mut()
109    }
110}
111
112impl<T: ?Sized> Deref for SpinRwLockReadGuard<'_, T> {
113    type Target = T;
114    fn deref(&self) -> &T {
115        &self.owner
116    }
117}
118impl<T: ?Sized> Deref for SpinRwLockWriteGuard<'_, T> {
119    type Target = T;
120    fn deref(&self) -> &T {
121        &self.owner
122    }
123}
124impl<T: ?Sized> DerefMut for SpinRwLockWriteGuard<'_, T> {
125    fn deref_mut(&mut self) -> &mut T {
126        &mut self.owner
127    }
128}
129impl<T: ?Sized> Drop for SpinRwLockReadGuard<'_, T> {
130    fn drop(&mut self) {
131        drop(self.migration.take());
132    }
133}
134impl<T: ?Sized> Drop for SpinRwLockWriteGuard<'_, T> {
135    fn drop(&mut self) {
136        drop(self.migration.take());
137    }
138}
139impl<T: Default> Default for SpinRwLock<T> {
140    fn default() -> Self {
141        Self::new(T::default())
142    }
143}
144impl<T: ?Sized + fmt::Debug> fmt::Debug for SpinRwLock<T> {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        self.lock.fmt(f)
147    }
148}