Implement many process syscalls.
This commit is contained in:
parent
e56ea17566
commit
8fbadfc951
20 changed files with 383 additions and 88 deletions
|
@ -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
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue