Skip to main content

os/sync/
up.rs

1use core::cell::{RefCell, RefMut, UnsafeCell};
2use core::ops::{Deref, DerefMut};
3use lazy_static::*;
4use riscv::register::sstatus;
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
36pub 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 data
94    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    /// Panic if the data has been borrowed.
109    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}