xref: /DragonOS/kernel/src/process/idle.rs (revision 7a29d4fcbcd89a226289c7bf541c2c78623de3ad)
1 use core::{
2     intrinsics::unlikely,
3     sync::atomic::{AtomicBool, Ordering},
4 };
5 
6 use alloc::{sync::Arc, vec::Vec};
7 
8 use crate::{
9     mm::{percpu::PerCpu, VirtAddr, INITIAL_PROCESS_ADDRESS_SPACE},
10     process::KernelStack,
11     smp::core::smp_get_processor_id,
12 };
13 
14 use super::{ProcessControlBlock, ProcessManager};
15 
16 static mut __IDLE_PCB: Option<Vec<Arc<ProcessControlBlock>>> = None;
17 
18 impl ProcessManager {
19     /// 初始化每个核的idle进程
20     pub fn init_idle() {
21         static INIT_IDLE: AtomicBool = AtomicBool::new(false);
22         if INIT_IDLE
23             .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
24             .is_err()
25         {
26             panic!("Idle process already initialized");
27         }
28 
29         assert!(
30             smp_get_processor_id() == 0,
31             "Idle process must be initialized on the first processor"
32         );
33         let mut v: Vec<Arc<ProcessControlBlock>> = Vec::with_capacity(PerCpu::MAX_CPU_NUM);
34 
35         for i in 0..PerCpu::MAX_CPU_NUM {
36             let kstack = if unlikely(i == 0) {
37                 let stack_ptr =
38                     VirtAddr::new(Self::stack_ptr().data() & (!(KernelStack::ALIGN - 1)));
39                 // 初始化bsp的idle进程
40                 let mut ks = unsafe { KernelStack::from_existed(stack_ptr) }
41                     .expect("Failed to create kernel stack struct for BSP.");
42                 unsafe { ks.clear_pcb(true) };
43                 ks
44             } else {
45                 KernelStack::new().unwrap_or_else(|e| {
46                     panic!("Failed to create kernel stack struct for AP {}: {:?}", i, e)
47                 })
48             };
49 
50             let idle_pcb = ProcessControlBlock::new_idle(i as u32, kstack);
51 
52             assert!(idle_pcb.basic().user_vm().is_none());
53             unsafe {
54                 idle_pcb
55                     .basic_mut()
56                     .set_user_vm(Some(INITIAL_PROCESS_ADDRESS_SPACE()))
57             };
58 
59             assert!(idle_pcb.sched_info().on_cpu().is_none());
60             idle_pcb.sched_info().set_on_cpu(Some(i as u32));
61             v.push(idle_pcb);
62         }
63 
64         unsafe {
65             __IDLE_PCB = Some(v);
66         }
67     }
68 
69     /// 获取当前的栈指针
70     ///
71     /// 请注意,该函数只是于辅助bsp核心的idle进程初始化
72     fn stack_ptr() -> VirtAddr {
73         #[cfg(target_arch = "x86_64")]
74         return VirtAddr::new(x86::current::registers::rsp() as usize);
75 
76         #[cfg(target_arch = "riscv64")]
77         unimplemented!("stack_ptr() is not implemented on RISC-V")
78     }
79 
80     /// 获取idle进程数组的引用
81     pub fn idle_pcb() -> &'static Vec<Arc<ProcessControlBlock>> {
82         unsafe { __IDLE_PCB.as_ref().unwrap() }
83     }
84 }
85