From patchwork Thu Aug 29 16:50:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Francis X-Patchwork-Id: 34330 Received: (qmail 127662 invoked by alias); 29 Aug 2019 16:53:56 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 127575 invoked by uid 89); 29 Aug 2019 16:53:56 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy= X-HELO: esa2.hgst.iphmx.com DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1567097697; x=1598633697; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=baQ3/OtiWKzLwbrJId3YSlgq2rCP3JKU/g1Z9NKbNMU=; b=BL80HaQUjxiOyVxM/lONGfwAhiulOeg0vwfCvqffNyVOugMCZoNzNhWb 5QWiojxq6cynjS+cFWJXc20sTjcRP72xSsW0yiPkMjf08G2sBHb4TZf8b QVTg2WV6uUT/nUM1weFJ0V3sHgcPN//D1jj0rin/m3PPJZ14oak2xg/mI /lTtE+rzrK1G/2Vm17vhj9PZCwGnKYgWxjOWZWVnjwem/naEYPjyJzAtj /fK9HohDD7NW/4pxVGQWuaeo9E7TbKMqH5cxx+r76cqgubeqaNCDTR+p8 wkqru4XND3J97EynVKp0Jzq6qGKD2hDjOZ7Mja+47WiAnXhlecjtUUv8M w==; 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= WDCIronportException: Internal From: Alistair Francis To: libc-alpha@sourceware.org Cc: arnd@arndb.de, adhemerval.zanella@linaro.org, fweimer@redhat.com, palmer@sifive.com, macro@wdc.com, zongbox@gmail.com, alistair.francis@wdc.com, alistair23@gmail.com Subject: [RFC v5 04/21] sysdeps/wait: Use waitid if avaliable Date: Thu, 29 Aug 2019 09:50:11 -0700 Message-Id: <7528c6e0937f88bcff0f226b67c662cf89286998.1567097252.git.alistair.francis@wdc.com> In-Reply-To: References: MIME-Version: 1.0 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 * 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 #include #include +#include __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)