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