use core::marker::PhantomData;
use crate::{CpuAreaRef, CpuLocalError, register};
#[must_use = "CPU-local access is valid only while this pin remains in scope"]
#[derive(Debug)]
pub struct CpuPin<'scope> {
area: CpuAreaRef,
_scope: PhantomData<&'scope mut &'scope ()>,
_not_send_or_sync: PhantomData<*mut ()>,
}
impl CpuPin<'_> {
pub const fn area(&self) -> CpuAreaRef {
self.area
}
}
#[must_use = "mutable CPU-local access is valid only while this token remains in scope"]
#[derive(Debug)]
pub struct ExclusiveCpu<'pin> {
area: CpuAreaRef,
_scope: PhantomData<&'pin mut &'pin ()>,
_not_send_or_sync: PhantomData<*mut ()>,
}
impl ExclusiveCpu<'_> {
pub const fn area(&self) -> CpuAreaRef {
self.area
}
}
pub unsafe fn with_cpu_pin<R>(
operation: impl for<'scope> FnOnce(&CpuPin<'scope>) -> R,
) -> Result<R, CpuLocalError> {
let area = register::current_area()?;
let pin = CpuPin {
area,
_scope: PhantomData,
_not_send_or_sync: PhantomData,
};
register::current_thread(&pin)?;
Ok(operation(&pin))
}
pub unsafe fn with_exclusive_cpu<R>(
pin: &CpuPin<'_>,
operation: impl for<'exclusive> FnOnce(&ExclusiveCpu<'exclusive>) -> R,
) -> R {
let exclusive = ExclusiveCpu {
area: pin.area,
_scope: PhantomData,
_not_send_or_sync: PhantomData,
};
operation(&exclusive)
}