xref: /DragonOS/kernel/src/process/idle.rs (revision 40314b30ab2a7e1fd06a05a00f693e644e446035)
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                 unsafe { KernelStack::from_existed(stack_ptr) }
41                     .expect("Failed to create kernel stack struct for BSP.")
42             } else {
43                 KernelStack::new().unwrap_or_else(|e| {
44                     panic!("Failed to create kernel stack struct for AP {}: {:?}", i, e)
45                 })
46             };
47 
48             let idle_pcb = ProcessControlBlock::new_idle(smp_get_processor_id(), kstack);
49 
50             assert!(idle_pcb.basic().user_vm().is_none());
51             unsafe {
52                 idle_pcb
53                     .basic_mut()
54                     .set_user_vm(Some(INITIAL_PROCESS_ADDRESS_SPACE()))
55             };
56 
57             assert!(idle_pcb.sched_info().on_cpu().is_none());
58             idle_pcb.sched_info().set_on_cpu(Some(i as u32));
59             v.push(idle_pcb);
60         }
61 
62         unsafe {
63             __IDLE_PCB = Some(v);
64         }
65     }
66 
67     /// 获取当前的栈指针
68     ///
69     /// 请注意,该函数只是于辅助bsp核心的idle进程初始化
70     fn stack_ptr() -> VirtAddr {
71         #[cfg(target_arch = "x86_64")]
72         return VirtAddr::new(x86::current::registers::rsp() as usize);
73     }
74 
75     /// 获取idle进程数组的引用
76     pub fn idle_pcb() -> &'static Vec<Arc<ProcessControlBlock>> {
77         unsafe { __IDLE_PCB.as_ref().unwrap() }
78     }
79 }
80