mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 04:56:30 +00:00
Patch fix sched (#419)
1.解决waitqueue sleep的时候,由于preempt count不为0,导致sched失败,从而导致该waitqueue下一次wakeup时,会把pcb多次加入调度队列的bug 2.修复socket inode 的read和write方法里面没有使用no_preempt的问题 3. 修复cpu0的内核栈由于脏数据导致new_idle的时候set pcb报错的问题 --------- Co-authored-by: longjin <longjin@DragonOS.org>
This commit is contained in:
@ -44,6 +44,7 @@ pub struct RwLock<T> {
|
||||
pub struct RwLockReadGuard<'a, T: 'a> {
|
||||
data: *const T,
|
||||
lock: &'a AtomicU32,
|
||||
irq_guard: Option<IrqFlagsGuard>,
|
||||
}
|
||||
|
||||
/// @brief UPGRADED是介于READER和WRITER之间的一种锁,它可以升级为WRITER,
|
||||
@ -53,6 +54,7 @@ pub struct RwLockReadGuard<'a, T: 'a> {
|
||||
pub struct RwLockUpgradableGuard<'a, T: 'a> {
|
||||
data: *const T,
|
||||
inner: &'a RwLock<T>,
|
||||
irq_guard: Option<IrqFlagsGuard>,
|
||||
}
|
||||
|
||||
/// @brief WRITER守卫的数据结构
|
||||
@ -144,6 +146,7 @@ impl<T> RwLock<T> {
|
||||
return Some(RwLockReadGuard {
|
||||
data: unsafe { &*self.data.get() },
|
||||
lock: &self.lock,
|
||||
irq_guard: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -160,6 +163,19 @@ impl<T> RwLock<T> {
|
||||
} //忙等待
|
||||
}
|
||||
|
||||
pub fn read_irqsave(&self) -> RwLockReadGuard<T> {
|
||||
loop {
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
match self.try_read() {
|
||||
Some(mut guard) => {
|
||||
guard.irq_guard = Some(irq_guard);
|
||||
return guard;
|
||||
}
|
||||
None => spin_loop(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief 获取读者+UPGRADER的数量, 不能保证能否获得同步值
|
||||
@ -256,6 +272,7 @@ impl<T> RwLock<T> {
|
||||
return Some(RwLockUpgradableGuard {
|
||||
inner: self,
|
||||
data: unsafe { &mut *self.data.get() },
|
||||
irq_guard: None,
|
||||
});
|
||||
} else {
|
||||
return None;
|
||||
@ -274,6 +291,21 @@ impl<T> RwLock<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// @brief 获得UPGRADER守卫
|
||||
pub fn upgradeable_read_irqsave(&self) -> RwLockUpgradableGuard<T> {
|
||||
loop {
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
match self.try_upgradeable_read() {
|
||||
Some(mut guard) => {
|
||||
guard.irq_guard = Some(irq_guard);
|
||||
return guard;
|
||||
}
|
||||
None => spin_loop(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
//extremely unsafe behavior
|
||||
@ -332,7 +364,7 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> {
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief 尝试将UPGRADER守卫升级为WRITER守卫
|
||||
pub fn try_upgrade(self) -> Result<RwLockWriteGuard<'rwlock, T>, Self> {
|
||||
pub fn try_upgrade(mut self) -> Result<RwLockWriteGuard<'rwlock, T>, Self> {
|
||||
let res = self.inner.lock.compare_exchange(
|
||||
UPGRADED,
|
||||
WRITER,
|
||||
@ -343,13 +375,13 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> {
|
||||
|
||||
if res.is_ok() {
|
||||
let inner = self.inner;
|
||||
|
||||
let irq_guard = self.irq_guard.take();
|
||||
mem::forget(self);
|
||||
|
||||
Ok(RwLockWriteGuard {
|
||||
data: unsafe { &mut *inner.data.get() },
|
||||
inner,
|
||||
irq_guard: None,
|
||||
irq_guard,
|
||||
})
|
||||
} else {
|
||||
Err(self)
|
||||
@ -373,19 +405,20 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> {
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief UPGRADER降级为READER
|
||||
pub fn downgrade(self) -> RwLockReadGuard<'rwlock, T> {
|
||||
pub fn downgrade(mut self) -> RwLockReadGuard<'rwlock, T> {
|
||||
while self.inner.current_reader().is_err() {
|
||||
spin_loop();
|
||||
}
|
||||
|
||||
let inner: &RwLock<T> = self.inner;
|
||||
|
||||
let irq_guard = self.irq_guard.take();
|
||||
// 自动移去UPGRADED比特位
|
||||
mem::drop(self);
|
||||
|
||||
RwLockReadGuard {
|
||||
data: unsafe { &*inner.data.get() },
|
||||
lock: &inner.lock,
|
||||
irq_guard,
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,26 +459,27 @@ impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief 将WRITER降级为READER
|
||||
pub fn downgrade(self) -> RwLockReadGuard<'rwlock, T> {
|
||||
pub fn downgrade(mut self) -> RwLockReadGuard<'rwlock, T> {
|
||||
while self.inner.current_reader().is_err() {
|
||||
spin_loop();
|
||||
}
|
||||
//本质上来说绝对保证没有任何读者
|
||||
|
||||
let inner = self.inner;
|
||||
|
||||
let irq_guard = self.irq_guard.take();
|
||||
mem::drop(self);
|
||||
|
||||
return RwLockReadGuard {
|
||||
data: unsafe { &*inner.data.get() },
|
||||
lock: &inner.lock,
|
||||
irq_guard,
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief 将WRITER降级为UPGRADER
|
||||
pub fn downgrade_to_upgradeable(self) -> RwLockUpgradableGuard<'rwlock, T> {
|
||||
pub fn downgrade_to_upgradeable(mut self) -> RwLockUpgradableGuard<'rwlock, T> {
|
||||
debug_assert_eq!(
|
||||
self.inner.lock.load(Ordering::Acquire) & (WRITER | UPGRADED),
|
||||
WRITER
|
||||
@ -455,11 +489,13 @@ impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
|
||||
|
||||
let inner = self.inner;
|
||||
|
||||
let irq_guard = self.irq_guard.take();
|
||||
mem::forget(self);
|
||||
|
||||
return RwLockUpgradableGuard {
|
||||
inner,
|
||||
data: unsafe { &*inner.data.get() },
|
||||
irq_guard,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
#![allow(dead_code)]
|
||||
use core::intrinsics::unlikely;
|
||||
|
||||
use alloc::{collections::LinkedList, sync::Arc, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
@ -26,8 +28,20 @@ pub struct WaitQueue(SpinLock<InnerWaitQueue>);
|
||||
impl WaitQueue {
|
||||
pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT));
|
||||
|
||||
fn before_sleep_check(&self, max_preempt: usize) {
|
||||
let pcb = ProcessManager::current_pcb();
|
||||
if unlikely(pcb.preempt_count() > max_preempt) {
|
||||
kwarn!(
|
||||
"Process {:?}: Try to sleep when preempt count is {}",
|
||||
pcb.pid(),
|
||||
pcb.preempt_count()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
|
||||
pub fn sleep(&self) {
|
||||
self.before_sleep_check(0);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
|
||||
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
|
||||
panic!("sleep error: {:?}", e);
|
||||
@ -42,6 +56,7 @@ impl WaitQueue {
|
||||
where
|
||||
F: FnOnce(),
|
||||
{
|
||||
self.before_sleep_check(0);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
|
||||
@ -50,6 +65,7 @@ impl WaitQueue {
|
||||
drop(irq_guard);
|
||||
guard.wait_list.push_back(ProcessManager::current_pcb());
|
||||
f();
|
||||
|
||||
drop(guard);
|
||||
sched();
|
||||
}
|
||||
@ -69,6 +85,7 @@ impl WaitQueue {
|
||||
/// 由于sleep_without_schedule不会调用调度函数,因此,如果开发者忘记在执行本函数之后,手动调用调度函数,
|
||||
/// 由于时钟中断到来或者‘其他cpu kick了当前cpu’,可能会导致一些未定义的行为。
|
||||
pub unsafe fn sleep_without_schedule(&self) {
|
||||
self.before_sleep_check(0);
|
||||
// 安全检查:确保当前处于中断禁止状态
|
||||
assert!(CurrentIrqArch::is_irq_enabled() == false);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
@ -80,6 +97,7 @@ impl WaitQueue {
|
||||
}
|
||||
|
||||
pub unsafe fn sleep_without_schedule_uninterruptible(&self) {
|
||||
self.before_sleep_check(0);
|
||||
// 安全检查:确保当前处于中断禁止状态
|
||||
assert!(CurrentIrqArch::is_irq_enabled() == false);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
@ -91,6 +109,7 @@ impl WaitQueue {
|
||||
}
|
||||
/// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
|
||||
pub fn sleep_uninterruptible(&self) {
|
||||
self.before_sleep_check(0);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
|
||||
@ -105,6 +124,7 @@ impl WaitQueue {
|
||||
/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
|
||||
/// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
|
||||
pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
|
||||
self.before_sleep_check(1);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
|
||||
@ -120,6 +140,7 @@ impl WaitQueue {
|
||||
/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
|
||||
/// 在当前进程的pcb加入队列后,解锁指定的Mutex。
|
||||
pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
|
||||
self.before_sleep_check(1);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
|
||||
@ -135,6 +156,7 @@ impl WaitQueue {
|
||||
/// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
|
||||
/// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
|
||||
pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
|
||||
self.before_sleep_check(1);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
|
||||
@ -150,6 +172,7 @@ impl WaitQueue {
|
||||
/// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
|
||||
/// 在当前进程的pcb加入队列后,解锁指定的Mutex。
|
||||
pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
|
||||
self.before_sleep_check(1);
|
||||
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
|
||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
|
||||
|
Reference in New Issue
Block a user