xref: /DragonOS/kernel/src/process/syscall.rs (revision 0d9b7d9240ef65c3e603a371db57a80d26a7b9dd)
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     resource::{RLimit64, RLimitID, RUsage, RUsageWho},
13     KernelStack, Pid, ProcessManager, ProcessState,
14 };
15 use crate::{
16     arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch, MMArch},
17     exception::InterruptArch,
18     filesystem::{
19         procfs::procfs_register_pid,
20         vfs::{file::FileDescriptorVec, MAX_PATHLEN},
21     },
22     include::bindings::bindings::verify_area,
23     mm::{ucontext::UserStack, MemoryManagementArch, VirtAddr},
24     process::ProcessControlBlock,
25     sched::completion::Completion,
26     syscall::{
27         user_access::{
28             check_and_clone_cstr, check_and_clone_cstr_array, UserBufferReader, UserBufferWriter,
29         },
30         Syscall, SystemError,
31     },
32 };
33 
34 impl Syscall {
35     pub fn fork(frame: &mut TrapFrame) -> Result<usize, SystemError> {
36         let r = ProcessManager::fork(frame, CloneFlags::empty()).map(|pid| pid.into());
37         return r;
38     }
39 
40     pub fn vfork(frame: &mut TrapFrame) -> Result<usize, SystemError> {
41         ProcessManager::fork(
42             frame,
43             CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
44         )
45         .map(|pid| pid.into())
46     }
47 
48     pub fn execve(
49         path: *const u8,
50         argv: *const *const u8,
51         envp: *const *const u8,
52         frame: &mut TrapFrame,
53     ) -> Result<(), SystemError> {
54         // kdebug!(
55         //     "execve path: {:?}, argv: {:?}, envp: {:?}\n",
56         //     path,
57         //     argv,
58         //     envp
59         // );
60         // kdebug!(
61         //     "before execve: strong count: {}",
62         //     Arc::strong_count(&ProcessManager::current_pcb())
63         // );
64 
65         if path.is_null() {
66             return Err(SystemError::EINVAL);
67         }
68 
69         let x = || {
70             let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
71             let argv: Vec<String> = check_and_clone_cstr_array(argv)?;
72             let envp: Vec<String> = check_and_clone_cstr_array(envp)?;
73             Ok((path, argv, envp))
74         };
75         let r: Result<(String, Vec<String>, Vec<String>), SystemError> = x();
76         if let Err(e) = r {
77             panic!("Failed to execve: {:?}", e);
78         }
79         let (path, argv, envp) = r.unwrap();
80         ProcessManager::current_pcb()
81             .basic_mut()
82             .set_name(ProcessControlBlock::generate_name(&path, &argv));
83 
84         Self::do_execve(path, argv, envp, frame)?;
85 
86         // 关闭设置了O_CLOEXEC的文件描述符
87         let fd_table = ProcessManager::current_pcb().fd_table();
88         fd_table.write().close_on_exec();
89         // kdebug!(
90         //     "after execve: strong count: {}",
91         //     Arc::strong_count(&ProcessManager::current_pcb())
92         // );
93 
94         return Ok(());
95     }
96 
97     pub fn wait4(
98         pid: i64,
99         wstatus: *mut i32,
100         options: i32,
101         rusage: *mut c_void,
102     ) -> Result<usize, SystemError> {
103         let ret = WaitOption::from_bits(options as u32);
104         let options = match ret {
105             Some(options) => options,
106             None => {
107                 return Err(SystemError::EINVAL);
108             }
109         };
110 
111         let mut _rusage_buf =
112             UserBufferReader::new::<c_void>(rusage, core::mem::size_of::<c_void>(), true)?;
113 
114         let mut wstatus_buf =
115             UserBufferWriter::new::<i32>(wstatus, core::mem::size_of::<i32>(), true)?;
116 
117         let cur_pcb = ProcessManager::current_pcb();
118         let rd_childen = cur_pcb.children.read();
119 
120         if pid > 0 {
121             let pid = Pid(pid as usize);
122             let child_pcb = ProcessManager::find(pid).ok_or(SystemError::ECHILD)?;
123             drop(rd_childen);
124 
125             loop {
126                 let state = child_pcb.sched_info().state();
127                 // 获取退出码
128                 match state {
129                     ProcessState::Runnable => {
130                         if options.contains(WaitOption::WNOHANG)
131                             || options.contains(WaitOption::WNOWAIT)
132                         {
133                             if !wstatus.is_null() {
134                                 wstatus_buf.copy_one_to_user(&WaitOption::WCONTINUED.bits(), 0)?;
135                             }
136                             return Ok(0);
137                         }
138                     }
139                     ProcessState::Blocked(_) | ProcessState::Stopped => {
140                         // 指定WUNTRACED则等待暂停的进程,不指定则返回0
141                         if !options.contains(WaitOption::WUNTRACED)
142                             || options.contains(WaitOption::WNOWAIT)
143                         {
144                             if !wstatus.is_null() {
145                                 wstatus_buf.copy_one_to_user(&WaitOption::WSTOPPED.bits(), 0)?;
146                             }
147                             return Ok(0);
148                         }
149                     }
150                     ProcessState::Exited(status) => {
151                         // kdebug!("wait4: child exited, pid: {:?}, status: {status}\n", pid);
152                         if !wstatus.is_null() {
153                             wstatus_buf.copy_one_to_user(
154                                 &(status as u32 | WaitOption::WEXITED.bits()),
155                                 0,
156                             )?;
157                         }
158                         drop(child_pcb);
159                         // kdebug!("wait4: to release {pid:?}");
160                         unsafe { ProcessManager::release(pid) };
161                         return Ok(pid.into());
162                     }
163                 };
164 
165                 // 等待指定进程
166                 child_pcb.wait_queue.sleep();
167             }
168         } else if pid < -1 {
169             // TODO 判断是否pgid == -pid(等待指定组任意进程)
170             // 暂时不支持
171             return Err(SystemError::EINVAL);
172         } else if pid == 0 {
173             // TODO 判断是否pgid == current_pgid(等待当前组任意进程)
174             // 暂时不支持
175             return Err(SystemError::EINVAL);
176         } else {
177             // 等待任意子进程(这两)
178             let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
179             for pid in rd_childen.iter() {
180                 let pcb = ProcessManager::find(*pid).ok_or(SystemError::ECHILD)?;
181                 if pcb.sched_info().state().is_exited() {
182                     if !wstatus.is_null() {
183                         wstatus_buf.copy_one_to_user(&0, 0)?;
184                     }
185                     return Ok(pid.clone().into());
186                 } else {
187                     unsafe { pcb.wait_queue.sleep_without_schedule() };
188                 }
189             }
190             drop(irq_guard);
191             sched();
192         }
193 
194         return Ok(0);
195     }
196 
197     /// # 退出进程
198     ///
199     /// ## 参数
200     ///
201     /// - status: 退出状态
202     pub fn exit(status: usize) -> ! {
203         ProcessManager::exit(status);
204     }
205 
206     /// @brief 获取当前进程的pid
207     pub fn getpid() -> Result<Pid, SystemError> {
208         let current_pcb = ProcessManager::current_pcb();
209         return Ok(current_pcb.tgid());
210     }
211 
212     /// @brief 获取指定进程的pgid
213     ///
214     /// @param pid 指定一个进程号
215     ///
216     /// @return 成功,指定进程的进程组id
217     /// @return 错误,不存在该进程
218     pub fn getpgid(mut pid: Pid) -> Result<Pid, SystemError> {
219         if pid == Pid(0) {
220             let current_pcb = ProcessManager::current_pcb();
221             pid = current_pcb.pid();
222         }
223         let target_proc = ProcessManager::find(pid).ok_or(SystemError::ESRCH)?;
224         return Ok(target_proc.basic().pgid());
225     }
226     /// @brief 获取当前进程的父进程id
227 
228     /// 若为initproc则ppid设置为0
229     pub fn getppid() -> Result<Pid, SystemError> {
230         let current_pcb = ProcessManager::current_pcb();
231         return Ok(current_pcb.basic().ppid());
232     }
233 
234     pub fn clone(
235         current_trapframe: &mut TrapFrame,
236         clone_args: KernelCloneArgs,
237     ) -> Result<usize, SystemError> {
238         let flags = clone_args.flags;
239 
240         let vfork = Arc::new(Completion::new());
241 
242         if flags.contains(CloneFlags::CLONE_PIDFD)
243             && flags.contains(CloneFlags::CLONE_PARENT_SETTID)
244         {
245             return Err(SystemError::EINVAL);
246         }
247 
248         let current_pcb = ProcessManager::current_pcb();
249         let new_kstack = KernelStack::new()?;
250         let name = current_pcb.basic().name().to_string();
251         let pcb = ProcessControlBlock::new(name, new_kstack);
252         // 克隆pcb
253         ProcessManager::copy_process(&current_pcb, &pcb, clone_args, current_trapframe)?;
254         ProcessManager::add_pcb(pcb.clone());
255 
256         // 向procfs注册进程
257         procfs_register_pid(pcb.pid()).unwrap_or_else(|e| {
258             panic!(
259                 "fork: Failed to register pid to procfs, pid: [{:?}]. Error: {:?}",
260                 pcb.pid(),
261                 e
262             )
263         });
264 
265         if flags.contains(CloneFlags::CLONE_VFORK) {
266             pcb.thread.write().vfork_done = Some(vfork.clone());
267         }
268 
269         if pcb.thread.read().set_child_tid.is_some() {
270             let addr = pcb.thread.read().set_child_tid.unwrap();
271             let mut writer =
272                 UserBufferWriter::new(addr.as_ptr::<i32>(), core::mem::size_of::<i32>(), true)?;
273             writer.copy_one_to_user(&(pcb.pid().data() as i32), 0)?;
274         }
275 
276         ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
277             panic!(
278                 "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}",
279                 pcb.pid(),
280                 e
281             )
282         });
283 
284         if flags.contains(CloneFlags::CLONE_VFORK) {
285             // 等待子进程结束或者exec;
286             vfork.wait_for_completion_interruptible()?;
287         }
288 
289         return Ok(pcb.pid().0);
290     }
291 
292     /// 设置线程地址
293     pub fn set_tid_address(ptr: usize) -> Result<usize, SystemError> {
294         if !unsafe { verify_area(ptr as u64, core::mem::size_of::<i32>() as u64) } {
295             return Err(SystemError::EFAULT);
296         }
297 
298         let pcb = ProcessManager::current_pcb();
299         pcb.thread.write().clear_child_tid = Some(VirtAddr::new(ptr));
300         Ok(pcb.pid.0)
301     }
302 
303     pub fn gettid() -> Result<Pid, SystemError> {
304         let pcb = ProcessManager::current_pcb();
305         Ok(pcb.pid)
306     }
307 
308     pub fn getuid() -> Result<usize, SystemError> {
309         // todo: 增加credit功能之后,需要修改
310         return Ok(0);
311     }
312 
313     pub fn getgid() -> Result<usize, SystemError> {
314         // todo: 增加credit功能之后,需要修改
315         return Ok(0);
316     }
317 
318     pub fn geteuid() -> Result<usize, SystemError> {
319         // todo: 增加credit功能之后,需要修改
320         return Ok(0);
321     }
322 
323     pub fn getegid() -> Result<usize, SystemError> {
324         // todo: 增加credit功能之后,需要修改
325         return Ok(0);
326     }
327 
328     pub fn get_rusage(who: i32, rusage: *mut RUsage) -> Result<usize, SystemError> {
329         let who = RUsageWho::try_from(who)?;
330         let mut writer = UserBufferWriter::new(rusage, core::mem::size_of::<RUsage>(), true)?;
331         let pcb = ProcessManager::current_pcb();
332         let rusage = pcb.get_rusage(who).ok_or(SystemError::EINVAL)?;
333 
334         let ubuf = writer.buffer::<RUsage>(0).unwrap();
335         ubuf.copy_from_slice(&[rusage]);
336 
337         return Ok(0);
338     }
339 
340     /// # 设置资源限制
341     ///
342     /// TODO: 目前暂时不支持设置资源限制,只提供读取默认值的功能
343     ///
344     /// ## 参数
345     ///
346     /// - pid: 进程号
347     /// - resource: 资源类型
348     /// - new_limit: 新的资源限制
349     /// - old_limit: 旧的资源限制
350     ///
351     /// ## 返回值
352     ///
353     /// - 成功,0
354     /// - 如果old_limit不为NULL,则返回旧的资源限制到old_limit
355     ///
356     pub fn prlimit64(
357         _pid: Pid,
358         resource: usize,
359         new_limit: *const RLimit64,
360         old_limit: *mut RLimit64,
361     ) -> Result<usize, SystemError> {
362         let resource = RLimitID::try_from(resource)?;
363         let mut writer = None;
364 
365         if new_limit.is_null() {
366             return Err(SystemError::EINVAL);
367         }
368 
369         if !old_limit.is_null() {
370             writer = Some(UserBufferWriter::new(
371                 old_limit,
372                 core::mem::size_of::<RLimit64>(),
373                 true,
374             )?);
375         }
376 
377         let _reader = UserBufferReader::new(new_limit, core::mem::size_of::<RLimit64>(), true)?;
378 
379         match resource {
380             RLimitID::Stack => {
381                 if let Some(mut writer) = writer {
382                     let mut rlimit = writer.buffer::<RLimit64>(0).unwrap()[0];
383                     rlimit.rlim_cur = UserStack::DEFAULT_USER_STACK_SIZE as u64;
384                     rlimit.rlim_max = UserStack::DEFAULT_USER_STACK_SIZE as u64;
385                 }
386                 return Ok(0);
387             }
388 
389             RLimitID::Nofile => {
390                 if let Some(mut writer) = writer {
391                     let mut rlimit = writer.buffer::<RLimit64>(0).unwrap()[0];
392                     rlimit.rlim_cur = FileDescriptorVec::PROCESS_MAX_FD as u64;
393                     rlimit.rlim_max = FileDescriptorVec::PROCESS_MAX_FD as u64;
394                 }
395                 return Ok(0);
396             }
397 
398             RLimitID::As | RLimitID::Rss => {
399                 if let Some(mut writer) = writer {
400                     let mut rlimit = writer.buffer::<RLimit64>(0).unwrap()[0];
401                     rlimit.rlim_cur = MMArch::USER_END_VADDR.data() as u64;
402                     rlimit.rlim_max = MMArch::USER_END_VADDR.data() as u64;
403                 }
404                 return Ok(0);
405             }
406 
407             _ => {
408                 return Err(SystemError::ENOSYS);
409             }
410         }
411     }
412 }
413