Implement many process syscalls.
This commit is contained in:
parent
e56ea17566
commit
8fbadfc951
20 changed files with 383 additions and 88 deletions
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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