xref: /DragonOS/kernel/src/libs/spinlock.rs (revision 90a0a49048fdaf5e31320d0c87f8bed8db1bd882)
166f67c6aSlogin #![allow(dead_code)]
2ec53d23eSlogin use core::cell::UnsafeCell;
3*90a0a490SLoGin use core::mem::ManuallyDrop;
4ec53d23eSlogin use core::ops::{Deref, DerefMut};
566f67c6aSlogin use core::ptr::read_volatile;
666f67c6aSlogin 
7ac643d42Slogin use core::sync::atomic::{AtomicBool, Ordering};
8ac643d42Slogin 
9adc1846bSlogin use crate::arch::asm::irqflags::{local_irq_restore, local_irq_save};
10adc1846bSlogin use crate::arch::interrupt::{cli, sti};
1166f67c6aSlogin use crate::include::bindings::bindings::{spin_lock, spin_unlock, spinlock_t};
12ac643d42Slogin use crate::process::preempt::{preempt_disable, preempt_enable};
13bacd691cSlogin use crate::syscall::SystemError;
1466f67c6aSlogin 
1566f67c6aSlogin /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
161a2eaa40Slogin #[inline]
1740fe15e0SLoGin pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut usize) {
1840fe15e0SLoGin     *flags = local_irq_save();
1966f67c6aSlogin     unsafe {
2066f67c6aSlogin         spin_lock(lock);
2166f67c6aSlogin     }
2266f67c6aSlogin }
2366f67c6aSlogin 
2466f67c6aSlogin /// @brief 恢复rflags以及中断状态并解锁自旋锁
251a2eaa40Slogin #[inline]
2640fe15e0SLoGin pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: usize) {
2766f67c6aSlogin     unsafe {
2866f67c6aSlogin         spin_unlock(lock);
2966f67c6aSlogin     }
3040fe15e0SLoGin     local_irq_restore(flags);
3166f67c6aSlogin }
3266f67c6aSlogin 
3366f67c6aSlogin /// 判断一个自旋锁是否已经被加锁
341a2eaa40Slogin #[inline]
3566f67c6aSlogin pub fn spin_is_locked(lock: &spinlock_t) -> bool {
3666f67c6aSlogin     let val = unsafe { read_volatile(&lock.lock as *const i8) };
3766f67c6aSlogin 
3866f67c6aSlogin     return if val == 0 { true } else { false };
3966f67c6aSlogin }
40c8025a88Slogin 
41c8025a88Slogin impl Default for spinlock_t {
42c8025a88Slogin     fn default() -> Self {
43c8025a88Slogin         Self { lock: 1 }
44c8025a88Slogin     }
45c8025a88Slogin }
461a2eaa40Slogin 
471a2eaa40Slogin /// @brief 关闭中断并加锁
481a2eaa40Slogin pub fn spin_lock_irq(lock: *mut spinlock_t) {
491a2eaa40Slogin     cli();
50ac643d42Slogin     unsafe {
51ac643d42Slogin         spin_lock(lock);
52ac643d42Slogin     }
531a2eaa40Slogin }
541a2eaa40Slogin 
551a2eaa40Slogin /// @brief 解锁并开中断
561a2eaa40Slogin pub fn spin_unlock_irq(lock: *mut spinlock_t) {
57ac643d42Slogin     unsafe {
58ac643d42Slogin         spin_unlock(lock);
59ac643d42Slogin     }
601a2eaa40Slogin     sti();
611a2eaa40Slogin }
62ac643d42Slogin 
6361de2cdcSlogin /// 原始的Spinlock(自旋锁)
6461de2cdcSlogin /// 请注意,这个自旋锁和C的不兼容。
6561de2cdcSlogin ///
6661de2cdcSlogin /// @param self.0 这个AtomicBool的值为false时,表示没有被加锁。当它为true时,表示自旋锁已经被上锁。
67d4f3de93Slogin #[derive(Debug)]
68ac643d42Slogin pub struct RawSpinlock(AtomicBool);
69ac643d42Slogin 
70ac643d42Slogin impl RawSpinlock {
71ac643d42Slogin     /// @brief 初始化自旋锁
72d4f3de93Slogin     pub const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
73ac643d42Slogin 
74ac643d42Slogin     /// @brief 加锁
75ec53d23eSlogin     pub fn lock(&self) {
76ac643d42Slogin         while !self.try_lock() {}
77ac643d42Slogin     }
78ac643d42Slogin 
79ac643d42Slogin     /// @brief 关中断并加锁
80ec53d23eSlogin     pub fn lock_irq(&self) {
81ac643d42Slogin         cli();
82ac643d42Slogin         self.lock();
83ac643d42Slogin     }
84ac643d42Slogin 
85ac643d42Slogin     /// @brief 尝试加锁
86ac643d42Slogin     /// @return 加锁成功->true
87ac643d42Slogin     ///         加锁失败->false
88ec53d23eSlogin     pub fn try_lock(&self) -> bool {
89ac643d42Slogin         // 先增加自旋锁持有计数
90ac643d42Slogin         preempt_disable();
91ac643d42Slogin 
92ac643d42Slogin         let res = self
93ac643d42Slogin             .0
94ac643d42Slogin             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
95ac643d42Slogin             .is_ok();
96ac643d42Slogin 
97ac643d42Slogin         // 如果加锁失败恢复自旋锁持有计数
98ac643d42Slogin         if res == false {
99ac643d42Slogin             preempt_enable();
100ac643d42Slogin         }
101ac643d42Slogin         return res;
102ac643d42Slogin     }
103ac643d42Slogin 
104ac643d42Slogin     /// @brief 解锁
105ec53d23eSlogin     pub fn unlock(&self) {
106ac643d42Slogin         // 减少自旋锁持有计数
107ac643d42Slogin         preempt_enable();
108ac643d42Slogin         self.0.store(false, Ordering::Release);
109ac643d42Slogin     }
110ac643d42Slogin 
111*90a0a490SLoGin     /// 解锁,但是不更改preempt count
112*90a0a490SLoGin     unsafe fn unlock_no_preempt(&self) {
113*90a0a490SLoGin         self.0.store(false, Ordering::Release);
114*90a0a490SLoGin     }
115*90a0a490SLoGin 
116ac643d42Slogin     /// @brief 放锁并开中断
117ec53d23eSlogin     pub fn unlock_irq(&self) {
118ac643d42Slogin         self.unlock();
119ac643d42Slogin         sti();
120ac643d42Slogin     }
121ac643d42Slogin 
12261de2cdcSlogin     /// @brief 判断自旋锁是否被上锁
12361de2cdcSlogin     ///
12461de2cdcSlogin     /// @return true 自旋锁被上锁
12561de2cdcSlogin     /// @return false 自旋锁处于解锁状态
126ec53d23eSlogin     pub fn is_locked(&self) -> bool {
12761de2cdcSlogin         return self.0.load(Ordering::Relaxed).into();
12861de2cdcSlogin     }
12961de2cdcSlogin 
13061de2cdcSlogin     /// @brief 强制设置自旋锁的状态
13161de2cdcSlogin     /// 请注意,这样操作可能会带来未知的风险。因此它是unsafe的。(尽管从Rust语言本身来说,它是safe的)
13261de2cdcSlogin     pub unsafe fn set_value(&mut self, value: bool) {
13361de2cdcSlogin         self.0.store(value, Ordering::SeqCst);
13461de2cdcSlogin     }
13561de2cdcSlogin 
136d8a06412SGou Ngai     /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
13740fe15e0SLoGin     pub fn lock_irqsave(&self, flags: &mut usize) {
13840fe15e0SLoGin         *flags = local_irq_save();
139d8a06412SGou Ngai         self.lock();
140ec53d23eSlogin     }
141ac643d42Slogin 
142d8a06412SGou Ngai     /// @brief 恢复rflags以及中断状态并解锁自旋锁
14340fe15e0SLoGin     pub fn unlock_irqrestore(&self, flags: usize) {
144d8a06412SGou Ngai         self.unlock();
14540fe15e0SLoGin         local_irq_restore(flags);
146d8a06412SGou Ngai     }
147bacd691cSlogin 
148bacd691cSlogin     /// @brief 尝试保存中断状态到flags中,关闭中断,并对自旋锁加锁
149bacd691cSlogin     /// @return 加锁成功->true
150bacd691cSlogin     ///         加锁失败->false
151bacd691cSlogin     #[inline(always)]
15240fe15e0SLoGin     pub fn try_lock_irqsave(&self, flags: &mut usize) -> bool {
15340fe15e0SLoGin         *flags = local_irq_save();
154bacd691cSlogin         if self.try_lock() {
155bacd691cSlogin             return true;
156bacd691cSlogin         }
15740fe15e0SLoGin         local_irq_restore(*flags);
158bacd691cSlogin         return false;
159bacd691cSlogin     }
160d8a06412SGou Ngai }
161ec53d23eSlogin /// 实现了守卫的SpinLock, 能够支持内部可变性
162ec53d23eSlogin ///
163ec53d23eSlogin #[derive(Debug)]
164ec53d23eSlogin pub struct SpinLock<T> {
165ec53d23eSlogin     lock: RawSpinlock,
166ec53d23eSlogin     /// 自旋锁保护的数据
167ec53d23eSlogin     data: UnsafeCell<T>,
168ec53d23eSlogin }
169ec53d23eSlogin 
170ec53d23eSlogin /// SpinLock的守卫
171ec53d23eSlogin /// 该守卫没有构造器,并且其信息均为私有的。我们只能通过SpinLock的lock()方法获得一个守卫。
172ec53d23eSlogin /// 因此我们可以认为,只要能够获得一个守卫,那么数据就在自旋锁的保护之下。
173ec53d23eSlogin #[derive(Debug)]
174ec53d23eSlogin pub struct SpinLockGuard<'a, T: 'a> {
175ec53d23eSlogin     lock: &'a SpinLock<T>,
17640fe15e0SLoGin     flag: usize,
177ec53d23eSlogin }
178ec53d23eSlogin 
179*90a0a490SLoGin impl<'a, T: 'a> SpinLockGuard<'a, T> {
180*90a0a490SLoGin     /// 泄露自旋锁的守卫,返回一个可变的引用
181*90a0a490SLoGin     ///
182*90a0a490SLoGin     ///  ## Safety
183*90a0a490SLoGin     ///
184*90a0a490SLoGin     /// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确,
185*90a0a490SLoGin     /// 因此必须小心的手动维护好preempt count。
186*90a0a490SLoGin     ///
187*90a0a490SLoGin     /// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。
188*90a0a490SLoGin     #[inline]
189*90a0a490SLoGin     pub unsafe fn leak(this: Self) -> &'a mut T {
190*90a0a490SLoGin         // Use ManuallyDrop to avoid stacked-borrow invalidation
191*90a0a490SLoGin         let this = ManuallyDrop::new(this);
192*90a0a490SLoGin         // We know statically that only we are referencing data
193*90a0a490SLoGin         unsafe { &mut *this.lock.data.get() }
194*90a0a490SLoGin     }
195*90a0a490SLoGin }
196*90a0a490SLoGin 
197ec53d23eSlogin /// 向编译器保证,SpinLock在线程之间是安全的.
198ec53d23eSlogin /// 其中要求类型T实现了Send这个Trait
199ec53d23eSlogin unsafe impl<T> Sync for SpinLock<T> where T: Send {}
200ec53d23eSlogin 
201ec53d23eSlogin impl<T> SpinLock<T> {
202ec53d23eSlogin     pub const fn new(value: T) -> Self {
203ec53d23eSlogin         return Self {
204ec53d23eSlogin             lock: RawSpinlock::INIT,
205ec53d23eSlogin             data: UnsafeCell::new(value),
206ec53d23eSlogin         };
207ec53d23eSlogin     }
208ec53d23eSlogin 
209ec53d23eSlogin     #[inline(always)]
210ec53d23eSlogin     pub fn lock(&self) -> SpinLockGuard<T> {
211ec53d23eSlogin         self.lock.lock();
212ec53d23eSlogin         // 加锁成功,返回一个守卫
213bacd691cSlogin         return SpinLockGuard {
214bacd691cSlogin             lock: self,
215bacd691cSlogin             flag: 0,
216bacd691cSlogin         };
217bacd691cSlogin     }
218bacd691cSlogin 
219bacd691cSlogin     pub fn lock_irqsave(&self) -> SpinLockGuard<T> {
22040fe15e0SLoGin         let mut flags: usize = 0;
22140fe15e0SLoGin 
222bacd691cSlogin         self.lock.lock_irqsave(&mut flags);
223bacd691cSlogin         // 加锁成功,返回一个守卫
224bacd691cSlogin         return SpinLockGuard {
225bacd691cSlogin             lock: self,
226bacd691cSlogin             flag: flags,
227bacd691cSlogin         };
228bacd691cSlogin     }
229bacd691cSlogin 
230bacd691cSlogin     pub fn try_lock(&self) -> Result<SpinLockGuard<T>, SystemError> {
231bacd691cSlogin         if self.lock.try_lock() {
232bacd691cSlogin             return Ok(SpinLockGuard {
233bacd691cSlogin                 lock: self,
234bacd691cSlogin                 flag: 0,
235bacd691cSlogin             });
236bacd691cSlogin         }
23779a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
238bacd691cSlogin     }
239bacd691cSlogin 
240bacd691cSlogin     pub fn try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError> {
24140fe15e0SLoGin         let mut flags: usize = 0;
242bacd691cSlogin         if self.lock.try_lock_irqsave(&mut flags) {
243bacd691cSlogin             return Ok(SpinLockGuard {
244bacd691cSlogin                 lock: self,
245bacd691cSlogin                 flag: flags,
246bacd691cSlogin             });
247bacd691cSlogin         }
24879a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
249ec53d23eSlogin     }
250*90a0a490SLoGin 
251*90a0a490SLoGin     /// 强制解锁,并且不更改preempt count
252*90a0a490SLoGin     ///
253*90a0a490SLoGin     /// ## Safety
254*90a0a490SLoGin     ///
255*90a0a490SLoGin     /// 由于这样做可能导致preempt count不正确,因此必须小心的手动维护好preempt count。
256*90a0a490SLoGin     /// 如非必要,请不要使用这个函数。
257*90a0a490SLoGin     pub unsafe fn force_unlock(&self) {
258*90a0a490SLoGin         self.lock.unlock_no_preempt();
259*90a0a490SLoGin     }
260ec53d23eSlogin }
261ec53d23eSlogin 
262ec53d23eSlogin /// 实现Deref trait,支持通过获取SpinLockGuard来获取临界区数据的不可变引用
263ec53d23eSlogin impl<T> Deref for SpinLockGuard<'_, T> {
264ec53d23eSlogin     type Target = T;
265ec53d23eSlogin 
266ec53d23eSlogin     fn deref(&self) -> &Self::Target {
267ec53d23eSlogin         return unsafe { &*self.lock.data.get() };
268ec53d23eSlogin     }
269ec53d23eSlogin }
270ec53d23eSlogin 
271ec53d23eSlogin /// 实现DerefMut trait,支持通过获取SpinLockGuard来获取临界区数据的可变引用
272ec53d23eSlogin impl<T> DerefMut for SpinLockGuard<'_, T> {
273ec53d23eSlogin     fn deref_mut(&mut self) -> &mut Self::Target {
274ec53d23eSlogin         return unsafe { &mut *self.lock.data.get() };
275ec53d23eSlogin     }
276ec53d23eSlogin }
277ec53d23eSlogin 
278ec53d23eSlogin /// @brief 为SpinLockGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况
279ec53d23eSlogin impl<T> Drop for SpinLockGuard<'_, T> {
280ec53d23eSlogin     fn drop(&mut self) {
281cde5492fSlogin         if self.flag != 0 {
28240fe15e0SLoGin             self.lock.lock.unlock_irqrestore(self.flag);
283cde5492fSlogin         } else {
284ec53d23eSlogin             self.lock.lock.unlock();
285ec53d23eSlogin         }
286ac643d42Slogin     }
287cde5492fSlogin }
288