os/syscall/
thread.rs

1use crate::{
2    mm::kernel_token,
3    task::{TaskControlBlock, add_task, current_task},
4    trap::{TrapContext, trap_handler},
5};
6use alloc::sync::Arc;
7
8pub fn sys_thread_create(entry: usize, arg: usize) -> isize {
9    let task = current_task().unwrap();
10    let process = task.process.upgrade().unwrap();
11    // create a new thread
12    let new_task = Arc::new(TaskControlBlock::new(
13        Arc::clone(&process),
14        task.inner_exclusive_access()
15            .res
16            .as_ref()
17            .unwrap()
18            .ustack_base,
19        true,
20    ));
21    // add new task to scheduler
22    add_task(Arc::clone(&new_task));
23    let new_task_inner = new_task.inner_exclusive_access();
24    let new_task_res = new_task_inner.res.as_ref().unwrap();
25    let new_task_tid = new_task_res.tid;
26    let mut process_inner = process.inner_exclusive_access();
27    // add new thread to current process
28    let tasks = &mut process_inner.tasks;
29    while tasks.len() < new_task_tid + 1 {
30        tasks.push(None);
31    }
32    tasks[new_task_tid] = Some(Arc::clone(&new_task));
33    let new_task_trap_cx = new_task_inner.get_trap_cx();
34    *new_task_trap_cx = TrapContext::app_init_context(
35        entry,
36        new_task_res.ustack_top(),
37        kernel_token(),
38        new_task.kstack.get_top(),
39        trap_handler as usize,
40    );
41    (*new_task_trap_cx).x[10] = arg;
42    new_task_tid as isize
43}
44
45pub fn sys_gettid() -> isize {
46    current_task()
47        .unwrap()
48        .inner_exclusive_access()
49        .res
50        .as_ref()
51        .unwrap()
52        .tid as isize
53}
54
55/// thread does not exist, return -1
56/// thread has not exited yet, return -2
57/// otherwise, return thread's exit code
58pub fn sys_waittid(tid: usize) -> i32 {
59    let task = current_task().unwrap();
60    let process = task.process.upgrade().unwrap();
61    let task_inner = task.inner_exclusive_access();
62    let mut process_inner = process.inner_exclusive_access();
63    // a thread cannot wait for itself
64    if task_inner.res.as_ref().unwrap().tid == tid {
65        return -1;
66    }
67    let mut exit_code: Option<i32> = None;
68    let waited_task = process_inner.tasks[tid].as_ref();
69    if let Some(waited_task) = waited_task {
70        if let Some(waited_exit_code) = waited_task.inner_exclusive_access().exit_code {
71            exit_code = Some(waited_exit_code);
72        }
73    } else {
74        // waited thread does not exist
75        return -1;
76    }
77    if let Some(exit_code) = exit_code {
78        // dealloc the exited thread
79        process_inner.tasks[tid] = None;
80        exit_code
81    } else {
82        // waited thread has not exited
83        -2
84    }
85}