This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[RFC v5 04/21] sysdeps/wait: Use waitid if avaliable
- From: Alistair Francis <alistair dot francis at wdc dot com>
- To: libc-alpha at sourceware dot org
- Cc: arnd at arndb dot de, adhemerval dot zanella at linaro dot org, fweimer at redhat dot com, palmer at sifive dot com, macro at wdc dot com, zongbox at gmail dot com, alistair dot francis at wdc dot com, alistair23 at gmail dot com
- Date: Thu, 29 Aug 2019 09:50:11 -0700
- Subject: [RFC v5 04/21] sysdeps/wait: Use waitid if avaliable
- Ironport-sdr: Ee7uToY79Ij4ze98SNeq0PwQKuFeoupYADE+mM2LMuvYCIKLsrZt+5o4lIA9G+bg+VpVPzc8Ba 3ftxmIVLVrCLGR70PB17B//LwgjFKosZ/e8O5DcJ11ZeK5oupuKTMgnYATAUdOqGkiJ5dkbR5d SdoxQbUYffflKlJO26FiZ+rk2znw7blCOn8FzyREe2Ayq2rMTaKPtYYfy0lEf7fcldcDLgv0Cf XZoH3TLdxyB9KMmQ5za7rxFGE5/J+V1Z+KNRiqcQDT7t3UNsob1gIOHP24oEWLJCxDEwBdwz1l yGE=
- Ironport-sdr: W0aJU7I7ULakvGjNKbikNyaFlOiTZ2trsxehY8tZQj8k7U77vpJanKsP6jYYzf/dePOynSmMi8 XK5DGmYl4W7x4BEitxlL0sZheJeMzRyUf5TeYvXB+Gdq5hW4ulz0SnT3bqnXXsUSWse8ZiSwVd 8reHbpiLnlnosq+gkwQEqUyaOS942SALigHFSnOow3Z0HwAQgDN0Ytz7vJJgy066cJ7LxiuTNR Ys6MbMsjfzKD409B23+F6R9t6jEtRDrbvP+y35R1ubv8WTzPDotFDBpZ3h2gQpjHHiGt8iqJDs J0ffep4OUMgZ6yR8eNVl0oiX
- Ironport-sdr: NFwS43uJCWfINEaNvCujiY26nqAdur/7mQO1ItQN4miDG+Lxx2967zbGCFJKFmqmh7SippnG9Q Y6ofgiZNzhZ22cakWS4DAckkUAoJR5PwFHKQrrgNm6o2Dc+293gSYAPMAICh0LeQIz8liJQGpH trVHm9wOZdZi0VmEucwG8JJji8iGj9vxJCac80G0iFYTpi76fACiYJQHZojGfiTF3E11jDWq5v p2knVyJ07HcCdrRuXXPxjbJ01GOrNvxrRotXRBY3gZKlBn9nbiouQUkt+4/KpXqswTIG0eIW4N Nas=
- References: <cover.1567097252.git.alistair.francis@wdc.com>
- Wdcironportexception: Internal
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.
For full support we need the 5.4+ kernel as that allows a pid of 0 with
the P_PGID idtype.
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
* 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.
---
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 498bd1c095e..cd124ed11fb 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 f0897574c0b..003d9ad8113 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 89e36a5c0b1..63a3571b8a5 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.22.0