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:
parent
74facd8e87
commit
6fc23e1134
@ -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]
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -33,4 +33,7 @@ impl Condvar {
|
|||||||
t.unpark();
|
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.
|
/// 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,23 +68,37 @@ 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 {
|
||||||
|
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) {
|
match processor().manager().get_status(pid) {
|
||||||
Some(Status::Exited(exit_code)) => {
|
Some(Status::Exited(exit_code)) => {
|
||||||
if !code.is_null() {
|
if !code.is_null() {
|
||||||
unsafe { code.write(exit_code as i32); }
|
unsafe { code.write(exit_code as i32); }
|
||||||
}
|
}
|
||||||
processor().manager().remove(pid);
|
processor().manager().remove(pid);
|
||||||
|
Process::do_wait(pid);
|
||||||
|
info!("wait: {} -> {}", thread::current().id(), pid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
None => return -1,
|
None => return -1,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if pid == 0 {
|
||||||
|
Process::wait_child();
|
||||||
|
} else {
|
||||||
processor().manager().wait(thread::current().id(), pid);
|
processor().manager().wait(thread::current().id(), pid);
|
||||||
processor().yield_now();
|
processor().yield_now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn sys_yield() -> i32 {
|
fn sys_yield() -> i32 {
|
||||||
thread::yield_now();
|
thread::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!();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user