提交 2bd7dcf0 编写于 作者: Y Yifan Wu

Exclusive UPSafeCell: A RefCell wrapper

上级 a70fbfdb
...@@ -26,7 +26,7 @@ fn clear_bss() { ...@@ -26,7 +26,7 @@ fn clear_bss() {
} }
unsafe { unsafe {
core::slice::from_raw_parts_mut( core::slice::from_raw_parts_mut(
sbss as usize as *mut u8, sbss as usize as *mut u8,
ebss as usize - sbss as usize, ebss as usize - sbss as usize,
).fill(0); ).fill(0);
} }
......
/// Wrap a static data structure inside it so that we are use core::cell::{RefCell, RefMut};
/// Wrap a static data structure inside it so that we are
/// able to access it without any `unsafe`. /// able to access it without any `unsafe`.
/// ///
/// We should only use it in uniprocessor. /// We should only use it in uniprocessor.
/// ///
/// In order to get mutable reference of inner data, call /// In order to get mutable reference of inner data, call
/// `upsafe_access`. /// `exclusive_access`.
pub struct UPSafeCell<T> { pub struct UPSafeCell<T> {
/// inner data /// inner data
data: T, inner: RefCell<T>,
} }
unsafe impl<T> Sync for UPSafeCell<T> {} unsafe impl<T> Sync for UPSafeCell<T> {}
...@@ -16,12 +18,10 @@ impl<T> UPSafeCell<T> { ...@@ -16,12 +18,10 @@ impl<T> UPSafeCell<T> {
/// User is responsible to guarantee that inner struct is only used in /// User is responsible to guarantee that inner struct is only used in
/// uniprocessor. /// uniprocessor.
pub unsafe fn new(value: T) -> Self { pub unsafe fn new(value: T) -> Self {
Self { data: value, } Self { inner: RefCell::new(value) }
} }
/// Mention that user should hold exactly one &mut T at a time. /// Panic if the data has been borrowed.
pub fn upsafe_access(&self) -> &mut T { pub fn exclusive_access(&self) -> RefMut<'_, T> {
unsafe { self.inner.borrow_mut()
&mut *(&self.data as *const _ as usize as *mut T)
}
} }
} }
\ No newline at end of file
...@@ -27,12 +27,12 @@ lazy_static! { ...@@ -27,12 +27,12 @@ lazy_static! {
let mut tasks = [ let mut tasks = [
TaskControlBlock { TaskControlBlock {
task_cx: TaskContext::zero_init(), task_cx: TaskContext::zero_init(),
task_status: TaskStatus::UnInit task_status: TaskStatus::UnInit
}; };
MAX_APP_NUM MAX_APP_NUM
]; ];
for i in 0..num_app { for i in 0..num_app {
tasks[i].task_cx = TaskContext::goto_restore(init_app_cx(i)); tasks[i].task_cx = TaskContext::goto_restore(init_app_cx(i));
tasks[i].task_status = TaskStatus::Ready; tasks[i].task_status = TaskStatus::Ready;
} }
TaskManager { TaskManager {
...@@ -46,33 +46,37 @@ lazy_static! { ...@@ -46,33 +46,37 @@ lazy_static! {
} }
impl TaskManager { impl TaskManager {
fn run_first_task(&self) { fn run_first_task(&self) -> ! {
let task0 = &mut self.inner.upsafe_access().tasks[0]; let mut inner = self.inner.exclusive_access();
let task0 = &mut inner.tasks[0];
task0.task_status = TaskStatus::Running; task0.task_status = TaskStatus::Running;
let next_task_cx_ptr = &task0.task_cx as *const TaskContext; let next_task_cx_ptr = &task0.task_cx as *const TaskContext;
drop(inner);
let mut _unused = TaskContext::zero_init(); let mut _unused = TaskContext::zero_init();
// before this, we should drop local variables that must be dropped manually
unsafe { unsafe {
__switch( __switch(
&mut _unused as *mut TaskContext, &mut _unused as *mut TaskContext,
next_task_cx_ptr, next_task_cx_ptr,
); );
} }
panic!("unreachable in run_first_task!");
} }
fn mark_current_suspended(&self) { fn mark_current_suspended(&self) {
let mut inner = self.inner.upsafe_access(); let mut inner = self.inner.exclusive_access();
let current = inner.current_task; let current = inner.current_task;
inner.tasks[current].task_status = TaskStatus::Ready; inner.tasks[current].task_status = TaskStatus::Ready;
} }
fn mark_current_exited(&self) { fn mark_current_exited(&self) {
let mut inner = self.inner.upsafe_access(); let mut inner = self.inner.exclusive_access();
let current = inner.current_task; let current = inner.current_task;
inner.tasks[current].task_status = TaskStatus::Exited; inner.tasks[current].task_status = TaskStatus::Exited;
} }
fn find_next_task(&self) -> Option<usize> { fn find_next_task(&self) -> Option<usize> {
let inner = self.inner.upsafe_access(); let inner = self.inner.exclusive_access();
let current = inner.current_task; let current = inner.current_task;
(current + 1..current + self.num_app + 1) (current + 1..current + self.num_app + 1)
.map(|id| id % self.num_app) .map(|id| id % self.num_app)
...@@ -83,19 +87,21 @@ impl TaskManager { ...@@ -83,19 +87,21 @@ impl TaskManager {
fn run_next_task(&self) { fn run_next_task(&self) {
if let Some(next) = self.find_next_task() { if let Some(next) = self.find_next_task() {
let mut inner = self.inner.upsafe_access(); let mut inner = self.inner.exclusive_access();
let current = inner.current_task; let current = inner.current_task;
inner.tasks[next].task_status = TaskStatus::Running; inner.tasks[next].task_status = TaskStatus::Running;
inner.current_task = next; inner.current_task = next;
let current_task_cx_ptr = &mut inner.tasks[current].task_cx as *mut TaskContext; let current_task_cx_ptr = &mut inner.tasks[current].task_cx as *mut TaskContext;
let next_task_cx_ptr = &inner.tasks[next].task_cx as *const TaskContext; let next_task_cx_ptr = &inner.tasks[next].task_cx as *const TaskContext;
drop(inner); drop(inner);
// before this, we should drop local variables that must be dropped manually
unsafe { unsafe {
__switch( __switch(
current_task_cx_ptr, current_task_cx_ptr,
next_task_cx_ptr, next_task_cx_ptr,
); );
} }
// go back to user mode
} else { } else {
panic!("All applications completed!"); panic!("All applications completed!");
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册