use core::ptr::NonNull;
use cpu_local::{CpuAreaPrefix, CpuAreaRef, CpuIndex, CpuPin, CpuRuntimeAnchor};
use crate::{PerCpuError, layout::installed_layout};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PerCpuArea {
cpu_index: CpuIndex,
runtime_base: usize,
area_size: usize,
}
impl PerCpuArea {
pub(crate) const fn new(cpu_index: CpuIndex, runtime_base: usize, area_size: usize) -> Self {
Self {
cpu_index,
runtime_base,
area_size,
}
}
pub const fn cpu_index(self) -> CpuIndex {
self.cpu_index
}
pub const fn runtime_base(self) -> usize {
self.runtime_base
}
pub const fn area_size(self) -> usize {
self.area_size
}
pub fn cpu_area(self) -> Result<CpuAreaRef, PerCpuError> {
Ok(unsafe { CpuAreaRef::from_initialized_base(self.runtime_base) }?)
}
pub fn prefix(self) -> Result<&'static CpuAreaPrefix, PerCpuError> {
Ok(self.cpu_area()?.prefix())
}
pub fn runtime_anchor(self) -> Result<&'static CpuRuntimeAnchor, PerCpuError> {
Ok(self.cpu_area()?.runtime_anchor())
}
pub(crate) fn runtime_ptr(self) -> *mut u8 {
self.runtime_base as *mut u8
}
pub(crate) fn prefix_ptr(self) -> *mut CpuAreaPrefix {
self.runtime_base as *mut CpuAreaPrefix
}
}
pub fn area(cpu_index: CpuIndex) -> Result<PerCpuArea, PerCpuError> {
installed_layout()?.area(cpu_index)
}
pub fn layout() -> Result<&'static crate::PerCpuLayout, PerCpuError> {
installed_layout()
}
pub fn current_area(pin: &CpuPin<'_>) -> Result<PerCpuArea, PerCpuError> {
let expected = area(pin.area().cpu_index())?;
let expected_cpu_area = expected.cpu_area()?;
if expected_cpu_area != pin.area() {
return Err(PerCpuError::CurrentAreaMismatch {
expected: expected_cpu_area,
actual: pin.area(),
});
}
Ok(expected)
}
pub const fn current_cpu_index(pin: &CpuPin<'_>) -> CpuIndex {
pin.area().cpu_index()
}
pub(crate) fn symbol_ptr<T>(area: PerCpuArea, offset: usize) -> NonNull<T> {
unsafe { NonNull::new_unchecked((area.runtime_base + offset) as *mut T) }
}