1use core::{
4 fmt,
5 ops::{Deref, DerefMut},
6};
7
8use super::{Mutex, MutexGuard, RawMutex};
9
10pub struct SpinLock<T: ?Sized> {
15 mutex: Mutex<T>,
16}
17
18#[must_use]
20pub struct SpinLockGuard<'a, T: ?Sized> {
21 migration: Option<RtCriticalGuard>,
22 owner: MutexGuard<'a, T>,
23}
24
25impl<T> SpinLock<T> {
26 pub const fn new(value: T) -> Self {
28 Self {
29 mutex: Mutex::const_new(RawMutex::new_rt_lock(), value),
30 }
31 }
32
33 pub fn into_inner(self) -> T {
35 self.mutex.into_inner()
36 }
37}
38
39impl<T: ?Sized> SpinLock<T> {
40 #[track_caller]
42 pub fn lock(&self) -> SpinLockGuard<'_, T> {
43 crate::thread::current::validate_rt_lock_context()
44 .expect("RT spin lock requires a preemptible task context");
45 let owner = self.mutex.lock();
46 let migration =
47 RtCriticalGuard::new().expect("RT spin lock owner must acquire its migration pin");
48 SpinLockGuard {
49 migration: Some(migration),
50 owner,
51 }
52 }
53
54 pub fn try_lock(&self) -> Option<SpinLockGuard<'_, T>> {
56 crate::thread::current::validate_rt_lock_context().ok()?;
57 let owner = self.mutex.try_lock()?;
58 let migration =
59 RtCriticalGuard::new().expect("RT spin lock owner must acquire its migration pin");
60 Some(SpinLockGuard {
61 migration: Some(migration),
62 owner,
63 })
64 }
65
66 pub fn lock_irqsave(&self) -> SpinLockGuard<'_, T> {
68 self.lock()
69 }
70
71 pub fn try_lock_irqsave(&self) -> Option<SpinLockGuard<'_, T>> {
73 self.try_lock()
74 }
75
76 pub fn get_mut(&mut self) -> &mut T {
78 self.mutex.get_mut()
79 }
80
81 pub fn is_locked(&self) -> bool {
83 self.mutex.is_locked()
84 }
85}
86
87impl<T: ?Sized> Deref for SpinLockGuard<'_, T> {
88 type Target = T;
89 fn deref(&self) -> &T {
90 &self.owner
91 }
92}
93
94impl<T: ?Sized> DerefMut for SpinLockGuard<'_, T> {
95 fn deref_mut(&mut self) -> &mut T {
96 &mut self.owner
97 }
98}
99
100impl<T: ?Sized> Drop for SpinLockGuard<'_, T> {
101 fn drop(&mut self) {
102 drop(self.migration.take());
103 }
105}
106
107impl<T: Default> Default for SpinLock<T> {
108 fn default() -> Self {
109 Self::new(T::default())
110 }
111}
112
113impl<T: ?Sized + fmt::Debug> fmt::Debug for SpinLock<T> {
114 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
115 self.mutex.fmt(formatter)
116 }
117}
118
119pub(super) struct RtCriticalGuard {
123 migration: Option<super::MigrationGuard>,
124 current: alloc::sync::Arc<crate::thread::ThreadCore>,
125}
126
127impl RtCriticalGuard {
128 pub(super) fn new() -> Result<Self, crate::thread::TaskError> {
129 let current = crate::thread::current::current_thread_core_arc()?;
130 current.enter_rt_lock_critical();
131 match super::MigrationGuard::new() {
132 Ok(migration) => Ok(Self {
133 migration: Some(migration),
134 current,
135 }),
136 Err(error) => {
137 current.leave_rt_lock_critical();
138 Err(error)
139 }
140 }
141 }
142}
143
144impl Drop for RtCriticalGuard {
145 fn drop(&mut self) {
146 drop(self.migration.take());
147 self.current.leave_rt_lock_critical();
148 }
149}