1bf4a4899SLoGin use core::intrinsics::likely; 2bf4a4899SLoGin 3bf4a4899SLoGin use alloc::sync::Arc; 4*2eab6dd7S曾俊 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)] 35bf4a4899SLoGin pub struct WaitIdInfo { 36bf4a4899SLoGin pub pid: Pid, 37bf4a4899SLoGin pub status: i32, 38bf4a4899SLoGin pub cause: i32, 39bf4a4899SLoGin } 40bf4a4899SLoGin 41bf4a4899SLoGin impl<'a> KernelWaitOption<'a> { 42bf4a4899SLoGin pub fn new(pid_type: PidType, pid: Pid, options: WaitOption) -> Self { 43bf4a4899SLoGin Self { 44bf4a4899SLoGin pid_type, 45bf4a4899SLoGin pid, 46bf4a4899SLoGin options, 47bf4a4899SLoGin ret_status: 0, 48bf4a4899SLoGin ret_info: None, 49bf4a4899SLoGin ret_rusage: None, 50bf4a4899SLoGin no_task_error: None, 51bf4a4899SLoGin } 52bf4a4899SLoGin } 53bf4a4899SLoGin } 54bf4a4899SLoGin 55bf4a4899SLoGin pub fn kernel_wait4( 56bf4a4899SLoGin mut pid: i64, 57bf4a4899SLoGin wstatus_buf: Option<UserBufferWriter<'_>>, 58bf4a4899SLoGin options: WaitOption, 59bf4a4899SLoGin rusage_buf: Option<&mut RUsage>, 60bf4a4899SLoGin ) -> Result<usize, SystemError> { 61bf4a4899SLoGin // i64::MIN is not defined 62bf4a4899SLoGin if pid == i64::MIN { 63bf4a4899SLoGin return Err(SystemError::ESRCH); 64bf4a4899SLoGin } 65bf4a4899SLoGin 66bf4a4899SLoGin // 判断pid类型 67bf4a4899SLoGin let pidtype: PidType; 68bf4a4899SLoGin 69bf4a4899SLoGin if pid == -1 { 70bf4a4899SLoGin pidtype = PidType::MAX; 71bf4a4899SLoGin } else if pid < 0 { 72bf4a4899SLoGin pidtype = PidType::PGID; 73*2eab6dd7S曾俊 warn!("kernel_wait4: currently not support pgid, default to wait for pid\n"); 74bf4a4899SLoGin pid = -pid; 75bf4a4899SLoGin } else if pid == 0 { 76bf4a4899SLoGin pidtype = PidType::PGID; 77*2eab6dd7S曾俊 warn!("kernel_wait4: currently not support pgid, default to wait for pid\n"); 78bf4a4899SLoGin pid = ProcessManager::current_pcb().pid().data() as i64; 79bf4a4899SLoGin } else { 80bf4a4899SLoGin pidtype = PidType::PID; 81bf4a4899SLoGin } 82bf4a4899SLoGin 83bf4a4899SLoGin let pid = Pid(pid as usize); 84bf4a4899SLoGin 85bf4a4899SLoGin // 构造参数 86bf4a4899SLoGin let mut kwo = KernelWaitOption::new(pidtype, pid, options); 87bf4a4899SLoGin 88bf4a4899SLoGin kwo.options.insert(WaitOption::WEXITED); 89bf4a4899SLoGin kwo.ret_rusage = rusage_buf; 90bf4a4899SLoGin 91bf4a4899SLoGin // 调用do_wait,执行等待 92bf4a4899SLoGin let r = do_wait(&mut kwo)?; 93bf4a4899SLoGin 94bf4a4899SLoGin // 如果有wstatus_buf,则将wstatus写入用户空间 95bf4a4899SLoGin if let Some(mut wstatus_buf) = wstatus_buf { 96bf4a4899SLoGin let wstatus = if let Some(ret_info) = &kwo.ret_info { 97bf4a4899SLoGin ret_info.status 98bf4a4899SLoGin } else { 99bf4a4899SLoGin kwo.ret_status 100bf4a4899SLoGin }; 101bf4a4899SLoGin wstatus_buf.copy_one_to_user(&wstatus, 0)?; 102bf4a4899SLoGin } 103bf4a4899SLoGin 104bf4a4899SLoGin return Ok(r); 105bf4a4899SLoGin } 106bf4a4899SLoGin 107e7071df6SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/exit.c#1573 108bf4a4899SLoGin fn do_wait(kwo: &mut KernelWaitOption) -> Result<usize, SystemError> { 109bf4a4899SLoGin let mut retval: Result<usize, SystemError>; 110bf4a4899SLoGin // todo: 在signal struct里面增加等待队列,并在这里初始化子进程退出的回调,使得子进程退出时,能唤醒当前进程。 111bf4a4899SLoGin 112bf4a4899SLoGin loop { 113bf4a4899SLoGin kwo.no_task_error = Some(SystemError::ECHILD); 114bf4a4899SLoGin let child_pcb = ProcessManager::find(kwo.pid).ok_or(SystemError::ECHILD); 115bf4a4899SLoGin if kwo.pid_type != PidType::MAX && child_pcb.is_err() { 116bf4a4899SLoGin if let Some(err) = &kwo.no_task_error { 117bf4a4899SLoGin retval = Err(err.clone()); 118bf4a4899SLoGin } else { 119bf4a4899SLoGin retval = Ok(0); 120bf4a4899SLoGin } 121bf4a4899SLoGin 122bf4a4899SLoGin if !kwo.options.contains(WaitOption::WNOHANG) { 123bf4a4899SLoGin retval = Err(SystemError::ERESTARTSYS); 124b5b571e0SLoGin if !ProcessManager::current_pcb() 125bf4a4899SLoGin .sig_info_irqsave() 126bf4a4899SLoGin .sig_pending() 127bf4a4899SLoGin .has_pending() 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); 144b5b571e0SLoGin if let Some(r) = r { 145b5b571e0SLoGin return r; 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)?; 1570d6cf65aSLoGin let state = pcb.sched_info().inner_lock_read_irqsave().state(); 1580d6cf65aSLoGin if state.is_exited() { 1590d6cf65aSLoGin kwo.ret_status = state.exit_code().unwrap() as i32; 160bf4a4899SLoGin drop(pcb); 161b5b571e0SLoGin unsafe { ProcessManager::release(*pid) }; 162b5b571e0SLoGin return Ok((*pid).into()); 163bf4a4899SLoGin } else { 164bf4a4899SLoGin unsafe { pcb.wait_queue.sleep_without_schedule() }; 165bf4a4899SLoGin } 166bf4a4899SLoGin } 167bf4a4899SLoGin drop(irq_guard); 168f0c87a89SGnoCiYeH schedule(SchedMode::SM_NONE); 169bf4a4899SLoGin } else { 170bf4a4899SLoGin // todo: 对于pgid的处理 171*2eab6dd7S曾俊 warn!("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>> { 1830d6cf65aSLoGin 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(); 229*2eab6dd7S曾俊 // debug!("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); 248*2eab6dd7S曾俊 // debug!("wait4: to release {pid:?}"); 249bf4a4899SLoGin unsafe { ProcessManager::release(pid) }; 250bf4a4899SLoGin return Some(Ok(pid.into())); 251bf4a4899SLoGin } 252bf4a4899SLoGin }; 253bf4a4899SLoGin 254bf4a4899SLoGin return None; 255bf4a4899SLoGin } 256