From patchwork Fri Oct 25 15:56:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Francis X-Patchwork-Id: 35343 Received: (qmail 74799 invoked by alias); 25 Oct 2019 16:01:53 -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 74788 invoked by uid 89); 25 Oct 2019 16:01:53 -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, KAM_SHORT autolearn=ham version=3.3.1 spammy=5.4, 0x7f X-HELO: esa4.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=1572019310; x=1603555310; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=IB4FeaGrglQOgbz+JfDqh2RYzURKfRiQVceqvA5ro9M=; b=GqS4nrvXLUCeu71rqasgzZko4Zebmnde0roexLj5BL+uxrJ1wKwm8cSv veadvfYO4RUdzznRfG6uC3bZ79D33YM6i673kkQ6ya6a8xDBFeIz9w25+ OPk8msFpwDy0MFf+p4dZNO2R2FRsX1P8F+2PP2HGMT5wQtBlYbgRsero5 gZPODpoZXZDqqDOT8+1pPq0SiuRqWIkgt+9tLKFmh8fWLbMumKoxyGXRT /fg/JRIsNDY8FBpYzCnROaxYCt0gY54i76RL5MHrUMdR93Vtxzp/lDJ7t bm74aRbt7e+xX+0FaAwFsrA0XC7MN4M0/TaY+/Vp/YZymBPxfccGazDVL w==; IronPort-SDR: HMEt809yk0Z3/p/ELUhJ9NWgJazYCsfTP/iJEwrrgLKl4zdKGf3eIJ8evZlaevL+yYB7TG2wRU KO8tNJJ5J0yUytbkX7rSzdwWrZh7SmKXC8+SW3WvNCSfKXv8gSKkLHX8uA1WidsUP5yXTIRLpR arKMrdT1jBBtF97A3GEa1CTDZU2ak7qIWhRCIDlYzxJi/MN/MWtuqogqWXk88+VnC47xs/4IeH AkVv0hpDPVkZiS+iDaj0tKdD4xkgf19o7baU1axP3slSKabKWfmgO/tWWOOsF/YzBqiIoOd3uw X4k= IronPort-SDR: bLpTQhl8A0Flxc9PUawmpgYVr/1Ak+RCGwJNgO4V8qy6rOBWOxyFLb1jDyQfG7/kGZliSH2PB0 FfZgHzjbXK5KkaqgyfXgOorr8t2lhxIGxe5jI7Esi6SezNupYXsefDuV2x9+OepMIqugpLRVUk bhGeSix7Xg9pm8uIp0/2fVMl6HPmlLWDlI2bicCpS3xERVPggROGsp2SIwzrpslost/IfPqFJG T15hBvigoaVs8Zdo0Yzmnfn5fxNFu6QbRWthHRnIqHSEMoNa7KwUbwkcbhLuGrpIjcSXcBvd85 kNIQ+3G/sKPPQyu/wZcHyvl+ IronPort-SDR: mB4IWoPq7PmZHU4FqgUfqJ3gL9bP6mbzXassj5hZClj6IjA5VapjPqVedSwKgcSRIh2tAGIo36 6dS7NhHd5iXg+4fkP3YHdDPWeS3YJKbCyl1Wo4u4fpYyBtbZbz0F616s7FvdzRVUrg3zWpKAZs DC/OsAbTHabzZ2E9Xhzp8uWn7jgxUHz2pba5Y5+48Z1IUX53diqKpuiPxjcgrFAldNAMJmOBV4 iEjOwx505E/GSSF17rirM8uwJPmWjZ5oNjeTQMGWvulcp95D+bXlLocD/JMJkog2zY3aQpaC3F mj4= WDCIronportException: Internal From: Alistair Francis To: libc-alpha@sourceware.org Cc: alistair23@gmail.com, Alistair Francis Subject: [PATCH v2] sysdeps/wait: Use the waitid syscall if required Date: Fri, 25 Oct 2019 08:56:51 -0700 Message-Id: <20191025155651.27221-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. This change also removes the wait4 syscall from syscalls.list and replaces it with a __wait4() implementation. --- This was patch was runtime tested with RV32 and RV64 It was build tested using the ./scripts/build-many-glibcs.py script. include/sys/wait.h | 3 +- sysdeps/unix/sysv/linux/syscalls.list | 1 - sysdeps/unix/sysv/linux/wait.c | 41 +++++++++- sysdeps/unix/sysv/linux/wait4.c | 87 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/waitpid.c | 59 ++++++++++++++- sysdeps/unix/sysv/linux/waitpid_nocancel.c | 56 +++++++++++++- 6 files changed, 239 insertions(+), 8 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/wait4.c diff --git a/include/sys/wait.h b/include/sys/wait.h index 5ac9cd6ca6b..fab0e17f7d5 100644 --- a/include/sys/wait.h +++ b/include/sys/wait.h @@ -13,7 +13,6 @@ extern __pid_t __wait (int *__stat_loc); extern __pid_t __wait3 (int *__stat_loc, int __options, struct rusage * __usage); extern __pid_t __wait4 (__pid_t __pid, int *__stat_loc, - int __options, struct rusage *__usage) - attribute_hidden; + int __options, struct rusage *__usage); #endif #endif diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index e374f97b5f8..31f1d258fe1 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -69,7 +69,6 @@ swapoff - swapoff i:s __swapoff swapoff unshare EXTRA unshare i:i unshare uselib EXTRA uselib i:s __compat_uselib uselib@GLIBC_2.0:GLIBC_2.23 utime - utime i:sP utime -wait4 - wait4 i:iWiP __wait4 wait4 chown - chown i:sii __libc_chown __chown chown 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/wait4.c b/sysdeps/unix/sysv/linux/wait4.c new file mode 100644 index 00000000000..6d6fea34f9a --- /dev/null +++ b/sysdeps/unix/sysv/linux/wait4.c @@ -0,0 +1,87 @@ +/* Linux wait4 syscall implementation. + Copyright (C) 1991-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +__pid_t +__wait4 (__pid_t pid, int *stat_loc, int options, + struct rusage *usage) +{ +#ifdef __NR_wait4 + return INLINE_SYSCALL_CALL (wait4, pid, stat_loc, options, usage); +#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, usage); + + 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 (__wait4, wait4) 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)