Skip to main content

os/syscall/
process.rs

1use crate::fs::{OpenFlags, open_file};
2use crate::mm::{translated_refmut, translated_str};
3use crate::task::{
4    add_task, current_task, current_user_token, exit_current_and_run_next,
5    suspend_current_and_run_next,
6};
7use crate::timer::get_time_ms;
8use alloc::sync::Arc;
9
10pub fn sys_exit(exit_code: i32) -> ! {
11    exit_current_and_run_next(exit_code);
12    panic!("Unreachable in sys_exit!");
13}
14
15pub fn sys_yield() -> isize {
16    suspend_current_and_run_next();
17    0
18}
19
20pub fn sys_get_time() -> isize {
21    get_time_ms() as isize
22}
23
24pub fn sys_getpid() -> isize {
25    current_task().unwrap().pid.0 as isize
26}
27
28pub fn sys_fork() -> isize {
29    let current_task = current_task().unwrap();
30    let new_task = current_task.fork();
31    let new_pid = new_task.pid.0;
32    // modify trap context of new_task, because it returns immediately after switching
33    let trap_cx = new_task.inner_exclusive_access().get_trap_cx();
34    // we do not have to move to next instruction since we have done it before
35    // for child process, fork returns 0
36    trap_cx.x[10] = 0;
37    // add new task to scheduler
38    add_task(new_task);
39    new_pid as isize
40}
41
42pub fn sys_exec(path: *const u8) -> isize {
43    let token = current_user_token();
44    let path = translated_str(token, path);
45    if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) {
46        let all_data = app_inode.read_all();
47        let task = current_task().unwrap();
48        task.exec(all_data.as_slice());
49        0
50    } else {
51        -1
52    }
53}
54
55/// If there is not a child process whose pid is same as given, return -1.
56/// Else if there is a child process but it is still running, return -2.
57pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
58    let task = current_task().unwrap();
59    // find a child process
60
61    // ---- access current PCB exclusively
62    let mut inner = task.inner_exclusive_access();
63    if !inner
64        .children
65        .iter()
66        .any(|p| pid == -1 || pid as usize == p.getpid())
67    {
68        return -1;
69        // ---- release current PCB
70    }
71    let pair = inner.children.iter().enumerate().find(|(_, p)| {
72        // ++++ temporarily access child PCB exclusively
73        p.inner_exclusive_access().is_zombie() && (pid == -1 || pid as usize == p.getpid())
74        // ++++ release child PCB
75    });
76    if let Some((idx, _)) = pair {
77        let child = inner.children.remove(idx);
78        // confirm that child will be deallocated after being removed from children list
79        assert_eq!(Arc::strong_count(&child), 1);
80        let found_pid = child.getpid();
81        // ++++ temporarily access child PCB exclusively
82        let exit_code = child.inner_exclusive_access().exit_code;
83        // ++++ release child PCB
84        *translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code;
85        found_pid as isize
86    } else {
87        -2
88    }
89    // ---- release current PCB automatically
90}