1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-23 08:26:17 +04:00

Ugly impl sys_wait(0)

This commit is contained in:
WangRunji 2018-11-01 00:45:02 +08:00
parent 74facd8e87
commit 6fc23e1134
4 changed files with 90 additions and 16 deletions

View File

@ -10,6 +10,7 @@
#![feature(global_asm)]
#![feature(compiler_builtins_lib)]
#![feature(raw)]
#![feature(vec_resize_default)]
#![no_std]

View File

@ -4,6 +4,8 @@ pub use ucore_process::*;
use consts::{MAX_CPU_NUM, MAX_PROCESS_NUM};
use arch::cpu;
use alloc::{boxed::Box, sync::Arc, vec::Vec};
use sync::Condvar;
use core::sync::atomic::*;
mod context;
@ -29,6 +31,55 @@ pub fn init() {
static PROCESSORS: [Processor; MAX_CPU_NUM] = [Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new()];
/// Ugly solution for sys_wait(0) (wait for any child)
#[derive(Default)]
pub struct Process {
parent: AtomicUsize,
children: Mutex<Vec<usize>>,
subproc_exit: Condvar, // Trigger parent's when exit
}
impl Process {
pub fn new_fork(pid: usize, parent: usize) {
PROCESS[pid].parent.store(parent, Ordering::Relaxed);
PROCESS[pid].subproc_exit._clear();
PROCESS[parent].children.lock().push(pid);
}
pub fn proc_exit(pid: usize) {
let parent = PROCESS[pid].parent.load(Ordering::Relaxed);
PROCESS[parent].subproc_exit.notify_all();
}
pub fn wait_child() {
Self::current().subproc_exit._wait();
}
pub fn get_children() -> Vec<usize> {
Self::current().children.lock().clone()
}
pub fn do_wait(pid: usize) {
Self::current().children.lock().retain(|&p| p != pid);
}
fn current() -> &'static Self {
&PROCESS[thread::current().id()]
}
}
lazy_static! {
pub static ref PROCESS: Vec<Process> = {
let mut vec = Vec::new();
vec.resize_default(MAX_PROCESS_NUM);
vec
};
}
/// Get current thread struct
pub fn process() -> &'static mut ContextImpl {
use core::mem::transmute;
let (process, _): (&mut ContextImpl, *const ()) = unsafe {
transmute(processor().context())
};
process
}
// Implement dependencies for std::thread

View File

@ -33,4 +33,7 @@ impl Condvar {
t.unpark();
}
}
pub fn _clear(&self) {
self.wait_queue.lock().clear();
}
}

View File

@ -58,9 +58,9 @@ fn sys_close(fd: usize) -> i32 {
/// Fork the current process. Return the child's PID.
fn sys_fork(tf: &TrapFrame) -> i32 {
use core::mem::transmute;
let (context, _): (&ContextImpl, *const ()) = unsafe { transmute(processor().context()) };
let pid = processor().manager().add(context.fork(tf));
let mut context = process().fork(tf);
let pid = processor().manager().add(context);
Process::new_fork(pid, thread::current().id());
info!("fork: {} -> {}", thread::current().id(), pid);
pid as i32
}
@ -68,21 +68,35 @@ fn sys_fork(tf: &TrapFrame) -> i32 {
/// Wait the process exit.
/// Return the PID. Store exit code to `code` if it's not null.
fn sys_wait(pid: usize, code: *mut i32) -> i32 {
assert_ne!(pid, 0, "wait for 0 is not supported yet");
loop {
match processor().manager().get_status(pid) {
Some(Status::Exited(exit_code)) => {
if !code.is_null() {
unsafe { code.write(exit_code as i32); }
}
processor().manager().remove(pid);
return 0;
}
None => return -1,
_ => {}
let wait_procs = match pid {
0 => Process::get_children(),
_ => vec![pid],
};
if wait_procs.is_empty() {
return -1;
}
for pid in wait_procs {
match processor().manager().get_status(pid) {
Some(Status::Exited(exit_code)) => {
if !code.is_null() {
unsafe { code.write(exit_code as i32); }
}
processor().manager().remove(pid);
Process::do_wait(pid);
info!("wait: {} -> {}", thread::current().id(), pid);
return 0;
}
None => return -1,
_ => {}
}
}
if pid == 0 {
Process::wait_child();
} else {
processor().manager().wait(thread::current().id(), pid);
processor().yield_now();
}
processor().manager().wait(thread::current().id(), pid);
processor().yield_now();
}
}
@ -94,6 +108,10 @@ fn sys_yield() -> i32 {
/// Kill the process
fn sys_kill(pid: usize) -> i32 {
processor().manager().exit(pid, 0x100);
Process::proc_exit(pid);
if pid == thread::current().id() {
processor().yield_now();
}
0
}
@ -106,6 +124,7 @@ fn sys_getpid() -> i32 {
fn sys_exit(exit_code: usize) -> i32 {
let pid = thread::current().id();
processor().manager().exit(pid, exit_code);
Process::proc_exit(pid);
processor().yield_now();
unreachable!();
}