1 #![allow(dead_code)] 2 use core::cell::UnsafeCell; 3 use core::hint::spin_loop; 4 use core::mem::ManuallyDrop; 5 use core::ops::{Deref, DerefMut}; 6 7 use core::sync::atomic::{AtomicBool, Ordering}; 8 9 use crate::arch::CurrentIrqArch; 10 use crate::exception::{InterruptArch, IrqFlagsGuard}; 11 use crate::process::ProcessManager; 12 use system_error::SystemError; 13 14 /// 实现了守卫的SpinLock, 能够支持内部可变性 15 /// 16 #[derive(Debug)] 17 pub struct SpinLock<T> { 18 lock: AtomicBool, 19 /// 自旋锁保护的数据 20 data: UnsafeCell<T>, 21 } 22 23 /// SpinLock的守卫 24 /// 该守卫没有构造器,并且其信息均为私有的。我们只能通过SpinLock的lock()方法获得一个守卫。 25 /// 因此我们可以认为,只要能够获得一个守卫,那么数据就在自旋锁的保护之下。 26 #[derive(Debug)] 27 pub struct SpinLockGuard<'a, T: 'a> { 28 lock: &'a SpinLock<T>, 29 data: *mut T, 30 irq_flag: Option<IrqFlagsGuard>, 31 flags: SpinLockGuardFlags, 32 } 33 34 impl<'a, T: 'a> SpinLockGuard<'a, T> { 35 /// 泄露自旋锁的守卫,返回一个可变的引用 36 /// 37 /// ## Safety 38 /// 39 /// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确, 40 /// 因此必须小心的手动维护好preempt count。 41 /// 42 /// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。 43 #[inline] leak(this: Self) -> &'a mut T44 pub unsafe fn leak(this: Self) -> &'a mut T { 45 // Use ManuallyDrop to avoid stacked-borrow invalidation 46 let this = ManuallyDrop::new(this); 47 // We know statically that only we are referencing data 48 unsafe { &mut *this.lock.data.get() } 49 } 50 unlock_no_preempt(&self)51 fn unlock_no_preempt(&self) { 52 unsafe { 53 self.lock.force_unlock(); 54 } 55 } 56 } 57 58 /// 向编译器保证,SpinLock在线程之间是安全的. 59 /// 其中要求类型T实现了Send这个Trait 60 unsafe impl<T> Sync for SpinLock<T> where T: Send {} 61 62 impl<T> SpinLock<T> { new(value: T) -> Self63 pub const fn new(value: T) -> Self { 64 return Self { 65 lock: AtomicBool::new(false), 66 data: UnsafeCell::new(value), 67 }; 68 } 69 70 #[inline(always)] lock(&self) -> SpinLockGuard<T>71 pub fn lock(&self) -> SpinLockGuard<T> { 72 loop { 73 let res = self.try_lock(); 74 if res.is_ok() { 75 return res.unwrap(); 76 } 77 spin_loop(); 78 } 79 } 80 81 /// 加锁,但是不更改preempt count 82 #[inline(always)] lock_no_preempt(&self) -> SpinLockGuard<T>83 pub fn lock_no_preempt(&self) -> SpinLockGuard<T> { 84 loop { 85 if let Ok(guard) = self.try_lock_no_preempt() { 86 return guard; 87 } 88 spin_loop(); 89 } 90 } 91 lock_irqsave(&self) -> SpinLockGuard<T>92 pub fn lock_irqsave(&self) -> SpinLockGuard<T> { 93 loop { 94 if let Ok(guard) = self.try_lock_irqsave() { 95 return guard; 96 } 97 spin_loop(); 98 } 99 } 100 try_lock(&self) -> Result<SpinLockGuard<T>, SystemError>101 pub fn try_lock(&self) -> Result<SpinLockGuard<T>, SystemError> { 102 // 先增加自旋锁持有计数 103 ProcessManager::preempt_disable(); 104 105 if self.inner_try_lock() { 106 return Ok(SpinLockGuard { 107 lock: self, 108 data: unsafe { &mut *self.data.get() }, 109 irq_flag: None, 110 flags: SpinLockGuardFlags::empty(), 111 }); 112 } 113 114 // 如果加锁失败恢复自旋锁持有计数 115 ProcessManager::preempt_enable(); 116 117 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 118 } 119 inner_try_lock(&self) -> bool120 fn inner_try_lock(&self) -> bool { 121 let res = self 122 .lock 123 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) 124 .is_ok(); 125 return res; 126 } 127 try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError>128 pub fn try_lock_irqsave(&self) -> Result<SpinLockGuard<T>, SystemError> { 129 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 130 ProcessManager::preempt_disable(); 131 if self.inner_try_lock() { 132 return Ok(SpinLockGuard { 133 lock: self, 134 data: unsafe { &mut *self.data.get() }, 135 irq_flag: Some(irq_guard), 136 flags: SpinLockGuardFlags::empty(), 137 }); 138 } 139 ProcessManager::preempt_enable(); 140 drop(irq_guard); 141 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 142 } 143 try_lock_no_preempt(&self) -> Result<SpinLockGuard<T>, SystemError>144 pub fn try_lock_no_preempt(&self) -> Result<SpinLockGuard<T>, SystemError> { 145 if self.inner_try_lock() { 146 return Ok(SpinLockGuard { 147 lock: self, 148 data: unsafe { &mut *self.data.get() }, 149 irq_flag: None, 150 flags: SpinLockGuardFlags::NO_PREEMPT, 151 }); 152 } 153 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 154 } 155 156 /// 强制解锁,并且不更改preempt count 157 /// 158 /// ## Safety 159 /// 160 /// 由于这样做可能导致preempt count不正确,因此必须小心的手动维护好preempt count。 161 /// 如非必要,请不要使用这个函数。 force_unlock(&self)162 pub unsafe fn force_unlock(&self) { 163 self.lock.store(false, Ordering::SeqCst); 164 } 165 unlock(&self)166 fn unlock(&self) { 167 self.lock.store(false, Ordering::SeqCst); 168 ProcessManager::preempt_enable(); 169 } 170 } 171 172 /// 实现Deref trait,支持通过获取SpinLockGuard来获取临界区数据的不可变引用 173 impl<T> Deref for SpinLockGuard<'_, T> { 174 type Target = T; 175 deref(&self) -> &Self::Target176 fn deref(&self) -> &Self::Target { 177 return unsafe { &*self.data }; 178 } 179 } 180 181 /// 实现DerefMut trait,支持通过获取SpinLockGuard来获取临界区数据的可变引用 182 impl<T> DerefMut for SpinLockGuard<'_, T> { deref_mut(&mut self) -> &mut Self::Target183 fn deref_mut(&mut self) -> &mut Self::Target { 184 return unsafe { &mut *self.data }; 185 } 186 } 187 188 /// @brief 为SpinLockGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况 189 impl<T> Drop for SpinLockGuard<'_, T> { drop(&mut self)190 fn drop(&mut self) { 191 if self.flags.contains(SpinLockGuardFlags::NO_PREEMPT) { 192 self.unlock_no_preempt(); 193 } else { 194 self.lock.unlock(); 195 } 196 // restore irq 197 self.irq_flag.take(); 198 } 199 } 200 201 bitflags! { 202 struct SpinLockGuardFlags: u8 { 203 /// 守卫是由“*no_preempt”方法获得的 204 const NO_PREEMPT = (1<<0); 205 } 206 } 207