From 19c6265ed5b475754216dca801408b833c293bc6 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Thu, 8 Jul 2021 18:15:52 +0800 Subject: [PATCH] RefCell->UPSafeCell --- os/src/batch.rs | 56 +++++++++++++++++++++------------------------- os/src/main.rs | 1 + os/src/sync/mod.rs | 3 +++ os/src/sync/up.rs | 27 ++++++++++++++++++++++ 4 files changed, 57 insertions(+), 30 deletions(-) create mode 100644 os/src/sync/mod.rs create mode 100644 os/src/sync/up.rs diff --git a/os/src/batch.rs b/os/src/batch.rs index a17346ed..7a29c9a1 100644 --- a/os/src/batch.rs +++ b/os/src/batch.rs @@ -1,6 +1,6 @@ -use core::cell::RefCell; use lazy_static::*; use crate::trap::TrapContext; +use crate::sync::UPSafeCell; const USER_STACK_SIZE: usize = 4096 * 2; const KERNEL_STACK_SIZE: usize = 4096 * 2; @@ -39,16 +39,12 @@ impl UserStack { } struct AppManager { - inner: RefCell, -} -struct AppManagerInner { num_app: usize, current_app: usize, app_start: [usize; MAX_APP_NUM + 1], } -unsafe impl Sync for AppManager {} -impl AppManagerInner { +impl AppManager { pub fn print_app_info(&self) { println!("[kernel] num_app = {}", self.num_app); for i in 0..self.num_app { @@ -64,9 +60,10 @@ impl AppManagerInner { // clear icache llvm_asm!("fence.i" :::: "volatile"); // clear app area - (APP_BASE_ADDRESS..APP_BASE_ADDRESS + APP_SIZE_LIMIT).for_each(|addr| { - (addr as *mut u8).write_volatile(0); - }); + core::slice::from_raw_parts_mut( + APP_BASE_ADDRESS as *mut u8, + APP_SIZE_LIMIT + ).fill(0); let app_src = core::slice::from_raw_parts( self.app_start[app_id] as *const u8, self.app_start[app_id + 1] - self.app_start[app_id] @@ -86,23 +83,21 @@ impl AppManagerInner { } lazy_static! { - static ref APP_MANAGER: AppManager = AppManager { - inner: RefCell::new({ - extern "C" { fn _num_app(); } - let num_app_ptr = _num_app as usize as *const usize; - let num_app = unsafe { num_app_ptr.read_volatile() }; - let mut app_start: [usize; MAX_APP_NUM + 1] = [0; MAX_APP_NUM + 1]; - let app_start_raw: &[usize] = unsafe { - core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1) - }; - app_start[..=num_app].copy_from_slice(app_start_raw); - AppManagerInner { - num_app, - current_app: 0, - app_start, - } - }), - }; + static ref APP_MANAGER: UPSafeCell = unsafe { UPSafeCell::new({ + extern "C" { fn _num_app(); } + let num_app_ptr = _num_app as usize as *const usize; + let num_app = num_app_ptr.read_volatile(); + let mut app_start: [usize; MAX_APP_NUM + 1] = [0; MAX_APP_NUM + 1]; + let app_start_raw: &[usize] = core::slice::from_raw_parts( + num_app_ptr.add(1), num_app + 1 + ); + app_start[..=num_app].copy_from_slice(app_start_raw); + AppManager { + num_app, + current_app: 0, + app_start, + } + })}; } pub fn init() { @@ -110,15 +105,16 @@ pub fn init() { } pub fn print_app_info() { - APP_MANAGER.inner.borrow().print_app_info(); + APP_MANAGER.upsafe_access().print_app_info(); } pub fn run_next_app() -> ! { - let current_app = APP_MANAGER.inner.borrow().get_current_app(); + let app_manager = APP_MANAGER.upsafe_access(); + let current_app = app_manager.get_current_app(); unsafe { - APP_MANAGER.inner.borrow().load_app(current_app); + app_manager.load_app(current_app); } - APP_MANAGER.inner.borrow_mut().move_to_next_app(); + app_manager.move_to_next_app(); extern "C" { fn __restore(cx_addr: usize); } unsafe { __restore(KERNEL_STACK.push_context( diff --git a/os/src/main.rs b/os/src/main.rs index 8f8fdeb7..b43c79ad 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -11,6 +11,7 @@ mod sbi; mod syscall; mod trap; mod batch; +mod sync; global_asm!(include_str!("entry.asm")); global_asm!(include_str!("link_app.S")); diff --git a/os/src/sync/mod.rs b/os/src/sync/mod.rs new file mode 100644 index 00000000..77295248 --- /dev/null +++ b/os/src/sync/mod.rs @@ -0,0 +1,3 @@ +mod up; + +pub use up::UPSafeCell; \ No newline at end of file diff --git a/os/src/sync/up.rs b/os/src/sync/up.rs new file mode 100644 index 00000000..849ac4bc --- /dev/null +++ b/os/src/sync/up.rs @@ -0,0 +1,27 @@ +/// 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`. +pub struct UPSafeCell { + /// inner data + data: T, +} + +unsafe impl Sync for UPSafeCell {} + +impl UPSafeCell { + /// User is responsible to guarantee that inner struct is only used in + /// uniprocessor. + pub unsafe fn new(value: T) -> Self { + Self { data: 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) + } + } +} \ No newline at end of file