Skip to main content

ax_sync/
context.rs

1//! Execution-context guards used by synchronization adapters.
2
3use core::marker::PhantomData;
4
5use crate::interface::{CONTEXT_IRQSAVE, CONTEXT_PREEMPT, CONTEXT_PREEMPT_IRQSAVE, ContextState};
6
7/// Saves the local interrupt state and disables local interrupts.
8#[doc(hidden)]
9#[inline(always)]
10pub fn irq_save_and_disable() -> usize {
11    crate::interface::context_enter(CONTEXT_IRQSAVE).irq()
12}
13
14/// Restores a local interrupt state returned by [`irq_save_and_disable`].
15///
16/// # Safety
17///
18/// `state` must come from the matching save operation on the current CPU and
19/// must be restored exactly once, in properly nested order.
20#[doc(hidden)]
21#[inline(always)]
22pub unsafe fn irq_restore(state: usize) {
23    crate::interface::context_exit(CONTEXT_IRQSAVE, ContextState::new(0, state));
24}
25
26/// Internal critical-section contract retained for low-level adapters.
27#[doc(hidden)]
28pub trait GuardState {
29    /// Saved state needed when the guard is released.
30    type State: Clone + Copy;
31
32    /// Enters the critical section.
33    fn acquire() -> Self::State;
34
35    /// Leaves the critical section.
36    fn release(state: Self::State);
37}
38
39/// Raw state which does not alter the execution context.
40#[doc(hidden)]
41pub struct RawState;
42
43/// State which disables kernel preemption.
44#[doc(hidden)]
45pub struct PreemptState;
46
47/// State which saves and disables local interrupts.
48#[doc(hidden)]
49pub struct IrqSaveState;
50
51/// State which disables preemption, then saves and disables interrupts.
52#[doc(hidden)]
53pub struct PreemptIrqSaveState;
54
55impl GuardState for RawState {
56    type State = ();
57
58    fn acquire() -> Self::State {}
59
60    fn release(_state: Self::State) {}
61}
62
63impl GuardState for PreemptState {
64    type State = ContextState;
65
66    fn acquire() -> Self::State {
67        crate::interface::context_enter(CONTEXT_PREEMPT)
68    }
69
70    fn release(state: Self::State) {
71        crate::interface::context_exit(CONTEXT_PREEMPT, state);
72    }
73}
74
75impl GuardState for IrqSaveState {
76    type State = ContextState;
77
78    fn acquire() -> Self::State {
79        crate::interface::context_enter(CONTEXT_IRQSAVE)
80    }
81
82    fn release(state: Self::State) {
83        crate::interface::context_exit(CONTEXT_IRQSAVE, state);
84    }
85}
86
87impl GuardState for PreemptIrqSaveState {
88    type State = ContextState;
89
90    fn acquire() -> Self::State {
91        crate::interface::context_enter(CONTEXT_PREEMPT_IRQSAVE)
92    }
93
94    fn release(state: Self::State) {
95        crate::interface::context_exit(CONTEXT_PREEMPT_IRQSAVE, state);
96    }
97}
98
99/// An RAII guard which disables kernel preemption while it is alive.
100///
101/// ```compile_fail
102/// fn require_send<T: Send>() {}
103/// require_send::<ax_sync::PreemptGuard>();
104/// ```
105pub struct PreemptGuard {
106    state: ContextState,
107    _not_send: PhantomData<*mut ()>,
108}
109
110impl PreemptGuard {
111    /// Disables preemption until the returned guard is dropped.
112    pub fn new() -> Self {
113        Self {
114            state: PreemptState::acquire(),
115            _not_send: PhantomData,
116        }
117    }
118}
119
120impl Default for PreemptGuard {
121    fn default() -> Self {
122        Self::new()
123    }
124}
125
126impl Drop for PreemptGuard {
127    fn drop(&mut self) {
128        PreemptState::release(self.state);
129    }
130}
131
132/// An RAII guard which saves and disables local interrupts.
133///
134/// ```compile_fail
135/// fn require_send<T: Send>() {}
136/// require_send::<ax_sync::IrqSaveGuard>();
137/// ```
138pub struct IrqSaveGuard {
139    state: ContextState,
140    _not_send: PhantomData<*mut ()>,
141}
142
143impl IrqSaveGuard {
144    /// Saves and disables local interrupts until drop.
145    pub fn new() -> Self {
146        Self {
147            state: IrqSaveState::acquire(),
148            _not_send: PhantomData,
149        }
150    }
151
152    /// Disables preemption for work completed by a hard-IRQ return epilogue.
153    pub fn disable_preempt_for_irq_return(&mut self) -> IrqReturnPreemptGuard<'_> {
154        IrqReturnPreemptGuard {
155            state: crate::interface::irq_return_preempt_enter(),
156            _irq_guard: PhantomData,
157            _not_send: PhantomData,
158        }
159    }
160}
161
162/// A preemption guard whose final release is an IRQ-return boundary.
163#[must_use = "dropping the guard completes IRQ-return preemption exit"]
164pub struct IrqReturnPreemptGuard<'irq> {
165    state: usize,
166    _irq_guard: PhantomData<&'irq mut IrqSaveGuard>,
167    _not_send: PhantomData<*mut ()>,
168}
169
170impl Drop for IrqReturnPreemptGuard<'_> {
171    fn drop(&mut self) {
172        crate::interface::irq_return_preempt_exit(self.state);
173    }
174}
175
176/// Publishes entry into the runtime hard-interrupt lifecycle.
177pub fn hardirq_enter() {
178    crate::interface::hardirq_enter();
179}
180
181/// Publishes exit from the runtime hard-interrupt lifecycle.
182pub fn hardirq_exit() {
183    crate::interface::hardirq_exit();
184}
185
186impl Default for IrqSaveGuard {
187    fn default() -> Self {
188        Self::new()
189    }
190}
191
192impl Drop for IrqSaveGuard {
193    fn drop(&mut self) {
194        IrqSaveState::release(self.state);
195    }
196}
197
198/// An RAII guard which disables preemption and local interrupts.
199///
200/// Entry disables preemption before interrupts. Drop restores interrupts
201/// before re-enabling preemption.
202///
203/// ```compile_fail
204/// fn require_send<T: Send>() {}
205/// require_send::<ax_sync::PreemptIrqSaveGuard>();
206/// ```
207pub struct PreemptIrqSaveGuard {
208    state: ContextState,
209    _not_send: PhantomData<*mut ()>,
210}
211
212impl PreemptIrqSaveGuard {
213    /// Enters a preemption-disabled, IRQ-disabled critical section.
214    pub fn new() -> Self {
215        Self {
216            state: PreemptIrqSaveState::acquire(),
217            _not_send: PhantomData,
218        }
219    }
220}
221
222impl Default for PreemptIrqSaveGuard {
223    fn default() -> Self {
224        Self::new()
225    }
226}
227
228impl Drop for PreemptIrqSaveGuard {
229    fn drop(&mut self) {
230        PreemptIrqSaveState::release(self.state);
231    }
232}