#![allow(unused)]
use core::cell::UnsafeCell;
use core::fmt;
use core::mem::size_of_val;
use core::mem::{align_of, size_of};
use core::ops::{Deref, DerefMut};
mod spin;
pub use spin::{Spin, SpinGuard};
mod ticket;
pub use ticket::{Ticket, TicketGuard};
mod once;
pub use once::{Lazy, Once, OnceError};
use crate::arch::{cpu, int};
use crate::interrupts::guard::GUARD;
use crate::MAX_CPUS;
#[derive(Debug)]
pub struct PerCPU<T>(UnsafeCell<[Align<T>; MAX_CPUS]>);
unsafe impl<T> Sync for PerCPU<T> {}
impl<T> PerCPU<T> {
pub const fn new(v: [Align<T>; MAX_CPUS]) -> Self {
Self(UnsafeCell::new(v))
}
#[allow(clippy::mut_from_ref)]
#[track_caller]
pub fn get(&self) -> &mut T {
debug_assert!(
!int::enabled() || GUARD.active(),
"Preemption not disabled {}",
core::panic::Location::caller()
);
unsafe { self.get_raw(cpu::id()) }
}
#[allow(clippy::mut_from_ref)]
pub unsafe fn get_raw(&self, id: usize) -> &mut T {
let inner = &mut *self.0.get();
&mut inner[id]
}
}
#[derive(Clone, Default, Hash, PartialEq, Eq)]
#[repr(align(64))]
pub struct Align<T = ()>(pub T);
const _: () = assert!(align_of::<Align>() == 64);
const _: () = assert!(align_of::<Align<usize>>() == 64);
impl<T> Deref for Align<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T> DerefMut for Align<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}
impl<T: fmt::Debug> fmt::Debug for Align<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl<T> From<T> for Align<T> {
fn from(t: T) -> Self {
Align(t)
}
}
pub fn align_up(v: usize, align: usize) -> usize {
v.next_multiple_of(align)
}
pub fn align_down(v: usize, align: usize) -> usize {
(v / align) * align
}
pub unsafe fn slice_cast<I: Sized, O: Sized>(input: &[I]) -> &[O] {
assert!(input.as_ptr().cast::<O>().is_aligned());
let len = size_of_val(input) / size_of::<O>();
core::slice::from_raw_parts(input.as_ptr().cast(), len)
}
pub unsafe fn slice_cast_mut<I: Sized, O: Sized>(input: &mut [I]) -> &mut [O] {
assert!(input.as_ptr().cast::<O>().is_aligned());
let len = size_of_val(input) / size_of::<O>();
core::slice::from_raw_parts_mut(input.as_mut_ptr().cast(), len)
}