From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS31976 209.132.180.0/23 X-Spam-Status: No, score=-3.9 required=3.0 tests=AWL,BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,SPF_HELO_PASS,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 0D5521F4B5 for ; Wed, 13 Nov 2019 21:00:41 +0000 (UTC) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:references:from:subject:message-id:date :mime-version:in-reply-to:content-type :content-transfer-encoding; q=dns; s=default; b=u/MeH5gjqw0mIou5 1Vyc2fX6OZU0Y9bS8FAbeG+1g7VubKctktHSmzevV1jicdFgI4TFeO9Mu2NZn24R LZbrDQviyR7EpPEnsrX9OpABcxdlf6f/7Lq+Mh4N7Hj+JOw56YQ7ide+eGNyWHpw 6DT6WoC1T7Vi64TN5WzCKGM98cI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:references:from:subject:message-id:date :mime-version:in-reply-to:content-type :content-transfer-encoding; s=default; bh=ZiABHE1gdPanFc3HpYyfkx PHgfo=; b=t3MhVve9l/1TeqHUwjyJFsovbP0dz2p+EgxqpA4KcuiKK+4wCu11Uu 723N/AT23A8HzMfc+gdkHK+5l5xMgQeuW6JVHbrJs4VCBBkcSr13VAI8tFydLGIi skR8qKClLDjOJoi6K0NzkOeAPXD3ABbiuM+jeyPwtEK+po4a2ICaE= Received: (qmail 57943 invoked by alias); 13 Nov 2019 21:00:38 -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 Received: (qmail 57929 invoked by uid 89); 13 Nov 2019 21:00:37 -0000 Authentication-Results: sourceware.org; auth=none X-HELO: mail-qk1-f195.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=to:references:from:openpgp:autocrypt:subject:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=rDtKhLfm/h9MRV5IZrcNht2LVOpkidROeoWHYNIimL4=; b=xl4ObjG2KpvwI5xx5AFxt0KC4ZB03Vc32zzthI3SWwpKOmhhKk374wcp8+WuEtZCfI 5RgjMJ+r9/T/xaxEpwND0G5LVB6FzlnUnE+LFX50gcCD1DSugw3WibHekwyzDkvQroFE ZdtduIEAoVFBry1gmJm7+7EMxW5MDPvwketYW9FY3n5Y3qYf1xjdtNjTyDr7v03knyNN g9MpD0S571vWax0l+lR5cF95aPSa9r7l5LtPru+O25TahCcpz9Hmvpy+3oPU7CJ3w417 9R7BL3jid+H6j/kGc8jcVsdO1GXZ/iuoybE9fX3sPFhx1vAMxH7U1tij+wWxYyK9E06z Kstw== To: libc-alpha@sourceware.org References: <20191025155651.27221-1-alistair.francis@wdc.com> From: Adhemerval Zanella Openpgp: preference=signencrypt Subject: Re: [PATCH v2] sysdeps/wait: Use the waitid syscall if required Message-ID: <208ded89-d884-9d78-5a09-8e58bec5800c@linaro.org> Date: Wed, 13 Nov 2019 18:00:29 -0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 MIME-Version: 1.0 In-Reply-To: <20191025155651.27221-1-alistair.francis@wdc.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit On 25/10/2019 12:56, Alistair Francis wrote: > 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 is worrisome, since waitid won't work with the expected semantic on architectures that do not provide waitpid/wait4 neither allows refactor waitpid in terms or waitid for all architectures. For latter we can live with it, since the idea is to first try for __NR_waitpid/__NR_wait4. However, the P_PGID issue would require that take care the new architectures that uses the waitid to implement waitpid to have a minimum supported kernel or 5.4+. Maybe should we enforce a __LINUX_KERNEL_VERSION check when __NR_waitid is used? > > This change also removes the wait4 syscall from syscalls.list and > replaces it with a __wait4() implementation. This duplicates a lot of code, where we could instead consolidate some implementations and just adapt wait4 instead. I think it would be better to: 1. Remove __waitpid_nocancel and just call pthread_setcancelstate to enable and disable cancellation while calling __waitpid (through __libc_ptf_call macros). 2. Move both wait and waitpid to libc, there is no need to add some internal symbol to implement wait in terms of waitpid. 3. Implement wait in terms of waitpid. 4. Add a C implementation for wait4 and add support to use waitid if __NR_wait4 is not supported. 4. Finally implement waitid by calling an internal __wait4 symbol. I have adapted these suggestion along with you patch to use waitid to implement wait4. I am testing on some platforms before sending, however I would like to check with other developers how should we proceed with waitid/P_PGID support on kernel older than 5.4. [1] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/wait-refactor > --- > 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) >