xref: /DragonOS/kernel/src/libs/spinlock.rs (revision 91e9d4ab55ef960f57a1b6287bc523ca4341f67a)
166f67c6aSlogin #![allow(dead_code)]
2ec53d23eSlogin use core::cell::UnsafeCell;
31496ba7bSLoGin use core::hint::spin_loop;
490a0a490SLoGin use core::mem::ManuallyDrop;
5ec53d23eSlogin use core::ops::{Deref, DerefMut};
666f67c6aSlogin 
7ac643d42Slogin use core::sync::atomic::{AtomicBool, Ordering};
8ac643d42Slogin 
91496ba7bSLoGin use crate::arch::CurrentIrqArch;
101496ba7bSLoGin use crate::exception::{InterruptArch, IrqFlagsGuard};
111496ba7bSLoGin use crate::process::ProcessManager;
12*91e9d4abSLoGin use system_error::SystemError;
1366f67c6aSlogin 
14ec53d23eSlogin /// 实现了守卫的SpinLock, 能够支持内部可变性
15ec53d23eSlogin ///
16ec53d23eSlogin #[derive(Debug)]
17ec53d23eSlogin pub struct SpinLock<T> {
181496ba7bSLoGin     lock: AtomicBool,
19ec53d23eSlogin     /// 自旋锁保护的数据
20ec53d23eSlogin     data: UnsafeCell<T>,
21ec53d23eSlogin }
22ec53d23eSlogin 
23ec53d23eSlogin /// SpinLock的守卫
24ec53d23eSlogin /// 该守卫没有构造器,并且其信息均为私有的。我们只能通过SpinLock的lock()方法获得一个守卫。
25ec53d23eSlogin /// 因此我们可以认为,只要能够获得一个守卫,那么数据就在自旋锁的保护之下。
26ec53d23eSlogin #[derive(Debug)]
27ec53d23eSlogin pub struct SpinLockGuard<'a, T: 'a> {
28ec53d23eSlogin     lock: &'a SpinLock<T>,
297ae679ddSLoGin     data: *mut T,
301496ba7bSLoGin     irq_flag: Option<IrqFlagsGuard>,
311496ba7bSLoGin     flags: SpinLockGuardFlags,
32ec53d23eSlogin }
33ec53d23eSlogin 
3490a0a490SLoGin impl<'a, T: 'a> SpinLockGuard<'a, T> {
3590a0a490SLoGin     /// 泄露自旋锁的守卫,返回一个可变的引用
3690a0a490SLoGin     ///
3790a0a490SLoGin     ///  ## Safety
3890a0a490SLoGin     ///
3990a0a490SLoGin     /// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确,
4090a0a490SLoGin     /// 因此必须小心的手动维护好preempt count。
4190a0a490SLoGin     ///
4290a0a490SLoGin     /// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。
4390a0a490SLoGin     #[inline]
4490a0a490SLoGin     pub unsafe fn leak(this: Self) -> &'a mut T {
4590a0a490SLoGin         // Use ManuallyDrop to avoid stacked-borrow invalidation
4690a0a490SLoGin         let this = ManuallyDrop::new(this);
4790a0a490SLoGin         // We know statically that only we are referencing data
4890a0a490SLoGin         unsafe { &mut *this.lock.data.get() }
4990a0a490SLoGin     }
501496ba7bSLoGin 
511496ba7bSLoGin     fn unlock_no_preempt(&self) {
521496ba7bSLoGin         unsafe {
531496ba7bSLoGin             self.lock.force_unlock();
541496ba7bSLoGin         }
551496ba7bSLoGin     }
5690a0a490SLoGin }
5790a0a490SLoGin 
58ec53d23eSlogin /// 向编译器保证,SpinLock在线程之间是安全的.
59ec53d23eSlogin /// 其中要求类型T实现了Send这个Trait
60ec53d23eSlogin unsafe impl<T> Sync for SpinLock<T> where T: Send {}
61ec53d23eSlogin 
62ec53d23eSlogin impl<T> SpinLock<T> {
63ec53d23eSlogin     pub const fn new(value: T) -> Self {
64ec53d23eSlogin         return Self {
651496ba7bSLoGin             lock: AtomicBool::new(false),
66ec53d23eSlogin             data: UnsafeCell::new(value),
67ec53d23eSlogin         };
68ec53d23eSlogin     }
69ec53d23eSlogin 
70ec53d23eSlogin     #[inline(always)]
71ec53d23eSlogin     pub fn lock(&self) -> SpinLockGuard<T> {
721496ba7bSLoGin         loop {
731496ba7bSLoGin             let res = self.try_lock();
741496ba7bSLoGin             if res.is_ok() {
751496ba7bSLoGin                 return res.unwrap();
761496ba7bSLoGin             }
771496ba7bSLoGin             spin_loop();
781496ba7bSLoGin         }
791496ba7bSLoGin     }
801496ba7bSLoGin 
811496ba7bSLoGin     /// 加锁,但是不更改preempt count
821496ba7bSLoGin     #[inline(always)]
831496ba7bSLoGin     pub fn lock_no_preempt(&self) -> SpinLockGuard<T> {
841496ba7bSLoGin         loop {
851496ba7bSLoGin             if let Ok(guard) = self.try_lock_no_preempt() {
861496ba7bSLoGin                 return guard;
871496ba7bSLoGin             }
881496ba7bSLoGin             spin_loop();
891496ba7bSLoGin         }
90bacd691cSlogin     }
91bacd691cSlogin 
92bacd691cSlogin     pub fn lock_irqsave(&self) -> SpinLockGuard<T> {
931496ba7bSLoGin         loop {
941496ba7bSLoGin             if let Ok(guard) = self.try_lock_irqsave() {
951496ba7bSLoGin                 return guard;
961496ba7bSLoGin             }
971496ba7bSLoGin             spin_loop();
981496ba7bSLoGin         }
99bacd691cSlogin     }
100bacd691cSlogin 
101bacd691cSlogin     pub fn try_lock(&self) -> Result<SpinLockGuard<T>, SystemError> {
1021496ba7bSLoGin         // 先增加自旋锁持有计数
1031496ba7bSLoGin         ProcessManager::preempt_disable();
1041496ba7bSLoGin 
1051496ba7bSLoGin         if self.inner_try_lock() {
106bacd691cSlogin             return Ok(SpinLockGuard {
107bacd691cSlogin                 lock: self,
1087ae679ddSLoGin                 data: unsafe { &mut *self.data.get() },
1091496ba7bSLoGin                 irq_flag: None,
1101496ba7bSLoGin                 flags: SpinLockGuardFlags::empty(),
111bacd691cSlogin             });
112bacd691cSlogin         }
1131496ba7bSLoGin 
1141496ba7bSLoGin         // 如果加锁失败恢复自旋锁持有计数
1151496ba7bSLoGin         ProcessManager::preempt_enable();
1161496ba7bSLoGin 
11779a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
118bacd691cSlogin     }
119bacd691cSlogin 
1201496ba7bSLoGin     fn inner_try_lock(&self) -> bool {
1211496ba7bSLoGin         let res = self
1221496ba7bSLoGin             .lock
1237ae679ddSLoGin             .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
1241496ba7bSLoGin             .is_ok();
1251496ba7bSLoGin         return res;
1261496ba7bSLoGin     }
1271496ba7bSLoGin 
128bacd691cSlogin     pub fn try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError> {
1291496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
1301496ba7bSLoGin         ProcessManager::preempt_disable();
1311496ba7bSLoGin         if self.inner_try_lock() {
132bacd691cSlogin             return Ok(SpinLockGuard {
133bacd691cSlogin                 lock: self,
1347ae679ddSLoGin                 data: unsafe { &mut *self.data.get() },
1351496ba7bSLoGin                 irq_flag: Some(irq_guard),
1361496ba7bSLoGin                 flags: SpinLockGuardFlags::empty(),
1371496ba7bSLoGin             });
1381496ba7bSLoGin         }
1391496ba7bSLoGin         ProcessManager::preempt_enable();
1401496ba7bSLoGin         drop(irq_guard);
1411496ba7bSLoGin         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
1421496ba7bSLoGin     }
1431496ba7bSLoGin 
1441496ba7bSLoGin     pub fn try_lock_no_preempt(&self) -> Result<SpinLockGuard<T>, SystemError> {
1451496ba7bSLoGin         if self.inner_try_lock() {
1461496ba7bSLoGin             return Ok(SpinLockGuard {
1471496ba7bSLoGin                 lock: self,
1487ae679ddSLoGin                 data: unsafe { &mut *self.data.get() },
1491496ba7bSLoGin                 irq_flag: None,
1501496ba7bSLoGin                 flags: SpinLockGuardFlags::NO_PREEMPT,
151bacd691cSlogin             });
152bacd691cSlogin         }
15379a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
154ec53d23eSlogin     }
15590a0a490SLoGin 
15690a0a490SLoGin     /// 强制解锁,并且不更改preempt count
15790a0a490SLoGin     ///
15890a0a490SLoGin     /// ## Safety
15990a0a490SLoGin     ///
16090a0a490SLoGin     /// 由于这样做可能导致preempt count不正确,因此必须小心的手动维护好preempt count。
16190a0a490SLoGin     /// 如非必要,请不要使用这个函数。
16290a0a490SLoGin     pub unsafe fn force_unlock(&self) {
1637ae679ddSLoGin         self.lock.store(false, Ordering::SeqCst);
1641496ba7bSLoGin     }
1651496ba7bSLoGin 
1661496ba7bSLoGin     fn unlock(&self) {
1677ae679ddSLoGin         self.lock.store(false, Ordering::SeqCst);
1681496ba7bSLoGin         ProcessManager::preempt_enable();
16990a0a490SLoGin     }
170ec53d23eSlogin }
171ec53d23eSlogin 
172ec53d23eSlogin /// 实现Deref trait,支持通过获取SpinLockGuard来获取临界区数据的不可变引用
173ec53d23eSlogin impl<T> Deref for SpinLockGuard<'_, T> {
174ec53d23eSlogin     type Target = T;
175ec53d23eSlogin 
176ec53d23eSlogin     fn deref(&self) -> &Self::Target {
1777ae679ddSLoGin         return unsafe { &*self.data };
178ec53d23eSlogin     }
179ec53d23eSlogin }
180ec53d23eSlogin 
181ec53d23eSlogin /// 实现DerefMut trait,支持通过获取SpinLockGuard来获取临界区数据的可变引用
182ec53d23eSlogin impl<T> DerefMut for SpinLockGuard<'_, T> {
183ec53d23eSlogin     fn deref_mut(&mut self) -> &mut Self::Target {
1847ae679ddSLoGin         return unsafe { &mut *self.data };
185ec53d23eSlogin     }
186ec53d23eSlogin }
187ec53d23eSlogin 
188ec53d23eSlogin /// @brief 为SpinLockGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况
189ec53d23eSlogin impl<T> Drop for SpinLockGuard<'_, T> {
190ec53d23eSlogin     fn drop(&mut self) {
1911496ba7bSLoGin         if self.flags.contains(SpinLockGuardFlags::NO_PREEMPT) {
1921496ba7bSLoGin             self.unlock_no_preempt();
193cde5492fSlogin         } else {
1941496ba7bSLoGin             self.lock.unlock();
195ec53d23eSlogin         }
1961496ba7bSLoGin         // restore irq
1971496ba7bSLoGin         self.irq_flag.take();
1981496ba7bSLoGin     }
1991496ba7bSLoGin }
2001496ba7bSLoGin 
2011496ba7bSLoGin bitflags! {
2021496ba7bSLoGin     struct SpinLockGuardFlags: u8 {
2031496ba7bSLoGin         /// 守卫是由“*no_preempt”方法获得的
2041496ba7bSLoGin         const NO_PREEMPT = (1<<0);
205ac643d42Slogin     }
206cde5492fSlogin }
207