RefCell->UPSafeCell

This commit is contained in:
Yifan Wu 2021-07-09 21:18:51 +08:00
parent 5a40784918
commit f1aabb5e0e
12 changed files with 65 additions and 22 deletions

1
.gitignore vendored
View file

@ -3,6 +3,7 @@ os/target/*
os/.idea/* os/.idea/*
os/Cargo.lock os/Cargo.lock
os/src/link_app.S os/src/link_app.S
os/last-*
user/target/* user/target/*
user/.idea/* user/.idea/*
user/Cargo.lock user/Cargo.lock

View file

@ -29,7 +29,14 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64
# Disassembly # Disassembly
DISASM ?= -x 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: env:
(rustup target list | grep "riscv64gc-unknown-none-elf (installed)") || rustup target add $(TARGET) (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 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 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

View file

@ -3,11 +3,13 @@ use crate::task::TaskContext;
use crate::config::*; use crate::config::*;
#[repr(align(4096))] #[repr(align(4096))]
#[derive(Copy, Clone)]
struct KernelStack { struct KernelStack {
data: [u8; KERNEL_STACK_SIZE], data: [u8; KERNEL_STACK_SIZE],
} }
#[repr(align(4096))] #[repr(align(4096))]
#[derive(Copy, Clone)]
struct UserStack { struct UserStack {
data: [u8; USER_STACK_SIZE], data: [u8; USER_STACK_SIZE],
} }

View file

@ -3,7 +3,6 @@
#![feature(global_asm)] #![feature(global_asm)]
#![feature(llvm_asm)] #![feature(llvm_asm)]
#![feature(panic_info_message)] #![feature(panic_info_message)]
#![feature(const_in_array_repeat_expressions)]
#[macro_use] #[macro_use]
mod console; mod console;
@ -15,6 +14,7 @@ mod loader;
mod config; mod config;
mod task; mod task;
mod timer; mod timer;
mod sync;
global_asm!(include_str!("entry.asm")); global_asm!(include_str!("entry.asm"));
global_asm!(include_str!("link_app.S")); global_asm!(include_str!("link_app.S"));
@ -24,9 +24,12 @@ fn clear_bss() {
fn sbss(); fn sbss();
fn ebss(); fn ebss();
} }
(sbss as usize..ebss as usize).for_each(|a| { unsafe {
unsafe { (a as *mut u8).write_volatile(0) } core::slice::from_raw_parts_mut(
}); sbss as usize as *mut u8,
ebss as usize - sbss as usize,
).fill(0);
}
} }
#[no_mangle] #[no_mangle]

3
os/src/sync/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod up;
pub use up::UPSafeCell;

27
os/src/sync/up.rs Normal file
View file

@ -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<T> {
/// inner data
data: T,
}
unsafe impl<T> Sync for UPSafeCell<T> {}
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, }
}
/// 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)
}
}
}

View file

@ -4,16 +4,16 @@ mod task;
use crate::config::MAX_APP_NUM; use crate::config::MAX_APP_NUM;
use crate::loader::{get_num_app, init_app_cx}; use crate::loader::{get_num_app, init_app_cx};
use core::cell::RefCell;
use lazy_static::*; use lazy_static::*;
use switch::__switch; use switch::__switch;
use task::{TaskControlBlock, TaskStatus}; use task::{TaskControlBlock, TaskStatus};
use crate::sync::UPSafeCell;
pub use context::TaskContext; pub use context::TaskContext;
pub struct TaskManager { pub struct TaskManager {
num_app: usize, num_app: usize,
inner: RefCell<TaskManagerInner>, inner: UPSafeCell<TaskManagerInner>,
} }
struct TaskManagerInner { struct TaskManagerInner {
@ -21,8 +21,6 @@ struct TaskManagerInner {
current_task: usize, current_task: usize,
} }
unsafe impl Sync for TaskManager {}
lazy_static! { lazy_static! {
pub static ref TASK_MANAGER: TaskManager = { pub static ref TASK_MANAGER: TaskManager = {
let num_app = get_num_app(); let num_app = get_num_app();
@ -36,18 +34,19 @@ lazy_static! {
} }
TaskManager { TaskManager {
num_app, num_app,
inner: RefCell::new(TaskManagerInner { inner: unsafe { UPSafeCell::new(TaskManagerInner {
tasks, tasks,
current_task: 0, current_task: 0,
}), })},
} }
}; };
} }
impl TaskManager { impl TaskManager {
fn run_first_task(&self) { fn run_first_task(&self) {
self.inner.borrow_mut().tasks[0].task_status = TaskStatus::Running; let task0 = &mut self.inner.upsafe_access().tasks[0];
let next_task_cx_ptr2 = self.inner.borrow().tasks[0].get_task_cx_ptr2(); task0.task_status = TaskStatus::Running;
let next_task_cx_ptr2 = task0.get_task_cx_ptr2();
let _unused: usize = 0; let _unused: usize = 0;
unsafe { unsafe {
__switch( __switch(
@ -58,19 +57,19 @@ impl TaskManager {
} }
fn mark_current_suspended(&self) { fn mark_current_suspended(&self) {
let mut inner = self.inner.borrow_mut(); let mut inner = self.inner.upsafe_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.borrow_mut(); let mut inner = self.inner.upsafe_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.borrow(); let inner = self.inner.upsafe_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)
@ -81,7 +80,7 @@ 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.borrow_mut(); let mut inner = self.inner.upsafe_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;

View file

@ -1,3 +1,4 @@
#[derive(Copy, Clone)]
pub struct TaskControlBlock { pub struct TaskControlBlock {
pub task_cx_ptr: usize, pub task_cx_ptr: usize,
pub task_status: TaskStatus, pub task_status: TaskStatus,

View file

@ -1 +1 @@
nightly-2021-01-30 nightly-2021-07-01

View file

@ -22,7 +22,7 @@ fn main() -> i32 {
println!("power_3 [{}/{}]", i, iter); println!("power_3 [{}/{}]", i, iter);
} }
} }
println!("{}^{} = {}", p, iter, s[cur]); println!("{}^{} = {}(MOD {})", p, iter, s[cur], m);
println!("Test power_3 OK!"); println!("Test power_3 OK!");
0 0
} }

View file

@ -22,7 +22,7 @@ fn main() -> i32 {
println!("power_5 [{}/{}]", i, iter); println!("power_5 [{}/{}]", i, iter);
} }
} }
println!("{}^{} = {}", p, iter, s[cur]); println!("{}^{} = {}(MOD {})", p, iter, s[cur], m);
println!("Test power_5 OK!"); println!("Test power_5 OK!");
0 0
} }

View file

@ -22,7 +22,7 @@ fn main() -> i32 {
println!("power_7 [{}/{}]", i, iter); println!("power_7 [{}/{}]", i, iter);
} }
} }
println!("{}^{} = {}", p, iter, s[cur]); println!("{}^{} = {}(MOD {})", p, iter, s[cur], m);
println!("Test power_7 OK!"); println!("Test power_7 OK!");
0 0
} }