[RFC,v1,04/16] sysdeps/wait: Use __NR_waitid if avaliable
Commit Message
If the __NR_waitid syscall is avaliable let's use that as __NR_waitpid
and __NR_wait4 aren't always avaliable (they aren't avaliable on RV32).
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
ChangeLog | 3 ++
sysdeps/unix/sysv/linux/wait.c | 19 ++++++++++++-
sysdeps/unix/sysv/linux/waitpid.c | 33 ++++++++++++++++++++++
sysdeps/unix/sysv/linux/waitpid_nocancel.c | 32 +++++++++++++++++++++
4 files changed, 86 insertions(+), 1 deletion(-)
@@ -5,6 +5,9 @@
* sysdeps/unix/sysv/linux/nanosleep_nocancel.c: Likewise.
* sysdeps/unix/sysv/linux/lowlevellock-futex.h: Use __NR_futex_time64 if we don't have __NR_futex.
* 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>
@@ -26,8 +26,25 @@
pid_t
__libc_wait (int *stat_loc)
{
- pid_t result = SYSCALL_CANCEL (wait4, WAIT_ANY, stat_loc, 0,
+ pid_t result;
+
+#if defined(__NR_waitid)
+ siginfo_t infop;
+
+ result = SYSCALL_CANCEL (waitid, P_ALL, 0, &infop, 0);
+
+ if (stat_loc) {
+ *stat_loc = infop.si_status;
+ }
+
+ if (result == 0) {
+ result = infop.si_pid;
+ }
+#else
+ result = SYSCALL_CANCEL (wait4, WAIT_ANY, stat_loc, 0,
(struct rusage *) NULL);
+#endif
+
return result;
}
@@ -20,12 +20,45 @@
#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)
+ int ret;
+ idtype_t idtype = P_PID;
+ siginfo_t infop;
+
+ /* Set this to zero so we can test if WNOHANG was specified in options
+ * and there were no children in a waitable state. This is required to match
+ * waitid() behaviour.
+ */
+ infop.si_pid = 0;
+
+ if (pid < -1) {
+ idtype = P_PGID;
+ pid *= -1;
+ } else if (pid == -1) {
+ idtype = P_ALL;
+ } else if (pid == 0) {
+ idtype = P_PGID;
+ pid = getpgrp();
+ }
+
+ ret = SYSCALL_CANCEL (waitid, idtype, pid, &infop, options);
+
+ if (stat_loc) {
+ *stat_loc = infop.si_status;
+ }
+
+ if (ret == 0) {
+ return infop.si_pid;
+ }
+
+ return ret;
#else
return SYSCALL_CANCEL (wait4, pid, stat_loc, options, NULL);
#endif
@@ -27,6 +27,38 @@ __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)
+ int ret;
+ idtype_t idtype = P_PID;
+ siginfo_t infop;
+
+ /* Set this to zero so we can test if WNOHANG was specified in options
+ * and there were no children in a waitable state. This is required to match
+ * waitid() behaviour.
+ */
+ infop.si_pid = 0;
+
+ if (pid < -1) {
+ idtype = P_PGID;
+ pid *= -1;
+ } else if (pid == -1) {
+ idtype = P_ALL;
+ } else if (pid == 0) {
+ idtype = P_PGID;
+ pid = getpgrp();
+ }
+
+ ret = INLINE_SYSCALL_CALL (waitid, idtype, pid, &infop, options);
+
+ if (stat_loc) {
+ *stat_loc = infop.si_status;
+ }
+
+ if (ret == 0) {
+ return infop.si_pid;
+ }
+
+ return ret;
#else
return INLINE_SYSCALL_CALL (wait4, pid, stat_loc, options, NULL);
#endif