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