strat9_kernel/sync/irq.rs
1use crate::arch::x86_64;
2
3/// Preuve typée que les IRQ sont masquées sur le CPU courant.
4///
5/// L'allocateur mémoire consomme ce token pour empêcher à la compilation les
6/// appels depuis des contextes où une interruption pourrait ré-entrer sur le
7/// même verrou et provoquer un deadlock.
8///
9/// Intentionnellement non-`Copy` et non-`Clone` : le token ne doit pas pouvoir
10/// s'échapper du contexte IRQ-off dans lequel il a été créé.
11#[derive(Debug)]
12pub struct IrqDisabledToken(());
13
14impl IrqDisabledToken {
15 /// Vérifie l'état courant des interruptions et retourne la preuve si elles
16 /// sont déjà désactivées.
17 #[inline]
18 pub fn verify() -> Option<Self> {
19 if x86_64::interrupts_enabled() {
20 None
21 } else {
22 Some(Self(()))
23 }
24 }
25
26 /// Builds the proof without re-checking `RFLAGS`.
27 /// Reserved for internal producers of the `sync` module (guardian, with_irqs_disabled).
28 ///
29 /// # Safety
30 /// The caller must guarantee that IRQs are indeed disabled on the current CPU for the entire
31 /// logical validity of the token.
32
33 #[inline]
34 pub(super) unsafe fn new_unchecked() -> Self {
35 Self(())
36 }
37
38 /// Create a token when the caller guarantees that IRQs are already disabled.
39 /// Only to be used for implementing external traits (e.g. `X86FrameAllocator`)
40 /// whose signature cannot accept a token parameter. The caller MUST guarantee
41 /// that interrupts are disabled on the current CPU.
42 ///
43 /// # Safety
44 /// The caller must guarantee that IRQs are disabled on the current CPU.
45 ///
46 #[inline]
47 pub(crate) unsafe fn token_from_trusted_context() -> Self {
48 Self::new_unchecked()
49 }
50}
51
52/// Execute a closure with IRQs disabled, providing an `IrqDisabledToken` as proof.
53///
54/// Saves and disables IRQs before calling `f`, then restores the previous flag state.
55#[inline]
56pub fn with_irqs_disabled<R>(f: impl FnOnce(&IrqDisabledToken) -> R) -> R {
57 let saved = crate::arch::x86_64::save_flags_and_cli();
58 // SAFETY: save_flags_and_cli() has just disabled interrupts on this CPU;
59 // the token is dropped before restore_flags() re-enables them.
60 let token = unsafe { IrqDisabledToken::new_unchecked() };
61 let result = f(&token);
62 crate::arch::x86_64::restore_flags(saved);
63 result
64}