RefCell->UPSafeCell
This commit is contained in:
parent
5a40784918
commit
f1aabb5e0e
12 changed files with 65 additions and 22 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -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
|
||||
|
|
11
os/Makefile
11
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
|
||||
|
|
|
@ -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],
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
3
os/src/sync/mod.rs
Normal file
3
os/src/sync/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
mod up;
|
||||
|
||||
pub use up::UPSafeCell;
|
27
os/src/sync/up.rs
Normal file
27
os/src/sync/up.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<TaskManagerInner>,
|
||||
inner: UPSafeCell<TaskManagerInner>,
|
||||
}
|
||||
|
||||
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<usize> {
|
||||
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;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#[derive(Copy, Clone)]
|
||||
pub struct TaskControlBlock {
|
||||
pub task_cx_ptr: usize,
|
||||
pub task_status: TaskStatus,
|
||||
|
|
|
@ -1 +1 @@
|
|||
nightly-2021-01-30
|
||||
nightly-2021-07-01
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue