1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-23 16:36:18 +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(global_asm)]
#![feature(compiler_builtins_lib)] #![feature(compiler_builtins_lib)]
#![feature(raw)] #![feature(raw)]
#![feature(vec_resize_default)]
#![no_std] #![no_std]

View File

@ -4,6 +4,8 @@ pub use ucore_process::*;
use consts::{MAX_CPU_NUM, MAX_PROCESS_NUM}; use consts::{MAX_CPU_NUM, MAX_PROCESS_NUM};
use arch::cpu; use arch::cpu;
use alloc::{boxed::Box, sync::Arc, vec::Vec}; use alloc::{boxed::Box, sync::Arc, vec::Vec};
use sync::Condvar;
use core::sync::atomic::*;
mod context; 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()]; 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 // Implement dependencies for std::thread

View File

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