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_cx_ptr: usize, pub task_status: TaskStatus, 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() } pub fn get_user_token(&self) -> usize { self.memory_set.token() } pub fn new(elf_data: &[u8], app_id: usize) -> Self { //println!("into TCB::new"); // memory_set with elf program headers/trampoline/trap context/user stack let (memory_set, user_sp, entry_point) = MemorySet::from_elf(elf_data); //println!("user_sp={:#x},entry_point={:#}", user_sp, entry_point); let trap_cx_ppn = memory_set .translate(VirtAddr::from(TRAP_CONTEXT).into()) .unwrap() .ppn(); //println!("trap_cx_ppn={:?}", trap_cx_ppn); let task_status = TaskStatus::Ready; // map a kernel-stack in kernel space //println!("mapping kernel-stack!"); let (kernel_stack_bottom, kernel_stack_top) = kernel_stack_position(app_id); //println!("kernel_stack={:#x},{:#x}", kernel_stack_bottom, kernel_stack_top); KERNEL_SPACE .lock() .insert_framed_area( kernel_stack_bottom.into(), kernel_stack_top.into(), MapPermission::R | MapPermission::W, ); let task_cx_ptr = (kernel_stack_top - core::mem::size_of::()) as *mut TaskContext; //println!("task_cx size={}", core::mem::size_of::()); //println!("init task_cx, ptr={:p}", task_cx_ptr); unsafe { *task_cx_ptr = TaskContext::goto_trap_return(); } //println!("after init task_cx"); let task_control_block = Self { task_cx_ptr: task_cx_ptr as usize, task_status, memory_set, trap_cx_ppn, base_size: user_sp, }; // prepare TrapContext in user space //println!("preparing trap_cx"); let trap_cx = task_control_block.get_trap_cx(); *trap_cx = TrapContext::app_init_context( entry_point, user_sp, KERNEL_SPACE.lock().token(), kernel_stack_top, trap_handler as usize, ); task_control_block } } #[derive(Copy, Clone, PartialEq)] pub enum TaskStatus { Ready, Running, Exited, }