xref: /DragonOS/kernel/src/process/idle.rs (revision 55e6f0b65f91b32638fd56581f711a816eccdcd1)
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, IDLE_PROCESS_ADDRESS_SPACE},
10     process::KernelStack,
11     sched::{cpu_rq, OnRq},
12     smp::{core::smp_get_processor_id, cpu::ProcessorId},
13 };
14 
15 use super::{ProcessControlBlock, ProcessManager};
16 
17 static mut __IDLE_PCB: Option<Vec<Arc<ProcessControlBlock>>> = None;
18 
19 impl ProcessManager {
20     /// 初始化每个核的idle进程
21     pub fn init_idle() {
22         static INIT_IDLE: AtomicBool = AtomicBool::new(false);
23         if INIT_IDLE
24             .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
25             .is_err()
26         {
27             panic!("Idle process already initialized");
28         }
29 
30         assert!(
31             smp_get_processor_id() == ProcessorId::new(0),
32             "Idle process must be initialized on the first processor"
33         );
34         let mut v: Vec<Arc<ProcessControlBlock>> = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize);
35 
36         for i in 0..PerCpu::MAX_CPU_NUM {
37             let kstack = if unlikely(i == 0) {
38                 let stack_ptr =
39                     VirtAddr::new(Self::stack_ptr().data() & (!(KernelStack::ALIGN - 1)));
40                 // 初始化bsp的idle进程
41                 let mut ks = unsafe { KernelStack::from_existed(stack_ptr) }
42                     .expect("Failed to create kernel stack struct for BSP.");
43                 unsafe { ks.clear_pcb(true) };
44                 ks
45             } else {
46                 KernelStack::new().unwrap_or_else(|e| {
47                     panic!("Failed to create kernel stack struct for AP {}: {:?}", i, e)
48                 })
49             };
50 
51             let idle_pcb = ProcessControlBlock::new_idle(i, kstack);
52 
53             assert!(idle_pcb.basic().user_vm().is_none());
54             unsafe {
55                 idle_pcb
56                     .basic_mut()
57                     .set_user_vm(Some(IDLE_PROCESS_ADDRESS_SPACE()))
58             };
59 
60             assert!(idle_pcb.sched_info().on_cpu().is_none());
61             idle_pcb.sched_info().set_on_cpu(Some(ProcessorId::new(i)));
62             *idle_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::IDLE;
63 
64             let rq = cpu_rq(i as usize);
65             let (rq, _guard) = rq.self_lock();
66             rq.set_current(Arc::downgrade(&idle_pcb));
67             rq.set_idle(Arc::downgrade(&idle_pcb));
68 
69             *idle_pcb.sched_info().on_rq.lock_irqsave() = OnRq::Queued;
70 
71             idle_pcb
72                 .sched_info()
73                 .sched_entity()
74                 .force_mut()
75                 .set_cfs(Arc::downgrade(&rq.cfs_rq()));
76 
77             v.push(idle_pcb);
78         }
79 
80         unsafe {
81             __IDLE_PCB = Some(v);
82         }
83     }
84 
85     /// 获取当前的栈指针
86     ///
87     /// 请注意,该函数只是于辅助bsp核心的idle进程初始化
88     fn stack_ptr() -> VirtAddr {
89         #[cfg(target_arch = "x86_64")]
90         return VirtAddr::new(x86::current::registers::rsp() as usize);
91 
92         #[cfg(target_arch = "riscv64")]
93         {
94             let stack_ptr: usize;
95             unsafe {
96                 core::arch::asm!("mv {}, sp", out(reg) stack_ptr);
97             }
98             return VirtAddr::new(stack_ptr);
99         }
100     }
101 
102     /// 获取idle进程数组的引用
103     pub fn idle_pcb() -> &'static Vec<Arc<ProcessControlBlock>> {
104         unsafe { __IDLE_PCB.as_ref().unwrap() }
105     }
106 }
107