kernel/types/
irq_mutex.rs1use core::cell::UnsafeCell;
7use core::ops::{Deref, DerefMut};
8use core::sync::atomic::{AtomicBool, Ordering};
9use x86_64::registers::rflags::RFlags;
10use crate::arch::instructions;
11
12pub struct IrqMutex<T> {
15 data: UnsafeCell<T>,
16 locked: AtomicBool,
17}
18
19unsafe impl<T: Send> Sync for IrqMutex<T> {}
20unsafe impl<T: Send> Send for IrqMutex<T> {}
21
22impl<T> IrqMutex<T> {
23 pub const fn new(val: T) -> Self {
25 IrqMutex {
26 data: UnsafeCell::new(val),
27 locked: AtomicBool::new(false),
28 }
29 }
30
31 pub fn lock(&self) -> IrqMutexGuard<'_, T> {
33 let rflags = x86_64::registers::rflags::read();
34 instructions::disable_interrupts();
35
36 loop {
37 let res = self.locked.compare_exchange(
38 false,
39 true,
40 Ordering::Acquire,
41 Ordering::Relaxed
42 );
43 if res.is_ok() { break; }
44 }
45
46 IrqMutexGuard::new(self, rflags)
47 }
48
49 pub unsafe fn force_unlock(&self) {
56 self.locked.store(false, Ordering::Release);
57 }
58}
59
60pub struct IrqMutexGuard<'g, T> {
62 mutex: &'g IrqMutex<T>,
63 rflags: RFlags,
65}
66
67impl<'g, T> IrqMutexGuard<'g, T> {
68 pub fn new(mutex: &'g IrqMutex<T>, rflags: RFlags) -> IrqMutexGuard<'g, T> {
70 IrqMutexGuard{ mutex, rflags }
71 }
72}
73
74impl<'g, T> Drop for IrqMutexGuard<'g, T> {
75 fn drop(&mut self) {
76 self.mutex.locked.store(false, Ordering::Release);
77 if self.rflags.contains(RFlags::INTERRUPT_FLAG) {
78 instructions::enable_interrupts();
79 }
80 }
81}
82
83impl<'g, T> Deref for IrqMutexGuard<'g, T> {
84 type Target = T;
85
86 fn deref(&self) -> &Self::Target {
87 unsafe { &*self.mutex.data.get() }
88 }
89}
90
91impl<'g, T> DerefMut for IrqMutexGuard<'g, T> {
92 fn deref_mut(&mut self) -> &mut Self::Target {
93 unsafe { &mut *self.mutex.data.get() }
94 }
95}