Skip to main content

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}