use crate::mm::{MemorySet, MapPermission, PhysPageNum, KERNEL_SPACE, VirtAddr}; use crate::trap::{TrapContext, trap_handler}; use crate::config::{TRAP_CONTEXT, kernel_stack_position}; use super::TaskContext; pub struct TaskControlBlock { 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_trap_cx(&self) -> &'static mut TrapContext { self.trap_cx_ppn.get_mut() } pub fn get_user_token(&self) -> usize { self.memory_set.token() } pub fn new(elf_data: &[u8], app_id: usize) -> Self { // memory_set with elf program headers/trampoline/trap context/user stack let (memory_set, user_sp, entry_point) = MemorySet::from_elf(elf_data); let trap_cx_ppn = memory_set .translate(VirtAddr::from(TRAP_CONTEXT).into()) .unwrap() .ppn(); let task_status = TaskStatus::Ready; // map a kernel-stack in kernel space let (kernel_stack_bottom, kernel_stack_top) = kernel_stack_position(app_id); KERNEL_SPACE .exclusive_access() .insert_framed_area( kernel_stack_bottom.into(), kernel_stack_top.into(), MapPermission::R | MapPermission::W, ); let task_control_block = Self { task_status, task_cx: TaskContext::goto_trap_return(kernel_stack_top), memory_set, trap_cx_ppn, base_size: user_sp, }; // prepare TrapContext in user space let trap_cx = task_control_block.get_trap_cx(); *trap_cx = TrapContext::app_init_context( entry_point, user_sp, KERNEL_SPACE.exclusive_access().token(), kernel_stack_top, trap_handler as usize, ); task_control_block } } #[derive(Copy, Clone, PartialEq)] pub enum TaskStatus { Ready, Running, Exited, }