xref: /DragonOS/kernel/src/libs/spinlock.rs (revision 79a452ce8f27ad9c7283ac0bcf4078ed6fa018d7)
166f67c6aSlogin #![allow(dead_code)]
2ec53d23eSlogin use core::cell::UnsafeCell;
3ec53d23eSlogin use core::ops::{Deref, DerefMut};
466f67c6aSlogin use core::ptr::read_volatile;
566f67c6aSlogin 
6ac643d42Slogin use core::sync::atomic::{AtomicBool, Ordering};
7ac643d42Slogin 
8adc1846bSlogin use crate::arch::asm::irqflags::{local_irq_restore, local_irq_save};
9adc1846bSlogin use crate::arch::interrupt::{cli, sti};
1066f67c6aSlogin use crate::include::bindings::bindings::{spin_lock, spin_unlock, spinlock_t};
11ac643d42Slogin use crate::process::preempt::{preempt_disable, preempt_enable};
12bacd691cSlogin use crate::syscall::SystemError;
1366f67c6aSlogin 
1466f67c6aSlogin /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
151a2eaa40Slogin #[inline]
1666f67c6aSlogin pub fn spin_lock_irqsave(lock: *mut spinlock_t, flags: &mut u64) {
1766f67c6aSlogin     local_irq_save(flags);
1866f67c6aSlogin     unsafe {
1966f67c6aSlogin         spin_lock(lock);
2066f67c6aSlogin     }
2166f67c6aSlogin }
2266f67c6aSlogin 
2366f67c6aSlogin /// @brief 恢复rflags以及中断状态并解锁自旋锁
241a2eaa40Slogin #[inline]
2566f67c6aSlogin pub fn spin_unlock_irqrestore(lock: *mut spinlock_t, flags: &u64) {
2666f67c6aSlogin     unsafe {
2766f67c6aSlogin         spin_unlock(lock);
2866f67c6aSlogin     }
2966f67c6aSlogin     // kdebug!("123");
3066f67c6aSlogin     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 
111ac643d42Slogin     /// @brief 放锁并开中断
112ec53d23eSlogin     pub fn unlock_irq(&self) {
113ac643d42Slogin         self.unlock();
114ac643d42Slogin         sti();
115ac643d42Slogin     }
116ac643d42Slogin 
11761de2cdcSlogin     /// @brief 判断自旋锁是否被上锁
11861de2cdcSlogin     ///
11961de2cdcSlogin     /// @return true 自旋锁被上锁
12061de2cdcSlogin     /// @return false 自旋锁处于解锁状态
121ec53d23eSlogin     pub fn is_locked(&self) -> bool {
12261de2cdcSlogin         return self.0.load(Ordering::Relaxed).into();
12361de2cdcSlogin     }
12461de2cdcSlogin 
12561de2cdcSlogin     /// @brief 强制设置自旋锁的状态
12661de2cdcSlogin     /// 请注意,这样操作可能会带来未知的风险。因此它是unsafe的。(尽管从Rust语言本身来说,它是safe的)
12761de2cdcSlogin     pub unsafe fn set_value(&mut self, value: bool) {
12861de2cdcSlogin         self.0.store(value, Ordering::SeqCst);
12961de2cdcSlogin     }
13061de2cdcSlogin 
131d8a06412SGou Ngai     /// @brief 保存中断状态到flags中,关闭中断,并对自旋锁加锁
132d8a06412SGou Ngai     pub fn lock_irqsave(&self, flags: &mut u64) {
133d8a06412SGou Ngai         local_irq_save(flags);
134d8a06412SGou Ngai         self.lock();
135ec53d23eSlogin     }
136ac643d42Slogin 
137d8a06412SGou Ngai     /// @brief 恢复rflags以及中断状态并解锁自旋锁
138d8a06412SGou Ngai     pub fn unlock_irqrestore(&self, flags: &u64) {
139d8a06412SGou Ngai         self.unlock();
140d8a06412SGou Ngai         local_irq_restore(flags);
141d8a06412SGou Ngai     }
142bacd691cSlogin 
143bacd691cSlogin     /// @brief 尝试保存中断状态到flags中,关闭中断,并对自旋锁加锁
144bacd691cSlogin     /// @return 加锁成功->true
145bacd691cSlogin     ///         加锁失败->false
146bacd691cSlogin     #[inline(always)]
147bacd691cSlogin     pub fn try_lock_irqsave(&self, flags: &mut u64) -> bool {
148bacd691cSlogin         local_irq_save(flags);
149bacd691cSlogin         if self.try_lock() {
150bacd691cSlogin             return true;
151bacd691cSlogin         }
152bacd691cSlogin         local_irq_restore(flags);
153bacd691cSlogin         return false;
154bacd691cSlogin     }
155d8a06412SGou Ngai }
156ec53d23eSlogin /// 实现了守卫的SpinLock, 能够支持内部可变性
157ec53d23eSlogin ///
158ec53d23eSlogin #[derive(Debug)]
159ec53d23eSlogin pub struct SpinLock<T> {
160ec53d23eSlogin     lock: RawSpinlock,
161ec53d23eSlogin     /// 自旋锁保护的数据
162ec53d23eSlogin     data: UnsafeCell<T>,
163ec53d23eSlogin }
164ec53d23eSlogin 
165ec53d23eSlogin /// SpinLock的守卫
166ec53d23eSlogin /// 该守卫没有构造器,并且其信息均为私有的。我们只能通过SpinLock的lock()方法获得一个守卫。
167ec53d23eSlogin /// 因此我们可以认为,只要能够获得一个守卫,那么数据就在自旋锁的保护之下。
168ec53d23eSlogin #[derive(Debug)]
169ec53d23eSlogin pub struct SpinLockGuard<'a, T: 'a> {
170ec53d23eSlogin     lock: &'a SpinLock<T>,
171bacd691cSlogin     flag: u64,
172ec53d23eSlogin }
173ec53d23eSlogin 
174ec53d23eSlogin /// 向编译器保证,SpinLock在线程之间是安全的.
175ec53d23eSlogin /// 其中要求类型T实现了Send这个Trait
176ec53d23eSlogin unsafe impl<T> Sync for SpinLock<T> where T: Send {}
177ec53d23eSlogin 
178ec53d23eSlogin impl<T> SpinLock<T> {
179ec53d23eSlogin     pub const fn new(value: T) -> Self {
180ec53d23eSlogin         return Self {
181ec53d23eSlogin             lock: RawSpinlock::INIT,
182ec53d23eSlogin             data: UnsafeCell::new(value),
183ec53d23eSlogin         };
184ec53d23eSlogin     }
185ec53d23eSlogin 
186ec53d23eSlogin     #[inline(always)]
187ec53d23eSlogin     pub fn lock(&self) -> SpinLockGuard<T> {
188ec53d23eSlogin         self.lock.lock();
189ec53d23eSlogin         // 加锁成功,返回一个守卫
190bacd691cSlogin         return SpinLockGuard {
191bacd691cSlogin             lock: self,
192bacd691cSlogin             flag: 0,
193bacd691cSlogin         };
194bacd691cSlogin     }
195bacd691cSlogin 
196bacd691cSlogin     pub fn lock_irqsave(&self) -> SpinLockGuard<T> {
197bacd691cSlogin         let mut flags: u64 = 0;
198bacd691cSlogin         self.lock.lock_irqsave(&mut flags);
199bacd691cSlogin         // 加锁成功,返回一个守卫
200bacd691cSlogin         return SpinLockGuard {
201bacd691cSlogin             lock: self,
202bacd691cSlogin             flag: flags,
203bacd691cSlogin         };
204bacd691cSlogin     }
205bacd691cSlogin 
206bacd691cSlogin     pub fn try_lock(&self) -> Result<SpinLockGuard<T>, SystemError> {
207bacd691cSlogin         if self.lock.try_lock() {
208bacd691cSlogin             return Ok(SpinLockGuard {
209bacd691cSlogin                 lock: self,
210bacd691cSlogin                 flag: 0,
211bacd691cSlogin             });
212bacd691cSlogin         }
213*79a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
214bacd691cSlogin     }
215bacd691cSlogin 
216bacd691cSlogin     pub fn try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError> {
217bacd691cSlogin         let mut flags: u64 = 0;
218bacd691cSlogin         if self.lock.try_lock_irqsave(&mut flags) {
219bacd691cSlogin             return Ok(SpinLockGuard {
220bacd691cSlogin                 lock: self,
221bacd691cSlogin                 flag: flags,
222bacd691cSlogin             });
223bacd691cSlogin         }
224*79a452ceShoumkh         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
225ec53d23eSlogin     }
226ec53d23eSlogin }
227ec53d23eSlogin 
228ec53d23eSlogin /// 实现Deref trait,支持通过获取SpinLockGuard来获取临界区数据的不可变引用
229ec53d23eSlogin impl<T> Deref for SpinLockGuard<'_, T> {
230ec53d23eSlogin     type Target = T;
231ec53d23eSlogin 
232ec53d23eSlogin     fn deref(&self) -> &Self::Target {
233ec53d23eSlogin         return unsafe { &*self.lock.data.get() };
234ec53d23eSlogin     }
235ec53d23eSlogin }
236ec53d23eSlogin 
237ec53d23eSlogin /// 实现DerefMut trait,支持通过获取SpinLockGuard来获取临界区数据的可变引用
238ec53d23eSlogin impl<T> DerefMut for SpinLockGuard<'_, T> {
239ec53d23eSlogin     fn deref_mut(&mut self) -> &mut Self::Target {
240ec53d23eSlogin         return unsafe { &mut *self.lock.data.get() };
241ec53d23eSlogin     }
242ec53d23eSlogin }
243ec53d23eSlogin 
244ec53d23eSlogin /// @brief 为SpinLockGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况
245ec53d23eSlogin impl<T> Drop for SpinLockGuard<'_, T> {
246ec53d23eSlogin     fn drop(&mut self) {
247ec53d23eSlogin         self.lock.lock.unlock();
248ec53d23eSlogin     }
249ac643d42Slogin }
250