diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2021-06-15 15:41:00 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2021-06-22 12:09:52 -0300 |
commit | ecf2661281c71a9752c7238ab93bc12b16cfff23 (patch) | |
tree | 4adb5c607a25b04e7e3aff43e1eba5f26823140f | |
parent | 92f7b465101c23e45f66c6ad25ba243df49556a0 (diff) | |
download | glibc-ecf2661281c71a9752c7238ab93bc12b16cfff23.tar glibc-ecf2661281c71a9752c7238ab93bc12b16cfff23.tar.gz glibc-ecf2661281c71a9752c7238ab93bc12b16cfff23.tar.bz2 glibc-ecf2661281c71a9752c7238ab93bc12b16cfff23.zip |
linux: Only use 64-bit syscall if required for ppoll
For !__ASSUME_TIME64_SYSCALLS there is no need to issue a 64-bit syscall
if the provided timeout fits in a 32-bit one. The 64-bit usage should
be rare since the timeout is a relative one. This also avoids the need
to use supports_time64() (which breaks the usage case of live migration
like CRIU or similar).
Checked on i686-linux-gnu on a 4.15 kernel and on a 5.11 kernel
(with and without --enable-kernel=5.1) and on x86_64-linux-gnu.
Reviewed-by: Lukasz Majewski <lukma@denx.de>
-rw-r--r-- | sysdeps/unix/sysv/linux/Makefile | 9 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ppoll.c | 40 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/tst-ppoll.c | 15 |
3 files changed, 39 insertions, 25 deletions
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 294c366e3b..c36ea0e494 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -137,6 +137,15 @@ tests-time64 += \ CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables +ifeq (yes,$(build-shared)) +librt = $(common-objpfx)rt/librt.so +else +librt = $(common-objpfx)rt/librt.a +endif + +$(objpfx)tst-ppoll: $(librt) +$(objpfx)tst-ppoll-time64: $(librt) + # Generate the list of SYS_* macros for the system calls (__NR_* # macros). The file syscall-names.list contains all possible system # call names, and the generated header file produces SYS_* macros for diff --git a/sysdeps/unix/sysv/linux/ppoll.c b/sysdeps/unix/sysv/linux/ppoll.c index 624f14f517..8ca133b1fa 100644 --- a/sysdeps/unix/sysv/linux/ppoll.c +++ b/sysdeps/unix/sysv/linux/ppoll.c @@ -21,9 +21,6 @@ #include <time.h> #include <sys/poll.h> #include <sysdep-cancel.h> -#include <kernel-features.h> -#include <time64-support.h> - int __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout, @@ -38,40 +35,33 @@ __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout, timeout = &tval; } - int ret; - - if (supports_time64 ()) - { #ifndef __NR_ppoll_time64 # define __NR_ppoll_time64 __NR_ppoll #endif + +#ifdef __ASSUME_TIME64_SYSCALLS + return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask, + __NSIG_BYTES); +#else + int ret; + bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec); + if (need_time64) + { ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask, __NSIG_BYTES); - if (ret == 0 || errno != ENOSYS) return ret; - - mark_time64_unsupported (); + __set_errno (EOVERFLOW); + return -1; } -#ifndef __ASSUME_TIME64_SYSCALLS struct timespec ts32; - if (timeout) - { - if (! in_time_t_range (timeout->tv_sec)) - { - __set_errno (EOVERFLOW); - return -1; - } - - ts32 = valid_timespec64_to_timespec (*timeout); - } + if (timeout != NULL) + ts32 = valid_timespec64_to_timespec (*timeout); - ret = SYSCALL_CANCEL (ppoll, fds, nfds, timeout ? &ts32 : NULL, sigmask, - __NSIG_BYTES); + return SYSCALL_CANCEL (ppoll, fds, nfds, timeout ? &ts32 : NULL, sigmask, + __NSIG_BYTES); #endif - - return ret; } #if __TIMESIZE != 64 diff --git a/sysdeps/unix/sysv/linux/tst-ppoll.c b/sysdeps/unix/sysv/linux/tst-ppoll.c index 9fe6ad07ce..e21e2fcc72 100644 --- a/sysdeps/unix/sysv/linux/tst-ppoll.c +++ b/sysdeps/unix/sysv/linux/tst-ppoll.c @@ -19,9 +19,11 @@ #include <time.h> #include <poll.h> #include <errno.h> +#include <intprops.h> #include <support/check.h> #include <support/xtime.h> #include <support/timespec.h> +#include <support/support.h> #include <stdbool.h> static int test_ppoll_timeout (bool zero_tmo) @@ -41,6 +43,16 @@ static int test_ppoll_timeout (bool zero_tmo) return 0; } +static void +test_ppoll_large_timeout (void) +{ + support_create_timer (0, 100000000, false, NULL); + struct timespec ts = { TYPE_MAXIMUM (time_t), 0 }; + struct pollfd fds = { -1, 0, 0 }; + TEST_COMPARE (ppoll (&fds, 1, &ts, 0), -1); + TEST_VERIFY (errno == EINTR || errno == EOVERFLOW); +} + static int do_test (void) { @@ -50,6 +62,9 @@ do_test (void) /* Check if ppoll exits after specified timeout. */ test_ppoll_timeout (false); + /* Check if ppoll with large timeout. */ + test_ppoll_large_timeout (); + return 0; } |