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 /// Construit la preuve sans relire `RFLAGS`.
27 ///
28 /// # Safety
29 ///
30 /// L'appelant doit garantir que les interruptions sont bien désactivées sur
31 /// le CPU courant pendant toute la durée de validité logique du token.
32 #[inline]
33 pub(crate) unsafe fn new_unchecked() -> Self {
34 Self(())
35 }
36}
37
38/// Execute a closure with IRQs disabled, providing an `IrqDisabledToken` as proof.
39///
40/// Saves and disables IRQs before calling `f`, then restores the previous flag state.
41#[inline]
42pub fn with_irqs_disabled<R>(f: impl FnOnce(&IrqDisabledToken) -> R) -> R {
43 let saved = crate::arch::x86_64::save_flags_and_cli();
44 // SAFETY: save_flags_and_cli() has just disabled interrupts on this CPU;
45 // the token is dropped before restore_flags() re-enables them.
46 let token = unsafe { IrqDisabledToken::new_unchecked() };
47 let result = f(&token);
48 crate::arch::x86_64::restore_flags(saved);
49 result
50}