spinlock.rs 6.2 KB

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