This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] sysdeps/wait: Use the waitid syscall if required
- From: Alistair Francis <alistair dot francis at wdc dot com>
- To: libc-alpha at sourceware dot org
- Cc: alistair23 at gmail dot com, Alistair Francis <alistair dot francis at wdc dot com>
- Date: Wed, 25 Sep 2019 15:55:14 -0700
- Subject: [PATCH] sysdeps/wait: Use the waitid syscall if required
- Ironport-sdr: +fXdEg/x7NseX43JbGfBjOxbs/uVb8gAZiL6ViG0VhOnYtQ5fjrgOelHsVJ9BHDKH63RVWbzal KNvp6ER2ZxLELWbpAt4uUsdLO02X8TE+L2JIqdASZtDreod208bz9CkZ6ssBIWaiMPNhbvCRNl aVecD6P/XOEsUjp3BAoZNHmqlmItWJ7itVUVGvznzmnNcbCmVJibZbpD5uEtKpgU6ocmSLxShe DceF8C3BVtPWf48BG1wU8e+i2dsz7OhTrtHyTcSr3LyC4rtFVEVgMGwYh0CQglrwaAXU14FoJU 2V8=
- Ironport-sdr: pYs8S3jgc3qBaZLdPz8e/e54tPLKZwnHwvODHEZqa850wTs3z7GyVIVWRgVdzdihP20LzIUjqo msfkpkQ8MSd2nBqY9NGoP87wlby4Yz8zXStO+722Dn8LNTP++eadPt+clAqU48SlwZdZzpy/Mj wVem0YmKSsQj12v+6GJAzVKL9/FKzwZQkuipAFco1keCcRoS+smP0lzrrJ7LkdQSD0yNncD/UW WmAmWEETqmPEodJ0SjbB5J8NChJjs+7msJ0sAzUArFPzqr9iJSlZo8B7we5YBzyi3A1c3pxJgH DomQEv/6JPGGSwnR7wd022zY
- Ironport-sdr: ZPIjkaF2yqadCqViG+9f9odsFeNvcaUk40WSMU4oHTMLyxeLs+gdkC2/RlNfMi5uoIClkbWGRy HtR6Aim/k2lixDeUfRBdDTCYDnk2eJG6z3xQyw+qnhe4rbIaWZIEnkvdEBwSgvpFwKy4m/+FhF hBtuWYvnGSNwXvNhc1evCFq9GrD3mO+QR3thV2ItPsI+vu3FriEfMkhY3/XpBKzh7/U2uMPBjG aw/1RIZKTzGj08BrpsV4OGzJDJLfNzjjey4afsEg+epELIPrJYS1MDhEprSfeZk5In3jKFx48c S10=
- Wdcironportexception: Internal
If the waitpid and wait4 syscalls aren't avaliable (such as y2038 safe
32-bit systems) let us use the waitid syscall isntead.
Unfortunately waitid is substantially differnt to waitpid and wait4, so
the conversion ends up being complex.
For full support we need the 5.4+ kernel as that allows a pid of 0 with
the P_PGID idtype.
2019-09-16 Alistair Francis <alistair.francis@wdc.com>
* sysdeps/unix/sysv/linux/wait.c: Use the waitid syscall if required.
* sysdeps/unix/sysv/linux/waitpid.c: Likewise.
* sysdeps/unix/sysv/linux/waitpid_nocancel.c: Likewise.
---
Tested with the 5.3 kernel + two waitid patches with RV32.
Currently no supported glibc architecture will use the new waitid
syscall.
sysdeps/unix/sysv/linux/wait.c | 41 +++++++++++++--
sysdeps/unix/sysv/linux/waitpid.c | 59 +++++++++++++++++++++-
sysdeps/unix/sysv/linux/waitpid_nocancel.c | 56 +++++++++++++++++++-
3 files changed, 151 insertions(+), 5 deletions(-)
diff --git a/sysdeps/unix/sysv/linux/wait.c b/sysdeps/unix/sysv/linux/wait.c
index c2385c752e2..28a27af8135 100644
--- a/sysdeps/unix/sysv/linux/wait.c
+++ b/sysdeps/unix/sysv/linux/wait.c
@@ -26,9 +26,44 @@
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_wait4
+ return SYSCALL_CANCEL (wait4, WAIT_ANY, stat_loc, 0,
+ (struct rusage *) NULL);
+#else
+ 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;
+ /* Fallthrough */
+ 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;
+#endif
}
weak_alias (__libc_wait, __wait)
diff --git a/sysdeps/unix/sysv/linux/waitpid.c b/sysdeps/unix/sysv/linux/waitpid.c
index d35aac01bcc..a02275c3ff5 100644
--- a/sysdeps/unix/sysv/linux/waitpid.c
+++ b/sysdeps/unix/sysv/linux/waitpid.c
@@ -20,14 +20,71 @@
#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);
-#else
+#elif defined(__NR_wait4)
return SYSCALL_CANCEL (wait4, pid, stat_loc, options, NULL);
+#else
+ __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)
+ {
+ /* Linux Kernels 5.4+ support pid 0 with P_PGID to specify wait on
+ * the current PID's group. Earlier kernels will return -EINVAL.
+ */
+ idtype = P_PGID;
+ }
+
+ 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;
+ /* Fallthrough */
+ 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;
#endif
}
libc_hidden_def (__waitpid)
diff --git a/sysdeps/unix/sysv/linux/waitpid_nocancel.c b/sysdeps/unix/sysv/linux/waitpid_nocancel.c
index 3697c6b938c..59b07c5f73d 100644
--- a/sysdeps/unix/sysv/linux/waitpid_nocancel.c
+++ b/sysdeps/unix/sysv/linux/waitpid_nocancel.c
@@ -27,8 +27,62 @@ __waitpid_nocancel (__pid_t pid, int *stat_loc, int options)
{
#ifdef __NR_waitpid
return INLINE_SYSCALL_CALL (waitpid, pid, stat_loc, options);
-#else
+#elif defined (__NR_wait4)
return INLINE_SYSCALL_CALL (wait4, pid, stat_loc, options, NULL);
+#else
+ __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)
+ {
+ /* Linux Kernels 5.4+ support pid 0 with P_PGID to specify wait on
+ * the current PID's group. Earlier kernels will return -EINVAL.
+ */
+ idtype = P_PGID;
+ }
+
+ 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;
+ /* Fallthrough */
+ 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;
#endif
}
libc_hidden_def (__waitpid_nocancel)
--
2.23.0