Skip to main content

frame_alloc/strategies/
interrupt.rs

1/// Strategy for disabling and restoring **local (per-CPU) interrupts**.
2///
3/// Implement this trait to tell the allocator how to disabling interrupts around a
4/// lock's critical section, so the locked allocators are safe to call from interrupt
5/// context.
6///
7/// [`disable`](InterruptControl::disable) must **save the prior state and then
8/// disable**, returning that state; [`restore`](InterruptControl::restore) must put
9/// it back. Saving the prior state (rather than unconditionally re-enabling) is
10/// what makes nesting correct: an inner lock taken while an outer lock already
11/// disabled interrupts will, on release, restore "still disabled", and only the
12/// outermost release re-enables.
13///
14/// # Safety
15///
16/// `restore` is `unsafe`: it changes the CPU interrupt-enable state and must be
17/// called exactly once, with the [`State`](InterruptControl::State) returned by the
18/// matching `disable`, after the critical section. `disable`/`restore` need to be
19/// faithful inverses.
20pub unsafe trait InterruptControl {
21    /// Opaque saved interrupt state.
22    type State: Copy;
23    /// A const-constructible placeholder used only to seed the lock's saved-state.
24    const INIT: Self::State;
25    /// Save the current local-interrupt state and disable interrupts on this CPU.
26    fn disable() -> Self::State;
27    /// Restore the interrupt state previously returned by [`disable`].
28    ///
29    /// # Safety
30    ///
31    /// Must be called once per `disable`, with that call's returned state, after
32    /// the critical section it guarded.
33    ///
34    /// [`disable`]: InterruptControl::disable
35    unsafe fn restore(state: Self::State);
36}
37
38/// The default [`InterruptControl`]: a no-op. Interrupts are never touched, so it
39/// is **not safe to call from an interrupt handler**.
40pub struct NoInterruptControl;
41
42// SAFETY: a no-op is a trivially faithful inverse of itself; `restore` changes no
43// machine state.
44unsafe impl InterruptControl for NoInterruptControl {
45    type State = ();
46    const INIT: () = ();
47    #[inline(always)]
48    fn disable() {}
49    #[inline(always)]
50    unsafe fn restore(_state: ()) {}
51}