From 95868335df1c55b9f3cec2a6ecac5a949f625d0d Mon Sep 17 00:00:00 2001 From: Chiichen <39649411+Chiichen@users.noreply.github.com> Date: Thu, 24 Aug 2023 22:11:20 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4rust=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E7=9A=84waitqueue=E4=B8=AD=E7=9A=84pcb=E4=B8=BA=E6=96=B0?= =?UTF-8?q?=E7=89=88=E7=9A=84pcb=20(#343)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/ipc/pipe.rs | 18 +++++--- kernel/src/libs/semaphore.rs | 6 +-- kernel/src/libs/wait_queue.rs | 78 ++++++++++++++++------------------- kernel/src/net/net_core.rs | 4 +- kernel/src/process/kthread.rs | 2 +- kernel/src/process/mod.rs | 15 +++++-- 6 files changed, 66 insertions(+), 57 deletions(-) diff --git a/kernel/src/ipc/pipe.rs b/kernel/src/ipc/pipe.rs index 863d60023..62adb8dba 100644 --- a/kernel/src/ipc/pipe.rs +++ b/kernel/src/ipc/pipe.rs @@ -5,8 +5,8 @@ use crate::{ core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, PollStatus, }, - include::bindings::bindings::PROC_INTERRUPTIBLE, libs::{spinlock::SpinLock, wait_queue::WaitQueue}, + process::ProcessState, syscall::SystemError, time::TimeSpec, }; @@ -87,7 +87,9 @@ impl IndexNode for LockedPipeInode { //如果管道里面没有数据,则唤醒写端, while inode.valid_cnt == 0 { - inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into()); + inode + .write_wait_queue + .wakeup(Some(ProcessState::Blocked(true))); // 在读等待队列中睡眠,并释放锁 unsafe { @@ -126,7 +128,9 @@ impl IndexNode for LockedPipeInode { inode.valid_cnt -= num as i32; //读完后解锁并唤醒等待在写等待队列中的进程 - inode.write_wait_queue.wakeup(PROC_INTERRUPTIBLE.into()); + inode + .write_wait_queue + .wakeup(Some(ProcessState::Blocked(true))); //返回读取的字节数 return Ok(num); } @@ -169,7 +173,9 @@ impl IndexNode for LockedPipeInode { while len + inode.valid_cnt as usize > PIPE_BUFF_SIZE { // 唤醒读端 - inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into()); + inode + .read_wait_queue + .wakeup(Some(ProcessState::Blocked(true))); // 解锁并睡眠 unsafe { let irq_guard = CurrentIrqArch::save_and_disable_irq(); @@ -197,7 +203,9 @@ impl IndexNode for LockedPipeInode { inode.valid_cnt += len as i32; // 读完后解锁并唤醒等待在读等待队列中的进程 - inode.read_wait_queue.wakeup(PROC_INTERRUPTIBLE.into()); + inode + .read_wait_queue + .wakeup(Some(ProcessState::Blocked(true))); // 返回写入的字节数 return Ok(len); } diff --git a/kernel/src/libs/semaphore.rs b/kernel/src/libs/semaphore.rs index 973551b7f..970d66805 100644 --- a/kernel/src/libs/semaphore.rs +++ b/kernel/src/libs/semaphore.rs @@ -1,6 +1,6 @@ use core::sync::atomic::{AtomicI32, Ordering}; -use crate::{arch::asm::current::current_pcb, kdebug, syscall::SystemError}; +use crate::{kdebug, process::ProcessManager, syscall::SystemError}; use super::wait_queue::WaitQueue; @@ -47,11 +47,11 @@ impl Semaphore { self.counter.fetch_add(1, Ordering::Release); } else { //尝试唤醒 - if !self.wait_queue.wakeup(0x_ffff_ffff_ffff_ffff) { + if !self.wait_queue.wakeup(None) { //如果唤醒失败,打印错误信息 kdebug!( "Semaphore wakeup failed: current pid= {}, semaphore={:?}", - current_pcb().pid, + ProcessManager::current_pcb().basic().pid().into(), self ); } diff --git a/kernel/src/libs/wait_queue.rs b/kernel/src/libs/wait_queue.rs index 6a523ada4..19c666682 100644 --- a/kernel/src/libs/wait_queue.rs +++ b/kernel/src/libs/wait_queue.rs @@ -1,12 +1,10 @@ #![allow(dead_code)] -use alloc::{collections::LinkedList, vec::Vec}; +use alloc::{collections::LinkedList, sync::Arc, vec::Vec}; use crate::{ - arch::{asm::current::current_pcb, sched::sched, CurrentIrqArch}, + arch::{sched::sched, CurrentIrqArch}, exception::InterruptArch, - include::bindings::bindings::{ - process_control_block, process_wakeup, PROC_INTERRUPTIBLE, PROC_UNINTERRUPTIBLE, - }, + process::{ProcessControlBlock, ProcessManager, ProcessState}, }; use super::{ @@ -17,7 +15,7 @@ use super::{ #[derive(Debug)] struct InnerWaitQueue { /// 等待队列的链表 - wait_list: LinkedList<&'static mut process_control_block>, + wait_list: LinkedList>, } /// 被自旋锁保护的等待队列 @@ -30,10 +28,9 @@ impl WaitQueue { /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断 pub fn sleep(&self) { let mut guard: SpinLockGuard = self.0.lock(); - current_pcb().state = PROC_INTERRUPTIBLE as u64; - guard.wait_list.push_back(current_pcb()); + ProcessManager::sleep(true); + guard.wait_list.push_back(ProcessManager::current_pcb()); drop(guard); - sched(); } @@ -43,8 +40,8 @@ impl WaitQueue { F: FnOnce(), { let mut guard: SpinLockGuard = self.0.lock(); - current_pcb().state = PROC_INTERRUPTIBLE as u64; - guard.wait_list.push_back(current_pcb()); + ProcessManager::sleep(true); + guard.wait_list.push_back(ProcessManager::current_pcb()); f(); drop(guard); sched(); @@ -68,15 +65,15 @@ impl WaitQueue { // 安全检查:确保当前处于中断禁止状态 assert!(CurrentIrqArch::is_irq_enabled() == false); let mut guard: SpinLockGuard = self.0.lock(); - current_pcb().state = PROC_INTERRUPTIBLE as u64; - guard.wait_list.push_back(current_pcb()); + ProcessManager::sleep(true); + guard.wait_list.push_back(ProcessManager::current_pcb()); drop(guard); } /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断 pub fn sleep_uninterruptible(&self) { let mut guard: SpinLockGuard = self.0.lock(); - current_pcb().state = PROC_UNINTERRUPTIBLE as u64; - guard.wait_list.push_back(current_pcb()); + ProcessManager::sleep(false); + guard.wait_list.push_back(ProcessManager::current_pcb()); drop(guard); sched(); } @@ -85,8 +82,8 @@ impl WaitQueue { /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。 pub fn sleep_unlock_spinlock(&self, to_unlock: SpinLockGuard) { let mut guard: SpinLockGuard = self.0.lock(); - current_pcb().state = PROC_INTERRUPTIBLE as u64; - guard.wait_list.push_back(current_pcb()); + ProcessManager::sleep(true); + guard.wait_list.push_back(ProcessManager::current_pcb()); drop(to_unlock); drop(guard); sched(); @@ -96,8 +93,8 @@ impl WaitQueue { /// 在当前进程的pcb加入队列后,解锁指定的Mutex。 pub fn sleep_unlock_mutex(&self, to_unlock: MutexGuard) { let mut guard: SpinLockGuard = self.0.lock(); - current_pcb().state = PROC_INTERRUPTIBLE as u64; - guard.wait_list.push_back(current_pcb()); + ProcessManager::sleep(true); + guard.wait_list.push_back(ProcessManager::current_pcb()); drop(to_unlock); drop(guard); sched(); @@ -107,8 +104,8 @@ impl WaitQueue { /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。 pub fn sleep_uninterruptible_unlock_spinlock(&self, to_unlock: SpinLockGuard) { let mut guard: SpinLockGuard = self.0.lock(); - current_pcb().state = PROC_UNINTERRUPTIBLE as u64; - guard.wait_list.push_back(current_pcb()); + ProcessManager::sleep(false); + guard.wait_list.push_back(ProcessManager::current_pcb()); drop(to_unlock); drop(guard); sched(); @@ -118,8 +115,8 @@ impl WaitQueue { /// 在当前进程的pcb加入队列后,解锁指定的Mutex。 pub fn sleep_uninterruptible_unlock_mutex(&self, to_unlock: MutexGuard) { let mut guard: SpinLockGuard = self.0.lock(); - current_pcb().state = PROC_UNINTERRUPTIBLE as u64; - guard.wait_list.push_back(current_pcb()); + ProcessManager::sleep(false); + guard.wait_list.push_back(ProcessManager::current_pcb()); drop(to_unlock); drop(guard); sched(); @@ -128,51 +125,48 @@ impl WaitQueue { /// @brief 唤醒在队列中等待的第一个进程。 /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。 /// - /// @param state 用于判断的state,如果队列中第一个进程的state与它进行and操作之后,结果不为0,则唤醒这个进程。 + /// @param state 用于判断的state,如果队列第一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。 /// /// @return true 成功唤醒进程 /// @return false 没有唤醒进程 - pub fn wakeup(&self, state: u64) -> bool { + pub fn wakeup(&self, state: Option) -> bool { let mut guard: SpinLockGuard = self.0.lock(); // 如果队列为空,则返回 if guard.wait_list.is_empty() { return false; } - // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 - if (guard.wait_list.front().unwrap().state & state) != 0 { - let to_wakeup = guard.wait_list.pop_front().unwrap(); - unsafe { - process_wakeup(to_wakeup); + if let Some(state) = state { + if guard.wait_list.front().unwrap().sched_info().state() != state { + return false; } - return true; - } else { - return false; } + let to_wakeup = guard.wait_list.pop_front().unwrap(); + ProcessManager::wakeup(&to_wakeup); + return true; } /// @brief 唤醒在队列中,符合条件的所有进程。 /// - /// @param state 用于判断的state,如果队列中第一个进程的state与它进行and操作之后,结果不为0,则唤醒这个进程。 - pub fn wakeup_all(&self, state: u64) { + /// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。 + pub fn wakeup_all(&self, state: Option) { let mut guard: SpinLockGuard = self.0.lock_irqsave(); // 如果队列为空,则返回 if guard.wait_list.is_empty() { return; } - let mut to_push_back: Vec<&mut process_control_block> = Vec::new(); + let mut to_push_back: Vec> = Vec::new(); // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 while let Some(to_wakeup) = guard.wait_list.pop_front() { - if (to_wakeup.state & state) != 0 { - unsafe { - process_wakeup(to_wakeup); + if let Some(state) = state { + if to_wakeup.sched_info().state() != state { + ProcessManager::wakeup(&to_wakeup); + continue; } - } else { - to_push_back.push(to_wakeup); } + to_push_back.push(to_wakeup); } - for to_wakeup in to_push_back { guard.wait_list.push_back(to_wakeup); } diff --git a/kernel/src/net/net_core.rs b/kernel/src/net/net_core.rs index 91af36dec..37a278e27 100644 --- a/kernel/src/net/net_core.rs +++ b/kernel/src/net/net_core.rs @@ -126,7 +126,7 @@ pub fn poll_ifaces() { for (_, iface) in guard.iter() { iface.poll(&mut sockets).ok(); } - SOCKET_WAITQUEUE.wakeup_all((-1i64) as u64); + SOCKET_WAITQUEUE.wakeup_all(None); } /// 对ifaces进行轮询,最多对SOCKET_SET尝试times次加锁。 @@ -154,7 +154,7 @@ pub fn poll_ifaces_try_lock(times: u16) -> Result<(), SystemError> { for (_, iface) in guard.iter() { iface.poll(&mut sockets).ok(); } - SOCKET_WAITQUEUE.wakeup_all((-1i64) as u64); + SOCKET_WAITQUEUE.wakeup_all(None); return Ok(()); } diff --git a/kernel/src/process/kthread.rs b/kernel/src/process/kthread.rs index 12ea2bd7b..51440d166 100644 --- a/kernel/src/process/kthread.rs +++ b/kernel/src/process/kthread.rs @@ -299,7 +299,7 @@ impl KernelThreadMechanism { list = KTHREAD_CREATE_LIST.lock(); } drop(list); - ProcessManager::sleep().ok(); + ProcessManager::sleep(true).ok(); } } } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 9d04430f4..89ac90cab 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -14,7 +14,7 @@ use alloc::{ use hashbrown::HashMap; use crate::{ - arch::{asm::current::current_pcb, process::ArchPCBInfo}, + arch::process::ArchPCBInfo, filesystem::vfs::{file::FileDescriptorVec, FileType}, include::bindings::bindings::CLONE_SIGNAL, kdebug, @@ -34,7 +34,10 @@ use crate::{ init::initial_kernel_thread, kthread::{KernelThreadClosure, KernelThreadCreateInfo, KernelThreadMechanism}, }, - sched::{core::CPU_EXECUTING, SchedPolicy, SchedPriority}, + sched::{ + core::{sched_enqueue, CPU_EXECUTING}, + SchedPolicy, SchedPriority, + }, smp::kick_cpu, syscall::SystemError, }; @@ -153,11 +156,15 @@ impl ProcessManager { /// 唤醒一个进程 pub fn wakeup(pcb: &Arc) -> Result<(), SystemError> { - todo!() + if pcb.sched_info().state() != ProcessState::Runnable { + sched_enqueue(pcb.clone(), true); + return Ok(()); + } + return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); } /// 标志当前进程永久睡眠,移出调度队列 - pub fn sleep() -> Result<(), SystemError> { + pub fn sleep(interruptable: bool) -> Result<(), SystemError> { todo!() }