Skip to content

Commit

Permalink
修复wakeup的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
fslongjin committed Aug 27, 2023
1 parent 2131757 commit 2890056
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 23 deletions.
7 changes: 0 additions & 7 deletions kernel/src/filesystem/vfs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,11 +523,4 @@ impl FileDescriptorVec {

return Ok(());
}

/// 释放文件描述符数组
pub fn drop_fds(&mut self) {
for i in 0..self.fds.len() {
self.fds[i] = None;
}
}
}
43 changes: 31 additions & 12 deletions kernel/src/libs/wait_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use alloc::{collections::LinkedList, sync::Arc, vec::Vec};
use crate::{
arch::{sched::sched, CurrentIrqArch},
exception::InterruptArch,
kerror,
process::{ProcessControlBlock, ProcessManager, ProcessState},
};

Expand All @@ -28,7 +29,9 @@ impl WaitQueue {
/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
pub fn sleep(&self) {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
ProcessManager::sleep(true);
ProcessManager::sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard);
sched();
Expand All @@ -40,7 +43,9 @@ impl WaitQueue {
F: FnOnce(),
{
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
ProcessManager::sleep(true);
ProcessManager::sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
f();
drop(guard);
Expand All @@ -65,14 +70,18 @@ impl WaitQueue {
// 安全检查:确保当前处于中断禁止状态
assert!(CurrentIrqArch::is_irq_enabled() == false);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
ProcessManager::sleep(true);
ProcessManager::sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard);
}
/// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
pub fn sleep_uninterruptible(&self) {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
ProcessManager::sleep(false);
ProcessManager::sleep(false).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard);
sched();
Expand All @@ -82,7 +91,9 @@ impl WaitQueue {
/// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
ProcessManager::sleep(true);
ProcessManager::sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(to_unlock);
drop(guard);
Expand All @@ -93,7 +104,9 @@ impl WaitQueue {
/// 在当前进程的pcb加入队列后,解锁指定的Mutex。
pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
ProcessManager::sleep(true);
ProcessManager::sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(to_unlock);
drop(guard);
Expand All @@ -104,7 +117,9 @@ impl WaitQueue {
/// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
ProcessManager::sleep(false);
ProcessManager::sleep(false).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(to_unlock);
drop(guard);
Expand All @@ -115,7 +130,9 @@ impl WaitQueue {
/// 在当前进程的pcb加入队列后,解锁指定的Mutex。
pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
ProcessManager::sleep(false);
ProcessManager::sleep(false).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(to_unlock);
drop(guard);
Expand All @@ -142,8 +159,8 @@ impl WaitQueue {
}
}
let to_wakeup = guard.wait_list.pop_front().unwrap();
ProcessManager::wakeup(&to_wakeup);
return true;
let res = ProcessManager::wakeup(&to_wakeup).is_ok();
return res;
}

/// @brief 唤醒在队列中,符合条件的所有进程。
Expand All @@ -160,8 +177,10 @@ impl WaitQueue {
// 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
while let Some(to_wakeup) = guard.wait_list.pop_front() {
if let Some(state) = state {
if to_wakeup.sched_info().state() != state {
ProcessManager::wakeup(&to_wakeup);
if to_wakeup.sched_info().state() == state {
ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.basic().pid(), e);
});
continue;
}
}
Expand Down
34 changes: 30 additions & 4 deletions kernel/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,19 +154,28 @@ impl ProcessManager {

/// 唤醒一个进程
pub fn wakeup(pcb: &Arc<ProcessControlBlock>) -> Result<(), SystemError> {
if pcb.sched_info().state() != ProcessState::Runnable {
let state = pcb.sched_info().state();
if state.is_blocked() {
let mut writer = pcb.sched_info_mut();
if writer.state() != ProcessState::Runnable {
let state = writer.state();
if state.is_blocked() {
writer.set_state(ProcessState::Runnable);
sched_enqueue(pcb.clone(), true);
return Ok(());
} else if state.is_exited() {
return Err(SystemError::EINVAL);
} else {
return Ok(());
}
} else if state.is_exited() {
return Err(SystemError::EINVAL);
} else {
return Ok(());
}
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
}

/// 标志当前进程永久睡眠,移出调度队列
pub unsafe fn sleep(interruptable: bool) -> Result<(), SystemError> {
pub fn sleep(interruptable: bool) -> Result<(), SystemError> {
let pcb = ProcessManager::current_pcb();
let mut writer = pcb.sched_info_mut();
if writer.state() != ProcessState::Exited(0) {
Expand Down Expand Up @@ -291,6 +300,23 @@ pub enum ProcessState {
Exited(usize),
}

impl ProcessState {
#[inline(always)]
pub fn is_runnable(&self) -> bool {
return matches!(self, ProcessState::Runnable);
}

#[inline(always)]
pub fn is_blocked(&self) -> bool {
return matches!(self, ProcessState::Blocked(_));
}

#[inline(always)]
pub fn is_exited(&self) -> bool {
return matches!(self, ProcessState::Exited(_));
}
}

bitflags! {
/// pcb的标志位
pub struct ProcessFlags: usize {
Expand Down

0 comments on commit 2890056

Please sign in to comment.