frame-alloc 0.1.0

A no_std, dependency-free, const-constructible physical frame allocator for kernels
Documentation
/// Strategy for disabling and restoring **local (per-CPU) interrupts**.
///
/// Implement this trait to tell the allocator how to disabling interrupts around a
/// lock's critical section, so the locked allocators are safe to call from interrupt
/// context.
///
/// [`disable`](InterruptControl::disable) must **save the prior state and then
/// disable**, returning that state; [`restore`](InterruptControl::restore) must put
/// it back. Saving the prior state (rather than unconditionally re-enabling) is
/// what makes nesting correct: an inner lock taken while an outer lock already
/// disabled interrupts will, on release, restore "still disabled", and only the
/// outermost release re-enables.
///
/// # Safety
///
/// `restore` is `unsafe`: it changes the CPU interrupt-enable state and must be
/// called exactly once, with the [`State`](InterruptControl::State) returned by the
/// matching `disable`, after the critical section. `disable`/`restore` need to be
/// faithful inverses.
pub unsafe trait InterruptControl {
    /// Opaque saved interrupt state.
    type State: Copy;
    /// A const-constructible placeholder used only to seed the lock's saved-state.
    const INIT: Self::State;
    /// Save the current local-interrupt state and disable interrupts on this CPU.
    fn disable() -> Self::State;
    /// Restore the interrupt state previously returned by [`disable`].
    ///
    /// # Safety
    ///
    /// Must be called once per `disable`, with that call's returned state, after
    /// the critical section it guarded.
    ///
    /// [`disable`]: InterruptControl::disable
    unsafe fn restore(state: Self::State);
}

/// The default [`InterruptControl`]: a no-op. Interrupts are never touched, so it
/// is **not safe to call from an interrupt handler**.
pub struct NoInterruptControl;

// SAFETY: a no-op is a trivially faithful inverse of itself; `restore` changes no
// machine state.
unsafe impl InterruptControl for NoInterruptControl {
    type State = ();
    const INIT: () = ();
    #[inline(always)]
    fn disable() {}
    #[inline(always)]
    unsafe fn restore(_state: ()) {}
}