rcore-tutorial/os/src/task/mod.rs
2021-07-12 22:09:34 +08:00

145 lines
No EOL
3.8 KiB
Rust

mod context;
mod switch;
mod task;
use crate::loader::{get_num_app, get_app_data};
use crate::trap::TrapContext;
use crate::sync::UPSafeCell;
use lazy_static::*;
use switch::__switch;
use task::{TaskControlBlock, TaskStatus};
use alloc::vec::Vec;
pub use context::TaskContext;
pub struct TaskManager {
num_app: usize,
inner: UPSafeCell<TaskManagerInner>,
}
struct TaskManagerInner {
tasks: Vec<TaskControlBlock>,
current_task: usize,
}
lazy_static! {
pub static ref TASK_MANAGER: TaskManager = {
println!("init TASK_MANAGER");
let num_app = get_num_app();
println!("num_app = {}", num_app);
let mut tasks: Vec<TaskControlBlock> = Vec::new();
for i in 0..num_app {
tasks.push(TaskControlBlock::new(
get_app_data(i),
i,
));
}
TaskManager {
num_app,
inner: unsafe { UPSafeCell::new(TaskManagerInner {
tasks,
current_task: 0,
})},
}
};
}
impl TaskManager {
fn run_first_task(&self) {
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(
&mut _unused as *mut _,
next_task_cx_ptr,
);
}
}
fn mark_current_suspended(&self) {
let inner = self.inner.upsafe_access();
inner.tasks[inner.current_task].task_status = TaskStatus::Ready;
}
fn mark_current_exited(&self) {
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.upsafe_access();
let current = inner.current_task;
(current + 1..current + self.num_app + 1)
.map(|id| id % self.num_app)
.find(|id| {
inner.tasks[*id].task_status == TaskStatus::Ready
})
}
fn get_current_token(&self) -> usize {
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.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.upsafe_access();
let current = inner.current_task;
inner.tasks[next].task_status = TaskStatus::Running;
inner.current_task = next;
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_ptr,
next_task_cx_ptr,
);
}
} else {
panic!("All applications completed!");
}
}
}
pub fn run_first_task() {
TASK_MANAGER.run_first_task();
}
fn run_next_task() {
TASK_MANAGER.run_next_task();
}
fn mark_current_suspended() {
TASK_MANAGER.mark_current_suspended();
}
fn mark_current_exited() {
TASK_MANAGER.mark_current_exited();
}
pub fn suspend_current_and_run_next() {
mark_current_suspended();
run_next_task();
}
pub fn exit_current_and_run_next() {
mark_current_exited();
run_next_task();
}
pub fn current_user_token() -> usize {
TASK_MANAGER.get_current_token()
}
pub fn current_trap_cx() -> &'static mut TrapContext {
TASK_MANAGER.get_current_trap_cx()
}