diff --git a/kernel/src/libs/rwlock.rs b/kernel/src/libs/rwlock.rs index 39917a9cb..cd357fe72 100644 --- a/kernel/src/libs/rwlock.rs +++ b/kernel/src/libs/rwlock.rs @@ -292,12 +292,19 @@ impl From for RwLock { } impl<'rwlock, T> RwLockReadGuard<'rwlock, T> { + /// @brief 释放守卫,获得保护的值的不可变引用 + /// + /// ## Safety + /// + /// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确, + /// 因此必须小心的手动维护好preempt count。 + /// + /// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。 #[allow(dead_code)] #[inline] - /// @brief 释放守卫,获得保护的值的不可变引用 - pub fn leak(this: Self) -> &'rwlock T { - let Self { data, .. } = this; - return unsafe { &*data }; + pub unsafe fn leak(this: Self) -> &'rwlock T { + let this = ManuallyDrop::new(this); + return unsafe { &*this.data }; } } @@ -363,9 +370,16 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> { #[allow(dead_code)] #[inline] - /// @brief 返回内部数据的引用,消除锁 - pub fn leak(this: Self) -> &'rwlock T { - let this = ManuallyDrop::new(this); + /// @brief 返回内部数据的引用,消除守卫 + /// + /// ## Safety + /// + /// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确, + /// 因此必须小心的手动维护好preempt count。 + /// + /// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。 + pub unsafe fn leak(this: Self) -> &'rwlock T { + let this: ManuallyDrop> = ManuallyDrop::new(this); unsafe { &*this.data } } @@ -374,8 +388,15 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> { impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> { #[allow(dead_code)] #[inline] - /// @brief 返回内部数据的引用,消除锁 - pub fn leak(this: Self) -> &'rwlock T { + /// @brief 返回内部数据的引用,消除守卫 + /// + /// ## Safety + /// + /// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确, + /// 因此必须小心的手动维护好preempt count。 + /// + /// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。 + pub unsafe fn leak(this: Self) -> &'rwlock T { let this = ManuallyDrop::new(this); return unsafe { &*this.data }; diff --git a/kernel/src/libs/spinlock.rs b/kernel/src/libs/spinlock.rs index b3548778b..1108b12f8 100644 --- a/kernel/src/libs/spinlock.rs +++ b/kernel/src/libs/spinlock.rs @@ -1,5 +1,6 @@ #![allow(dead_code)] use core::cell::UnsafeCell; +use core::mem::ManuallyDrop; use core::ops::{Deref, DerefMut}; use core::ptr::read_volatile; @@ -107,6 +108,11 @@ impl RawSpinlock { self.0.store(false, Ordering::Release); } + /// 解锁,但是不更改preempt count + unsafe fn unlock_no_preempt(&self) { + self.0.store(false, Ordering::Release); + } + /// @brief 放锁并开中断 pub fn unlock_irq(&self) { self.unlock(); @@ -170,6 +176,24 @@ pub struct SpinLockGuard<'a, T: 'a> { flag: usize, } +impl<'a, T: 'a> SpinLockGuard<'a, T> { + /// 泄露自旋锁的守卫,返回一个可变的引用 + /// + /// ## Safety + /// + /// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确, + /// 因此必须小心的手动维护好preempt count。 + /// + /// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。 + #[inline] + pub unsafe fn leak(this: Self) -> &'a mut T { + // Use ManuallyDrop to avoid stacked-borrow invalidation + let this = ManuallyDrop::new(this); + // We know statically that only we are referencing data + unsafe { &mut *this.lock.data.get() } + } +} + /// 向编译器保证,SpinLock在线程之间是安全的. /// 其中要求类型T实现了Send这个Trait unsafe impl Sync for SpinLock where T: Send {} @@ -223,6 +247,16 @@ impl SpinLock { } return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); } + + /// 强制解锁,并且不更改preempt count + /// + /// ## Safety + /// + /// 由于这样做可能导致preempt count不正确,因此必须小心的手动维护好preempt count。 + /// 如非必要,请不要使用这个函数。 + pub unsafe fn force_unlock(&self) { + self.lock.unlock_no_preempt(); + } } /// 实现Deref trait,支持通过获取SpinLockGuard来获取临界区数据的不可变引用