os/sync/
raw_spin_lock_without_guard.rs1use crate::arch::intr::{read_and_disable_interrupts, restore_interrupts};
23use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
24
25pub struct RawSpinLockWithoutGuard {
27 locked: AtomicBool,
28 saved_intr_flags: AtomicUsize,
29}
30
31impl RawSpinLockWithoutGuard {
32 pub const fn new() -> Self {
34 Self {
35 locked: AtomicBool::new(false),
36 saved_intr_flags: AtomicUsize::new(0),
37 }
38 }
39}
40
41unsafe impl lock_api::RawMutex for RawSpinLockWithoutGuard {
42 #[allow(clippy::declare_interior_mutable_const)]
43 const INIT: Self = Self::new();
44
45 type GuardMarker = lock_api::GuardNoSend;
46
47 fn lock(&self) {
49 let flags = unsafe { read_and_disable_interrupts() };
51
52 while self
54 .locked
55 .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
56 .is_err()
57 {
58 core::hint::spin_loop();
59 }
60
61 self.saved_intr_flags.store(flags, Ordering::Release);
63 }
64
65 fn try_lock(&self) -> bool {
67 let flags = unsafe { read_and_disable_interrupts() };
69
70 if self
72 .locked
73 .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
74 .is_ok()
75 {
76 self.saved_intr_flags.store(flags, Ordering::Release);
78 true
79 } else {
80 unsafe { restore_interrupts(flags) };
82 false
83 }
84 }
85
86 unsafe fn unlock(&self) {
88 let flags = self.saved_intr_flags.load(Ordering::Acquire);
90
91 self.locked.store(false, Ordering::Release);
93
94 unsafe { restore_interrupts(flags) };
96 }
97}
98
99unsafe impl Send for RawSpinLockWithoutGuard {}
101unsafe impl Sync for RawSpinLockWithoutGuard {}
102
103#[cfg(test)]
104mod tests {
105 use lock_api::RawMutex;
106
107 use super::*;
108 use crate::{kassert, test_case};
109
110 test_case!(test_mutex_wrapper_guard_basic, {
112 let m = lock_api::Mutex::<RawSpinLockWithoutGuard, usize>::new(0);
113
114 {
115 let mut g = m.lock();
116 *g = 42;
117 } {
120 let g = m.lock();
121 kassert!(*g == 42);
122 }
123 });
124
125 test_case!(test_try_lock_and_unlock_roundtrip, {
127 let raw = RawSpinLockWithoutGuard::new();
128
129 let ok = raw.try_lock();
131 kassert!(ok);
132
133 let fail = raw.try_lock();
135 kassert!(!fail);
136
137 unsafe {
139 raw.unlock();
140 }
141
142 let ok2 = raw.try_lock();
144 kassert!(ok2);
145
146 unsafe {
148 raw.unlock();
149 }
150 });
151
152 test_case!(test_lock_then_unlock, {
154 let raw = RawSpinLockWithoutGuard::new();
155
156 raw.lock();
158
159 let fail = raw.try_lock();
161 kassert!(!fail);
162
163 unsafe {
165 raw.unlock();
166 }
167 let ok = raw.try_lock();
168 kassert!(ok);
169 unsafe {
170 raw.unlock();
171 }
172 });
173}