|
|
@ -54,7 +54,6 @@ impl Syscall<'_> {
|
|
|
|
let new_thread = self
|
|
|
|
let new_thread = self
|
|
|
|
.thread
|
|
|
|
.thread
|
|
|
|
.clone(self.tf, newsp, newtls, child_tid as usize);
|
|
|
|
.clone(self.tf, newsp, newtls, child_tid as usize);
|
|
|
|
// FIXME: parent pid
|
|
|
|
|
|
|
|
let tid = processor().manager().add(new_thread);
|
|
|
|
let tid = processor().manager().add(new_thread);
|
|
|
|
processor().manager().detach(tid);
|
|
|
|
processor().manager().detach(tid);
|
|
|
|
info!("clone: {} -> {}", thread::current().id(), tid);
|
|
|
|
info!("clone: {} -> {}", thread::current().id(), tid);
|
|
|
@ -66,7 +65,7 @@ impl Syscall<'_> {
|
|
|
|
/// Wait for the process exit.
|
|
|
|
/// Wait for the process exit.
|
|
|
|
/// Return the PID. Store exit code to `wstatus` if it's not null.
|
|
|
|
/// Return the PID. Store exit code to `wstatus` if it's not null.
|
|
|
|
pub fn sys_wait4(&mut self, pid: isize, wstatus: *mut i32) -> SysResult {
|
|
|
|
pub fn sys_wait4(&mut self, pid: isize, wstatus: *mut i32) -> SysResult {
|
|
|
|
//info!("wait4: pid: {}, code: {:?}", pid, wstatus);
|
|
|
|
info!("wait4: pid: {}, code: {:?}", pid, wstatus);
|
|
|
|
let wstatus = if !wstatus.is_null() {
|
|
|
|
let wstatus = if !wstatus.is_null() {
|
|
|
|
Some(unsafe { self.vm().check_write_ptr(wstatus)? })
|
|
|
|
Some(unsafe { self.vm().check_write_ptr(wstatus)? })
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -75,10 +74,12 @@ impl Syscall<'_> {
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum WaitFor {
|
|
|
|
enum WaitFor {
|
|
|
|
AnyChild,
|
|
|
|
AnyChild,
|
|
|
|
|
|
|
|
AnyChildInGroup,
|
|
|
|
Pid(usize),
|
|
|
|
Pid(usize),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let target = match pid {
|
|
|
|
let target = match pid {
|
|
|
|
-1 | 0 => WaitFor::AnyChild,
|
|
|
|
-1 => WaitFor::AnyChild,
|
|
|
|
|
|
|
|
0 => WaitFor::AnyChildInGroup,
|
|
|
|
p if p > 0 => WaitFor::Pid(p as usize),
|
|
|
|
p if p > 0 => WaitFor::Pid(p as usize),
|
|
|
|
_ => unimplemented!(),
|
|
|
|
_ => unimplemented!(),
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -86,7 +87,7 @@ impl Syscall<'_> {
|
|
|
|
let mut proc = self.process();
|
|
|
|
let mut proc = self.process();
|
|
|
|
// check child_exit_code
|
|
|
|
// check child_exit_code
|
|
|
|
let find = match target {
|
|
|
|
let find = match target {
|
|
|
|
WaitFor::AnyChild => proc
|
|
|
|
WaitFor::AnyChild | WaitFor::AnyChildInGroup => proc
|
|
|
|
.child_exit_code
|
|
|
|
.child_exit_code
|
|
|
|
.iter()
|
|
|
|
.iter()
|
|
|
|
.next()
|
|
|
|
.next()
|
|
|
@ -102,17 +103,19 @@ impl Syscall<'_> {
|
|
|
|
return Ok(pid);
|
|
|
|
return Ok(pid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if not, check pid
|
|
|
|
// if not, check pid
|
|
|
|
|
|
|
|
let invalid = {
|
|
|
|
let children: Vec<_> = proc
|
|
|
|
let children: Vec<_> = proc
|
|
|
|
.children
|
|
|
|
.children
|
|
|
|
.iter()
|
|
|
|
.iter()
|
|
|
|
.filter_map(|weak| weak.upgrade())
|
|
|
|
.filter_map(|weak| weak.upgrade())
|
|
|
|
.collect();
|
|
|
|
.collect();
|
|
|
|
let invalid = match target {
|
|
|
|
match target {
|
|
|
|
WaitFor::AnyChild => children.len() == 0,
|
|
|
|
WaitFor::AnyChild | WaitFor::AnyChildInGroup => children.len() == 0,
|
|
|
|
WaitFor::Pid(pid) => children
|
|
|
|
WaitFor::Pid(pid) => children
|
|
|
|
.iter()
|
|
|
|
.iter()
|
|
|
|
.find(|p| p.lock().pid.get() == pid)
|
|
|
|
.find(|p| p.lock().pid.get() == pid)
|
|
|
|
.is_none(),
|
|
|
|
.is_none(),
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
if invalid {
|
|
|
|
if invalid {
|
|
|
|
return Err(SysError::ECHILD);
|
|
|
|
return Err(SysError::ECHILD);
|
|
|
@ -204,7 +207,7 @@ impl Syscall<'_> {
|
|
|
|
/// Kill the process
|
|
|
|
/// Kill the process
|
|
|
|
pub fn sys_kill(&mut self, pid: usize, sig: usize) -> SysResult {
|
|
|
|
pub fn sys_kill(&mut self, pid: usize, sig: usize) -> SysResult {
|
|
|
|
info!(
|
|
|
|
info!(
|
|
|
|
"kill: {} killed: {} with sig {}",
|
|
|
|
"kill: thread {} kill process {} with signal {}",
|
|
|
|
thread::current().id(),
|
|
|
|
thread::current().id(),
|
|
|
|
pid,
|
|
|
|
pid,
|
|
|
|
sig
|
|
|
|
sig
|
|
|
@ -215,21 +218,8 @@ impl Syscall<'_> {
|
|
|
|
self.sys_exit_group(sig);
|
|
|
|
self.sys_exit_group(sig);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if let Some(proc_arc) = PROCESSES.read().get(&pid).and_then(|weak| weak.upgrade()) {
|
|
|
|
if let Some(proc_arc) = PROCESSES.read().get(&pid).and_then(|weak| weak.upgrade()) {
|
|
|
|
let proc = proc_arc.lock();
|
|
|
|
let mut proc = proc_arc.lock();
|
|
|
|
// quit all threads
|
|
|
|
proc.exit(sig);
|
|
|
|
for tid in proc.threads.iter() {
|
|
|
|
|
|
|
|
processor().manager().exit(*tid, sig);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// notify parent and fill exit code
|
|
|
|
|
|
|
|
// avoid deadlock
|
|
|
|
|
|
|
|
let proc_parent = proc.parent.clone();
|
|
|
|
|
|
|
|
let pid = proc.pid.get();
|
|
|
|
|
|
|
|
drop(proc);
|
|
|
|
|
|
|
|
if let Some(parent) = proc_parent {
|
|
|
|
|
|
|
|
let mut parent = parent.lock();
|
|
|
|
|
|
|
|
parent.child_exit_code.insert(pid, sig);
|
|
|
|
|
|
|
|
parent.child_exit.notify_one();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(0)
|
|
|
|
Ok(0)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Err(SysError::EINVAL)
|
|
|
|
Err(SysError::EINVAL)
|
|
|
@ -252,7 +242,7 @@ impl Syscall<'_> {
|
|
|
|
|
|
|
|
|
|
|
|
/// Get the parent process id
|
|
|
|
/// Get the parent process id
|
|
|
|
pub fn sys_getppid(&mut self) -> SysResult {
|
|
|
|
pub fn sys_getppid(&mut self) -> SysResult {
|
|
|
|
if let Some(parent) = self.process().parent.as_ref() {
|
|
|
|
if let Some(parent) = self.process().parent.upgrade() {
|
|
|
|
Ok(parent.lock().pid.get())
|
|
|
|
Ok(parent.lock().pid.get())
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Ok(0)
|
|
|
|
Ok(0)
|
|
|
@ -266,26 +256,15 @@ impl Syscall<'_> {
|
|
|
|
let mut proc = self.process();
|
|
|
|
let mut proc = self.process();
|
|
|
|
proc.threads.retain(|&id| id != tid);
|
|
|
|
proc.threads.retain(|&id| id != tid);
|
|
|
|
|
|
|
|
|
|
|
|
// for last thread,
|
|
|
|
// for last thread, exit the process
|
|
|
|
// notify parent and fill exit code
|
|
|
|
if proc.threads.len() == 0 {
|
|
|
|
// avoid deadlock
|
|
|
|
proc.exit(exit_code);
|
|
|
|
let exit = proc.threads.len() == 0;
|
|
|
|
|
|
|
|
let proc_parent = proc.parent.clone();
|
|
|
|
|
|
|
|
let pid = proc.pid.get();
|
|
|
|
|
|
|
|
drop(proc);
|
|
|
|
|
|
|
|
if exit {
|
|
|
|
|
|
|
|
if let Some(parent) = proc_parent {
|
|
|
|
|
|
|
|
let mut parent = parent.lock();
|
|
|
|
|
|
|
|
parent.child_exit_code.insert(pid, exit_code);
|
|
|
|
|
|
|
|
parent.child_exit.notify_one();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// perform futex wake 1
|
|
|
|
// perform futex wake 1
|
|
|
|
// ref: http://man7.org/linux/man-pages/man2/set_tid_address.2.html
|
|
|
|
// ref: http://man7.org/linux/man-pages/man2/set_tid_address.2.html
|
|
|
|
// FIXME: do it in all possible ways a thread can exit
|
|
|
|
// FIXME: do it in all possible ways a thread can exit
|
|
|
|
// it has memory access so we can't move it to Thread::drop?
|
|
|
|
// it has memory access so we can't move it to Thread::drop?
|
|
|
|
let mut proc = self.process();
|
|
|
|
|
|
|
|
let clear_child_tid = self.thread.clear_child_tid as *mut u32;
|
|
|
|
let clear_child_tid = self.thread.clear_child_tid as *mut u32;
|
|
|
|
if !clear_child_tid.is_null() {
|
|
|
|
if !clear_child_tid.is_null() {
|
|
|
|
info!("exit: futex {:#?} wake 1", clear_child_tid);
|
|
|
|
info!("exit: futex {:#?} wake 1", clear_child_tid);
|
|
|
@ -304,24 +283,10 @@ impl Syscall<'_> {
|
|
|
|
|
|
|
|
|
|
|
|
/// Exit the current thread group (i.e. process)
|
|
|
|
/// Exit the current thread group (i.e. process)
|
|
|
|
pub fn sys_exit_group(&mut self, exit_code: usize) -> ! {
|
|
|
|
pub fn sys_exit_group(&mut self, exit_code: usize) -> ! {
|
|
|
|
let proc = self.process();
|
|
|
|
let mut proc = self.process();
|
|
|
|
info!("exit_group: {}, code: {}", proc.pid, exit_code);
|
|
|
|
info!("exit_group: {}, code: {}", proc.pid, exit_code);
|
|
|
|
|
|
|
|
|
|
|
|
// quit all threads
|
|
|
|
proc.exit(exit_code);
|
|
|
|
for tid in proc.threads.iter() {
|
|
|
|
|
|
|
|
processor().manager().exit(*tid, exit_code);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// notify parent and fill exit code
|
|
|
|
|
|
|
|
// avoid deadlock
|
|
|
|
|
|
|
|
let proc_parent = proc.parent.clone();
|
|
|
|
|
|
|
|
let pid = proc.pid.get();
|
|
|
|
|
|
|
|
drop(proc);
|
|
|
|
|
|
|
|
if let Some(parent) = proc_parent {
|
|
|
|
|
|
|
|
let mut parent = parent.lock();
|
|
|
|
|
|
|
|
parent.child_exit_code.insert(pid, exit_code);
|
|
|
|
|
|
|
|
parent.child_exit.notify_one();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
processor().yield_now();
|
|
|
|
processor().yield_now();
|
|
|
|
unreachable!();
|
|
|
|
unreachable!();
|
|
|
|