xref: /DragonOS/kernel/src/process/syscall.rs (revision 7b32f5080f42bcbf7d2421013f3ea53c776a063c)
1 use core::ffi::c_void;
2 
3 use alloc::{
4     string::{String, ToString},
5     sync::Arc,
6     vec::Vec,
7 };
8 
9 use super::{
10     abi::WaitOption,
11     fork::{CloneFlags, KernelCloneArgs},
12     KernelStack, Pid, ProcessManager, ProcessState,
13 };
14 use crate::{
15     arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch},
16     exception::InterruptArch,
17     filesystem::{procfs::procfs_register_pid, vfs::MAX_PATHLEN},
18     include::bindings::bindings::verify_area,
19     mm::VirtAddr,
20     process::ProcessControlBlock,
21     sched::completion::Completion,
22     syscall::{
23         user_access::{
24             check_and_clone_cstr, check_and_clone_cstr_array, UserBufferReader, UserBufferWriter,
25         },
26         Syscall, SystemError,
27     },
28 };
29 
30 impl Syscall {
31     pub fn fork(frame: &mut TrapFrame) -> Result<usize, SystemError> {
32         let r = ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into());
33         return r;
34     }
35 
36     pub fn vfork(frame: &mut TrapFrame) -> Result<usize, SystemError> {
37         ProcessManager::fork(
38             frame,
39             CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
40         )
41         .map(|pid| pid.into())
42     }
43 
44     pub fn execve(
45         path: *const u8,
46         argv: *const *const u8,
47         envp: *const *const u8,
48         frame: &mut TrapFrame,
49     ) -> Result<(), SystemError> {
50         // kdebug!(
51         //     "execve path: {:?}, argv: {:?}, envp: {:?}\n",
52         //     path,
53         //     argv,
54         //     envp
55         // );
56         // kdebug!(
57         //     "before execve: strong count: {}",
58         //     Arc::strong_count(&ProcessManager::current_pcb())
59         // );
60 
61         if path.is_null() {
62             return Err(SystemError::EINVAL);
63         }
64 
65         let x = || {
66             let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
67             let argv: Vec<String> = check_and_clone_cstr_array(argv)?;
68             let envp: Vec<String> = check_and_clone_cstr_array(envp)?;
69             Ok((path, argv, envp))
70         };
71         let r: Result<(String, Vec<String>, Vec<String>), SystemError> = x();
72         if let Err(e) = r {
73             panic!("Failed to execve: {:?}", e);
74         }
75         let (path, argv, envp) = r.unwrap();
76         ProcessManager::current_pcb()
77             .basic_mut()
78             .set_name(ProcessControlBlock::generate_name(&path, &argv));
79 
80         Self::do_execve(path, argv, envp, frame)?;
81 
82         // 关闭设置了O_CLOEXEC的文件描述符
83         let fd_table = ProcessManager::current_pcb().fd_table();
84         fd_table.write().close_on_exec();
85         // kdebug!(
86         //     "after execve: strong count: {}",
87         //     Arc::strong_count(&ProcessManager::current_pcb())
88         // );
89 
90         return Ok(());
91     }
92 
93     pub fn wait4(
94         pid: i64,
95         wstatus: *mut i32,
96         options: i32,
97         rusage: *mut c_void,
98     ) -> Result<usize, SystemError> {
99         let ret = WaitOption::from_bits(options as u32);
100         let options = match ret {
101             Some(options) => options,
102             None => {
103                 return Err(SystemError::EINVAL);
104             }
105         };
106 
107         let mut _rusage_buf =
108             UserBufferReader::new::<c_void>(rusage, core::mem::size_of::<c_void>(), true)?;
109 
110         let mut wstatus_buf =
111             UserBufferWriter::new::<i32>(wstatus, core::mem::size_of::<i32>(), true)?;
112 
113         let cur_pcb = ProcessManager::current_pcb();
114         let rd_childen = cur_pcb.children.read();
115 
116         if pid > 0 {
117             let pid = Pid(pid as usize);
118             let child_pcb = ProcessManager::find(pid).ok_or(SystemError::ECHILD)?;
119             drop(rd_childen);
120 
121             loop {
122                 let state = child_pcb.sched_info().state();
123                 // 获取退出码
124                 match state {
125                     ProcessState::Runnable => {
126                         if options.contains(WaitOption::WNOHANG)
127                             || options.contains(WaitOption::WNOWAIT)
128                         {
129                             if !wstatus.is_null() {
130                                 wstatus_buf.copy_one_to_user(&WaitOption::WCONTINUED.bits(), 0)?;
131                             }
132                             return Ok(0);
133                         }
134                     }
135                     ProcessState::Blocked(_) | ProcessState::Stopped => {
136                         // 指定WUNTRACED则等待暂停的进程,不指定则返回0
137                         if !options.contains(WaitOption::WUNTRACED)
138                             || options.contains(WaitOption::WNOWAIT)
139                         {
140                             if !wstatus.is_null() {
141                                 wstatus_buf.copy_one_to_user(&WaitOption::WSTOPPED.bits(), 0)?;
142                             }
143                             return Ok(0);
144                         }
145                     }
146                     ProcessState::Exited(status) => {
147                         // kdebug!("wait4: child exited, pid: {:?}, status: {status}\n", pid);
148                         if !wstatus.is_null() {
149                             wstatus_buf.copy_one_to_user(
150                                 &(status as u32 | WaitOption::WEXITED.bits()),
151                                 0,
152                             )?;
153                         }
154                         drop(child_pcb);
155                         // kdebug!("wait4: to release {pid:?}");
156                         unsafe { ProcessManager::release(pid) };
157                         return Ok(pid.into());
158                     }
159                 };
160 
161                 // 等待指定进程
162                 child_pcb.wait_queue.sleep();
163             }
164         } else if pid < -1 {
165             // TODO 判断是否pgid == -pid(等待指定组任意进程)
166             // 暂时不支持
167             return Err(SystemError::EINVAL);
168         } else if pid == 0 {
169             // TODO 判断是否pgid == current_pgid(等待当前组任意进程)
170             // 暂时不支持
171             return Err(SystemError::EINVAL);
172         } else {
173             // 等待任意子进程(这两)
174             let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
175             for pid in rd_childen.iter() {
176                 let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
177                 if pcb.sched_info().state().is_exited() {
178                     if !wstatus.is_null() {
179                         wstatus_buf.copy_one_to_user(&0, 0)?;
180                     }
181                     return Ok(pid.clone().into());
182                 } else {
183                     unsafe { pcb.wait_queue.sleep_without_schedule() };
184                 }
185             }
186             drop(irq_guard);
187             sched();
188         }
189 
190         return Ok(0);
191     }
192 
193     /// # 退出进程
194     ///
195     /// ## 参数
196     ///
197     /// - status: 退出状态
198     pub fn exit(status: usize) -> ! {
199         ProcessManager::exit(status);
200     }
201 
202     /// @brief 获取当前进程的pid
203     pub fn getpid() -> Result<Pid, SystemError> {
204         let current_pcb = ProcessManager::current_pcb();
205         return Ok(current_pcb.pid());
206     }
207 
208     /// @brief 获取指定进程的pgid
209     ///
210     /// @param pid 指定一个进程号
211     ///
212     /// @return 成功,指定进程的进程组id
213     /// @return 错误,不存在该进程
214     pub fn getpgid(mut pid: Pid) -> Result<Pid, SystemError> {
215         if pid == Pid(0) {
216             let current_pcb = ProcessManager::current_pcb();
217             pid = current_pcb.pid();
218         }
219         let target_proc = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?;
220         return Ok(target_proc.basic().pgid());
221     }
222     /// @brief 获取当前进程的父进程id
223 
224     /// 若为initproc则ppid设置为0
225     pub fn getppid() -> Result<Pid, SystemError> {
226         let current_pcb = ProcessManager::current_pcb();
227         return Ok(current_pcb.basic().ppid());
228     }
229 
230     pub fn clone(
231         current_trapframe: &mut TrapFrame,
232         clone_args: KernelCloneArgs,
233     ) -> Result<usize, SystemError> {
234         let flags = clone_args.flags;
235 
236         let vfork = Arc::new(Completion::new());
237 
238         if flags.contains(CloneFlags::CLONE_PIDFD)
239             && flags.contains(CloneFlags::CLONE_PARENT_SETTID)
240         {
241             return Err(SystemError::EINVAL);
242         }
243 
244         let current_pcb = ProcessManager::current_pcb();
245         let new_kstack = KernelStack::new()?;
246         let name = current_pcb.basic().name().to_string();
247         let pcb = ProcessControlBlock::new(name, new_kstack);
248         // 克隆pcb
249         ProcessManager::copy_process(&current_pcb, &pcb, clone_args, current_trapframe)?;
250         ProcessManager::add_pcb(pcb.clone());
251 
252         // 向procfs注册进程
253         procfs_register_pid(pcb.pid()).unwrap_or_else(|e| {
254             panic!(
255                 "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}",
256                 pcb.pid(),
257                 e
258             )
259         });
260 
261         if flags.contains(CloneFlags::CLONE_VFORK) {
262             pcb.thread.write().vfork_done = Some(vfork.clone());
263         }
264 
265         if pcb.thread.read().set_child_tid.is_some() {
266             let addr = pcb.thread.read().set_child_tid.unwrap();
267             let mut writer =
268                 UserBufferWriter::new(addr.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
269             writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?;
270         }
271 
272         ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
273             panic!(
274                 "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}",
275                 pcb.pid(),
276                 e
277             )
278         });
279 
280         if flags.contains(CloneFlags::CLONE_VFORK) {
281             // 等待子进程结束或者exec;
282             vfork.wait_for_completion_interruptible()?;
283         }
284 
285         return Ok(pcb.pid().0);
286     }
287 
288     /// 设置线程地址
289     pub fn set_tid_address(ptr: usize) -> Result<usize, SystemError> {
290         if !unsafe { verify_area(ptr as u64, core::mem::size_of::<i32>() as u64) } {
291             return Err(SystemError::EFAULT);
292         }
293 
294         let pcb = ProcessManager::current_pcb();
295         pcb.thread.write().clear_child_tid = Some(VirtAddr::new(ptr));
296         Ok(pcb.pid.0)
297     }
298 }
299