This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[glibc] y2038: linux: Provide __ppoll64 implementation


https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=258c242128a35e7fc17aff34c9dc23cd7576e88f

commit 258c242128a35e7fc17aff34c9dc23cd7576e88f
Author: Lukasz Majewski <lukma@denx.de>
Date:   Tue Oct 29 15:08:00 2019 +0100

    y2038: linux: Provide __ppoll64 implementation
    
    This patch provides new __ppoll64 explicit 64 bit function for handling polling
    events (with struct timespec specified timeout) for a set of file descriptors.
    Moreover, a 32 bit version - __ppoll has been refactored to internally use
    __ppoll64.
    
    The __ppoll is now supposed to be used on systems still supporting 32 bit time
    (__TIMESIZE != 64) - hence the necessary conversion to 64 bit struct
    __timespec64.
    
    The new ppoll_time64 syscall available from Linux 5.1+ has been used, when
    applicable.
    
    The Linux kernel checks if passed tv_nsec value overflows, so there is no need
    to repeat it in the glibc.
    
    When ppoll syscall on systems supporting 32 bit time ABI is used, the check is
    performed if passed data (which may have 64 bit tv_sec) fits into 32 bit range.
    
    Build tests:
    - The code has been tested on x86_64/x86 (native compilation):
    make PARALLELMFLAGS="-j8" && make check PARALLELMFLAGS="-j8" && \\
    make xcheck PARALLELMFLAGS="-j8"
    
    - The glibc has been build tested (make PARALLELMFLAGS="-j8") for
    x86 (i386), x86_64-x32, and armv7
    
    Run-time tests:
    - Run specific tests on ARM/x86 32bit systems (qemu):
      https://github.com/lmajewski/meta-y2038 and run tests:
      https://github.com/lmajewski/y2038-tests/commits/master
    
    - Use of cross-test-ssh.sh for ARM (armv7):
      make PARALLELMFLAGS="-j8" test-wrapper='./cross-test-ssh.sh root@192.168.7.2' xcheck
    
    Linux kernel, headers and minimal kernel version for glibc build test
    matrix:
    - Linux v5.1 (with ppoll_time64) and glibc build with v5.1 as
      minimal kernel version (--enable-kernel="5.1.0")
      The __ASSUME_TIME64_SYSCALLS flag defined.
    
    - Linux v5.1 and default minimal kernel version
      The __ASSUME_TIME64_SYSCALLS not defined, but kernel supports ppoll_time64
      syscall.
    
    - Linux v4.19 (no ppoll_time64 support) with default minimal kernel version for
      contemporary glibc
      This kernel doesn't support ppoll_time64 syscall, so the fallback to ppoll is
      tested.
    
    Above tests were performed with Y2038 redirection applied as well as without
    (so the __TIMESIZE != 64 execution path is checked as well).
    
    No regressions were observed.

Diff:
---
 include/sys/poll.h              | 13 ++++++++++-
 sysdeps/unix/sysv/linux/ppoll.c | 49 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/include/sys/poll.h b/include/sys/poll.h
index a42bc93..f904e21 100644
--- a/include/sys/poll.h
+++ b/include/sys/poll.h
@@ -6,6 +6,17 @@ extern int __poll (struct pollfd *__fds, unsigned long int __nfds,
 		   int __timeout);
 libc_hidden_proto (__poll)
 libc_hidden_proto (ppoll)
-#endif
 
+# if __TIMESIZE == 64
+#  define __ppoll64 __ppoll
+# else
+# include <time.h>
+# include <signal.h>
+
+extern int __ppoll64 (struct pollfd *fds, nfds_t nfds,
+                      const struct __timespec64 *timeout,
+                      const sigset_t *sigmask);
+libc_hidden_proto (__ppoll64)
+# endif
+#endif
 #endif
diff --git a/sysdeps/unix/sysv/linux/ppoll.c b/sysdeps/unix/sysv/linux/ppoll.c
index 8a6ccd1..beafeb3 100644
--- a/sysdeps/unix/sysv/linux/ppoll.c
+++ b/sysdeps/unix/sysv/linux/ppoll.c
@@ -21,21 +21,62 @@
 #include <time.h>
 #include <sys/poll.h>
 #include <sysdep-cancel.h>
+#include <kernel-features.h>
 
 
 int
-ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
-       const sigset_t *sigmask)
+__ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout,
+           const sigset_t *sigmask)
 {
   /* The Linux kernel can in some situations update the timeout value.
      We do not want that so use a local variable.  */
-  struct timespec tval;
+  struct __timespec64 tval;
   if (timeout != NULL)
     {
       tval = *timeout;
       timeout = &tval;
     }
 
-  return SYSCALL_CANCEL (ppoll, fds, nfds, timeout, sigmask, _NSIG / 8);
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_ppoll_time64
+#  define __NR_ppoll_time64 __NR_ppoll
+# endif
+  return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask, _NSIG / 8);
+#else
+# ifdef __NR_ppoll_time64
+  int ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
+                            _NSIG / 8);
+  if (ret >= 0 || errno != ENOSYS)
+    return ret;
+# endif
+  struct timespec ts32;
+  if (timeout)
+    {
+      if (! in_time_t_range (timeout->tv_sec))
+        {
+          __set_errno (EOVERFLOW);
+          return -1;
+        }
+
+      ts32 = valid_timespec64_to_timespec (*timeout);
+    }
+
+  return SYSCALL_CANCEL (ppoll, fds, nfds, timeout ? &ts32 : NULL, sigmask,
+                         _NSIG / 8);
+#endif
+}
+
+#if __TIMESIZE != 64
+int
+__ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
+         const sigset_t *sigmask)
+{
+  struct __timespec64 ts64;
+  if (timeout)
+    ts64 = valid_timespec_to_timespec64 (*timeout);
+
+  return __ppoll64 (fds, nfds, timeout ? &ts64 : NULL, sigmask);
 }
+#endif
+strong_alias (__ppoll, ppoll)
 libc_hidden_def (ppoll)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]