Browse Source

修正由于init proc union导致的无法运行的问题 && 修正由于内核线程启动后默认sleep的行为导致init进程无法正常运行的bug (#381)

1. 修正由于init proc union导致的无法运行的问题
2. 修正由于内核线程启动后默认sleep的行为导致init进程无法正常运行的bug
LoGin 1 year ago
parent
commit
de71ec259c

+ 1 - 1
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 {

+ 14 - 0
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);
     }

+ 1 - 6
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对齐

+ 38 - 4
kernel/src/process/kthread.rs

@@ -112,6 +112,8 @@ pub struct KernelThreadCreateInfo {
     /// 不安全的Arc引用计数,当内核线程创建失败时,需要减少这个计数
     has_unsafe_arc_instance: AtomicBool,
     self_ref: Weak<Self>,
+    /// 如果该值为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<KernelThreadClosure> = 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();
 

+ 1 - 0
kernel/src/process/mod.rs

@@ -160,6 +160,7 @@ impl ProcessManager {
 
     /// 唤醒一个进程
     pub fn wakeup(pcb: &Arc<ProcessControlBlock>) -> 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();

+ 4 - 0
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<Arc<ProcessControlBlock>> {
+        assert!(CurrentIrqArch::is_irq_enabled() == false);
+
         ProcessManager::current_pcb()
             .flags()
             .remove(ProcessFlags::NEED_SCHEDULE);

+ 7 - 2
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);