From de71ec259cd21c782f4031b01635eb8ad3df1943 Mon Sep 17 00:00:00 2001 From: LoGin Date: Fri, 15 Sep 2023 19:44:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=94=B1=E4=BA=8Einit=20proc?= =?UTF-8?q?=20union=E5=AF=BC=E8=87=B4=E7=9A=84=E6=97=A0=E6=B3=95=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E7=9A=84=E9=97=AE=E9=A2=98=20&&=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E7=94=B1=E4=BA=8E=E5=86=85=E6=A0=B8=E7=BA=BF=E7=A8=8B=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=90=8E=E9=BB=98=E8=AE=A4sleep=E7=9A=84=E8=A1=8C?= =?UTF-8?q?=E4=B8=BA=E5=AF=BC=E8=87=B4init=E8=BF=9B=E7=A8=8B=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=AD=A3=E5=B8=B8=E8=BF=90=E8=A1=8C=E7=9A=84bug=20(#3?= =?UTF-8?q?81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修正由于init proc union导致的无法运行的问题 2. 修正由于内核线程启动后默认sleep的行为导致init进程无法正常运行的bug --- kernel/src/arch/x86_64/interrupt/mod.rs | 2 +- kernel/src/arch/x86_64/process/mod.rs | 14 +++++++++ kernel/src/head.S | 7 +---- kernel/src/process/kthread.rs | 42 ++++++++++++++++++++++--- kernel/src/process/mod.rs | 1 + kernel/src/sched/cfs.rs | 4 +++ kernel/src/sched/syscall.rs | 9 ++++-- 7 files changed, 66 insertions(+), 13 deletions(-) diff --git a/kernel/src/arch/x86_64/interrupt/mod.rs b/kernel/src/arch/x86_64/interrupt/mod.rs index 44e18635..f27941b4 100644 --- a/kernel/src/arch/x86_64/interrupt/mod.rs +++ b/kernel/src/arch/x86_64/interrupt/mod.rs @@ -43,7 +43,7 @@ impl InterruptArch for X86_64InterruptArch { unsafe { asm!("pushfq; pop {}", out(reg) rflags, options(nomem, preserves_flags)); } - return rflags & (1 << 9) != 0; + return (rflags & (1 << 9)) != 0; } unsafe fn save_and_disable_irq() -> IrqFlagsGuard { diff --git a/kernel/src/arch/x86_64/process/mod.rs b/kernel/src/arch/x86_64/process/mod.rs index 75fb1409..cae6cb91 100644 --- a/kernel/src/arch/x86_64/process/mod.rs +++ b/kernel/src/arch/x86_64/process/mod.rs @@ -42,6 +42,19 @@ extern "C" { fn ret_from_intr(); } +#[allow(dead_code)] +#[repr(align(32768))] +union InitProcUnion { + /// 用于存放idle进程的内核栈 + idle_stack: [u8; 32768], +} + +#[link_section = ".data.init_proc_union"] +#[no_mangle] +static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion { + idle_stack: [0; 32768], +}; + /// PCB中与架构相关的信息 #[derive(Debug, Clone)] #[allow(dead_code)] @@ -321,6 +334,7 @@ impl ProcessManager { ); // kdebug!("switch tss ok"); + compiler_fence(Ordering::SeqCst); // 正式切换上下文 switch_to_inner(prev_arch, next_arch); } diff --git a/kernel/src/head.S b/kernel/src/head.S index efe432ab..af906cf0 100644 --- a/kernel/src/head.S +++ b/kernel/src/head.S @@ -481,13 +481,8 @@ m_ignore_int: go_to_ignore_int: .quad ignore_int_handler - ENTRY(head_stack_start) - .quad initial_proc_union + 32768 - -.align 32768 -initial_proc_union: - .fill 32768, 1, 0 + .quad BSP_IDLE_STACK_SPACE + 32768 // 初始化页表 .align 0x1000 //设置为4k对齐 diff --git a/kernel/src/process/kthread.rs b/kernel/src/process/kthread.rs index dabb5ebc..7060d7be 100644 --- a/kernel/src/process/kthread.rs +++ b/kernel/src/process/kthread.rs @@ -112,6 +112,8 @@ pub struct KernelThreadCreateInfo { /// 不安全的Arc引用计数,当内核线程创建失败时,需要减少这个计数 has_unsafe_arc_instance: AtomicBool, self_ref: Weak, + /// 如果该值为true在进入bootstrap stage2之后,就会进入睡眠状态 + to_mark_sleep: AtomicBool, } #[atomic_enum] @@ -132,6 +134,7 @@ impl KernelThreadCreateInfo { result_pcb: SpinLock::new(None), has_unsafe_arc_instance: AtomicBool::new(false), self_ref: Weak::new(), + to_mark_sleep: AtomicBool::new(true), }); let tmp = result.clone(); unsafe { @@ -209,12 +212,35 @@ impl KernelThreadCreateInfo { assert!(Arc::strong_count(&arc) > 0); return arc; } + + /// 设置是否在进入bootstrap stage2之后,就进入睡眠状态 + /// + /// ## 参数 + /// + /// - to_mark_sleep: 是否在进入bootstrap stage2之后,就进入睡眠状态 + /// + /// ## 返回值 + /// 如果已经创建完成,返回EINVAL + pub fn set_to_mark_sleep(&self, to_mark_sleep: bool) -> Result<(), SystemError> { + let result_guard = self.result_pcb.lock(); + if result_guard.is_some() { + // 已经创建完成,不需要设置 + return Err(SystemError::EINVAL); + } + self.to_mark_sleep.store(to_mark_sleep, Ordering::SeqCst); + return Ok(()); + } + + pub fn to_mark_sleep(&self) -> bool { + self.to_mark_sleep.load(Ordering::SeqCst) + } } pub struct KernelThreadMechanism; impl KernelThreadMechanism { pub fn init_stage1() { + assert!(ProcessManager::current_pcb().pid() == Pid::new(0)); kinfo!("Initializing kernel thread mechanism stage1..."); // 初始化第一个内核线程 @@ -229,7 +255,9 @@ impl KernelThreadMechanism { .flags .lock() .insert(ProcessFlags::KTHREAD); - + create_info + .set_to_mark_sleep(false) + .expect("Failed to set to_mark_sleep"); KernelThreadMechanism::__inner_create( &create_info, CloneFlags::CLONE_VM | CloneFlags::CLONE_SIGNAL, @@ -259,6 +287,7 @@ impl KernelThreadMechanism { .expect("Failed to create kthread daemon"); let pcb = ProcessManager::find(kthreadd_pid).unwrap(); + ProcessManager::wakeup(&pcb).expect("Failed to wakeup kthread daemon"); unsafe { KTHREAD_DAEMON_PCB.replace(pcb); } @@ -437,11 +466,16 @@ pub unsafe extern "C" fn kernel_thread_bootstrap_stage2(ptr: *const KernelThread let closure: Box = info.take_closure().unwrap(); info.set_create_ok(ProcessManager::current_pcb()); + let to_mark_sleep = info.to_mark_sleep(); drop(info); - let irq_guard = CurrentIrqArch::save_and_disable_irq(); - ProcessManager::mark_sleep(true).expect("Failed to mark sleep"); - drop(irq_guard); + if to_mark_sleep { + // 进入睡眠状态 + let irq_guard = CurrentIrqArch::save_and_disable_irq(); + ProcessManager::mark_sleep(true).expect("Failed to mark sleep"); + drop(irq_guard); + sched(); + } let mut retval = SystemError::EINTR.to_posix_errno(); diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 43d709d9..496a4a15 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -160,6 +160,7 @@ impl ProcessManager { /// 唤醒一个进程 pub fn wakeup(pcb: &Arc) -> Result<(), SystemError> { + 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(); diff --git a/kernel/src/sched/cfs.rs b/kernel/src/sched/cfs.rs index ac78c461..5d24bc1a 100644 --- a/kernel/src/sched/cfs.rs +++ b/kernel/src/sched/cfs.rs @@ -3,6 +3,8 @@ use core::sync::atomic::compiler_fence; use alloc::{boxed::Box, sync::Arc, vec::Vec}; use crate::{ + arch::CurrentIrqArch, + exception::InterruptArch, include::bindings::bindings::MAX_CPU_NUM, kBUG, libs::{ @@ -190,6 +192,8 @@ impl Scheduler for SchedulerCFS { /// @brief 在当前cpu上进行调度。 /// 请注意,进入该函数之前,需要关中断 fn sched(&mut self) -> Option> { + assert!(CurrentIrqArch::is_irq_enabled() == false); + ProcessManager::current_pcb() .flags() .remove(ProcessFlags::NEED_SCHEDULE); diff --git a/kernel/src/sched/syscall.rs b/kernel/src/sched/syscall.rs index 1c7d2aeb..dd5c1c89 100644 --- a/kernel/src/sched/syscall.rs +++ b/kernel/src/sched/syscall.rs @@ -23,8 +23,13 @@ impl Syscall { let pcb = do_sched(); if pcb.is_some() { - CPU_EXECUTING.set(smp_get_processor_id(), pcb.as_ref().unwrap().pid()); - unsafe { ProcessManager::switch_process(ProcessManager::current_pcb(), pcb.unwrap()) }; + let next_pcb = pcb.unwrap(); + let current_pcb = ProcessManager::current_pcb(); + + if current_pcb.pid() != next_pcb.pid() { + CPU_EXECUTING.set(smp_get_processor_id(), next_pcb.pid()); + unsafe { ProcessManager::switch_process(current_pcb, next_pcb) }; + } } drop(irq_guard); return Ok(0);