From 6ffe9c0d035809324fb37654b1e1259a7f2e61c7 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Fri, 9 Jul 2021 21:18:51 +0800 Subject: [PATCH] RefCell->UPSafeCell --- .gitignore | 1 + os/Makefile | 11 +++++++++-- os/src/loader.rs | 2 ++ os/src/main.rs | 11 +++++++---- os/src/sync/mod.rs | 3 +++ os/src/sync/up.rs | 27 +++++++++++++++++++++++++++ os/src/task/mod.rs | 23 +++++++++++------------ os/src/task/task.rs | 1 + rust-toolchain | 2 +- user/src/bin/00power_3.rs | 2 +- user/src/bin/01power_5.rs | 2 +- user/src/bin/02power_7.rs | 2 +- 12 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 os/src/sync/mod.rs create mode 100644 os/src/sync/up.rs diff --git a/.gitignore b/.gitignore index 4b5497cf..614368ae 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ os/target/* os/.idea/* os/Cargo.lock os/src/link_app.S +os/last-* user/target/* user/.idea/* user/Cargo.lock diff --git a/os/Makefile b/os/Makefile index 2a4b3870..5330215f 100644 --- a/os/Makefile +++ b/os/Makefile @@ -29,7 +29,14 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64 # Disassembly DISASM ?= -x -build: env $(KERNEL_BIN) +build: env switch-check $(KERNEL_BIN) + +switch-check: +ifeq ($(BOARD), qemu) + (which last-qemu) || (rm last-k210 -f && touch last-qemu && make clean) +else ifeq ($(BOARD), k210) + (which last-k210) || (rm last-qemu -f && touch last-k210 && make clean) +endif env: (rustup target list | grep "riscv64gc-unknown-none-elf (installed)") || rustup target add $(TARGET) @@ -85,4 +92,4 @@ debug: build tmux split-window -h "riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'" && \ tmux -2 attach-session -d -.PHONY: build env kernel clean disasm disasm-vim run-inner +.PHONY: build env kernel clean disasm disasm-vim run-inner switch-check diff --git a/os/src/loader.rs b/os/src/loader.rs index 893a0677..99166998 100644 --- a/os/src/loader.rs +++ b/os/src/loader.rs @@ -3,11 +3,13 @@ use crate::task::TaskContext; use crate::config::*; #[repr(align(4096))] +#[derive(Copy, Clone)] struct KernelStack { data: [u8; KERNEL_STACK_SIZE], } #[repr(align(4096))] +#[derive(Copy, Clone)] struct UserStack { data: [u8; USER_STACK_SIZE], } diff --git a/os/src/main.rs b/os/src/main.rs index c4ab3b5b..9bef1444 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -3,7 +3,6 @@ #![feature(global_asm)] #![feature(llvm_asm)] #![feature(panic_info_message)] -#![feature(const_in_array_repeat_expressions)] #[macro_use] mod console; @@ -15,6 +14,7 @@ mod loader; mod config; mod task; mod timer; +mod sync; global_asm!(include_str!("entry.asm")); global_asm!(include_str!("link_app.S")); @@ -24,9 +24,12 @@ fn clear_bss() { fn sbss(); fn ebss(); } - (sbss as usize..ebss as usize).for_each(|a| { - unsafe { (a as *mut u8).write_volatile(0) } - }); + unsafe { + core::slice::from_raw_parts_mut( + sbss as usize as *mut u8, + ebss as usize - sbss as usize, + ).fill(0); + } } #[no_mangle] 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 diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 24062bee..2c05cb52 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -4,16 +4,16 @@ mod task; use crate::config::MAX_APP_NUM; use crate::loader::{get_num_app, init_app_cx}; -use core::cell::RefCell; use lazy_static::*; use switch::__switch; use task::{TaskControlBlock, TaskStatus}; +use crate::sync::UPSafeCell; pub use context::TaskContext; pub struct TaskManager { num_app: usize, - inner: RefCell, + inner: UPSafeCell, } struct TaskManagerInner { @@ -21,8 +21,6 @@ struct TaskManagerInner { current_task: usize, } -unsafe impl Sync for TaskManager {} - lazy_static! { pub static ref TASK_MANAGER: TaskManager = { let num_app = get_num_app(); @@ -36,18 +34,19 @@ lazy_static! { } TaskManager { num_app, - inner: RefCell::new(TaskManagerInner { + inner: unsafe { UPSafeCell::new(TaskManagerInner { tasks, current_task: 0, - }), + })}, } }; } impl TaskManager { fn run_first_task(&self) { - self.inner.borrow_mut().tasks[0].task_status = TaskStatus::Running; - let next_task_cx_ptr2 = self.inner.borrow().tasks[0].get_task_cx_ptr2(); + let task0 = &mut self.inner.upsafe_access().tasks[0]; + task0.task_status = TaskStatus::Running; + let next_task_cx_ptr2 = task0.get_task_cx_ptr2(); let _unused: usize = 0; unsafe { __switch( @@ -58,19 +57,19 @@ impl TaskManager { } fn mark_current_suspended(&self) { - let mut inner = self.inner.borrow_mut(); + let mut inner = self.inner.upsafe_access(); let current = inner.current_task; inner.tasks[current].task_status = TaskStatus::Ready; } fn mark_current_exited(&self) { - let mut inner = self.inner.borrow_mut(); + let mut inner = self.inner.upsafe_access(); let current = inner.current_task; inner.tasks[current].task_status = TaskStatus::Exited; } fn find_next_task(&self) -> Option { - let inner = self.inner.borrow(); + let inner = self.inner.upsafe_access(); let current = inner.current_task; (current + 1..current + self.num_app + 1) .map(|id| id % self.num_app) @@ -81,7 +80,7 @@ impl TaskManager { fn run_next_task(&self) { if let Some(next) = self.find_next_task() { - let mut inner = self.inner.borrow_mut(); + let mut inner = self.inner.upsafe_access(); let current = inner.current_task; inner.tasks[next].task_status = TaskStatus::Running; inner.current_task = next; diff --git a/os/src/task/task.rs b/os/src/task/task.rs index 54dc3600..fbae53e0 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -1,3 +1,4 @@ +#[derive(Copy, Clone)] pub struct TaskControlBlock { pub task_cx_ptr: usize, pub task_status: TaskStatus, diff --git a/rust-toolchain b/rust-toolchain index a08f00d1..a14eedce 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2021-01-30 +nightly-2021-07-01 diff --git a/user/src/bin/00power_3.rs b/user/src/bin/00power_3.rs index 064b4e07..e0ec5f3d 100644 --- a/user/src/bin/00power_3.rs +++ b/user/src/bin/00power_3.rs @@ -22,7 +22,7 @@ fn main() -> i32 { println!("power_3 [{}/{}]", i, iter); } } - println!("{}^{} = {}", p, iter, s[cur]); + println!("{}^{} = {}(MOD {})", p, iter, s[cur], m); println!("Test power_3 OK!"); 0 } \ No newline at end of file diff --git a/user/src/bin/01power_5.rs b/user/src/bin/01power_5.rs index 157af298..e47761b7 100644 --- a/user/src/bin/01power_5.rs +++ b/user/src/bin/01power_5.rs @@ -22,7 +22,7 @@ fn main() -> i32 { println!("power_5 [{}/{}]", i, iter); } } - println!("{}^{} = {}", p, iter, s[cur]); + println!("{}^{} = {}(MOD {})", p, iter, s[cur], m); println!("Test power_5 OK!"); 0 } diff --git a/user/src/bin/02power_7.rs b/user/src/bin/02power_7.rs index a5c72dba..a97d2f50 100644 --- a/user/src/bin/02power_7.rs +++ b/user/src/bin/02power_7.rs @@ -22,7 +22,7 @@ fn main() -> i32 { println!("power_7 [{}/{}]", i, iter); } } - println!("{}^{} = {}", p, iter, s[cur]); + println!("{}^{} = {}(MOD {})", p, iter, s[cur], m); println!("Test power_7 OK!"); 0 }