RefCell->UPSafeCell && TaskCx->TCB
This commit is contained in:
parent
bf53e6d211
commit
cf7c2abaa6
14 changed files with 105 additions and 65 deletions
|
@ -3,13 +3,22 @@ use crate::trap::trap_return;
|
|||
#[repr(C)]
|
||||
pub struct TaskContext {
|
||||
ra: usize,
|
||||
sp: usize,
|
||||
s: [usize; 12],
|
||||
}
|
||||
|
||||
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 {
|
||||
ra: trap_return as usize,
|
||||
sp: kstack_ptr,
|
||||
s: [0; 12],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ mod task;
|
|||
|
||||
use crate::loader::{get_num_app, get_app_data};
|
||||
use crate::trap::TrapContext;
|
||||
use core::cell::RefCell;
|
||||
use crate::sync::UPSafeCell;
|
||||
use lazy_static::*;
|
||||
use switch::__switch;
|
||||
use task::{TaskControlBlock, TaskStatus};
|
||||
|
@ -14,7 +14,7 @@ pub use context::TaskContext;
|
|||
|
||||
pub struct TaskManager {
|
||||
num_app: usize,
|
||||
inner: RefCell<TaskManagerInner>,
|
||||
inner: UPSafeCell<TaskManagerInner>,
|
||||
}
|
||||
|
||||
struct TaskManagerInner {
|
||||
|
@ -22,8 +22,6 @@ struct TaskManagerInner {
|
|||
current_task: usize,
|
||||
}
|
||||
|
||||
unsafe impl Sync for TaskManager {}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref TASK_MANAGER: TaskManager = {
|
||||
println!("init TASK_MANAGER");
|
||||
|
@ -38,41 +36,41 @@ 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 _unused: usize = 0;
|
||||
let next_task = &mut self.inner.upsafe_access().tasks[0];
|
||||
next_task.task_status = TaskStatus::Running;
|
||||
let next_task_cx_ptr = &next_task.task_cx as *const TaskContext;
|
||||
drop(next_task);
|
||||
let mut _unused = TaskContext::zero_init();
|
||||
unsafe {
|
||||
__switch(
|
||||
&_unused as *const _,
|
||||
next_task_cx_ptr2,
|
||||
&mut _unused as *mut _,
|
||||
next_task_cx_ptr,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_current_suspended(&self) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let current = inner.current_task;
|
||||
inner.tasks[current].task_status = TaskStatus::Ready;
|
||||
let inner = self.inner.upsafe_access();
|
||||
inner.tasks[inner.current_task].task_status = TaskStatus::Ready;
|
||||
}
|
||||
|
||||
fn mark_current_exited(&self) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let current = inner.current_task;
|
||||
inner.tasks[current].task_status = TaskStatus::Exited;
|
||||
let inner = self.inner.upsafe_access();
|
||||
inner.tasks[inner.current_task].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)
|
||||
|
@ -82,30 +80,28 @@ impl TaskManager {
|
|||
}
|
||||
|
||||
fn get_current_token(&self) -> usize {
|
||||
let inner = self.inner.borrow();
|
||||
let current = inner.current_task;
|
||||
inner.tasks[current].get_user_token()
|
||||
let inner = self.inner.upsafe_access();
|
||||
inner.tasks[inner.current_task].get_user_token()
|
||||
}
|
||||
|
||||
fn get_current_trap_cx(&self) -> &mut TrapContext {
|
||||
let inner = self.inner.borrow();
|
||||
let current = inner.current_task;
|
||||
inner.tasks[current].get_trap_cx()
|
||||
let inner = self.inner.upsafe_access();
|
||||
inner.tasks[inner.current_task].get_trap_cx()
|
||||
}
|
||||
|
||||
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;
|
||||
let current_task_cx_ptr2 = inner.tasks[current].get_task_cx_ptr2();
|
||||
let next_task_cx_ptr2 = inner.tasks[next].get_task_cx_ptr2();
|
||||
core::mem::drop(inner);
|
||||
let current_task_cx_ptr = &mut inner.tasks[current].task_cx as *mut TaskContext;
|
||||
let next_task_cx_ptr = &inner.tasks[next].task_cx as *const TaskContext;
|
||||
drop(inner);
|
||||
unsafe {
|
||||
__switch(
|
||||
current_task_cx_ptr2,
|
||||
next_task_cx_ptr2,
|
||||
current_task_cx_ptr,
|
||||
next_task_cx_ptr,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,37 +1,34 @@
|
|||
.altmacro
|
||||
.macro SAVE_SN n
|
||||
sd s\n, (\n+1)*8(sp)
|
||||
sd s\n, (\n+2)*8(a0)
|
||||
.endm
|
||||
.macro LOAD_SN n
|
||||
ld s\n, (\n+1)*8(sp)
|
||||
ld s\n, (\n+2)*8(a1)
|
||||
.endm
|
||||
.section .text
|
||||
.globl __switch
|
||||
__switch:
|
||||
# __switch(
|
||||
# current_task_cx_ptr2: &*const TaskContext,
|
||||
# next_task_cx_ptr2: &*const TaskContext
|
||||
# current_task_cx_ptr: *mut TaskContext,
|
||||
# next_task_cx_ptr: *const TaskContext
|
||||
# )
|
||||
# push TaskContext to current sp and save its address to where a0 points to
|
||||
addi sp, sp, -13*8
|
||||
sd sp, 0(a0)
|
||||
# fill TaskContext with ra & s0-s11
|
||||
sd ra, 0(sp)
|
||||
# save kernel stack of current task
|
||||
sd sp, 8(a0)
|
||||
# save ra & s0~s11 of current execution
|
||||
sd ra, 0(a0)
|
||||
.set n, 0
|
||||
.rept 12
|
||||
SAVE_SN %n
|
||||
.set n, n + 1
|
||||
.endr
|
||||
# ready for loading TaskContext a1 points to
|
||||
ld sp, 0(a1)
|
||||
# load registers in the TaskContext
|
||||
ld ra, 0(sp)
|
||||
# restore ra & s0~s11 of next execution
|
||||
ld ra, 0(a1)
|
||||
.set n, 0
|
||||
.rept 12
|
||||
LOAD_SN %n
|
||||
.set n, n + 1
|
||||
.endr
|
||||
# pop TaskContext
|
||||
addi sp, sp, 13*8
|
||||
# restore kernel stack of next task
|
||||
ld sp, 8(a1)
|
||||
ret
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
global_asm!(include_str!("switch.S"));
|
||||
|
||||
use super::TaskContext;
|
||||
|
||||
extern "C" {
|
||||
pub fn __switch(
|
||||
current_task_cx_ptr2: *const usize,
|
||||
next_task_cx_ptr2: *const usize
|
||||
current_task_cx_ptr: *mut TaskContext,
|
||||
next_task_cx_ptr: *const TaskContext
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,17 +4,14 @@ use crate::config::{TRAP_CONTEXT, kernel_stack_position};
|
|||
use super::TaskContext;
|
||||
|
||||
pub struct TaskControlBlock {
|
||||
pub task_cx_ptr: usize,
|
||||
pub task_status: TaskStatus,
|
||||
pub task_cx: TaskContext,
|
||||
pub memory_set: MemorySet,
|
||||
pub trap_cx_ppn: PhysPageNum,
|
||||
pub base_size: usize,
|
||||
}
|
||||
|
||||
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 {
|
||||
self.trap_cx_ppn.get_mut()
|
||||
}
|
||||
|
@ -38,11 +35,9 @@ impl TaskControlBlock {
|
|||
kernel_stack_top.into(),
|
||||
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 {
|
||||
task_cx_ptr: task_cx_ptr as usize,
|
||||
task_status,
|
||||
task_cx: TaskContext::goto_trap_return(kernel_stack_top),
|
||||
memory_set,
|
||||
trap_cx_ppn,
|
||||
base_size: user_sp,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue