Implement many process syscalls.

This commit is contained in:
Yifan Wu 2020-12-10 11:57:26 +08:00
parent e56ea17566
commit 8fbadfc951
20 changed files with 383 additions and 88 deletions

View file

@ -1,11 +1,30 @@
use crate::task::{
suspend_current_and_run_next,
exit_current_and_run_next,
current_task,
current_user_token,
add_task,
};
use crate::timer::get_time;
use crate::mm::{
translated_str,
translated_refmut,
};
use crate::loader::get_app_data_by_name;
use alloc::sync::Arc;
pub fn sys_exit(exit_code: i32) -> ! {
// save exit code
let task = current_task().unwrap();
// ---- hold current PCB lock
task.acquire_inner_lock().exit_code = exit_code;
// ---- release current PCB lock
// this function will not return
// drop task manually to maintain rc correctly
drop(task);
pub fn sys_exit(xstate: i32) -> ! {
println!("[kernel] Application exited with code {}", xstate);
exit_current_and_run_next();
panic!("Unreachable in sys_exit!");
}
@ -17,4 +36,60 @@ pub fn sys_yield() -> isize {
pub fn sys_get_time() -> isize {
get_time() as isize
}
pub fn sys_getpid() -> isize {
current_task().unwrap().pid.0 as isize
}
pub fn sys_fork() -> isize {
let current_task = current_task().unwrap();
let new_task = current_task.fork();
let new_pid = new_task.pid.0;
// modify trap context of new_task, because it returns immediately after switching
let trap_cx = new_task.acquire_inner_lock().get_trap_cx();
// we do not have to move to next instruction since we have done it before
// for child process, fork returns 0
trap_cx.x[10] = 0;
// add new task to scheduler
add_task(new_task);
new_pid as isize
}
pub fn sys_exec(path: *const u8) -> isize {
let token = current_user_token();
let path = translated_str(token, path);
let data = get_app_data_by_name(path.as_str()).unwrap();
let task = current_task().unwrap();
task.exec(data);
0
}
pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
let task = current_task().unwrap();
// find a child process
// ---- hold current PCB lock
let mut inner = task.acquire_inner_lock();
let pair = inner.children
.iter()
.enumerate()
.find(|(_, p)| {
// ++++ temporarily hold child PCB lock
p.acquire_inner_lock().is_zombie() && (pid == -1 || pid as usize == p.getpid())
// ++++ release child PCB lock
});
if let Some((idx, _)) = pair {
let child = inner.children.remove(idx);
// confirm that child will be deallocated after removing from children list
assert_eq!(Arc::strong_count(&child), 1);
let found_pid = child.getpid();
// ++++ temporarily hold child lock
let exit_code = child.acquire_inner_lock().exit_code;
// ++++ release child PCB lock
*translated_refmut(inner.memory_set.token(), exit_code_ptr) = exit_code;
found_pid as isize
} else {
-1
}
// ---- release current PCB lock automatically
}