Message ID | 20230325140815.4170296-1-xry111@xry111.site |
---|---|
Headers |
Return-Path: <libc-alpha-bounces+patchwork=sourceware.org@sourceware.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 62CB93858C50 for <patchwork@sourceware.org>; Sat, 25 Mar 2023 14:08:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 62CB93858C50 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679753338; bh=tT31TShGij3O2lJ8KDFtK6TcOW2qtEq0jk1GDtmK/vY=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=bhLRqAHQkq3CNwX/HvEhRSC76VGTMHWL9mp6+XTLtAVm9xqwsd+cu6BP5spZjXwPI J5ckpEFGUn7rTPSQ5i468Fu2hv+VM3whihWxS+1xHZusR90khoA90dlkw9lncO78uh cIbSr9pvPL+FsvzSoXDwmXg/WVm83JsAh07r5aEw= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from xry111.site (xry111.site [IPv6:2001:470:683e::1]) by sourceware.org (Postfix) with ESMTPS id 2454F3858D20 for <libc-alpha@sourceware.org>; Sat, 25 Mar 2023 14:08:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2454F3858D20 Received: from stargazer.. (unknown [IPv6:240e:358:1172:ca00:dc73:854d:832e:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (Client did not present a certificate) (Authenticated sender: xry111@xry111.site) by xry111.site (Postfix) with ESMTPSA id 5CC1666479; Sat, 25 Mar 2023 10:08:25 -0400 (EDT) To: libc-alpha@sourceware.org Cc: caiyinyu <caiyinyu@loongson.cn>, Wang Xuerui <i@xen0n.name>, Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>, Andreas Schwab <schwab@suse.de>, Florian Weimer <fw@deneb.enyo.de>, Xi Ruoyao <xry111@xry111.site> Subject: [PATCH v2 0/5] linux: Avoid va_list for generic syscall wrappers if possible Date: Sat, 25 Mar 2023 22:08:10 +0800 Message-Id: <20230325140815.4170296-1-xry111@xry111.site> X-Mailer: git-send-email 2.40.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, LIKELY_SPAM_FROM, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list <libc-alpha.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/libc-alpha>, <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/libc-alpha/> List-Post: <mailto:libc-alpha@sourceware.org> List-Help: <mailto:libc-alpha-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/libc-alpha>, <mailto:libc-alpha-request@sourceware.org?subject=subscribe> From: Xi Ruoyao via Libc-alpha <libc-alpha@sourceware.org> Reply-To: Xi Ruoyao <xry111@xry111.site> Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" <libc-alpha-bounces+patchwork=sourceware.org@sourceware.org> |
Series |
linux: Avoid va_list for generic syscall wrappers if possible
|
|
Message
Xi Ruoyao
March 25, 2023, 2:08 p.m. UTC
Currently GCC generates highly sub-optimal code on architectures where the calling convention prefers registers for arugment passing. This is GCC PR100955. While it's technically a missed-optimization in GCC, it seems not trivial to fix (I've not seen any compiler which can optimize this properly yet). As the generic Linux syscall wrappers often uses a fixed number of arguments, and "overreading" the variable arguments is usually safe (fcntl etc. is already doing this), we can pretend these wrappers were declared with named arguments and make the compiler do right thing. Add a macro __ASSUME_SYSCALL_NAMED_WORKS to control this, which should be defined if we can safely replace "..." with several named arguments. Use an internal function prototype with named arguments if it's defined, for fcntl64, fcntl_nocancel, ioctl, mremap, open64, open64_nocancel, openat64, openat64_nocancel, prctl, ptrace, and generic syscall() wrapper. I've not changed open* without "64" because I don't have a test platform. shm_ctl is also not changed because it contains aggregate variable arugment which is more tricky than integers or pointers. Define this macro for LoongArch, x86-64, and AArch64. This should be also suitable for some other architectures (I think it will be fine on RISC-V) but again I don't have a test platform. This is the first time I make such a large change in Glibc so it's likely I've done something wrong. Please correct me :). Xi Ruoyao (5): linux: Add __ASSUME_SYSCALL_NAMED_WORKS to allow avoiding va_list for generic syscall linux: [__ASSUME_SYSCALL_NAMED_WORKS] Avoid using va_list for various syscall wrappers LoongArch: Define __ASSUME_SYSCALL_NAMED_WORKS for Linux x86_64: Define __ASSUME_SYSCALL_NAMED_WORKS for Linux aarch64: Define __ASSUME_SYSCALL_NAMED_WORKS for Linux include/fcntl.h | 32 ++++++++----- .../unix/sysv/linux/aarch64/kernel-features.h | 9 ++++ sysdeps/unix/sysv/linux/fcntl64.c | 40 +++++++++++++---- sysdeps/unix/sysv/linux/fcntl_nocancel.c | 30 ++++++++++--- sysdeps/unix/sysv/linux/ioctl.c | 38 ++++++++++++---- .../sysv/linux/loongarch/kernel-features.h | 29 ++++++++++++ sysdeps/unix/sysv/linux/mremap.c | 36 +++++++++++++-- sysdeps/unix/sysv/linux/not-cancel.h | 8 ++-- sysdeps/unix/sysv/linux/open64.c | 35 ++++++++++++--- sysdeps/unix/sysv/linux/open64_nocancel.c | 29 ++++++++++-- sysdeps/unix/sysv/linux/openat64.c | 30 +++++++++++-- sysdeps/unix/sysv/linux/openat64_nocancel.c | 29 ++++++++++-- sysdeps/unix/sysv/linux/prctl.c | 23 +++++++++- sysdeps/unix/sysv/linux/ptrace.c | 45 ++++++++++++++----- sysdeps/unix/sysv/linux/syscall.c | 35 +++++++++++---- .../unix/sysv/linux/x86_64/kernel-features.h | 9 ++++ 16 files changed, 382 insertions(+), 75 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/loongarch/kernel-features.h
Comments
On 3/25/23 10:08, Xi Ruoyao via Libc-alpha wrote: > Currently GCC generates highly sub-optimal code on architectures where > the calling convention prefers registers for arugment passing. This is > GCC PR100955. While it's technically a missed-optimization in GCC, it > seems not trivial to fix (I've not seen any compiler which can optimize > this properly yet). I'm glad to see we have a gcc PR open for this. We should be working to improve the compiler instead of working around the issue in glibc. > As the generic Linux syscall wrappers often uses a fixed number of > arguments, and "overreading" the variable arguments is usually safe > (fcntl etc. is already doing this), we can pretend these wrappers were > declared with named arguments and make the compiler do right thing. > Add a macro __ASSUME_SYSCALL_NAMED_WORKS to control this, which should > be defined if we can safely replace "..." with several named arguments. > Use an internal function prototype with named arguments if it's defined, > for fcntl64, fcntl_nocancel, ioctl, mremap, open64, open64_nocancel, > openat64, openat64_nocancel, prctl, ptrace, and generic syscall() > wrapper. I've not changed open* without "64" because I don't have a > test platform. shm_ctl is also not changed because it contains > aggregate variable arugment which is more tricky than integers or > pointers. > Define this macro for LoongArch, x86-64, and AArch64. This should be > also suitable for some other architectures (I think it will be fine on > RISC-V) but again I don't have a test platform. > > This is the first time I make such a large change in Glibc so it's > likely I've done something wrong. Please correct me :). There are few things that I see are wrong, and I'll list them out here at the top-level: (1) Error prone macro usage. #ifdef foo /* Some Stuff. */ #else /* Other stuff. */ #endif (a) Always define foo, either 0 or 1. (b) Always use #if foo / #else (2) Public declarations must match internal declarations. The biggest problem I see here is that the public declaration of the functions you are changing are all variadic, and so my strong opinion is that we should not change the internal definition of these functions to be non-variadic. I expect there are going to be knock-on effects with developer tooling that expects the implementation not to over-read e.g. valgrind looking at reading of registers that have undefined values. --- In summary, I think this is a compiler problem, and that working around this in glibc is going to result in: - Odd corner case ABI issues between public declarations of variadic functions and internal non-variadic definitions. - Poorer testing of #else code that uses variadic arguments, as the public interface requires. I don't support going in this direction. Is there an alternative that could generate better code that doesn't go this way? > Xi Ruoyao (5): > linux: Add __ASSUME_SYSCALL_NAMED_WORKS to allow avoiding va_list for > generic syscall > linux: [__ASSUME_SYSCALL_NAMED_WORKS] Avoid using va_list for various > syscall wrappers > LoongArch: Define __ASSUME_SYSCALL_NAMED_WORKS for Linux > x86_64: Define __ASSUME_SYSCALL_NAMED_WORKS for Linux > aarch64: Define __ASSUME_SYSCALL_NAMED_WORKS for Linux > > include/fcntl.h | 32 ++++++++----- > .../unix/sysv/linux/aarch64/kernel-features.h | 9 ++++ > sysdeps/unix/sysv/linux/fcntl64.c | 40 +++++++++++++---- > sysdeps/unix/sysv/linux/fcntl_nocancel.c | 30 ++++++++++--- > sysdeps/unix/sysv/linux/ioctl.c | 38 ++++++++++++---- > .../sysv/linux/loongarch/kernel-features.h | 29 ++++++++++++ > sysdeps/unix/sysv/linux/mremap.c | 36 +++++++++++++-- > sysdeps/unix/sysv/linux/not-cancel.h | 8 ++-- > sysdeps/unix/sysv/linux/open64.c | 35 ++++++++++++--- > sysdeps/unix/sysv/linux/open64_nocancel.c | 29 ++++++++++-- > sysdeps/unix/sysv/linux/openat64.c | 30 +++++++++++-- > sysdeps/unix/sysv/linux/openat64_nocancel.c | 29 ++++++++++-- > sysdeps/unix/sysv/linux/prctl.c | 23 +++++++++- > sysdeps/unix/sysv/linux/ptrace.c | 45 ++++++++++++++----- > sysdeps/unix/sysv/linux/syscall.c | 35 +++++++++++---- > .../unix/sysv/linux/x86_64/kernel-features.h | 9 ++++ > 16 files changed, 382 insertions(+), 75 deletions(-) > create mode 100644 sysdeps/unix/sysv/linux/loongarch/kernel-features.h >
On Mon, 2023-03-27 at 10:04 -0400, Carlos O'Donell wrote: > In summary, I think this is a compiler problem Definitely true. > and that working around this in glibc > is going to result in: > > - Odd corner case ABI issues between public declarations of variadic functions and > internal non-variadic definitions. > > - Poorer testing of #else code that uses variadic arguments, as the public interface > requires. > > I don't support going in this direction. Valid reasons. Abandon this series then. But I hope these could be raised earlier (in the discussion about LoongArch syscall.S) so I wouldn't write all the code :). > Is there an alternative that could generate better code that doesn't go this way? For LoongArch I can improve GCC to save only the GARs containing the arguments really used in va_arg (i.e. one GAR for things like open() or fcntl() instead of all 8 GARs), but I guess the patch will be delayed into GCC 14. Generally I've not got an idea about how to make GCC avoid saving GARs unnecessarily with va_arg.
On Mon, 2023-03-27 at 10:04 -0400, Carlos O'Donell wrote: > In summary, I think this is a compiler problem Definitely true. > and that working around this in glibc > is going to result in: > > - Odd corner case ABI issues between public declarations of variadic > functions and > internal non-variadic definitions. > > - Poorer testing of #else code that uses variadic arguments, as the > public interface > requires. > > I don't support going in this direction. Valid reasons. Abandon this series then. But I hope these could be raised earlier (in the discussion about LoongArch syscall.S) so I wouldn't write all the code :). > Is there an alternative that could generate better code that doesn't > go this way? For LoongArch I can improve GCC to save only the GARs containing the arguments really used in va_arg (i.e. one GAR for things like open() or fcntl() instead of all 8 GARs), but I guess the patch will be delayed into GCC 14. Generally I've not got an idea about how to make GCC avoid saving GARs unnecessarily with va_arg.
Sorry, mail duplicated because of some network issue. On Mon, 2023-03-27 at 22:45 +0800, Xi Ruoyao wrote: > On Mon, 2023-03-27 at 10:04 -0400, Carlos O'Donell wrote: > > > In summary, I think this is a compiler problem > > Definitely true. /* snip */
在 2023/3/27 下午10:45, Xi Ruoyao 写道: > On Mon, 2023-03-27 at 10:04 -0400, Carlos O'Donell wrote: > >> In summary, I think this is a compiler problem > Definitely true. > >> and that working around this in glibc >> is going to result in: >> >> - Odd corner case ABI issues between public declarations of variadic >> functions and >> internal non-variadic definitions. >> >> - Poorer testing of #else code that uses variadic arguments, as the >> public interface >> requires. >> >> I don't support going in this direction. > Valid reasons. Abandon this series then. > > But I hope these could be raised earlier (in the discussion about > LoongArch syscall.S) so I wouldn't write all the code :). > >> Is there an alternative that could generate better code that doesn't >> go this way? > For LoongArch I can improve GCC to save only the GARs containing the > arguments really used in va_arg (i.e. one GAR for things like open() or > fcntl() instead of all 8 GARs), but I guess the patch will be delayed > into GCC 14. > > Generally I've not got an idea about how to make GCC avoid saving GARs > unnecessarily with va_arg. So I believe that the assembly implementation of syscalls is still necessary, especially for users who are using GCC<=13. patch: https://sourceware.org/pipermail/libc-alpha/2023-March/146588.html >
On Tue, 2023-04-04 at 09:25 +0800, caiyinyu wrote: > > 在 2023/3/27 下午10:45, Xi Ruoyao 写道: > > On Mon, 2023-03-27 at 10:04 -0400, Carlos O'Donell wrote: > > > > > In summary, I think this is a compiler problem > > Definitely true. > > > > > and that working around this in glibc > > > is going to result in: > > > > > > - Odd corner case ABI issues between public declarations of variadic > > > functions and > > > internal non-variadic definitions. > > > > > > - Poorer testing of #else code that uses variadic arguments, as the > > > public interface > > > requires. > > > > > > I don't support going in this direction. > > Valid reasons. Abandon this series then. > > > > But I hope these could be raised earlier (in the discussion about > > LoongArch syscall.S) so I wouldn't write all the code :). > > > > > Is there an alternative that could generate better code that doesn't > > > go this way? > > For LoongArch I can improve GCC to save only the GARs containing the > > arguments really used in va_arg (i.e. one GAR for things like open() or > > fcntl() instead of all 8 GARs), but I guess the patch will be delayed > > into GCC 14. > > > > Generally I've not got an idea about how to make GCC avoid saving GARs > > unnecessarily with va_arg. > > So I believe that the assembly implementation of syscalls is still > necessary, especially for users who are using GCC<=13. Maybe we can use a custom C implementation (like RISC-V) as well. But strictly speaking the RISC-V syscall.c is invoking undefined behavior (like my proposal) so I agree with assembly here. > patch: > > https://sourceware.org/pipermail/libc-alpha/2023-March/146588.html >