1use crate::arch::{
2 constant::SSTATUS_SIE,
3 intr::{read_and_disable_interrupts, restore_interrupts},
4};
5use core::ops::Drop;
6
7pub struct IntrGuard {
19 flags: usize,
20}
21
22impl IntrGuard {
23 pub fn new() -> Self {
26 let flags = unsafe { read_and_disable_interrupts() };
29 IntrGuard { flags }
30 }
31
32 #[allow(dead_code)]
35 pub fn was_enabled(&self) -> bool {
36 self.flags & SSTATUS_SIE != 0
37 }
38}
39
40impl Drop for IntrGuard {
41 fn drop(&mut self) {
43 unsafe { restore_interrupts(self.flags) };
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 use crate::{arch::intr::*, kassert, println, test_case};
54
55 test_case!(test_guard_disables_interrupts, {
57 println!("Testing: test_guard_disables_interrupts");
58 unsafe { enable_interrupts() };
59 kassert!(are_interrupts_enabled());
60
61 let guard = IntrGuard::new();
62
63 kassert!(guard.was_enabled());
64
65 kassert!(!are_interrupts_enabled());
66 });
67
68 test_case!(test_guard_restores_on_drop, {
70 println!("Testing: test_guard_restores_on_drop");
71 let initial_flags: usize = {
72 let flags = unsafe { read_and_disable_interrupts() };
73 unsafe { enable_interrupts() };
74 flags
75 };
76
77 let initial_state = are_interrupts_enabled();
78
79 kassert!(initial_state);
80
81 {
82 let guard = IntrGuard::new();
83 kassert!(!are_interrupts_enabled());
84
85 kassert!(guard.flags & SSTATUS_SIE != 0);
86 }
87
88 kassert!(are_interrupts_enabled());
89
90 unsafe { restore_interrupts(initial_flags) };
91 });
92}