use crate::{ mm::kernel_token, task::{add_task, current_task, TaskControlBlock}, trap::{trap_handler, TrapContext}, }; use alloc::sync::Arc; pub fn sys_thread_create(entry: usize, arg: usize) -> isize { let task = current_task().unwrap(); let process = task.process.upgrade().unwrap(); // create a new thread let new_task = Arc::new(TaskControlBlock::new( Arc::clone(&process), task.inner_exclusive_access() .res .as_ref() .unwrap() .ustack_base, true, )); // add new task to scheduler add_task(Arc::clone(&new_task)); let new_task_inner = new_task.inner_exclusive_access(); let new_task_res = new_task_inner.res.as_ref().unwrap(); let new_task_tid = new_task_res.tid; let mut process_inner = process.inner_exclusive_access(); // add new thread to current process let tasks = &mut process_inner.tasks; while tasks.len() < new_task_tid + 1 { tasks.push(None); } tasks[new_task_tid] = Some(Arc::clone(&new_task)); let new_task_trap_cx = new_task_inner.get_trap_cx(); *new_task_trap_cx = TrapContext::app_init_context( entry, new_task_res.ustack_top(), kernel_token(), new_task.kstack.get_top(), trap_handler as usize, ); (*new_task_trap_cx).x[10] = arg; new_task_tid as isize } pub fn sys_gettid() -> isize { current_task() .unwrap() .inner_exclusive_access() .res .as_ref() .unwrap() .tid as isize } /// thread does not exist, return -1 /// thread has not exited yet, return -2 /// otherwise, return thread's exit code pub fn sys_waittid(tid: usize) -> i32 { let task = current_task().unwrap(); let process = task.process.upgrade().unwrap(); let task_inner = task.inner_exclusive_access(); let mut process_inner = process.inner_exclusive_access(); // a thread cannot wait for itself if task_inner.res.as_ref().unwrap().tid == tid { return -1; } let mut exit_code: Option = None; let waited_task = process_inner.tasks[tid].as_ref(); if let Some(waited_task) = waited_task { if let Some(waited_exit_code) = waited_task.inner_exclusive_access().exit_code { exit_code = Some(waited_exit_code); } } else { // waited thread does not exist return -1; } if let Some(exit_code) = exit_code { // dealloc the exited thread process_inner.tasks[tid] = None; exit_code } else { // waited thread has not exited -2 } }