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}