xref: /DragonOS/kernel/src/libs/spinlock.rs (revision b087521e07f601b30e3d48df788fcc2f09f19566)
1 #![allow(dead_code)]
2 use core::cell::UnsafeCell;
3 use core::mem::ManuallyDrop;
4 use core::ops::{Deref, DerefMut};
5 use core::ptr::read_volatile;
6 
7 use core::sync::atomic::{AtomicBool, Ordering};
8 
9 use crate::arch::asm::irqflags::{local_irq_restore, local_irq_save};
10 use crate::arch::interrupt::{cli, sti};
11 
12 use crate::include::bindings::bindings::{spin_lock, spin_unlock, spinlock_t};
13 use crate::process::preempt::{preempt_disable, preempt_enable};
14 use crate::syscall::SystemError;
15 
16 /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
17 #[inline]
18 pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut usize) {
19     *flags = local_irq_save();
20     unsafe {
21         spin_lock(lock);
22     }
23 }
24 
25 /// @brief 恢复rflags以及中断状态并解锁自旋锁
26 #[inline]
27 pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: usize) {
28     unsafe {
29         spin_unlock(lock);
30     }
31     local_irq_restore(flags);
32 }
33 
34 /// 判断一个自旋锁是否已经被加锁
35 #[inline]
36 pub fn spin_is_locked(lock: &spinlock_t) -> bool {
37     let val = unsafe { read_volatile(&lock.lock as *const i8) };
38 
39     return if val == 0 { true } else { false };
40 }
41 
42 impl Default for spinlock_t {
43     fn default() -> Self {
44         Self { lock: 1 }
45     }
46 }
47 
48 /// @brief 关闭中断并加锁
49 pub fn spin_lock_irq(lock: *mut spinlock_t) {
50     cli();
51     unsafe {
52         spin_lock(lock);
53     }
54 }
55 
56 /// @brief 解锁并开中断
57 pub fn spin_unlock_irq(lock: *mut spinlock_t) {
58     unsafe {
59         spin_unlock(lock);
60     }
61     sti();
62 }
63 
64 /// 原始的Spinlock(自旋锁)
65 /// 请注意,这个自旋锁和C的不兼容。
66 ///
67 /// @param self.0 这个AtomicBool的值为false时,表示没有被加锁。当它为true时,表示自旋锁已经被上锁。
68 #[derive(Debug)]
69 pub struct RawSpinlock(AtomicBool);
70 
71 impl RawSpinlock {
72     /// @brief 初始化自旋锁
73     pub const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
74 
75     /// @brief 加锁
76     pub fn lock(&self) {
77         while !self.try_lock() {}
78     }
79 
80     /// @brief 关中断并加锁
81     pub fn lock_irq(&self) {
82         cli();
83         self.lock();
84     }
85 
86     /// @brief 尝试加锁
87     /// @return 加锁成功->true
88     ///         加锁失败->false
89     pub fn try_lock(&self) -> bool {
90         // 先增加自旋锁持有计数
91         preempt_disable();
92 
93         let res = self
94             .0
95             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
96             .is_ok();
97 
98         // 如果加锁失败恢复自旋锁持有计数
99         if res == false {
100             preempt_enable();
101         }
102         return res;
103     }
104 
105     /// @brief 解锁
106     pub fn unlock(&self) {
107         // 减少自旋锁持有计数
108         preempt_enable();
109         self.0.store(false, Ordering::Release);
110     }
111 
112     /// 解锁,但是不更改preempt count
113     unsafe fn unlock_no_preempt(&self) {
114         self.0.store(false, Ordering::Release);
115     }
116 
117     /// @brief 放锁并开中断
118     pub fn unlock_irq(&self) {
119         self.unlock();
120         sti();
121     }
122 
123     /// @brief 判断自旋锁是否被上锁
124     ///
125     /// @return true 自旋锁被上锁
126     /// @return false 自旋锁处于解锁状态
127     pub fn is_locked(&self) -> bool {
128         return self.0.load(Ordering::Relaxed).into();
129     }
130 
131     /// @brief 强制设置自旋锁的状态
132     /// 请注意,这样操作可能会带来未知的风险。因此它是unsafe的。(尽管从Rust语言本身来说,它是safe的)
133     pub unsafe fn set_value(&mut self, value: bool) {
134         self.0.store(value, Ordering::SeqCst);
135     }
136 
137     /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
138     pub fn lock_irqsave(&self, flags: &mut usize) {
139         *flags = local_irq_save();
140         self.lock();
141     }
142 
143     /// @brief 恢复rflags以及中断状态并解锁自旋锁
144     pub fn unlock_irqrestore(&self, flags: usize) {
145         self.unlock();
146         local_irq_restore(flags);
147     }
148 
149     /// @brief 尝试保存中断状态到flags中,关闭中断,并对自旋锁加锁
150     /// @return 加锁成功->true
151     ///         加锁失败->false
152     #[inline(always)]
153     pub fn try_lock_irqsave(&self, flags: &mut usize) -> bool {
154         *flags = local_irq_save();
155         if self.try_lock() {
156             return true;
157         }
158         local_irq_restore(*flags);
159         return false;
160     }
161 }
162 /// 实现了守卫的SpinLock, 能够支持内部可变性
163 ///
164 #[derive(Debug)]
165 pub struct SpinLock<T> {
166     lock: RawSpinlock,
167     /// 自旋锁保护的数据
168     data: UnsafeCell<T>,
169 }
170 
171 /// SpinLock的守卫
172 /// 该守卫没有构造器,并且其信息均为私有的。我们只能通过SpinLock的lock()方法获得一个守卫。
173 /// 因此我们可以认为,只要能够获得一个守卫,那么数据就在自旋锁的保护之下。
174 #[derive(Debug)]
175 pub struct SpinLockGuard<'a, T: 'a> {
176     lock: &'a SpinLock<T>,
177     flag: usize,
178 }
179 
180 impl<'a, T: 'a> SpinLockGuard<'a, T> {
181     /// 泄露自旋锁的守卫,返回一个可变的引用
182     ///
183     ///  ## Safety
184     ///
185     /// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确,
186     /// 因此必须小心的手动维护好preempt count。
187     ///
188     /// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。
189     #[inline]
190     pub unsafe fn leak(this: Self) -> &'a mut T {
191         // Use ManuallyDrop to avoid stacked-borrow invalidation
192         let this = ManuallyDrop::new(this);
193         // We know statically that only we are referencing data
194         unsafe { &mut *this.lock.data.get() }
195     }
196 }
197 
198 /// 向编译器保证,SpinLock在线程之间是安全的.
199 /// 其中要求类型T实现了Send这个Trait
200 unsafe impl<T> Sync for SpinLock<T> where T: Send {}
201 
202 impl<T> SpinLock<T> {
203     pub const fn new(value: T) -> Self {
204         return Self {
205             lock: RawSpinlock::INIT,
206             data: UnsafeCell::new(value),
207         };
208     }
209 
210     #[inline(always)]
211     pub fn lock(&self) -> SpinLockGuard<T> {
212         self.lock.lock();
213         // 加锁成功,返回一个守卫
214         return SpinLockGuard {
215             lock: self,
216             flag: 0,
217         };
218     }
219 
220     pub fn lock_irqsave(&self) -> SpinLockGuard<T> {
221         let mut flags: usize = 0;
222 
223         self.lock.lock_irqsave(&mut flags);
224         // 加锁成功,返回一个守卫
225         return SpinLockGuard {
226             lock: self,
227             flag: flags,
228         };
229     }
230 
231     pub fn try_lock(&self) -> Result<SpinLockGuard<T>, SystemError> {
232         if self.lock.try_lock() {
233             return Ok(SpinLockGuard {
234                 lock: self,
235                 flag: 0,
236             });
237         }
238         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
239     }
240 
241     pub fn try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError> {
242         let mut flags: usize = 0;
243         if self.lock.try_lock_irqsave(&mut flags) {
244             return Ok(SpinLockGuard {
245                 lock: self,
246                 flag: flags,
247             });
248         }
249         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
250     }
251 
252     /// 强制解锁,并且不更改preempt count
253     ///
254     /// ## Safety
255     ///
256     /// 由于这样做可能导致preempt count不正确,因此必须小心的手动维护好preempt count。
257     /// 如非必要,请不要使用这个函数。
258     pub unsafe fn force_unlock(&self) {
259         self.lock.unlock_no_preempt();
260     }
261 }
262 
263 /// 实现Deref trait,支持通过获取SpinLockGuard来获取临界区数据的不可变引用
264 impl<T> Deref for SpinLockGuard<'_, T> {
265     type Target = T;
266 
267     fn deref(&self) -> &Self::Target {
268         return unsafe { &*self.lock.data.get() };
269     }
270 }
271 
272 /// 实现DerefMut trait,支持通过获取SpinLockGuard来获取临界区数据的可变引用
273 impl<T> DerefMut for SpinLockGuard<'_, T> {
274     fn deref_mut(&mut self) -> &mut Self::Target {
275         return unsafe { &mut *self.lock.data.get() };
276     }
277 }
278 
279 /// @brief 为SpinLockGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况
280 impl<T> Drop for SpinLockGuard<'_, T> {
281     fn drop(&mut self) {
282         if self.flag != 0 {
283             self.lock.lock.unlock_irqrestore(self.flag);
284         } else {
285             self.lock.lock.unlock();
286         }
287     }
288 }
289