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