From patchwork Wed Sep 25 22:55:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Francis X-Patchwork-Id: 34665 Received: (qmail 96050 invoked by alias); 25 Sep 2019 22:59:35 -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 96042 invoked by uid 89); 25 Sep 2019 22:59:35 -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=2762, HContent-Transfer-Encoding:8bit X-HELO: esa1.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=1569452373; x=1600988373; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=T466zNbSixrJ+fx+my4AgEY1dHw3ZDpxeXpX/qaie1s=; b=pQ8hD1KY6AstwTJsmoekyincU2MxbsXIDf983mZc3sJ05RMrb7bmhriP MUaznL7oxbAPl2zsJuVe3h/mbWMfXeF1Q9g78v3fx24DXkuEvOr8+fjBa qVyN6FC1pe0r5XI/RH0Nev7f5FKf12HBvNc9U+oTRaf3T5sRNlCR8tnX+ iI4nYHZVeTAxINM7HwmxMI+VcAfmSB8Ny3Axu1Wy2n6JWXHCf960CyC09 ogST+1MHLTS+2WLT1CdMqp4Phwlj6g+yycPFyL0/kPovp6cKgyzUknZ3w Br2joby/3fcYkrBBPF+/Bvdxk5S6K+Bbi74AHcNeQ3XHj9NEaXtmZbpZT Q==; 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 From: Alistair Francis To: libc-alpha@sourceware.org Cc: alistair23@gmail.com, Alistair Francis Subject: [PATCH] sysdeps/wait: Use the waitid syscall if required Date: Wed, 25 Sep 2019 15:55:14 -0700 Message-Id: <20190925225514.7224-1-alistair.francis@wdc.com> MIME-Version: 1.0 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 * 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 #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 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)