1bf4a4899SLoGin use core::intrinsics::likely;
2bf4a4899SLoGin
3bf4a4899SLoGin use alloc::sync::Arc;
42eab6dd7S曾俊 use log::warn;
591e9d4abSLoGin use system_error::SystemError;
6bf4a4899SLoGin
7bf4a4899SLoGin use crate::{
8bf4a4899SLoGin arch::{
9bf4a4899SLoGin ipc::signal::{SigChildCode, Signal},
10bf4a4899SLoGin CurrentIrqArch,
11bf4a4899SLoGin },
12bf4a4899SLoGin exception::InterruptArch,
13f0c87a89SGnoCiYeH sched::{schedule, SchedMode},
1491e9d4abSLoGin syscall::user_access::UserBufferWriter,
15bf4a4899SLoGin };
16bf4a4899SLoGin
17bf4a4899SLoGin use super::{
18bf4a4899SLoGin abi::WaitOption, pid::PidType, resource::RUsage, Pid, ProcessControlBlock, ProcessManager,
19bf4a4899SLoGin ProcessState,
20bf4a4899SLoGin };
21bf4a4899SLoGin
22bf4a4899SLoGin /// 内核wait4时的参数
23bf4a4899SLoGin #[derive(Debug)]
24bf4a4899SLoGin pub struct KernelWaitOption<'a> {
25bf4a4899SLoGin pub pid_type: PidType,
26bf4a4899SLoGin pub pid: Pid,
27bf4a4899SLoGin pub options: WaitOption,
28bf4a4899SLoGin pub ret_status: i32,
29bf4a4899SLoGin pub ret_info: Option<WaitIdInfo>,
30bf4a4899SLoGin pub ret_rusage: Option<&'a mut RUsage>,
31bf4a4899SLoGin pub no_task_error: Option<SystemError>,
32bf4a4899SLoGin }
33bf4a4899SLoGin
34bf4a4899SLoGin #[derive(Debug, Clone)]
35*bd70d2d1SLoGin #[allow(dead_code)]
36bf4a4899SLoGin pub struct WaitIdInfo {
37bf4a4899SLoGin pub pid: Pid,
38bf4a4899SLoGin pub status: i32,
39bf4a4899SLoGin pub cause: i32,
40bf4a4899SLoGin }
41bf4a4899SLoGin
42bf4a4899SLoGin impl<'a> KernelWaitOption<'a> {
new(pid_type: PidType, pid: Pid, options: WaitOption) -> Self43bf4a4899SLoGin pub fn new(pid_type: PidType, pid: Pid, options: WaitOption) -> Self {
44bf4a4899SLoGin Self {
45bf4a4899SLoGin pid_type,
46bf4a4899SLoGin pid,
47bf4a4899SLoGin options,
48bf4a4899SLoGin ret_status: 0,
49bf4a4899SLoGin ret_info: None,
50bf4a4899SLoGin ret_rusage: None,
51bf4a4899SLoGin no_task_error: None,
52bf4a4899SLoGin }
53bf4a4899SLoGin }
54bf4a4899SLoGin }
55bf4a4899SLoGin
kernel_wait4( mut pid: i64, wstatus_buf: Option<UserBufferWriter<'_>>, options: WaitOption, rusage_buf: Option<&mut RUsage>, ) -> Result<usize, SystemError>56bf4a4899SLoGin pub fn kernel_wait4(
57bf4a4899SLoGin mut pid: i64,
58bf4a4899SLoGin wstatus_buf: Option<UserBufferWriter<'_>>,
59bf4a4899SLoGin options: WaitOption,
60bf4a4899SLoGin rusage_buf: Option<&mut RUsage>,
61bf4a4899SLoGin ) -> Result<usize, SystemError> {
62bf4a4899SLoGin // i64::MIN is not defined
63bf4a4899SLoGin if pid == i64::MIN {
64bf4a4899SLoGin return Err(SystemError::ESRCH);
65bf4a4899SLoGin }
66bf4a4899SLoGin
67bf4a4899SLoGin // 判断pid类型
68bf4a4899SLoGin let pidtype: PidType;
69bf4a4899SLoGin
70bf4a4899SLoGin if pid == -1 {
71bf4a4899SLoGin pidtype = PidType::MAX;
72bf4a4899SLoGin } else if pid < 0 {
73bf4a4899SLoGin pidtype = PidType::PGID;
742eab6dd7S曾俊 warn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
75bf4a4899SLoGin pid = -pid;
76bf4a4899SLoGin } else if pid == 0 {
77bf4a4899SLoGin pidtype = PidType::PGID;
782eab6dd7S曾俊 warn!("kernel_wait4: currently not support pgid, default to wait for pid\n");
79bf4a4899SLoGin pid = ProcessManager::current_pcb().pid().data() as i64;
80bf4a4899SLoGin } else {
81bf4a4899SLoGin pidtype = PidType::PID;
82bf4a4899SLoGin }
83bf4a4899SLoGin
84bf4a4899SLoGin let pid = Pid(pid as usize);
85bf4a4899SLoGin
86bf4a4899SLoGin // 构造参数
87bf4a4899SLoGin let mut kwo = KernelWaitOption::new(pidtype, pid, options);
88bf4a4899SLoGin
89bf4a4899SLoGin kwo.options.insert(WaitOption::WEXITED);
90bf4a4899SLoGin kwo.ret_rusage = rusage_buf;
91bf4a4899SLoGin
92bf4a4899SLoGin // 调用do_wait,执行等待
93bf4a4899SLoGin let r = do_wait(&mut kwo)?;
94bf4a4899SLoGin
95bf4a4899SLoGin // 如果有wstatus_buf,则将wstatus写入用户空间
96bf4a4899SLoGin if let Some(mut wstatus_buf) = wstatus_buf {
97bf4a4899SLoGin let wstatus = if let Some(ret_info) = &kwo.ret_info {
98bf4a4899SLoGin ret_info.status
99bf4a4899SLoGin } else {
100bf4a4899SLoGin kwo.ret_status
101bf4a4899SLoGin };
102bf4a4899SLoGin wstatus_buf.copy_one_to_user(&wstatus, 0)?;
103bf4a4899SLoGin }
104bf4a4899SLoGin
105bf4a4899SLoGin return Ok(r);
106bf4a4899SLoGin }
107bf4a4899SLoGin
108e7071df6SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/exit.c#1573
do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError>109bf4a4899SLoGin fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> {
110bf4a4899SLoGin let mut retval: Result<usize, SystemError>;
111bf4a4899SLoGin // todo: 在signal struct里面增加等待队列,并在这里初始化子进程退出的回调,使得子进程退出时,能唤醒当前进程。
112bf4a4899SLoGin
113bf4a4899SLoGin loop {
114bf4a4899SLoGin kwo.no_task_error = Some(SystemError::ECHILD);
115bf4a4899SLoGin let child_pcb = ProcessManager::find(kwo.pid).ok_or(SystemError::ECHILD);
116bf4a4899SLoGin if kwo.pid_type != PidType::MAX && child_pcb.is_err() {
117bf4a4899SLoGin if let Some(err) = &kwo.no_task_error {
118bf4a4899SLoGin retval = Err(err.clone());
119bf4a4899SLoGin } else {
120bf4a4899SLoGin retval = Ok(0);
121bf4a4899SLoGin }
122bf4a4899SLoGin
123bf4a4899SLoGin if !kwo.options.contains(WaitOption::WNOHANG) {
124bf4a4899SLoGin retval = Err(SystemError::ERESTARTSYS);
125b5b571e0SLoGin if !ProcessManager::current_pcb()
126bf4a4899SLoGin .sig_info_irqsave()
127bf4a4899SLoGin .sig_pending()
128bf4a4899SLoGin .has_pending()
129bf4a4899SLoGin {
130bf4a4899SLoGin // todo: 增加子进程退出的回调后,这里可以直接等待在自身的child_wait等待队列上。
131bf4a4899SLoGin continue;
132bf4a4899SLoGin } else {
133bf4a4899SLoGin break;
134bf4a4899SLoGin }
135bf4a4899SLoGin } else {
136bf4a4899SLoGin break;
137bf4a4899SLoGin }
138bf4a4899SLoGin }
139bf4a4899SLoGin
140bf4a4899SLoGin if kwo.pid_type == PidType::PID {
141bf4a4899SLoGin let child_pcb = child_pcb.unwrap();
142bf4a4899SLoGin // 获取weak引用,以便于在do_waitpid中能正常drop pcb
143bf4a4899SLoGin let child_weak = Arc::downgrade(&child_pcb);
144bf4a4899SLoGin let r = do_waitpid(child_pcb, kwo);
145b5b571e0SLoGin if let Some(r) = r {
146b5b571e0SLoGin return r;
147bf4a4899SLoGin } else {
148bf4a4899SLoGin child_weak.upgrade().unwrap().wait_queue.sleep();
149bf4a4899SLoGin }
150bf4a4899SLoGin } else if kwo.pid_type == PidType::MAX {
151bf4a4899SLoGin // 等待任意子进程
152bf4a4899SLoGin // todo: 这里有问题!如果正在for循环的过程中,子进程退出了,可能会导致父进程永远等待。
153bf4a4899SLoGin let current_pcb = ProcessManager::current_pcb();
154bf4a4899SLoGin let rd_childen = current_pcb.children.read();
155bf4a4899SLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
156bf4a4899SLoGin for pid in rd_childen.iter() {
157bf4a4899SLoGin let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
1580d6cf65aSLoGin let state = pcb.sched_info().inner_lock_read_irqsave().state();
1590d6cf65aSLoGin if state.is_exited() {
1600d6cf65aSLoGin kwo.ret_status = state.exit_code().unwrap() as i32;
161bf4a4899SLoGin drop(pcb);
162b5b571e0SLoGin unsafe { ProcessManager::release(*pid) };
163b5b571e0SLoGin return Ok((*pid).into());
164bf4a4899SLoGin } else {
165bf4a4899SLoGin unsafe { pcb.wait_queue.sleep_without_schedule() };
166bf4a4899SLoGin }
167bf4a4899SLoGin }
168bf4a4899SLoGin drop(irq_guard);
169f0c87a89SGnoCiYeH schedule(SchedMode::SM_NONE);
170bf4a4899SLoGin } else {
171bf4a4899SLoGin // todo: 对于pgid的处理
1722eab6dd7S曾俊 warn!("kernel_wait4: currently not support {:?}", kwo.pid_type);
173bf4a4899SLoGin return Err(SystemError::EINVAL);
174bf4a4899SLoGin }
175bf4a4899SLoGin }
176bf4a4899SLoGin
177bf4a4899SLoGin return retval;
178bf4a4899SLoGin }
179bf4a4899SLoGin
do_waitpid( child_pcb: Arc<ProcessControlBlock>, kwo: &mut KernelWaitOption, ) -> Option<Result<usize, SystemError>>180bf4a4899SLoGin fn do_waitpid(
181bf4a4899SLoGin child_pcb: Arc<ProcessControlBlock>,
182bf4a4899SLoGin kwo: &mut KernelWaitOption,
183bf4a4899SLoGin ) -> Option<Result<usize, SystemError>> {
1840d6cf65aSLoGin let state = child_pcb.sched_info().inner_lock_read_irqsave().state();
185bf4a4899SLoGin // 获取退出码
186bf4a4899SLoGin match state {
187bf4a4899SLoGin ProcessState::Runnable => {
188bf4a4899SLoGin if kwo.options.contains(WaitOption::WNOHANG)
189bf4a4899SLoGin || kwo.options.contains(WaitOption::WNOWAIT)
190bf4a4899SLoGin {
191bf4a4899SLoGin if let Some(info) = &mut kwo.ret_info {
192bf4a4899SLoGin *info = WaitIdInfo {
193bf4a4899SLoGin pid: child_pcb.pid(),
194bf4a4899SLoGin status: Signal::SIGCONT as i32,
195bf4a4899SLoGin cause: SigChildCode::Continued.into(),
196bf4a4899SLoGin };
197bf4a4899SLoGin } else {
198bf4a4899SLoGin kwo.ret_status = 0xffff;
199bf4a4899SLoGin }
200bf4a4899SLoGin
201bf4a4899SLoGin return Some(Ok(0));
202bf4a4899SLoGin }
203bf4a4899SLoGin }
204bf4a4899SLoGin ProcessState::Blocked(_) | ProcessState::Stopped => {
205bf4a4899SLoGin // todo: 在stopped里面,添加code字段,表示停止的原因
206bf4a4899SLoGin let exitcode = 0;
207bf4a4899SLoGin // 由于目前不支持ptrace,因此这个值为false
208bf4a4899SLoGin let ptrace = false;
209bf4a4899SLoGin
210bf4a4899SLoGin if (!ptrace) && (!kwo.options.contains(WaitOption::WUNTRACED)) {
211bf4a4899SLoGin kwo.ret_status = 0;
212bf4a4899SLoGin return Some(Ok(0));
213bf4a4899SLoGin }
214bf4a4899SLoGin
215bf4a4899SLoGin if likely(!(kwo.options.contains(WaitOption::WNOWAIT))) {
216bf4a4899SLoGin kwo.ret_status = (exitcode << 8) | 0x7f;
217bf4a4899SLoGin }
218bf4a4899SLoGin if let Some(infop) = &mut kwo.ret_info {
219bf4a4899SLoGin *infop = WaitIdInfo {
220bf4a4899SLoGin pid: child_pcb.pid(),
221bf4a4899SLoGin status: exitcode,
222bf4a4899SLoGin cause: SigChildCode::Stopped.into(),
223bf4a4899SLoGin };
224bf4a4899SLoGin }
225bf4a4899SLoGin
226bf4a4899SLoGin return Some(Ok(child_pcb.pid().data()));
227bf4a4899SLoGin }
228bf4a4899SLoGin ProcessState::Exited(status) => {
229bf4a4899SLoGin let pid = child_pcb.pid();
2302eab6dd7S曾俊 // debug!("wait4: child exited, pid: {:?}, status: {status}\n", pid);
231bf4a4899SLoGin
232bf4a4899SLoGin if likely(!kwo.options.contains(WaitOption::WEXITED)) {
233bf4a4899SLoGin return None;
234bf4a4899SLoGin }
235bf4a4899SLoGin
236bf4a4899SLoGin // todo: 增加对线程组的group leader的处理
237bf4a4899SLoGin
238bf4a4899SLoGin if let Some(infop) = &mut kwo.ret_info {
239bf4a4899SLoGin *infop = WaitIdInfo {
240bf4a4899SLoGin pid,
241bf4a4899SLoGin status: status as i32,
242bf4a4899SLoGin cause: SigChildCode::Exited.into(),
243bf4a4899SLoGin };
244bf4a4899SLoGin }
245bf4a4899SLoGin
246bf4a4899SLoGin kwo.ret_status = status as i32;
247bf4a4899SLoGin
248bf4a4899SLoGin drop(child_pcb);
2492eab6dd7S曾俊 // debug!("wait4: to release {pid:?}");
250bf4a4899SLoGin unsafe { ProcessManager::release(pid) };
251bf4a4899SLoGin return Some(Ok(pid.into()));
252bf4a4899SLoGin }
253bf4a4899SLoGin };
254bf4a4899SLoGin
255bf4a4899SLoGin return None;
256bf4a4899SLoGin }
257