1use core::cell::{RefCell, RefMut, UnsafeCell};
2use core::ops::{Deref, DerefMut};
3use lazy_static::*;
4use riscv::register::sstatus;
5
6pub struct UPSafeCellRaw<T> {
37 inner: UnsafeCell<T>,
38}
39
40unsafe impl<T> Sync for UPSafeCellRaw<T> {}
41
42impl<T> UPSafeCellRaw<T> {
43 pub unsafe fn new(value: T) -> Self {
44 Self {
45 inner: UnsafeCell::new(value),
46 }
47 }
48 pub fn get_mut(&self) -> &mut T {
49 unsafe { &mut (*self.inner.get()) }
50 }
51}
52
53pub struct IntrMaskingInfo {
54 nested_level: usize,
55 sie_before_masking: bool,
56}
57
58lazy_static! {
59 static ref INTR_MASKING_INFO: UPSafeCellRaw<IntrMaskingInfo> =
60 unsafe { UPSafeCellRaw::new(IntrMaskingInfo::new()) };
61}
62
63impl IntrMaskingInfo {
64 pub fn new() -> Self {
65 Self {
66 nested_level: 0,
67 sie_before_masking: false,
68 }
69 }
70
71 pub fn enter(&mut self) {
72 let sie = sstatus::read().sie();
73 unsafe {
74 sstatus::clear_sie();
75 }
76 if self.nested_level == 0 {
77 self.sie_before_masking = sie;
78 }
79 self.nested_level += 1;
80 }
81
82 pub fn exit(&mut self) {
83 self.nested_level -= 1;
84 if self.nested_level == 0 && self.sie_before_masking {
85 unsafe {
86 sstatus::set_sie();
87 }
88 }
89 }
90}
91
92pub struct UPIntrFreeCell<T> {
93 inner: RefCell<T>,
95}
96
97unsafe impl<T> Sync for UPIntrFreeCell<T> {}
98
99pub struct UPIntrRefMut<'a, T>(Option<RefMut<'a, T>>);
100
101impl<T> UPIntrFreeCell<T> {
102 pub unsafe fn new(value: T) -> Self {
103 Self {
104 inner: RefCell::new(value),
105 }
106 }
107
108 pub fn exclusive_access(&self) -> UPIntrRefMut<'_, T> {
110 INTR_MASKING_INFO.get_mut().enter();
111 UPIntrRefMut(Some(self.inner.borrow_mut()))
112 }
113
114 pub fn exclusive_session<F, V>(&self, f: F) -> V
115 where
116 F: FnOnce(&mut T) -> V,
117 {
118 let mut inner = self.exclusive_access();
119 f(inner.deref_mut())
120 }
121}
122
123impl<'a, T> Drop for UPIntrRefMut<'a, T> {
124 fn drop(&mut self) {
125 self.0 = None;
126 INTR_MASKING_INFO.get_mut().exit();
127 }
128}
129
130impl<'a, T> Deref for UPIntrRefMut<'a, T> {
131 type Target = T;
132 fn deref(&self) -> &Self::Target {
133 self.0.as_ref().unwrap().deref()
134 }
135}
136impl<'a, T> DerefMut for UPIntrRefMut<'a, T> {
137 fn deref_mut(&mut self) -> &mut Self::Target {
138 self.0.as_mut().unwrap().deref_mut()
139 }
140}