kernel_api/sync/
irq_cell.rs1use core::cell::{Cell, UnsafeCell};
2use core::fmt::{Debug, Formatter};
3use core::marker::{PhantomData, Unsize};
4use core::mem::ManuallyDrop;
5use core::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn};
6
7pub struct IrqCell<T: ?Sized> {
8 state: Cell<Option<usize>>,
9 data: UnsafeCell<T>
10}
11
12impl<T> IrqCell<T> {
13 pub const fn new(val: T) -> Self {
14 Self { state: Cell::new(None), data: UnsafeCell::new(val) }
15 }
16}
17
18impl<T: ?Sized> IrqCell<T> {
19 pub fn lock(&self) -> IrqGuard<'_, T> {
20 if self.state.get().is_some() { panic!("IrqCell cannot be borrowed multiple times"); }
22
23 self.state.set(Some(crate::bridge::irq::disable()));
24 IrqGuard { cell: self, _phantom_not_send: PhantomData }
25 }
26
27 pub unsafe fn make_guard_unchecked(&self) -> IrqGuard<'_, T> {
28 debug_assert!(self.state.get().is_some(), "Created IrqGuard for unlocked IrqCell");
30
31 IrqGuard { cell: self, _phantom_not_send: PhantomData }
32 }
33
34 pub unsafe fn unlock(&self) {
35 let old_state = self.state.take();
36 crate::bridge::irq::set(old_state.unwrap());
37 }
38}
39
40impl<T: Debug> Debug for IrqCell<T> {
41 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
42 let guard = self.lock();
43 let r = f.debug_struct("IrqCell")
44 .field("data", &*guard)
45 .finish_non_exhaustive();
46 IrqGuard::unlock(guard);
47 r
48 }
49}
50
51pub struct IrqGuard<'cell, T: ?Sized> {
52 cell: &'cell IrqCell<T>,
53 _phantom_not_send: PhantomData<*mut u8>, }
55
56impl<T: ?Sized> IrqGuard<'_, T> {
57 pub fn unlock_no_interrupts(this: IrqGuard<T>) {
58 let this = ManuallyDrop::new(this);
59 this.cell.state.take();
60 }
61
62 fn unlock(this: IrqGuard<T>) {
63 let this = ManuallyDrop::new(this);
64 unsafe { this.cell.unlock(); }
65 }
66}
67
68impl<T: Debug> Debug for IrqGuard<'_, T> {
69 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
70 f.debug_struct("IrqGuard")
71 .field("cell", &**self)
72 .finish()
73 }
74}
75
76impl<T: ?Sized> Deref for IrqGuard<'_, T> {
77 type Target = T;
78
79 fn deref(&self) -> &T {
80 unsafe { &*self.cell.data.get() }
81 }
82}
83
84impl<T: ?Sized> DerefMut for IrqGuard<'_, T> {
85 fn deref_mut(&mut self) -> &mut T {
86 unsafe { &mut *self.cell.data.get() }
87 }
88}
89
90impl<T: ?Sized> Drop for IrqGuard<'_, T> {
91 fn drop(&mut self) {
92 unsafe { self.cell.unlock(); }
93 }
94}
95
96impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<IrqGuard<'a, U>> for IrqGuard<'a, T> {}
97impl<'b, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<IrqGuard<'b, U>> for IrqGuard<'b, T> {}