90 lines
2.1 KiB
Rust

use core::ops::{Deref, DerefMut};
use device_api::interrupt::IpiMessage;
use kernel_arch::{Architecture, ArchitectureImpl, CpuImpl, LocalCpuImpl};
use libk_util::sync::IrqGuard;
use crate::task::sched::CpuQueue;
/// Kernel wrapper for local CPU info structure. See [kernel_arch::LocalCpuImpl].
#[repr(transparent)]
pub struct LocalCpu<'a>(LocalCpuImpl<'a, CpuQueue>);
/// Kernel wrapper for per-CPU info structure. See [kernel_arch::LocalCpuImpl].
#[repr(transparent)]
pub struct Cpu(CpuImpl<CpuQueue>);
impl Cpu {
/// # Safety
///
/// Precondition: this function has not yet been called on the local CPU.
pub unsafe fn init_local(
id: Option<u32>,
data: <ArchitectureImpl as Architecture>::PerCpuData,
) {
ArchitectureImpl::init_local_cpu::<CpuQueue>(id, data)
}
/// Returns local CPU reference
#[inline]
pub fn local<'a>() -> LocalCpu<'a> {
LocalCpu(CpuImpl::local())
}
/// Returns local CPU reference or None if it hasn't yet been initialized
#[inline]
pub fn try_local<'a>() -> Option<LocalCpu<'a>> {
CpuImpl::try_local().map(LocalCpu)
}
/// Pushes a message to the IPI queue
#[inline]
pub fn push_ipi_queue(cpu_id: u32, msg: IpiMessage) {
CpuImpl::<CpuQueue>::push_ipi_queue(cpu_id, msg)
}
/// Initialize the IPI queues for all present CPUs
#[inline]
pub fn init_ipi_queues(cpu_count: usize) {
CpuImpl::<CpuQueue>::init_ipi_queues(cpu_count)
}
}
impl Deref for Cpu {
type Target = CpuImpl<CpuQueue>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Cpu {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl LocalCpu<'_> {
/// Converts the local CPU handle into its IRQ guard
pub fn into_guard(self) -> IrqGuard {
self.0.into_guard()
}
}
impl Deref for LocalCpu<'_> {
type Target = CpuImpl<CpuQueue>;
#[inline]
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl DerefMut for LocalCpu<'_> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.deref_mut()
}
}