os/syscall/
process.rs

1use crate::fs::{OpenFlags, open_file};
2use crate::mm::{translated_ref, translated_refmut, translated_str};
3use crate::task::{
4    SignalFlags, current_process, current_task, current_user_token, exit_current_and_run_next,
5    pid2process, suspend_current_and_run_next,
6};
7use crate::timer::get_time_ms;
8use alloc::string::String;
9use alloc::sync::Arc;
10use alloc::vec::Vec;
11
12pub fn sys_exit(exit_code: i32) -> ! {
13    exit_current_and_run_next(exit_code);
14    panic!("Unreachable in sys_exit!");
15}
16
17pub fn sys_yield() -> isize {
18    suspend_current_and_run_next();
19    0
20}
21
22pub fn sys_get_time() -> isize {
23    get_time_ms() as isize
24}
25
26pub fn sys_getpid() -> isize {
27    current_task().unwrap().process.upgrade().unwrap().getpid() as isize
28}
29
30pub fn sys_fork() -> isize {
31    let current_process = current_process();
32    let new_process = current_process.fork();
33    let new_pid = new_process.getpid();
34    // modify trap context of new_task, because it returns immediately after switching
35    let new_process_inner = new_process.inner_exclusive_access();
36    let task = new_process_inner.tasks[0].as_ref().unwrap();
37    let trap_cx = task.inner_exclusive_access().get_trap_cx();
38    // we do not have to move to next instruction since we have done it before
39    // for child process, fork returns 0
40    trap_cx.x[10] = 0;
41    new_pid as isize
42}
43
44pub fn sys_exec(path: *const u8, mut args: *const usize) -> isize {
45    let token = current_user_token();
46    let path = translated_str(token, path);
47    let mut args_vec: Vec<String> = Vec::new();
48    loop {
49        let arg_str_ptr = *translated_ref(token, args);
50        if arg_str_ptr == 0 {
51            break;
52        }
53        args_vec.push(translated_str(token, arg_str_ptr as *const u8));
54        unsafe {
55            args = args.add(1);
56        }
57    }
58    if let Some(app_inode) = open_file(path.as_str(), OpenFlags::RDONLY) {
59        let all_data = app_inode.read_all();
60        let process = current_process();
61        let argc = args_vec.len();
62        process.exec(all_data.as_slice(), args_vec);
63        // return argc because cx.x[10] will be covered with it later
64        argc as isize
65    } else {
66        -1
67    }
68}
69
70/// If there is not a child process whose pid is same as given, return -1.
71/// Else if there is a child process but it is still running, return -2.
72pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
73    let process = current_process();
74    // find a child process
75
76    let mut inner = process.inner_exclusive_access();
77    if !inner
78        .children
79        .iter()
80        .any(|p| pid == -1 || pid as usize == p.getpid())
81    {
82        return -1;
83        // ---- release current PCB
84    }
85    let pair = inner.children.iter().enumerate().find(|(_, p)| {
86        // ++++ temporarily access child PCB exclusively
87        p.inner_exclusive_access().is_zombie && (pid == -1 || pid as usize == p.getpid())
88        // ++++ release child PCB
89    });
90    if let Some((idx, _)) = pair {
91        let child = inner.children.remove(idx);
92        // confirm that child will be deallocated after being removed from children list
93        assert_eq!(Arc::strong_count(&child), 1);
94        let found_pid = child.getpid();
95        // ++++ temporarily access child PCB exclusively
96        let exit_code = child.inner_exclusive_access().exit_code;
97        // ++++ release child PCB
98        *translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code;
99        found_pid as isize
100    } else {
101        -2
102    }
103    // ---- release current PCB automatically
104}
105
106pub fn sys_kill(pid: usize, signal: u32) -> isize {
107    if let Some(process) = pid2process(pid) {
108        if let Some(flag) = SignalFlags::from_bits(signal) {
109            process.inner_exclusive_access().signals |= flag;
110            0
111        } else {
112            -1
113        }
114    } else {
115        -1
116    }
117}