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,5 +1,5 @@
use crate::mm::translated_byte_buffer;
use crate::task::{current_user_token, suspend_current_and_run_next};
use crate::task::{current_user_token};
use crate::sbi::console_getchar;
const FD_STDIN: usize = 0;
@ -28,7 +28,7 @@ pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize {
loop {
c = console_getchar();
if c == 0 {
suspend_current_and_run_next();
//suspend_current_and_run_next();
continue;
} else {
break;

View file

@ -3,6 +3,10 @@ const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
const SYSCALL_YIELD: usize = 124;
const SYSCALL_GET_TIME: usize = 169;
const SYSCALL_GETPID: usize = 172;
const SYSCALL_FORK: usize = 220;
const SYSCALL_EXEC: usize = 221;
const SYSCALL_WAITPID: usize = 260;
mod fs;
mod process;
@ -17,6 +21,10 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
SYSCALL_EXIT => sys_exit(args[0] as i32),
SYSCALL_YIELD => sys_yield(),
SYSCALL_GET_TIME => sys_get_time(),
SYSCALL_GETPID => sys_getpid(),
SYSCALL_FORK => sys_fork(),
SYSCALL_EXEC => sys_exec(args[0] as *const u8),
SYSCALL_WAITPID => sys_waitpid(args[0] as isize, args[1] as *mut i32),
_ => panic!("Unsupported syscall_id: {}", syscall_id),
}
}

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
}