1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use alloc::vec::Vec;
use crate::{
executor::ControlFlow,
mem::UserPtr,
sync::{wait_for_event, Event},
syscall::SystemCall,
task::Status,
};
impl SystemCall<'_> {
pub fn sys_exit(&self, exit_code: usize) -> (isize, ControlFlow) {
(0, ControlFlow::Exit(exit_code))
}
pub fn sys_sched_yield(&self) -> (isize, ControlFlow) {
(0, ControlFlow::Yield)
}
pub fn sys_fork(&self) -> (isize, ControlFlow) {
let process = self.thread.process().fork();
(process.pid() as isize, ControlFlow::Continue)
}
pub async fn sys_waitpid(
&self,
pid: isize,
mut wait_status: UserPtr<usize>,
) -> (isize, ControlFlow) {
loop {
let process = self.thread.process();
let mut process_state = process.state().lock();
let child_list = process_state.child_list_mut();
if let Some((pid, exit_code)) = match pid {
-1 | 0 => child_list.iter().find_map(|child_process| {
let child_process_state = child_process.state().lock();
if child_process_state.status() == Status::Zombie {
Some((child_process.pid(), child_process_state.exit_code()))
} else {
None
}
}),
pid => child_list.iter().find_map(|child_process| {
let child_process_state = child_process.state().lock();
if child_process.pid() == pid as usize
&& child_process_state.status() == Status::Zombie
{
Some((child_process.pid(), child_process_state.exit_code()))
} else {
None
}
}),
} {
child_list.retain(|child_process| child_process.pid() != pid);
*wait_status = exit_code;
return (pid as isize, ControlFlow::Continue);
} else {
let event_bus = process.event_bus();
drop(process_state);
wait_for_event(event_bus.clone(), Event::CHILD_PROCESS_QUIT).await;
event_bus.lock().clear(Event::CHILD_PROCESS_QUIT);
}
}
}
pub fn sys_exec(&self, path: UserPtr<u8>) -> (isize, ControlFlow) {
self.thread.process().exec(&path.as_string(), Vec::new());
(0, ControlFlow::Continue)
}
}