This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC v3 03/23] sysdeps/wait: Use waitid if avaliable


If the waitid syscall is avaliable let's use that as waitpid
and wait4 aren't always avaliable (they aren't avaliable on RV32).

Unfortunately waitid is substantially differnt to waitpid and wait4, so
the conversion ends up being complex.

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 ChangeLog                                  |  3 ++
 sysdeps/unix/sysv/linux/wait.c             | 39 ++++++++++++++++--
 sysdeps/unix/sysv/linux/waitpid.c          | 46 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/waitpid_nocancel.c | 45 +++++++++++++++++++++
 4 files changed, 130 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9ca390a9c3..fb54a4aa61 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1029,6 +1029,9 @@
 	* sysdeps/unix/sysv/linux/nanosleep.c: Likewise.
 	* sysdeps/unix/sysv/linux/nanosleep_nocancel.c: Likewise.
 	* sysdeps/unix/sysv/linux/gettimeofday.c: Use clock_gettime64 syscall for gettimeofday.
+	* sysdeps/unix/sysv/linux/wait.c: Use __NR_waitid if avaliable.
+	* sysdeps/unix/sysv/linux/waitpid.c: Likewise.
+	* sysdeps/unix/sysv/linux/waitpid_nocancel.c: Likewise.
 
 2019-06-20  Dmitry V. Levin  <ldv@altlinux.org>
 	    Florian Weimer  <fweimer@redhat.com>
diff --git a/sysdeps/unix/sysv/linux/wait.c b/sysdeps/unix/sysv/linux/wait.c
index 498bd1c095..e727afa14b 100644
--- a/sysdeps/unix/sysv/linux/wait.c
+++ b/sysdeps/unix/sysv/linux/wait.c
@@ -26,9 +26,42 @@
 pid_t
 __libc_wait (int *stat_loc)
 {
-  pid_t result = SYSCALL_CANCEL (wait4, WAIT_ANY, stat_loc, 0,
-				 (struct rusage *) NULL);
-  return result;
+#ifdef __NR_waitid
+  siginfo_t infop;
+  __pid_t ret;
+
+  ret = SYSCALL_CANCEL (waitid, P_ALL, 0, &infop, WEXITED, NULL);
+
+  if (ret < 0) {
+    return ret;
+  }
+
+  if (stat_loc) {
+    *stat_loc = 0;
+    switch (infop.si_code) {
+    case CLD_EXITED:
+      *stat_loc = infop.si_status << 8;
+      break;
+    case CLD_DUMPED:
+      *stat_loc = 0x80;
+    case CLD_KILLED:
+      *stat_loc |= infop.si_status;
+      break;
+    case CLD_TRAPPED:
+    case CLD_STOPPED:
+      *stat_loc = infop.si_status << 8 | 0x7f;
+      break;
+    case CLD_CONTINUED:
+      *stat_loc = 0xffff;
+      break;
+    }
+  }
+
+  return infop.si_pid;
+#else
+  return SYSCALL_CANCEL (wait4, WAIT_ANY, stat_loc, 0,
+                         (struct rusage *) NULL);
+#endif
 }
 
 weak_alias (__libc_wait, __wait)
diff --git a/sysdeps/unix/sysv/linux/waitpid.c b/sysdeps/unix/sysv/linux/waitpid.c
index f0897574c0..7d4e0bb77d 100644
--- a/sysdeps/unix/sysv/linux/waitpid.c
+++ b/sysdeps/unix/sysv/linux/waitpid.c
@@ -20,12 +20,58 @@
 #include <sysdep-cancel.h>
 #include <stdlib.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 __pid_t
 __waitpid (__pid_t pid, int *stat_loc, int options)
 {
 #ifdef __NR_waitpid
   return SYSCALL_CANCEL (waitpid, pid, stat_loc, options);
+#elif defined(__NR_waitid)
+  __pid_t ret;
+  idtype_t idtype = P_PID;
+  siginfo_t infop;
+
+  if (pid < -1) {
+    idtype = P_PGID;
+    pid *= -1;
+  } else if (pid == -1) {
+    idtype = P_ALL;
+  } else if (pid == 0) {
+    idtype = P_PGID;
+    pid = getpgrp();
+  }
+
+  options |= WEXITED;
+
+  ret = SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, NULL);
+
+  if (ret < 0) {
+    return ret;
+  }
+
+  if (stat_loc) {
+    *stat_loc = 0;
+    switch (infop.si_code) {
+    case CLD_EXITED:
+      *stat_loc = infop.si_status << 8;
+      break;
+    case CLD_DUMPED:
+      *stat_loc = 0x80;
+    case CLD_KILLED:
+      *stat_loc |= infop.si_status;
+      break;
+    case CLD_TRAPPED:
+    case CLD_STOPPED:
+      *stat_loc = infop.si_status << 8 | 0x7f;
+      break;
+    case CLD_CONTINUED:
+      *stat_loc = 0xffff;
+      break;
+    }
+  }
+
+  return infop.si_pid;
 #else
   return SYSCALL_CANCEL (wait4, pid, stat_loc, options, NULL);
 #endif
diff --git a/sysdeps/unix/sysv/linux/waitpid_nocancel.c b/sysdeps/unix/sysv/linux/waitpid_nocancel.c
index 89e36a5c0b..c92f05421b 100644
--- a/sysdeps/unix/sysv/linux/waitpid_nocancel.c
+++ b/sysdeps/unix/sysv/linux/waitpid_nocancel.c
@@ -27,6 +27,51 @@ __waitpid_nocancel (__pid_t pid, int *stat_loc, int options)
 {
 #ifdef __NR_waitpid
   return INLINE_SYSCALL_CALL (waitpid, pid, stat_loc, options);
+#elif defined(__NR_waitid)
+  __pid_t ret;
+  idtype_t idtype = P_PID;
+  siginfo_t infop;
+
+  if (pid < -1) {
+    idtype = P_PGID;
+    pid *= -1;
+  } else if (pid == -1) {
+    idtype = P_ALL;
+  } else if (pid == 0) {
+    idtype = P_PGID;
+    pid = getpgrp();
+  }
+
+  options |= WEXITED;
+
+  ret = INLINE_SYSCALL_CALL (waitid, idtype, pid, &infop, options, NULL);
+
+  if (ret < 0) {
+    return ret;
+  }
+
+  if (stat_loc) {
+    *stat_loc = 0;
+    switch (infop.si_code) {
+    case CLD_EXITED:
+      *stat_loc = infop.si_status << 8;
+      break;
+    case CLD_DUMPED:
+      *stat_loc = 0x80;
+    case CLD_KILLED:
+      *stat_loc |= infop.si_status;
+      break;
+    case CLD_TRAPPED:
+    case CLD_STOPPED:
+      *stat_loc = infop.si_status << 8 | 0x7f;
+      break;
+    case CLD_CONTINUED:
+      *stat_loc = 0xffff;
+      break;
+    }
+  }
+
+  return infop.si_pid;
 #else
   return INLINE_SYSCALL_CALL (wait4, pid, stat_loc, options, NULL);
 #endif
-- 
2.22.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]