Forráskód Böngészése

feat(wait): refactor waitid handling and introduce WaitId enum

zhuowei shao 7 hónapja
szülő
commit
ede54cb224
3 módosított fájl, 65 hozzáadás és 27 törlés
  1. 9 22
      src/kernel/syscall/procops.rs
  2. 1 1
      src/kernel/task.rs
  3. 55 4
      src/kernel/task/process.rs

+ 9 - 22
src/kernel/syscall/procops.rs

@@ -7,7 +7,7 @@ use crate::kernel::constants::{
 use crate::kernel::mem::PageBuffer;
 use crate::kernel::task::{
     do_clone, futex_wait, futex_wake, FutexFlags, FutexOp, ProcessList, ProgramLoader,
-    RobustListHead, SignalAction, Thread, WaitType,
+    RobustListHead, SignalAction, Thread, WaitId, WaitType,
 };
 use crate::kernel::task::{parse_futexop, CloneArgs};
 use crate::kernel::timer::sleep;
@@ -26,7 +26,6 @@ use eonix_hal::traits::trap::RawTrapContext;
 use eonix_mm::address::{Addr as _, VAddr};
 use eonix_runtime::task::Task;
 use eonix_sync::AsProof as _;
-use posix_types::constants::{P_ALL, P_PID};
 use posix_types::ctypes::PtrT;
 use posix_types::signal::{SigAction, SigInfo, SigSet, Signal};
 use posix_types::stat::TimeVal;
@@ -215,16 +214,11 @@ enum WaitInfo {
 
 fn do_waitid(
     thread: &Thread,
-    id_type: u32,
-    _id: u32,
+    wait_id: WaitId,
     info: WaitInfo,
     options: u32,
     rusage: *mut RUsage,
 ) -> KResult<u32> {
-    if id_type != P_ALL {
-        unimplemented!("waitid with id_type {id_type}");
-    }
-
     if !rusage.is_null() {
         unimplemented!("waitid with rusage pointer");
     }
@@ -235,6 +229,7 @@ fn do_waitid(
     };
 
     let Some(wait_object) = Task::block_on(thread.process.wait(
+        wait_id,
         options.contains(UserWaitOptions::WNOHANG),
         options.contains(UserWaitOptions::WUNTRACED),
         options.contains(UserWaitOptions::WCONTINUED),
@@ -273,15 +268,10 @@ fn waitid(
     options: u32,
     rusage: *mut RUsage,
 ) -> KResult<u32> {
+    let wait_id = WaitId::from_type_and_id(id_type, id)?;
+
     if let Some(info) = NonNull::new(info) {
-        do_waitid(
-            thread,
-            id_type,
-            id,
-            WaitInfo::SigInfo(info),
-            options,
-            rusage,
-        )
+        do_waitid(thread, wait_id, WaitInfo::SigInfo(info), options, rusage)
     } else {
         /*
          * According to POSIX.1-2008, an application calling waitid() must
@@ -296,19 +286,16 @@ fn waitid(
 }
 
 #[eonix_macros::define_syscall(SYS_WAIT4)]
-fn wait4(waitpid: u32, arg1: *mut u32, options: u32, rusage: *mut RUsage) -> KResult<u32> {
+fn wait4(wait_id: i32, arg1: *mut u32, options: u32, rusage: *mut RUsage) -> KResult<u32> {
     let waitinfo = if let Some(status) = NonNull::new(arg1) {
         WaitInfo::Status(status)
     } else {
         WaitInfo::None
     };
 
-    let idtype = match waitpid {
-        u32::MAX => P_ALL,
-        _ => P_PID,
-    };
+    let wait_id = WaitId::from_id(wait_id, thread);
 
-    do_waitid(thread, idtype, waitpid, waitinfo, options, rusage)
+    do_waitid(thread, wait_id, waitinfo, options, rusage)
 }
 
 #[cfg(target_arch = "x86_64")]

+ 1 - 1
src/kernel/task.rs

@@ -13,7 +13,7 @@ pub use clone::{do_clone, CloneArgs, CloneFlags};
 pub use futex::{futex_wait, futex_wake, parse_futexop, FutexFlags, FutexOp, RobustListHead};
 pub use kernel_stack::KernelStack;
 pub use loader::ProgramLoader;
-pub use process::{alloc_pid, Process, ProcessBuilder, WaitObject, WaitType};
+pub use process::{alloc_pid, Process, ProcessBuilder, WaitId, WaitObject, WaitType};
 pub use process_group::ProcessGroup;
 pub use process_list::ProcessList;
 pub use session::Session;

+ 55 - 4
src/kernel/task/process.rs

@@ -2,7 +2,7 @@ use super::{
     process_group::ProcessGroupBuilder, signal::RaiseResult, thread::ThreadBuilder, ProcessGroup,
     ProcessList, Session, Thread,
 };
-use crate::kernel::constants::{ECHILD, EINTR, EPERM, ESRCH};
+use crate::kernel::constants::{ECHILD, EINTR, EINVAL, EPERM, ESRCH};
 use crate::kernel::task::{CloneArgs, CloneFlags};
 use crate::{
     kernel::mem::MMList,
@@ -21,7 +21,10 @@ use eonix_sync::{
     UnlockableGuard as _, UnlockedGuard as _,
 };
 use pointers::BorrowedArc;
-use posix_types::constants::{CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED};
+use posix_types::constants::{
+    CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, P_PGID, P_PIDFD,
+};
+use posix_types::constants::{P_ALL, P_PID};
 use posix_types::signal::Signal;
 use posix_types::SIGNAL_COREDUMP;
 
@@ -95,12 +98,46 @@ pub struct Entry<'waitlist, 'proclist, 'cv> {
     cv: &'cv CondVar,
     want_stop: bool,
     want_continue: bool,
+    want_id: WaitId,
 }
 
 pub struct DrainExited<'waitlist> {
     wait_procs: SpinGuard<'waitlist, VecDeque<WaitObject>>,
 }
 
+pub enum WaitId {
+    Any,
+    Pid(u32),
+    Pgid(u32),
+}
+
+impl WaitId {
+    pub fn from_type_and_id(id_type: u32, id: u32) -> KResult<Self> {
+        match id_type {
+            P_ALL => Ok(WaitId::Any),
+            P_PID => Ok(WaitId::Pid(id)),
+            P_PGID => Ok(WaitId::Pgid(id)),
+            P_PIDFD => {
+                panic!("PDIFD type is unsupported")
+            }
+            _ => Err(EINVAL),
+        }
+    }
+
+    pub fn from_id(id: i32, thread: &Thread) -> Self {
+        if id < -1 {
+            WaitId::Pgid((-id).cast_unsigned())
+        } else if id == -1 {
+            WaitId::Any
+        } else if id == 0 {
+            let procs = Task::block_on(ProcessList::get().read());
+            WaitId::Pgid(thread.process.pgroup(procs.prove()).pgid)
+        } else {
+            WaitId::Pid(id.cast_unsigned())
+        }
+    }
+}
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub enum WaitType {
     Exited(u32),
@@ -303,12 +340,13 @@ impl Process {
 
     pub async fn wait(
         &self,
+        wait_id: WaitId,
         no_block: bool,
         trace_stop: bool,
         trace_continue: bool,
     ) -> KResult<Option<WaitObject>> {
         let wait_object = {
-            let mut waits = self.wait_list.entry(trace_stop, trace_continue);
+            let mut waits = self.wait_list.entry(wait_id, trace_stop, trace_continue);
             loop {
                 if let Some(object) = waits.get() {
                     break object;
@@ -530,13 +568,14 @@ impl WaitList {
     /// # Safety
     /// Locks `ProcessList` and `WaitList` at the same time. When `wait` is called,
     /// releases the lock on `ProcessList` and `WaitList` and waits on `cv_wait_procs`.
-    pub fn entry(&self, want_stop: bool, want_continue: bool) -> Entry {
+    pub fn entry(&self, wait_id: WaitId, want_stop: bool, want_continue: bool) -> Entry {
         Entry {
             process_list: Task::block_on(ProcessList::get().read()),
             wait_procs: self.wait_procs.lock(),
             cv: &self.cv_wait_procs,
             want_stop,
             want_continue,
+            want_id: wait_id,
         }
     }
 }
@@ -556,6 +595,17 @@ impl Entry<'_, '_, '_> {
                     true
                 }
             })
+            .filter(|(_, item)| match self.want_id {
+                WaitId::Any => true,
+                WaitId::Pid(pid) => item.pid == pid,
+                WaitId::Pgid(pgid) => {
+                    let procs = Task::block_on(ProcessList::get().read());
+                    if let Some(process) = procs.try_find_process(item.pid) {
+                        return process.pgroup(procs.prove()).pgid == pgid;
+                    }
+                    false
+                }
+            })
             .map(|(idx, _)| idx)
             .next()
         {
@@ -581,6 +631,7 @@ impl Entry<'_, '_, '_> {
                     cv: self.cv,
                     want_stop: self.want_stop,
                     want_continue: self.want_continue,
+                    want_id: self.want_id,
                 })
             }
         }