修正rwlock有的地方由于未使用ManuallyDrop导致的use after free && spinlock守卫新增leak,spinlock新增force unlock功能.(#329)

1.修正rwlock有的地方由于未使用ManuallyDrop导致的use after free
2. spinlock守卫新增leak,spinlock新增force unlock功能.
This commit is contained in:
LoGin
2023-08-14 01:24:49 +08:00
committed by GitHub
parent c3dad0011d
commit 90a0a49048
2 changed files with 64 additions and 9 deletions

View File

@ -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<T> Sync for SpinLock<T> where T: Send {}
@ -223,6 +247,16 @@ impl<T> SpinLock<T> {
}
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来获取临界区数据的不可变引用