xref: /DragonOS/kernel/src/process/syscall.rs (revision b7b843beddea12cdedda90f6129b7c9980876112)
11496ba7bSLoGin use core::ffi::c_void;
2ab5c8ca4Slogin 
31496ba7bSLoGin use alloc::{string::String, vec::Vec};
41496ba7bSLoGin 
5*b7b843beSGnoCiYeH use super::{abi::WaitOption, fork::CloneFlags, Pid, ProcessManager, ProcessState};
6ab5c8ca4Slogin use crate::{
71496ba7bSLoGin     arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch},
81496ba7bSLoGin     exception::InterruptArch,
91496ba7bSLoGin     filesystem::vfs::MAX_PATHLEN,
101496ba7bSLoGin     process::ProcessControlBlock,
111496ba7bSLoGin     syscall::{
121496ba7bSLoGin         user_access::{
131496ba7bSLoGin             check_and_clone_cstr, check_and_clone_cstr_array, UserBufferReader, UserBufferWriter,
141496ba7bSLoGin         },
151496ba7bSLoGin         Syscall, SystemError,
161496ba7bSLoGin     },
17ab5c8ca4Slogin };
18ab5c8ca4Slogin 
19ab5c8ca4Slogin impl Syscall {
201496ba7bSLoGin     pub fn fork(frame: &mut TrapFrame) -> Result<usize, SystemError> {
211496ba7bSLoGin         let r = ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into());
221496ba7bSLoGin         return r;
23ab5c8ca4Slogin     }
24ab5c8ca4Slogin 
251496ba7bSLoGin     pub fn vfork(frame: &mut TrapFrame) -> Result<usize, SystemError> {
261496ba7bSLoGin         ProcessManager::fork(
271496ba7bSLoGin             frame,
281496ba7bSLoGin             CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
291496ba7bSLoGin         )
301496ba7bSLoGin         .map(|pid| pid.into())
31ab5c8ca4Slogin     }
32ab5c8ca4Slogin 
33ab5c8ca4Slogin     pub fn execve(
341496ba7bSLoGin         path: *const u8,
351496ba7bSLoGin         argv: *const *const u8,
361496ba7bSLoGin         envp: *const *const u8,
371496ba7bSLoGin         frame: &mut TrapFrame,
381496ba7bSLoGin     ) -> Result<(), SystemError> {
391496ba7bSLoGin         // kdebug!(
401496ba7bSLoGin         //     "execve path: {:?}, argv: {:?}, envp: {:?}\n",
411496ba7bSLoGin         //     path,
421496ba7bSLoGin         //     argv,
431496ba7bSLoGin         //     envp
441496ba7bSLoGin         // );
451496ba7bSLoGin         if path.is_null() {
461496ba7bSLoGin             return Err(SystemError::EINVAL);
471496ba7bSLoGin         }
481496ba7bSLoGin 
491496ba7bSLoGin         let x = || {
501496ba7bSLoGin             let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
511496ba7bSLoGin             let argv: Vec<String> = check_and_clone_cstr_array(argv)?;
521496ba7bSLoGin             let envp: Vec<String> = check_and_clone_cstr_array(envp)?;
531496ba7bSLoGin             Ok((path, argv, envp))
541496ba7bSLoGin         };
551496ba7bSLoGin         let r: Result<(String, Vec<String>, Vec<String>), SystemError> = x();
561496ba7bSLoGin         if let Err(e) = r {
571496ba7bSLoGin             panic!("Failed to execve: {:?}", e);
581496ba7bSLoGin         }
591496ba7bSLoGin         let (path, argv, envp) = r.unwrap();
601496ba7bSLoGin         ProcessManager::current_pcb()
611496ba7bSLoGin             .basic_mut()
621496ba7bSLoGin             .set_name(ProcessControlBlock::generate_name(&path, &argv));
631496ba7bSLoGin 
64876cb89eSGnoCiYeH         Self::do_execve(path, argv, envp, frame)?;
65876cb89eSGnoCiYeH 
66876cb89eSGnoCiYeH         // 关闭设置了O_CLOEXEC的文件描述符
67876cb89eSGnoCiYeH         let fd_table = ProcessManager::current_pcb().fd_table();
68876cb89eSGnoCiYeH         fd_table.write().close_on_exec();
69876cb89eSGnoCiYeH 
70876cb89eSGnoCiYeH         return Ok(());
71ab5c8ca4Slogin     }
72ab5c8ca4Slogin 
73ab5c8ca4Slogin     pub fn wait4(
741496ba7bSLoGin         pid: i64,
751496ba7bSLoGin         wstatus: *mut i32,
761496ba7bSLoGin         options: i32,
77ab5c8ca4Slogin         rusage: *mut c_void,
78ab5c8ca4Slogin     ) -> Result<usize, SystemError> {
79*b7b843beSGnoCiYeH         let ret = WaitOption::from_bits(options as u32);
80*b7b843beSGnoCiYeH         let options = match ret {
81*b7b843beSGnoCiYeH             Some(options) => options,
82*b7b843beSGnoCiYeH             None => {
83*b7b843beSGnoCiYeH                 return Err(SystemError::EINVAL);
84*b7b843beSGnoCiYeH             }
85*b7b843beSGnoCiYeH         };
86*b7b843beSGnoCiYeH 
871496ba7bSLoGin         let mut _rusage_buf =
881496ba7bSLoGin             UserBufferReader::new::<c_void>(rusage, core::mem::size_of::<c_void>(), true)?;
891496ba7bSLoGin 
901496ba7bSLoGin         let mut wstatus_buf =
911496ba7bSLoGin             UserBufferWriter::new::<i32>(wstatus, core::mem::size_of::<i32>(), true)?;
921496ba7bSLoGin 
931496ba7bSLoGin         let cur_pcb = ProcessManager::current_pcb();
941496ba7bSLoGin         let rd_childen = cur_pcb.children.read();
951496ba7bSLoGin 
961496ba7bSLoGin         if pid > 0 {
971496ba7bSLoGin             let pid = Pid(pid as usize);
981496ba7bSLoGin             let child_pcb = rd_childen.get(&pid).ok_or(SystemError::ECHILD)?.clone();
991496ba7bSLoGin             drop(rd_childen);
1001496ba7bSLoGin 
101*b7b843beSGnoCiYeH             loop {
1021496ba7bSLoGin                 // 获取退出码
103*b7b843beSGnoCiYeH                 match child_pcb.sched_info().state() {
104*b7b843beSGnoCiYeH                     ProcessState::Runnable => {
105*b7b843beSGnoCiYeH                         if options.contains(WaitOption::WNOHANG)
106*b7b843beSGnoCiYeH                             || options.contains(WaitOption::WNOWAIT)
107*b7b843beSGnoCiYeH                         {
1081496ba7bSLoGin                             if !wstatus.is_null() {
109*b7b843beSGnoCiYeH                                 wstatus_buf.copy_one_to_user(&WaitOption::WCONTINUED.bits(), 0)?;
110*b7b843beSGnoCiYeH                             }
111*b7b843beSGnoCiYeH                             return Ok(0);
112*b7b843beSGnoCiYeH                         }
113*b7b843beSGnoCiYeH                     }
114*b7b843beSGnoCiYeH                     ProcessState::Blocked(_) => {
115*b7b843beSGnoCiYeH                         // 指定WUNTRACED则等待暂停的进程,不指定则返回0
116*b7b843beSGnoCiYeH                         if !options.contains(WaitOption::WUNTRACED)
117*b7b843beSGnoCiYeH                             || options.contains(WaitOption::WNOWAIT)
118*b7b843beSGnoCiYeH                         {
119*b7b843beSGnoCiYeH                             if !wstatus.is_null() {
120*b7b843beSGnoCiYeH                                 wstatus_buf.copy_one_to_user(&WaitOption::WSTOPPED.bits(), 0)?;
121*b7b843beSGnoCiYeH                             }
122*b7b843beSGnoCiYeH                             return Ok(0);
123*b7b843beSGnoCiYeH                         }
124*b7b843beSGnoCiYeH                     }
125*b7b843beSGnoCiYeH                     ProcessState::Exited(status) => {
126*b7b843beSGnoCiYeH                         if !wstatus.is_null() {
127*b7b843beSGnoCiYeH                             wstatus_buf.copy_one_to_user(
128*b7b843beSGnoCiYeH                                 &(status | WaitOption::WEXITED.bits() as usize),
129*b7b843beSGnoCiYeH                                 0,
130*b7b843beSGnoCiYeH                             )?;
1311496ba7bSLoGin                         }
1321496ba7bSLoGin                         return Ok(pid.into());
1331496ba7bSLoGin                     }
134*b7b843beSGnoCiYeH                 };
135*b7b843beSGnoCiYeH 
1361496ba7bSLoGin                 // 等待指定进程
1371496ba7bSLoGin                 child_pcb.wait_queue.sleep();
138*b7b843beSGnoCiYeH             }
1391496ba7bSLoGin         } else if pid < -1 {
1401496ba7bSLoGin             // TODO 判断是否pgid == -pid(等待指定组任意进程)
1411496ba7bSLoGin             // 暂时不支持
1421496ba7bSLoGin             return Err(SystemError::EINVAL);
1431496ba7bSLoGin         } else if pid == 0 {
1441496ba7bSLoGin             // TODO 判断是否pgid == current_pgid(等待当前组任意进程)
1451496ba7bSLoGin             // 暂时不支持
1461496ba7bSLoGin             return Err(SystemError::EINVAL);
1471496ba7bSLoGin         } else {
1481496ba7bSLoGin             // 等待任意子进程(这两)
1491496ba7bSLoGin             let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
1501496ba7bSLoGin             for (pid, pcb) in rd_childen.iter() {
1511496ba7bSLoGin                 if pcb.sched_info().state().is_exited() {
1521496ba7bSLoGin                     if !wstatus.is_null() {
1531496ba7bSLoGin                         wstatus_buf.copy_one_to_user(&0, 0)?;
1541496ba7bSLoGin                     }
1551496ba7bSLoGin                     return Ok(pid.clone().into());
1561496ba7bSLoGin                 } else {
1571496ba7bSLoGin                     unsafe { pcb.wait_queue.sleep_without_schedule() };
1581496ba7bSLoGin                 }
1591496ba7bSLoGin             }
1601496ba7bSLoGin             drop(irq_guard);
1611496ba7bSLoGin             sched();
1621496ba7bSLoGin         }
1631496ba7bSLoGin 
1641496ba7bSLoGin         return Ok(0);
165ab5c8ca4Slogin     }
166ab5c8ca4Slogin 
167ab5c8ca4Slogin     /// # 退出进程
168ab5c8ca4Slogin     ///
169ab5c8ca4Slogin     /// ## 参数
170ab5c8ca4Slogin     ///
171ab5c8ca4Slogin     /// - status: 退出状态
172ab5c8ca4Slogin     pub fn exit(status: usize) -> ! {
1731496ba7bSLoGin         ProcessManager::exit(status);
174ab5c8ca4Slogin     }
175ab5c8ca4Slogin 
1761496ba7bSLoGin     /// @brief 获取当前进程的pid
1771496ba7bSLoGin     pub fn getpid() -> Result<Pid, SystemError> {
1781496ba7bSLoGin         let current_pcb = ProcessManager::current_pcb();
1791496ba7bSLoGin         return Ok(current_pcb.pid());
1801496ba7bSLoGin     }
1811496ba7bSLoGin 
1821496ba7bSLoGin     /// @brief 获取指定进程的pgid
1831496ba7bSLoGin     ///
1841496ba7bSLoGin     /// @param pid 指定一个进程号
1851496ba7bSLoGin     ///
1861496ba7bSLoGin     /// @return 成功,指定进程的进程组id
1871496ba7bSLoGin     /// @return 错误,不存在该进程
1881496ba7bSLoGin     pub fn getpgid(mut pid: Pid) -> Result<Pid, SystemError> {
1891496ba7bSLoGin         if pid == Pid(0) {
1901496ba7bSLoGin             let current_pcb = ProcessManager::current_pcb();
1911496ba7bSLoGin             pid = current_pcb.pid();
1921496ba7bSLoGin         }
1931496ba7bSLoGin         let target_proc = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?;
1941496ba7bSLoGin         return Ok(target_proc.basic().pgid());
1951496ba7bSLoGin     }
1961496ba7bSLoGin     /// @brief 获取当前进程的父进程id
1971496ba7bSLoGin 
1981496ba7bSLoGin     /// 若为initproc则ppid设置为0
1991496ba7bSLoGin     pub fn getppid() -> Result<Pid, SystemError> {
2001496ba7bSLoGin         let current_pcb = ProcessManager::current_pcb();
2011496ba7bSLoGin         return Ok(current_pcb.basic().ppid());
202ab5c8ca4Slogin     }
203ab5c8ca4Slogin }
204