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

Exclusive UPSafeCell: A RefCell wrapper

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