tg_rcore_tutorial_sync/up.rs
1use core::cell::{RefCell, RefMut, UnsafeCell};
2use core::ops::{Deref, DerefMut};
3use riscv::register::sstatus;
4use spin::Lazy;
5
6/*
7/// Wrap a static data structure inside it so that we are
8/// able to access it without any `unsafe`.
9///
10/// We should only use it in uniprocessor.
11///
12/// In order to get mutable reference of inner data, call
13/// `exclusive_access`.
14pub struct UPSafeCell<T> {
15 /// inner data
16 inner: RefCell<T>,
17}
18
19unsafe impl<T> Sync for UPSafeCell<T> {}
20
21impl<T> UPSafeCell<T> {
22 /// User is responsible to guarantee that inner struct is only used in
23 /// uniprocessor.
24 pub unsafe fn new(value: T) -> Self {
25 Self {
26 inner: RefCell::new(value),
27 }
28 }
29 /// Panic if the data has been borrowed.
30 pub fn exclusive_access(&self) -> RefMut<'_, T> {
31 self.inner.borrow_mut()
32 }
33}
34*/
35
36/// 单处理器环境下的内部可变性容器(原始版本)。
37///
38/// 这个类型绕过了 Rust 的借用检查,仅适用于单处理器环境。
39pub struct UPSafeCellRaw<T> {
40 inner: UnsafeCell<T>,
41}
42
43// SAFETY: 此类型仅用于单处理器环境,不会发生数据竞争。
44// 使用者需要确保不会在单处理器上产生重入问题。
45unsafe impl<T> Sync for UPSafeCellRaw<T> {}
46
47impl<T> UPSafeCellRaw<T> {
48 /// 创建一个新的 `UPSafeCellRaw`。
49 ///
50 /// # Safety
51 ///
52 /// 调用者必须确保此类型仅在单处理器环境下使用,
53 /// 且不会在持有可变引用时发生重入。
54 pub unsafe fn new(value: T) -> Self {
55 Self {
56 inner: UnsafeCell::new(value),
57 }
58 }
59
60 /// 获取内部值的可变引用。
61 ///
62 /// 注意:此函数不进行借用检查,调用者需要确保不会产生多个可变引用。
63 pub fn get_mut(&self) -> &mut T {
64 // SAFETY: 单处理器环境下,只要调用者确保不重入,就不会产生数据竞争。
65 // 此函数的安全性由 UPSafeCellRaw::new 的 unsafe 约定保证。
66 unsafe { &mut (*self.inner.get()) }
67 }
68}
69
70/// 中断屏蔽信息
71pub struct IntrMaskingInfo {
72 nested_level: usize,
73 sie_before_masking: bool,
74}
75
76/// 全局中断屏蔽信息。
77///
78/// SAFETY: 此静态变量仅在单处理器内核中使用,通过中断屏蔽保证访问安全。
79pub static INTR_MASKING_INFO: Lazy<UPSafeCellRaw<IntrMaskingInfo>> = Lazy::new(|| {
80 // SAFETY: 内核运行在单处理器环境下
81 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 /// 进入中断屏蔽区域。
93 pub fn enter(&mut self) {
94 let sie = sstatus::read().sie();
95 // SAFETY: 清除 sstatus.SIE 位以禁用中断,这是单处理器同步的标准做法
96 unsafe {
97 sstatus::clear_sie();
98 }
99 if self.nested_level == 0 {
100 // 只在最外层临界区记录进入前状态,支持可重入的“嵌套关中断”。
101 self.sie_before_masking = sie;
102 }
103 self.nested_level += 1;
104 }
105
106 /// 退出中断屏蔽区域。
107 pub fn exit(&mut self) {
108 self.nested_level -= 1;
109 if self.nested_level == 0 && self.sie_before_masking {
110 // SAFETY: 恢复 sstatus.SIE 位以重新启用中断
111 unsafe {
112 sstatus::set_sie();
113 }
114 }
115 }
116}
117
118/// 带中断屏蔽的内部可变性容器。
119///
120/// 在访问内部数据时自动禁用中断,保证单处理器环境下的数据安全。
121pub struct UPIntrFreeCell<T> {
122 /// inner data
123 inner: RefCell<T>,
124}
125
126// SAFETY: 此类型通过中断屏蔽保证单处理器环境下不会发生数据竞争。
127// RefCell 的动态借用检查会在运行时捕获重入错误。
128unsafe impl<T> Sync for UPIntrFreeCell<T> {}
129
130/// A wrapper type for a mutably borrowed value from a RefCell<T>
131pub struct UPIntrRefMut<'a, T>(Option<RefMut<'a, T>>);
132
133impl<T> UPIntrFreeCell<T> {
134 /// 创建一个新的 `UPIntrFreeCell`。
135 ///
136 /// # Safety
137 ///
138 /// 调用者必须确保此类型仅在单处理器环境下使用。
139 pub unsafe fn new(value: T) -> Self {
140 Self {
141 inner: RefCell::new(value),
142 }
143 }
144
145 /// Panic if the data has been borrowed.
146 pub fn exclusive_access(&self) -> UPIntrRefMut<'_, T> {
147 // 先关中断,再借用 RefCell,确保单核下不会被时钟中断打断而重入。
148 INTR_MASKING_INFO.get_mut().enter();
149 UPIntrRefMut(Some(self.inner.borrow_mut()))
150 }
151 /// exclusive_session
152 pub fn exclusive_session<F, V>(&self, f: F) -> V
153 where
154 F: FnOnce(&mut T) -> V,
155 {
156 let mut inner = self.exclusive_access();
157 f(inner.deref_mut())
158 }
159}
160
161impl<'a, T> Drop for UPIntrRefMut<'a, T> {
162 fn drop(&mut self) {
163 self.0 = None;
164 INTR_MASKING_INFO.get_mut().exit();
165 }
166}
167
168impl<'a, T> Deref for UPIntrRefMut<'a, T> {
169 type Target = T;
170 fn deref(&self) -> &Self::Target {
171 self.0.as_ref().unwrap().deref()
172 }
173}
174impl<'a, T> DerefMut for UPIntrRefMut<'a, T> {
175 fn deref_mut(&mut self) -> &mut Self::Target {
176 self.0.as_mut().unwrap().deref_mut()
177 }
178}