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:
parent
74facd8e87
commit
6fc23e1134
@ -10,6 +10,7 @@
|
||||
#![feature(global_asm)]
|
||||
#![feature(compiler_builtins_lib)]
|
||||
#![feature(raw)]
|
||||
#![feature(vec_resize_default)]
|
||||
#![no_std]
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -33,4 +33,7 @@ impl Condvar {
|
||||
t.unpark();
|
||||
}
|
||||
}
|
||||
pub fn _clear(&self) {
|
||||
self.wait_queue.lock().clear();
|
||||
}
|
||||
}
|
@ -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,23 +68,37 @@ 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 {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sys_yield() -> i32 {
|
||||
thread::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!();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user