Message ID | 20230324072745.4138-1-xry111@xry111.site |
---|---|
State | New |
Headers | show |
Series | linux: Allow avoiding va_list for generic syscall and use it for LoongArch | expand |
* Xi Ruoyao via Libc-alpha: > Currently GCC generates highly sub-optimal code on architectures where > the calling convention prefers registers for arugment passing. This is Typo: ar[gu]ment > LoongArch is benefited from this (saving about 430 CPU cycles per > syscall, though I won't call it a significant improvement because > syscall is "slow" in nature). And in the future we may switch more > ports to use the generic syscall without a performance regression, > reducing the number of target-specific syscall.{c,S} files we need to > maintain. Does this impact the open* and fcntl* wrappers as well?
On Fri, 2023-03-24 at 10:47 +0100, Florian Weimer wrote: > * Xi Ruoyao via Libc-alpha: > > > Currently GCC generates highly sub-optimal code on architectures > > where > > the calling convention prefers registers for arugment passing. This > > is > > Typo: ar[gu]ment > > > LoongArch is benefited from this (saving about 430 CPU cycles per > > syscall, though I won't call it a significant improvement because > > syscall is "slow" in nature). And in the future we may switch more > > ports to use the generic syscall without a performance regression, > > reducing the number of target-specific syscall.{c,S} files we need > > to > > maintain. > > Does this impact the open* and fcntl* wrappers as well? Yes, on LoongArch all GARs are saved :(. I'll see if it's possible to avoid using va_list for them too.
* Xi Ruoyao: > On Fri, 2023-03-24 at 10:47 +0100, Florian Weimer wrote: >> * Xi Ruoyao via Libc-alpha: >> >> > Currently GCC generates highly sub-optimal code on architectures >> > where >> > the calling convention prefers registers for arugment passing. This >> > is >> >> Typo: ar[gu]ment >> >> > LoongArch is benefited from this (saving about 430 CPU cycles per >> > syscall, though I won't call it a significant improvement because >> > syscall is "slow" in nature). And in the future we may switch more >> > ports to use the generic syscall without a performance regression, >> > reducing the number of target-specific syscall.{c,S} files we need >> > to >> > maintain. >> >> Does this impact the open* and fcntl* wrappers as well? > > Yes, on LoongArch all GARs are saved :(. I'll see if it's possible to > avoid using va_list for them too. If we had overread the argument list in open*, that certainly would have avoided all the grief we had with O_TMPFILE (where the original glibc implementation did not pass the mode argument to the kernel). I think fcntl* already overreads the argument list, so it should be safe.
diff --git a/sysdeps/unix/sysv/linux/loongarch/kernel-features.h b/sysdeps/unix/sysv/linux/loongarch/kernel-features.h new file mode 100644 index 0000000000..4a1c115831 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/kernel-features.h @@ -0,0 +1,25 @@ +/* Set flags signalling availability of kernel features based on given + kernel version number. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#include_next <kernel-features.h> + +/* Define this if the calling convention for passing 7 named arguments is + same as passing one named argument and 6 variable arguments, and the + kernel ABI uses registers for syscall number and arguments. */ +#define __ASSUME_SYSCALL_NAMED_WORKS 1 diff --git a/sysdeps/unix/sysv/linux/syscall.c b/sysdeps/unix/sysv/linux/syscall.c index a5a2843b73..ed5ad5afd5 100644 --- a/sysdeps/unix/sysv/linux/syscall.c +++ b/sysdeps/unix/sysv/linux/syscall.c @@ -16,9 +16,33 @@ License along with the GNU C Library. If not, see <https://www.gnu.org/licenses/>. */ -#include <stdarg.h> #include <sysdep.h> +#ifndef __ASSUME_SYSCALL_NAMED_WORKS +#include <stdarg.h> +#endif + +static inline long int +__syscall (long int number, long int a0, long int a1, long int a2, long int a3, + long int a4, long int a5) +{ + long int r = INTERNAL_SYSCALL_NCS_CALL (number, a0, a1, a2, a3, a4, a5); + if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (r))) + { + __set_errno (-r); + return -1; + } + return r; +} + +#ifdef __ASSUME_SYSCALL_NAMED_WORKS +long int +syscall (long int number, long int a0, long int a1, long int a2, long int a3, + long int a4, long int a5) +{ + return __syscall (number, a0, a1, a2, a3, a4, a5); +} +#else long int syscall (long int number, ...) { @@ -33,11 +57,6 @@ syscall (long int number, ...) long int a5 = va_arg (args, long int); va_end (args); - long int r = INTERNAL_SYSCALL_NCS_CALL (number, a0, a1, a2, a3, a4, a5); - if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (r))) - { - __set_errno (-r); - return -1; - } - return r; + return __syscall (number, a0, a1, a2, a3, a4, a5); } +#endif