1 use core::sync::atomic::AtomicU32;
2 
3 use crate::libs::cpumask::CpuMask;
4 
5 mod c_adapter;
6 
7 int_like!(ProcessorId, AtomicProcessorId, u32, AtomicU32);
8 
9 impl ProcessorId {
10     pub const INVALID: ProcessorId = ProcessorId::new(u32::MAX);
11 }
12 
13 static mut SMP_CPU_MANAGER: Option<SmpCpuManager> = None;
14 
15 #[inline]
smp_cpu_manager() -> &'static SmpCpuManager16 pub fn smp_cpu_manager() -> &'static SmpCpuManager {
17     unsafe { SMP_CPU_MANAGER.as_ref().unwrap() }
18 }
19 
20 pub struct SmpCpuManager {
21     possible_cpus: CpuMask,
22 }
23 
24 impl SmpCpuManager {
new() -> Self25     fn new() -> Self {
26         let possible_cpus = CpuMask::new();
27         Self { possible_cpus }
28     }
29 
30     /// 设置可用的CPU
31     ///
32     /// # Safety
33     ///
34     /// - 该函数不会检查CPU的有效性,调用者需要保证CPU的有效性。
35     /// - 由于possible_cpus是一个全局变量,且为了性能考虑,并不会加锁
36     ///     访问,因此该函数只能在初始化阶段调用。
set_possible_cpu(&self, cpu: ProcessorId, value: bool)37     pub unsafe fn set_possible_cpu(&self, cpu: ProcessorId, value: bool) {
38         // 强制获取mut引用,因为该函数只能在初始化阶段调用
39         let p = (self as *const Self as *mut Self).as_mut().unwrap();
40 
41         p.possible_cpus.set(cpu, value);
42     }
43 
44     /// 获取可用的CPU
45     #[allow(dead_code)]
possible_cpus(&self) -> &CpuMask46     pub fn possible_cpus(&self) -> &CpuMask {
47         &self.possible_cpus
48     }
49 }
50 
smp_cpu_manager_init(boot_cpu: ProcessorId)51 pub fn smp_cpu_manager_init(boot_cpu: ProcessorId) {
52     unsafe {
53         SMP_CPU_MANAGER = Some(SmpCpuManager::new());
54     }
55 
56     unsafe { smp_cpu_manager().set_possible_cpu(boot_cpu, true) };
57 
58     SmpCpuManager::arch_init(boot_cpu);
59 }
60