1use core::cell::{RefCell, RefMut, UnsafeCell};
2use core::ops::{Deref, DerefMut};
3use riscv::register::sstatus;
4use spin::Lazy;
5
6pub struct UPSafeCellRaw<T> {
40 inner: UnsafeCell<T>,
41}
42
43unsafe impl<T> Sync for UPSafeCellRaw<T> {}
46
47impl<T> UPSafeCellRaw<T> {
48 pub unsafe fn new(value: T) -> Self {
55 Self {
56 inner: UnsafeCell::new(value),
57 }
58 }
59
60 pub fn get_mut(&self) -> &mut T {
64 unsafe { &mut (*self.inner.get()) }
67 }
68}
69
70pub struct IntrMaskingInfo {
72 nested_level: usize,
73 sie_before_masking: bool,
74}
75
76pub static INTR_MASKING_INFO: Lazy<UPSafeCellRaw<IntrMaskingInfo>> = Lazy::new(|| {
80 unsafe { UPSafeCellRaw::new(IntrMaskingInfo::new()) }
82});
83
84impl IntrMaskingInfo {
85 pub fn new() -> Self {
86 Self {
87 nested_level: 0,
88 sie_before_masking: false,
89 }
90 }
91
92 pub fn enter(&mut self) {
94 let sie = sstatus::read().sie();
95 unsafe {
97 sstatus::clear_sie();
98 }
99 if self.nested_level == 0 {
100 self.sie_before_masking = sie;
101 }
102 self.nested_level += 1;
103 }
104
105 pub fn exit(&mut self) {
107 self.nested_level -= 1;
108 if self.nested_level == 0 && self.sie_before_masking {
109 unsafe {
111 sstatus::set_sie();
112 }
113 }
114 }
115}
116
117pub struct UPIntrFreeCell<T> {
121 inner: RefCell<T>,
123}
124
125unsafe impl<T> Sync for UPIntrFreeCell<T> {}
128
129pub struct UPIntrRefMut<'a, T>(Option<RefMut<'a, T>>);
131
132impl<T> UPIntrFreeCell<T> {
133 pub unsafe fn new(value: T) -> Self {
139 Self {
140 inner: RefCell::new(value),
141 }
142 }
143
144 pub fn exclusive_access(&self) -> UPIntrRefMut<'_, T> {
146 INTR_MASKING_INFO.get_mut().enter();
147 UPIntrRefMut(Some(self.inner.borrow_mut()))
148 }
149 pub fn exclusive_session<F, V>(&self, f: F) -> V
151 where
152 F: FnOnce(&mut T) -> V,
153 {
154 let mut inner = self.exclusive_access();
155 f(inner.deref_mut())
156 }
157}
158
159impl<'a, T> Drop for UPIntrRefMut<'a, T> {
160 fn drop(&mut self) {
161 self.0 = None;
162 INTR_MASKING_INFO.get_mut().exit();
163 }
164}
165
166impl<'a, T> Deref for UPIntrRefMut<'a, T> {
167 type Target = T;
168 fn deref(&self) -> &Self::Target {
169 self.0.as_ref().unwrap().deref()
170 }
171}
172impl<'a, T> DerefMut for UPIntrRefMut<'a, T> {
173 fn deref_mut(&mut self) -> &mut Self::Target {
174 self.0.as_mut().unwrap().deref_mut()
175 }
176}