xref: /DragonOS/kernel/src/libs/spinlock.rs (revision 1496ba7b24a5e6954291ca9643b9f3cec567479a)
166f67c6aSlogin #![allow(dead_code)]
2ec53d23eSlogin use core::cell::UnsafeCell;
3*1496ba7bSLoGin 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 
9*1496ba7bSLoGin use crate::arch::CurrentIrqArch;
10*1496ba7bSLoGin use crate::exception::{InterruptArch, IrqFlagsGuard};
11*1496ba7bSLoGin use crate::process::ProcessManager;
12bacd691cSlogin use crate::syscall::SystemError;
1366f67c6aSlogin 
14ec53d23eSlogin /// 实现了守卫的SpinLock, 能够支持内部可变性
15ec53d23eSlogin ///
16ec53d23eSlogin #[derive(Debug)]
17ec53d23eSlogin pub struct SpinLock<T> {
18*1496ba7bSLoGin     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>,
29*1496ba7bSLoGin     irq_flag: Option<IrqFlagsGuard>,
30*1496ba7bSLoGin     flags: SpinLockGuardFlags,
31ec53d23eSlogin }
32ec53d23eSlogin 
3390a0a490SLoGin impl<'a, T: 'a> SpinLockGuard<'a, T> {
3490a0a490SLoGin     /// 泄露自旋锁的守卫,返回一个可变的引用
3590a0a490SLoGin     ///
3690a0a490SLoGin     ///  ## Safety
3790a0a490SLoGin     ///
3890a0a490SLoGin     /// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确,
3990a0a490SLoGin     /// 因此必须小心的手动维护好preempt count。
4090a0a490SLoGin     ///
4190a0a490SLoGin     /// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。
4290a0a490SLoGin     #[inline]
4390a0a490SLoGin     pub unsafe fn leak(this: Self) -> &'a mut T {
4490a0a490SLoGin         // Use ManuallyDrop to avoid stacked-borrow invalidation
4590a0a490SLoGin         let this = ManuallyDrop::new(this);
4690a0a490SLoGin         // We know statically that only we are referencing data
4790a0a490SLoGin         unsafe { &mut *this.lock.data.get() }
4890a0a490SLoGin     }
49*1496ba7bSLoGin 
50*1496ba7bSLoGin     fn unlock_no_preempt(&self) {
51*1496ba7bSLoGin         unsafe {
52*1496ba7bSLoGin             self.lock.force_unlock();
53*1496ba7bSLoGin         }
54*1496ba7bSLoGin     }
5590a0a490SLoGin }
5690a0a490SLoGin 
57ec53d23eSlogin /// 向编译器保证,SpinLock在线程之间是安全的.
58ec53d23eSlogin /// 其中要求类型T实现了Send这个Trait
59ec53d23eSlogin unsafe impl<T> Sync for SpinLock<T> where T: Send {}
60ec53d23eSlogin 
61ec53d23eSlogin impl<T> SpinLock<T> {
62ec53d23eSlogin     pub const fn new(value: T) -> Self {
63ec53d23eSlogin         return Self {
64*1496ba7bSLoGin             lock: AtomicBool::new(false),
65ec53d23eSlogin             data: UnsafeCell::new(value),
66ec53d23eSlogin         };
67ec53d23eSlogin     }
68ec53d23eSlogin 
69ec53d23eSlogin     #[inline(always)]
70ec53d23eSlogin     pub fn lock(&self) -> SpinLockGuard<T> {
71*1496ba7bSLoGin         loop {
72*1496ba7bSLoGin             let res = self.try_lock();
73*1496ba7bSLoGin             if res.is_ok() {
74*1496ba7bSLoGin                 return res.unwrap();
75*1496ba7bSLoGin             }
76*1496ba7bSLoGin             spin_loop();
77*1496ba7bSLoGin         }
78*1496ba7bSLoGin     }
79*1496ba7bSLoGin 
80*1496ba7bSLoGin     /// 加锁,但是不更改preempt count
81*1496ba7bSLoGin     #[inline(always)]
82*1496ba7bSLoGin     pub fn lock_no_preempt(&self) -> SpinLockGuard<T> {
83*1496ba7bSLoGin         loop {
84*1496ba7bSLoGin             if let Ok(guard) = self.try_lock_no_preempt() {
85*1496ba7bSLoGin                 return guard;
86*1496ba7bSLoGin             }
87*1496ba7bSLoGin             spin_loop();
88*1496ba7bSLoGin         }
89bacd691cSlogin     }
90bacd691cSlogin 
91bacd691cSlogin     pub fn lock_irqsave(&self) -> SpinLockGuard<T> {
92*1496ba7bSLoGin         loop {
93*1496ba7bSLoGin             if let Ok(guard) = self.try_lock_irqsave() {
94*1496ba7bSLoGin                 return guard;
95*1496ba7bSLoGin             }
96*1496ba7bSLoGin             spin_loop();
97*1496ba7bSLoGin         }
98bacd691cSlogin     }
99bacd691cSlogin 
100bacd691cSlogin     pub fn try_lock(&self) -> Result<SpinLockGuard<T>, SystemError> {
101*1496ba7bSLoGin         // 先增加自旋锁持有计数
102*1496ba7bSLoGin         ProcessManager::preempt_disable();
103*1496ba7bSLoGin 
104*1496ba7bSLoGin         if self.inner_try_lock() {
105bacd691cSlogin             return Ok(SpinLockGuard {
106bacd691cSlogin                 lock: self,
107*1496ba7bSLoGin                 irq_flag: None,
108*1496ba7bSLoGin                 flags: SpinLockGuardFlags::empty(),
109bacd691cSlogin             });
110bacd691cSlogin         }
111*1496ba7bSLoGin 
112*1496ba7bSLoGin         // 如果加锁失败恢复自旋锁持有计数
113*1496ba7bSLoGin         ProcessManager::preempt_enable();
114*1496ba7bSLoGin 
11579a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
116bacd691cSlogin     }
117bacd691cSlogin 
118*1496ba7bSLoGin     fn inner_try_lock(&self) -> bool {
119*1496ba7bSLoGin         let res = self
120*1496ba7bSLoGin             .lock
121*1496ba7bSLoGin             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
122*1496ba7bSLoGin             .is_ok();
123*1496ba7bSLoGin         return res;
124*1496ba7bSLoGin     }
125*1496ba7bSLoGin 
126bacd691cSlogin     pub fn try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError> {
127*1496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
128*1496ba7bSLoGin         ProcessManager::preempt_disable();
129*1496ba7bSLoGin         if self.inner_try_lock() {
130bacd691cSlogin             return Ok(SpinLockGuard {
131bacd691cSlogin                 lock: self,
132*1496ba7bSLoGin                 irq_flag: Some(irq_guard),
133*1496ba7bSLoGin                 flags: SpinLockGuardFlags::empty(),
134*1496ba7bSLoGin             });
135*1496ba7bSLoGin         }
136*1496ba7bSLoGin         ProcessManager::preempt_enable();
137*1496ba7bSLoGin         drop(irq_guard);
138*1496ba7bSLoGin         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
139*1496ba7bSLoGin     }
140*1496ba7bSLoGin 
141*1496ba7bSLoGin     pub fn try_lock_no_preempt(&self) -> Result<SpinLockGuard<T>, SystemError> {
142*1496ba7bSLoGin         if self.inner_try_lock() {
143*1496ba7bSLoGin             return Ok(SpinLockGuard {
144*1496ba7bSLoGin                 lock: self,
145*1496ba7bSLoGin                 irq_flag: None,
146*1496ba7bSLoGin                 flags: SpinLockGuardFlags::NO_PREEMPT,
147bacd691cSlogin             });
148bacd691cSlogin         }
14979a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
150ec53d23eSlogin     }
15190a0a490SLoGin 
15290a0a490SLoGin     /// 强制解锁,并且不更改preempt count
15390a0a490SLoGin     ///
15490a0a490SLoGin     /// ## Safety
15590a0a490SLoGin     ///
15690a0a490SLoGin     /// 由于这样做可能导致preempt count不正确,因此必须小心的手动维护好preempt count。
15790a0a490SLoGin     /// 如非必要,请不要使用这个函数。
15890a0a490SLoGin     pub unsafe fn force_unlock(&self) {
159*1496ba7bSLoGin         self.lock.store(false, Ordering::Release);
160*1496ba7bSLoGin     }
161*1496ba7bSLoGin 
162*1496ba7bSLoGin     fn unlock(&self) {
163*1496ba7bSLoGin         self.lock.store(false, Ordering::Release);
164*1496ba7bSLoGin         ProcessManager::preempt_enable();
16590a0a490SLoGin     }
166ec53d23eSlogin }
167ec53d23eSlogin 
168ec53d23eSlogin /// 实现Deref trait,支持通过获取SpinLockGuard来获取临界区数据的不可变引用
169ec53d23eSlogin impl<T> Deref for SpinLockGuard<'_, T> {
170ec53d23eSlogin     type Target = T;
171ec53d23eSlogin 
172ec53d23eSlogin     fn deref(&self) -> &Self::Target {
173ec53d23eSlogin         return unsafe { &*self.lock.data.get() };
174ec53d23eSlogin     }
175ec53d23eSlogin }
176ec53d23eSlogin 
177ec53d23eSlogin /// 实现DerefMut trait,支持通过获取SpinLockGuard来获取临界区数据的可变引用
178ec53d23eSlogin impl<T> DerefMut for SpinLockGuard<'_, T> {
179ec53d23eSlogin     fn deref_mut(&mut self) -> &mut Self::Target {
180ec53d23eSlogin         return unsafe { &mut *self.lock.data.get() };
181ec53d23eSlogin     }
182ec53d23eSlogin }
183ec53d23eSlogin 
184ec53d23eSlogin /// @brief 为SpinLockGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况
185ec53d23eSlogin impl<T> Drop for SpinLockGuard<'_, T> {
186ec53d23eSlogin     fn drop(&mut self) {
187*1496ba7bSLoGin         if self.flags.contains(SpinLockGuardFlags::NO_PREEMPT) {
188*1496ba7bSLoGin             self.unlock_no_preempt();
189cde5492fSlogin         } else {
190*1496ba7bSLoGin             self.lock.unlock();
191ec53d23eSlogin         }
192*1496ba7bSLoGin         // restore irq
193*1496ba7bSLoGin         self.irq_flag.take();
194*1496ba7bSLoGin     }
195*1496ba7bSLoGin }
196*1496ba7bSLoGin 
197*1496ba7bSLoGin bitflags! {
198*1496ba7bSLoGin     struct SpinLockGuardFlags: u8 {
199*1496ba7bSLoGin         /// 守卫是由“*no_preempt”方法获得的
200*1496ba7bSLoGin         const NO_PREEMPT = (1<<0);
201ac643d42Slogin     }
202cde5492fSlogin }
203