use core::cell::UnsafeCell; use core::mem::MaybeUninit; use core::sync::atomic::{AtomicBool, Ordering}; pub struct KernelCell { initialized: AtomicBool, inner: UnsafeCell>, } // Single-core, interrupts disabled during kernel access. unsafe impl Sync for KernelCell {} impl KernelCell { pub const fn uninit() -> Self { Self { initialized: AtomicBool::new(false), inner: UnsafeCell::new(MaybeUninit::uninit()), } } /// Initializes the cell by letting `build` write the value straight /// into its storage, so a large `T` never lives on the stack. /// /// # Safety /// `build` must fully initialize the `T` behind the pointer. pub unsafe fn init_with(&self, build: impl FnOnce(*mut T)) { build(unsafe { (*self.inner.get()).as_mut_ptr() }); self.initialized.store(true, Ordering::Release); } /// Returns a raw pointer to the kernel. Callers must ensure /// no aliasing `&mut` references exist. Safe on single-core /// with interrupts disabled during kernel calls. pub fn as_ptr(&self) -> *mut T { debug_assert!(self.initialized.load(Ordering::Acquire)); unsafe { (*self.inner.get()).as_mut_ptr() } } }