pub mod local;
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
pub use crate::arch::x86::cpu::*;
} else if #[cfg(target_arch = "riscv64")] {
pub use crate::arch::riscv::cpu::*;
}
}
use bitvec::prelude::BitVec;
use local::cpu_local_cell;
use spin::Once;
use crate::{
arch::boot::smp::get_num_processors, task::DisabledPreemptGuard, trap::DisabledLocalIrqGuard,
};
static NUM_CPUS: Once<u32> = Once::new();
pub(crate) unsafe fn init_num_cpus() {
let num_processors = get_num_processors().unwrap_or(1);
NUM_CPUS.call_once(|| num_processors);
}
pub(crate) unsafe fn set_this_cpu_id(id: u32) {
CURRENT_CPU.store(id);
}
pub fn num_cpus() -> u32 {
debug_assert!(
NUM_CPUS.get().is_some(),
"The number of CPUs is not initialized"
);
unsafe { *NUM_CPUS.get_unchecked() }
}
pub unsafe trait PinCurrentCpu {
fn current_cpu(&self) -> u32 {
let id = CURRENT_CPU.load();
debug_assert_ne!(id, u32::MAX, "This CPU is not initialized");
id
}
}
unsafe impl PinCurrentCpu for DisabledLocalIrqGuard {}
unsafe impl PinCurrentCpu for DisabledPreemptGuard {}
cpu_local_cell! {
static CURRENT_CPU: u32 = u32::MAX;
}
#[derive(Clone, Debug, Default)]
pub struct CpuSet {
bitset: BitVec,
}
impl CpuSet {
pub fn new_full() -> Self {
let num_cpus = num_cpus();
let mut bitset = BitVec::with_capacity(num_cpus as usize);
bitset.resize(num_cpus as usize, true);
Self { bitset }
}
pub fn new_empty() -> Self {
let num_cpus = num_cpus();
let mut bitset = BitVec::with_capacity(num_cpus as usize);
bitset.resize(num_cpus as usize, false);
Self { bitset }
}
pub fn add(&mut self, cpu_id: u32) {
self.bitset.set(cpu_id as usize, true);
}
pub fn add_all(&mut self) {
self.bitset.fill(true);
}
pub fn remove(&mut self, cpu_id: u32) {
self.bitset.set(cpu_id as usize, false);
}
pub fn clear(&mut self) {
self.bitset.fill(false);
}
pub fn contains(&self, cpu_id: u32) -> bool {
self.bitset.get(cpu_id as usize).as_deref() == Some(&true)
}
pub fn count(&self) -> usize {
self.bitset.count_ones()
}
pub fn iter(&self) -> impl Iterator<Item = u32> + '_ {
self.bitset.iter_ones().map(|idx| idx as u32)
}
}
impl From<u32> for CpuSet {
fn from(cpu_id: u32) -> Self {
let mut set = Self::new_empty();
set.add(cpu_id);
set
}
}