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