From 9a3702d099ca4e761d9bb37bd81c1ebc94bb4f4b Mon Sep 17 00:00:00 2001 From: longjin Date: Tue, 7 Nov 2023 19:06:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3signal=E5=92=8C=E8=B0=83?= =?UTF-8?q?=E5=BA=A6=E5=99=A8=E7=9A=84=E9=83=A8=E5=88=86=E5=8A=A0=E9=94=81?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=9B=9E=E9=80=80?= =?UTF-8?q?=E7=AD=96=E7=95=A5=E3=80=82=20todo:=20=E6=8A=8APCB=E7=9A=84flag?= =?UTF-8?q?s=E6=94=B9=E4=B8=BA=E6=97=A0=E9=94=81=E7=9A=84=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/arch/x86_64/ipc/signal.rs | 57 ++++++++++++++++++---------- kernel/src/exception/entry.S | 3 +- kernel/src/libs/rwlock.rs | 14 +++++++ kernel/src/process/mod.rs | 45 ++++++++++++++++++++-- kernel/src/sched/cfs.rs | 14 ++++--- kernel/src/sched/core.rs | 23 +++++++++-- 6 files changed, 122 insertions(+), 34 deletions(-) diff --git a/kernel/src/arch/x86_64/ipc/signal.rs b/kernel/src/arch/x86_64/ipc/signal.rs index df946b408..aebfc4898 100644 --- a/kernel/src/arch/x86_64/ipc/signal.rs +++ b/kernel/src/arch/x86_64/ipc/signal.rs @@ -1,4 +1,4 @@ -use core::{ffi::c_void, mem::size_of}; +use core::{ffi::c_void, intrinsics::unlikely, mem::size_of}; use crate::{ arch::{ @@ -322,7 +322,7 @@ impl SigContext { //TODO 引入线程后补上 // let current_thread = ProcessManager::current_pcb().thread; let pcb = ProcessManager::current_pcb(); - let mut archinfo_guard = pcb.arch_info(); + let mut archinfo_guard = pcb.arch_info_irqsave(); self.oldmask = *mask; self.frame = frame.clone(); // context.trap_num = unsafe { (*current_thread).trap_num }; @@ -368,6 +368,7 @@ pub struct SigStack { #[no_mangle] unsafe extern "C" fn do_signal(frame: &mut TrapFrame) { X86_64SignalArch::do_signal(frame); + return; } pub struct X86_64SignalArch; @@ -377,35 +378,46 @@ impl SignalArch for X86_64SignalArch { let pcb = ProcessManager::current_pcb(); let siginfo = pcb.try_siginfo(5); + if unlikely(siginfo.is_none()) { + return; + } + + let siginfo_read_guard = siginfo.unwrap(); + // 检查sigpending是否为0 - if siginfo - .map(|s| s.sig_pending().signal().bits() == 0) - .unwrap_or(true) - || !frame.from_user() - { - // 若没有正在等待处理的信号,或者将要返回到的是内核态,则启用中断,然后返回 - CurrentIrqArch::interrupt_enable(); + if siginfo_read_guard.sig_pending().signal().bits() == 0 || !frame.from_user() { + // 若没有正在等待处理的信号,或者将要返回到的是内核态,则返回 return; } - // 做完上面的检查后,开中断 - CurrentIrqArch::interrupt_enable(); let pcb = ProcessManager::current_pcb(); - let sig_guard = pcb.sig_struct(); + let mut sig_number: Signal; let mut info: Option; let mut sigaction: Sigaction; - let reader = pcb.sig_info(); - let sig_block: SigSet = reader.sig_block().clone(); - drop(reader); + let sig_block: SigSet = siginfo_read_guard.sig_block().clone(); + drop(siginfo_read_guard); + + let sig_guard = pcb.try_sig_struct_irq(5); + if unlikely(sig_guard.is_none()) { + return; + } + let siginfo_mut = pcb.try_siginfo_mut(5); + if unlikely(siginfo_mut.is_none()) { + return; + } + + let sig_guard = sig_guard.unwrap(); + let mut siginfo_mut_guard = siginfo_mut.unwrap(); loop { - (sig_number, info) = pcb.sig_info_mut().dequeue_signal(&sig_block); + (sig_number, info) = siginfo_mut_guard.dequeue_signal(&sig_block); // 如果信号非法,则直接返回 if sig_number == Signal::INVALID { return; } sigaction = sig_guard.handlers[sig_number as usize - 1]; + match sigaction.action() { SigactionType::SaHandler(action_type) => match action_type { SaHandlerType::SigError => { @@ -425,12 +437,14 @@ impl SignalArch for X86_64SignalArch { } // 如果当前动作是忽略这个信号,就继续循环。 } - // 所有的信号都处理完了 - let reader = pcb.sig_info(); - let oldset = reader.sig_block().clone(); + + let oldset = siginfo_mut_guard.sig_block().clone(); //避免死锁 - drop(reader); + drop(siginfo_mut_guard); drop(sig_guard); + + // 做完上面的检查后,开中断 + CurrentIrqArch::interrupt_enable(); let res: Result = handle_signal(sig_number, &mut sigaction, &info.unwrap(), &oldset, frame); if res.is_err() { @@ -564,7 +578,8 @@ fn setup_frame( let frame: *mut SigFrame = get_stack(&trap_frame, size_of::()); // kdebug!("frame=0x{:016x}", frame as usize); // 要求这个frame的地址位于用户空间,因此进行校验 - let r = UserBufferWriter::new(frame, size_of::(), true); + let r: Result, SystemError> = + UserBufferWriter::new(frame, size_of::(), true); if r.is_err() { // 如果地址区域位于内核空间,则直接报错 // todo: 生成一个sigsegv diff --git a/kernel/src/exception/entry.S b/kernel/src/exception/entry.S index 734e104db..ce67d50c1 100644 --- a/kernel/src/exception/entry.S +++ b/kernel/src/exception/entry.S @@ -68,7 +68,7 @@ ENTRY(ret_from_intr) // 将原本要返回的栈帧的栈指针传入do_signal的第一个参数 movq %rsp, %rdi callq do_signal - + cli __entry_ret_from_intr_before_gs_check_2: push %rcx @@ -138,6 +138,7 @@ __entry_err_code_after_gs_check_1: callq *%rdx //调用服务程序 带*号表示调用的是绝对地址 +__entry_err_code_to_ret_from_exception: jmp ret_from_exception diff --git a/kernel/src/libs/rwlock.rs b/kernel/src/libs/rwlock.rs index c1f183c60..23dd651d5 100644 --- a/kernel/src/libs/rwlock.rs +++ b/kernel/src/libs/rwlock.rs @@ -265,6 +265,20 @@ impl RwLock { return r; } + #[allow(dead_code)] + pub fn try_upgradeable_read_irqsave(&self) -> Option> { + let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; + ProcessManager::preempt_disable(); + let mut r = self.inner_try_upgradeable_read(); + if r.is_none() { + ProcessManager::preempt_enable(); + } else { + r.as_mut().unwrap().irq_guard = Some(irq_guard); + } + + return r; + } + fn inner_try_upgradeable_read(&self) -> Option> { // 获得UPGRADER守卫不需要查看读者位 // 如果获得读者锁失败,不需要撤回fetch_or的原子操作 diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 7ec0dc7a4..9d08737a5 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -182,7 +182,7 @@ impl ProcessManager { let _guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; let state = pcb.sched_info().state(); if state.is_blocked() { - let mut writer = pcb.sched_info_mut(); + let mut writer: RwLockWriteGuard<'_, ProcessSchedulerInfo> = pcb.sched_info_mut(); let state = writer.state(); if state.is_blocked() { writer.set_state(ProcessState::Runnable); @@ -707,6 +707,17 @@ impl ProcessControlBlock { return self.sched_info.read(); } + #[inline(always)] + pub fn try_sched_info(&self, times: u8) -> Option> { + for _ in 0..times { + if let Some(r) = self.sched_info.try_read() { + return Some(r); + } + } + + return None; + } + #[allow(dead_code)] #[inline(always)] pub fn sched_info_irqsave(&self) -> RwLockReadGuard { @@ -714,8 +725,16 @@ impl ProcessControlBlock { } #[inline(always)] - pub fn sched_info_upgradeable_irqsave(&self) -> RwLockUpgradableGuard { - return self.sched_info.upgradeable_read(); + pub fn sched_info_try_upgradeable_irqsave( + &self, + times: u8, + ) -> Option> { + for _ in 0..times { + if let Some(r) = self.sched_info.try_upgradeable_read_irqsave() { + return Some(r); + } + } + return None; } #[inline(always)] @@ -816,10 +835,30 @@ impl ProcessControlBlock { self.sig_info.write() } + pub fn try_siginfo_mut(&self, times: u8) -> Option> { + for _ in 0..times { + if let Some(r) = self.sig_info.try_write() { + return Some(r); + } + } + + return None; + } + pub fn sig_struct(&self) -> SpinLockGuard { self.sig_struct.lock() } + pub fn try_sig_struct_irq(&self, times: u8) -> Option> { + for _ in 0..times { + if let Ok(r) = self.sig_struct.try_lock_irqsave() { + return Some(r); + } + } + + return None; + } + pub fn sig_struct_irq(&self) -> SpinLockGuard { self.sig_struct.lock_irqsave() } diff --git a/kernel/src/sched/cfs.rs b/kernel/src/sched/cfs.rs index 500656c3e..da9dc6fe2 100644 --- a/kernel/src/sched/cfs.rs +++ b/kernel/src/sched/cfs.rs @@ -9,9 +9,12 @@ use crate::{ kBUG, libs::{ rbtree::RBTree, + rwlock::RwLockReadGuard, spinlock::{SpinLock, SpinLockGuard}, }, - process::{ProcessControlBlock, ProcessFlags, ProcessManager, ProcessState}, + process::{ + ProcessControlBlock, ProcessFlags, ProcessManager, ProcessSchedulerInfo, ProcessState, + }, smp::core::smp_get_processor_id, }; @@ -142,7 +145,10 @@ impl SchedulerCFS { } /// @brief 时钟中断到来时,由sched的core模块中的函数,调用本函数,更新CFS进程的可执行时间 - pub fn timer_update_jiffies(&mut self) { + pub fn timer_update_jiffies( + &mut self, + sched_info_guard: &RwLockReadGuard<'_, ProcessSchedulerInfo>, + ) { let current_cpu_queue: &mut CFSQueue = self.cpu_queue[smp_get_processor_id() as usize]; // todo: 引入调度周期以及所有进程的优先权进行计算,然后设置进程的可执行时间 @@ -168,9 +174,7 @@ impl SchedulerCFS { drop(queue); // 更新当前进程的虚拟运行时间 - ProcessManager::current_pcb() - .sched_info() - .increase_virtual_runtime(1); + sched_info_guard.increase_virtual_runtime(1); } /// @brief 将进程加入cpu的cfs调度队列,并且重设其虚拟运行时间为当前队列的最小值 diff --git a/kernel/src/sched/core.rs b/kernel/src/sched/core.rs index b51f835c0..a89181808 100644 --- a/kernel/src/sched/core.rs +++ b/kernel/src/sched/core.rs @@ -1,4 +1,7 @@ -use core::sync::atomic::{compiler_fence, Ordering}; +use core::{ + intrinsics::unlikely, + sync::atomic::{compiler_fence, Ordering}, +}; use alloc::{sync::Arc, vec::Vec}; @@ -99,7 +102,13 @@ pub fn do_sched() -> Option> { // 当前进程持有锁,不切换,避免死锁 if ProcessManager::current_pcb().preempt_count() != 0 { let binding = ProcessManager::current_pcb(); - let mut guard = binding.sched_info_upgradeable_irqsave(); + let guard = binding.sched_info_try_upgradeable_irqsave(5); + if unlikely(guard.is_none()) { + return None; + } + + let mut guard = guard.unwrap(); + let state = guard.state(); if state.is_blocked() { // try to upgrade @@ -191,10 +200,16 @@ pub extern "C" fn sched_init() { /// @brief 当时钟中断到达时,更新时间片 /// 请注意,该函数只能被时钟中断处理程序调用 pub extern "C" fn sched_update_jiffies() { - let policy = ProcessManager::current_pcb().sched_info().policy(); + let binding = ProcessManager::current_pcb(); + let guard = binding.try_sched_info(10); + if unlikely(guard.is_none()) { + return; + } + let guard = guard.unwrap(); + let policy = guard.policy(); match policy { SchedPolicy::CFS => { - __get_cfs_scheduler().timer_update_jiffies(); + __get_cfs_scheduler().timer_update_jiffies(&guard); } SchedPolicy::FIFO | SchedPolicy::RR => { __get_rt_scheduler().timer_update_jiffies();