RefCell->UPSafeCell && TaskCx->TCB
This commit is contained in:
parent
bf53e6d211
commit
cf7c2abaa6
14 changed files with 105 additions and 65 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,6 +2,7 @@
|
||||||
os/target/*
|
os/target/*
|
||||||
os/.idea/*
|
os/.idea/*
|
||||||
os/src/link_app.S
|
os/src/link_app.S
|
||||||
|
os/last-*
|
||||||
os/Cargo.lock
|
os/Cargo.lock
|
||||||
user/target/*
|
user/target/*
|
||||||
user/.idea/*
|
user/.idea/*
|
||||||
|
|
11
os/Makefile
11
os/Makefile
|
@ -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
|
||||||
|
|
|
@ -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)]
|
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
@ -21,6 +20,7 @@ mod loader;
|
||||||
mod config;
|
mod config;
|
||||||
mod task;
|
mod task;
|
||||||
mod timer;
|
mod timer;
|
||||||
|
mod sync;
|
||||||
mod mm;
|
mod mm;
|
||||||
|
|
||||||
global_asm!(include_str!("entry.asm"));
|
global_asm!(include_str!("entry.asm"));
|
||||||
|
@ -31,9 +31,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
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,13 +3,22 @@ use crate::trap::trap_return;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct TaskContext {
|
pub struct TaskContext {
|
||||||
ra: usize,
|
ra: usize,
|
||||||
|
sp: usize,
|
||||||
s: [usize; 12],
|
s: [usize; 12],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskContext {
|
impl TaskContext {
|
||||||
pub fn goto_trap_return() -> Self {
|
pub fn zero_init() -> Self {
|
||||||
|
Self {
|
||||||
|
ra: 0,
|
||||||
|
sp: 0,
|
||||||
|
s: [0; 12],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn goto_trap_return(kstack_ptr: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ra: trap_return as usize,
|
ra: trap_return as usize,
|
||||||
|
sp: kstack_ptr,
|
||||||
s: [0; 12],
|
s: [0; 12],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod task;
|
||||||
|
|
||||||
use crate::loader::{get_num_app, get_app_data};
|
use crate::loader::{get_num_app, get_app_data};
|
||||||
use crate::trap::TrapContext;
|
use crate::trap::TrapContext;
|
||||||
use core::cell::RefCell;
|
use crate::sync::UPSafeCell;
|
||||||
use lazy_static::*;
|
use lazy_static::*;
|
||||||
use switch::__switch;
|
use switch::__switch;
|
||||||
use task::{TaskControlBlock, TaskStatus};
|
use task::{TaskControlBlock, TaskStatus};
|
||||||
|
@ -14,7 +14,7 @@ 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 {
|
||||||
|
@ -22,8 +22,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 = {
|
||||||
println!("init TASK_MANAGER");
|
println!("init TASK_MANAGER");
|
||||||
|
@ -38,41 +36,41 @@ 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 next_task = &mut self.inner.upsafe_access().tasks[0];
|
||||||
let next_task_cx_ptr2 = self.inner.borrow().tasks[0].get_task_cx_ptr2();
|
next_task.task_status = TaskStatus::Running;
|
||||||
let _unused: usize = 0;
|
let next_task_cx_ptr = &next_task.task_cx as *const TaskContext;
|
||||||
|
drop(next_task);
|
||||||
|
let mut _unused = TaskContext::zero_init();
|
||||||
unsafe {
|
unsafe {
|
||||||
__switch(
|
__switch(
|
||||||
&_unused as *const _,
|
&mut _unused as *mut _,
|
||||||
next_task_cx_ptr2,
|
next_task_cx_ptr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_current_suspended(&self) {
|
fn mark_current_suspended(&self) {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let inner = self.inner.upsafe_access();
|
||||||
let current = inner.current_task;
|
inner.tasks[inner.current_task].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 inner = self.inner.upsafe_access();
|
||||||
let current = inner.current_task;
|
inner.tasks[inner.current_task].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)
|
||||||
|
@ -82,30 +80,28 @@ impl TaskManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_token(&self) -> usize {
|
fn get_current_token(&self) -> usize {
|
||||||
let inner = self.inner.borrow();
|
let inner = self.inner.upsafe_access();
|
||||||
let current = inner.current_task;
|
inner.tasks[inner.current_task].get_user_token()
|
||||||
inner.tasks[current].get_user_token()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_trap_cx(&self) -> &mut TrapContext {
|
fn get_current_trap_cx(&self) -> &mut TrapContext {
|
||||||
let inner = self.inner.borrow();
|
let inner = self.inner.upsafe_access();
|
||||||
let current = inner.current_task;
|
inner.tasks[inner.current_task].get_trap_cx()
|
||||||
inner.tasks[current].get_trap_cx()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
let current_task_cx_ptr2 = inner.tasks[current].get_task_cx_ptr2();
|
let current_task_cx_ptr = &mut inner.tasks[current].task_cx as *mut TaskContext;
|
||||||
let next_task_cx_ptr2 = inner.tasks[next].get_task_cx_ptr2();
|
let next_task_cx_ptr = &inner.tasks[next].task_cx as *const TaskContext;
|
||||||
core::mem::drop(inner);
|
drop(inner);
|
||||||
unsafe {
|
unsafe {
|
||||||
__switch(
|
__switch(
|
||||||
current_task_cx_ptr2,
|
current_task_cx_ptr,
|
||||||
next_task_cx_ptr2,
|
next_task_cx_ptr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,37 +1,34 @@
|
||||||
.altmacro
|
.altmacro
|
||||||
.macro SAVE_SN n
|
.macro SAVE_SN n
|
||||||
sd s\n, (\n+1)*8(sp)
|
sd s\n, (\n+2)*8(a0)
|
||||||
.endm
|
.endm
|
||||||
.macro LOAD_SN n
|
.macro LOAD_SN n
|
||||||
ld s\n, (\n+1)*8(sp)
|
ld s\n, (\n+2)*8(a1)
|
||||||
.endm
|
.endm
|
||||||
.section .text
|
.section .text
|
||||||
.globl __switch
|
.globl __switch
|
||||||
__switch:
|
__switch:
|
||||||
# __switch(
|
# __switch(
|
||||||
# current_task_cx_ptr2: &*const TaskContext,
|
# current_task_cx_ptr: *mut TaskContext,
|
||||||
# next_task_cx_ptr2: &*const TaskContext
|
# next_task_cx_ptr: *const TaskContext
|
||||||
# )
|
# )
|
||||||
# push TaskContext to current sp and save its address to where a0 points to
|
# save kernel stack of current task
|
||||||
addi sp, sp, -13*8
|
sd sp, 8(a0)
|
||||||
sd sp, 0(a0)
|
# save ra & s0~s11 of current execution
|
||||||
# fill TaskContext with ra & s0-s11
|
sd ra, 0(a0)
|
||||||
sd ra, 0(sp)
|
|
||||||
.set n, 0
|
.set n, 0
|
||||||
.rept 12
|
.rept 12
|
||||||
SAVE_SN %n
|
SAVE_SN %n
|
||||||
.set n, n + 1
|
.set n, n + 1
|
||||||
.endr
|
.endr
|
||||||
# ready for loading TaskContext a1 points to
|
# restore ra & s0~s11 of next execution
|
||||||
ld sp, 0(a1)
|
ld ra, 0(a1)
|
||||||
# load registers in the TaskContext
|
|
||||||
ld ra, 0(sp)
|
|
||||||
.set n, 0
|
.set n, 0
|
||||||
.rept 12
|
.rept 12
|
||||||
LOAD_SN %n
|
LOAD_SN %n
|
||||||
.set n, n + 1
|
.set n, n + 1
|
||||||
.endr
|
.endr
|
||||||
# pop TaskContext
|
# restore kernel stack of next task
|
||||||
addi sp, sp, 13*8
|
ld sp, 8(a1)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
global_asm!(include_str!("switch.S"));
|
global_asm!(include_str!("switch.S"));
|
||||||
|
|
||||||
|
use super::TaskContext;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn __switch(
|
pub fn __switch(
|
||||||
current_task_cx_ptr2: *const usize,
|
current_task_cx_ptr: *mut TaskContext,
|
||||||
next_task_cx_ptr2: *const usize
|
next_task_cx_ptr: *const TaskContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,14 @@ use crate::config::{TRAP_CONTEXT, kernel_stack_position};
|
||||||
use super::TaskContext;
|
use super::TaskContext;
|
||||||
|
|
||||||
pub struct TaskControlBlock {
|
pub struct TaskControlBlock {
|
||||||
pub task_cx_ptr: usize,
|
|
||||||
pub task_status: TaskStatus,
|
pub task_status: TaskStatus,
|
||||||
|
pub task_cx: TaskContext,
|
||||||
pub memory_set: MemorySet,
|
pub memory_set: MemorySet,
|
||||||
pub trap_cx_ppn: PhysPageNum,
|
pub trap_cx_ppn: PhysPageNum,
|
||||||
pub base_size: usize,
|
pub base_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskControlBlock {
|
impl TaskControlBlock {
|
||||||
pub fn get_task_cx_ptr2(&self) -> *const usize {
|
|
||||||
&self.task_cx_ptr as *const usize
|
|
||||||
}
|
|
||||||
pub fn get_trap_cx(&self) -> &'static mut TrapContext {
|
pub fn get_trap_cx(&self) -> &'static mut TrapContext {
|
||||||
self.trap_cx_ppn.get_mut()
|
self.trap_cx_ppn.get_mut()
|
||||||
}
|
}
|
||||||
|
@ -38,11 +35,9 @@ impl TaskControlBlock {
|
||||||
kernel_stack_top.into(),
|
kernel_stack_top.into(),
|
||||||
MapPermission::R | MapPermission::W,
|
MapPermission::R | MapPermission::W,
|
||||||
);
|
);
|
||||||
let task_cx_ptr = (kernel_stack_top - core::mem::size_of::<TaskContext>()) as *mut TaskContext;
|
|
||||||
unsafe { *task_cx_ptr = TaskContext::goto_trap_return(); }
|
|
||||||
let task_control_block = Self {
|
let task_control_block = Self {
|
||||||
task_cx_ptr: task_cx_ptr as usize,
|
|
||||||
task_status,
|
task_status,
|
||||||
|
task_cx: TaskContext::goto_trap_return(kernel_stack_top),
|
||||||
memory_set,
|
memory_set,
|
||||||
trap_cx_ppn,
|
trap_cx_ppn,
|
||||||
base_size: user_sp,
|
base_size: user_sp,
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
nightly-2021-01-30
|
nightly-2021-07-01
|
||||||
|
|
|
@ -23,7 +23,7 @@ unsafe fn main() -> i32 {
|
||||||
println!("power_3 [{}/{}]", i, iter);
|
println!("power_3 [{}/{}]", i, iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("{}^{} = {}(mod {})", p, iter, S[cur], m);
|
println!("{}^{} = {}(MOD {})", p, iter, S[cur], m);
|
||||||
println!("Test power_3 OK!");
|
println!("Test power_3 OK!");
|
||||||
0
|
0
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@ unsafe fn main() -> i32 {
|
||||||
println!("power_5 [{}/{}]", i, iter);
|
println!("power_5 [{}/{}]", i, iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("{}^{} = {}(mod {})", p, iter, S[cur], m);
|
println!("{}^{} = {}(MOD {})", p, iter, S[cur], m);
|
||||||
println!("Test power_5 OK!");
|
println!("Test power_5 OK!");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ unsafe fn main() -> i32 {
|
||||||
println!("power_7 [{}/{}]", i, iter);
|
println!("power_7 [{}/{}]", i, iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("{}^{} = {}(mod {})", p, iter, S[cur], m);
|
println!("{}^{} = {}(MOD {})", p, iter, S[cur], m);
|
||||||
println!("Test power_7 OK!");
|
println!("Test power_7 OK!");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue