libstdc++: Revert changes for SYS_clock_gettime64 [PR 93421]
authorJonathan Wakely <jwakely@redhat.com>
Tue, 17 Nov 2020 16:13:02 +0000 (16:13 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Tue, 17 Nov 2020 22:38:49 +0000 (22:38 +0000)
As discussed in the PR, it's incredibly unlikely that a system that
needs to use the SYS_clock_gettime syscall (e.g. glibc 2.16 or older) is
going to define the SYS_clock_gettime64 macro. Ancient systems that need
to use the syscall aren't going to have time64 support.

This reverts the recent changes to try and make clock_gettime syscalls
be compatible with systems that have been updated for time64 (those
changes were wrong anyway as they misspelled the SYS_clock_gettime64
macro). The changes for futex syscalls are retained, because we still
use them on modern systems that might be using time64.

To ensure that the clock_gettime syscalls are safe, configure will fail
if SYS_clock_gettime is needed, and SYS_clock_gettime64 is also defined
(but to a distinct value from SYS_clock_gettime), and the tv_sec member
of timespec is larger than long. This means we will be unable to build
on a hypothetical system where we need the time32 version of
SYS_clock_gettime but where userspace is using a time64 struct timespec.
In the unlikely event that this failure is triggered on any real
systems, we can fix it later. But we probably won't need to.

libstdc++-v3/ChangeLog:

PR libstdc++/93421
* acinclude.m4 (GLIBCXX_ENABLE_LIBSTDCXX_TIME): Fail if struct
timespec isn't compatible with SYS_clock_gettime.
* configure: Regenerate.
* src/c++11/chrono.cc: Revert changes for time64 compatibility.
Add static_assert instead.
* src/c++11/futex.cc (_M_futex_wait_until_steady): Assume
SYS_clock_gettime can use struct timespec.

libstdc++-v3/acinclude.m4
libstdc++-v3/configure
libstdc++-v3/src/c++11/chrono.cc
libstdc++-v3/src/c++11/futex.cc

index 650d63ab3d75a3aa2b9dfaf696da40a83a47a6e3..486347b34d9469b4fb085e0a74e66e1d34ed1713 100644 (file)
@@ -1561,13 +1561,34 @@ AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_TIME], [
           #endif
           syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &tp);
           syscall(SYS_clock_gettime, CLOCK_REALTIME, &tp);
-         ], [ac_has_clock_monotonic_syscall=yes], [ac_has_clock_monotonic_syscall=no])
-       AC_MSG_RESULT($ac_has_clock_monotonic_syscall)
-       if test x"$ac_has_clock_monotonic_syscall" = x"yes"; then
+         ], [ac_has_clock_gettime_syscall=yes], [ac_has_clock_gettime_syscall=no])
+       AC_MSG_RESULT($ac_has_clock_gettime_syscall)
+       if test x"$ac_has_clock_gettime_syscall" = x"yes"; then
          AC_DEFINE(_GLIBCXX_USE_CLOCK_GETTIME_SYSCALL, 1,
-         [ Defined if clock_gettime syscall has monotonic and realtime clock support. ])
+         [Defined if clock_gettime syscall has monotonic and realtime clock support. ])
          ac_has_clock_monotonic=yes
          ac_has_clock_realtime=yes
+         AC_MSG_CHECKING([for struct timespec that matches syscall])
+         AC_TRY_COMPILE(
+           [#include <time.h>
+            #include <sys/syscall.h>
+           ],
+           [#ifdef SYS_clock_gettime64
+            #if SYS_clock_gettime64 != SYS_clock_gettime
+            // We need to use SYS_clock_gettime and libc appears to
+            // also know about the SYS_clock_gettime64 syscall.
+            // Check that userspace doesn't use time64 version of timespec.
+            static_assert(sizeof(timespec::tv_sec) == sizeof(long),
+              "struct timespec must be compatible with SYS_clock_gettime");
+            #endif
+            #endif
+           ],
+           [ac_timespec_matches_syscall=yes],
+           [ac_timespec_matches_syscall=no])
+         AC_MSG_RESULT($ac_timespec_matches_syscall)
+         if test x"$ac_timespec_matches_syscall" = no; then
+           AC_MSG_ERROR([struct timespec is not compatible with SYS_clock_gettime, please report a bug to http://gcc.gnu.org/bugzilla])
+         fi
        fi;;
     esac
   fi
index 1997c1fce4a913b8d37283b5585673d291d46120..d9ed414cc773bcc5fe3806f545c489948ae0e3a8 100755 (executable)
@@ -21661,19 +21661,54 @@ main ()
 }
 _ACEOF
 if ac_fn_cxx_try_compile "$LINENO"; then :
-  ac_has_clock_monotonic_syscall=yes
+  ac_has_clock_gettime_syscall=yes
 else
-  ac_has_clock_monotonic_syscall=no
+  ac_has_clock_gettime_syscall=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_has_clock_monotonic_syscall" >&5
-$as_echo "$ac_has_clock_monotonic_syscall" >&6; }
-       if test x"$ac_has_clock_monotonic_syscall" = x"yes"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_has_clock_gettime_syscall" >&5
+$as_echo "$ac_has_clock_gettime_syscall" >&6; }
+       if test x"$ac_has_clock_gettime_syscall" = x"yes"; then
 
 $as_echo "#define _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL 1" >>confdefs.h
 
          ac_has_clock_monotonic=yes
          ac_has_clock_realtime=yes
+         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct timespec that matches syscall" >&5
+$as_echo_n "checking for struct timespec that matches syscall... " >&6; }
+         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <time.h>
+            #include <sys/syscall.h>
+
+int
+main ()
+{
+#ifdef SYS_clock_gettime64
+            #if SYS_clock_gettime64 != SYS_clock_gettime
+            // We need to use SYS_clock_gettime and libc appears to
+            // also know about the SYS_clock_gettime64 syscall.
+            // Check that userspace doesn't use time64 version of timespec.
+            static_assert(sizeof(timespec::tv_sec) == sizeof(long),
+              "struct timespec must be compatible with SYS_clock_gettime");
+            #endif
+            #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_timespec_matches_syscall=yes
+else
+  ac_timespec_matches_syscall=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+         { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_timespec_matches_syscall" >&5
+$as_echo "$ac_timespec_matches_syscall" >&6; }
+         if test x"$ac_timespec_matches_syscall" = no; then
+           as_fn_error $? "struct timespec is not compatible with SYS_clock_gettime, please report a bug to http://gcc.gnu.org/bugzilla" "$LINENO" 5
+         fi
        fi;;
     esac
   fi
index f10be7d8c073b21b062242c421dc34fee3c4a96b..723f3002d11a138d14df42b3d43e9007ece7f1fd 100644 (file)
 #ifdef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL
 #include <unistd.h>
 #include <sys/syscall.h>
-
-# if defined(SYS_clock_gettime_time64) \
-  && SYS_clock_gettime_time64 != SYS_clock_gettime
-  // Userspace knows about the new time64 syscalls, so it's possible that
-  // userspace has also updated timespec to use a 64-bit tv_sec.
-  // The SYS_clock_gettime syscall still uses the old definition
-  // of timespec where tv_sec is 32 bits, so define a type that matches that.
-  struct syscall_timespec { long tv_sec; long tv_nsec; };
-# else
-  using syscall_timespec = ::timespec;
-# endif
 #endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -63,12 +52,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     system_clock::now() noexcept
     {
 #ifdef _GLIBCXX_USE_CLOCK_REALTIME
+      timespec tp;
       // -EINVAL, -EFAULT
 #ifdef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL
-      syscall_timespec tp;
       syscall(SYS_clock_gettime, CLOCK_REALTIME, &tp);
 #else
-      timespec tp;
       clock_gettime(CLOCK_REALTIME, &tp);
 #endif
       return time_point(duration(chrono::seconds(tp.tv_sec)
@@ -92,12 +80,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     steady_clock::now() noexcept
     {
 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
+      timespec tp;
       // -EINVAL, -EFAULT
 #ifdef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL
-      syscall_timespec tp;
       syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &tp);
 #else
-      timespec tp;
       clock_gettime(CLOCK_MONOTONIC, &tp);
 #endif
       return time_point(duration(chrono::seconds(tp.tv_sec)
index 9adfb898b4f1adf883b1c3b0addf0944e245ba9d..33e2097e19cfa38863e773f08eb1e8c2904faf17 100644 (file)
@@ -61,8 +61,8 @@ namespace
 #if defined(SYS_futex_time64) && SYS_futex_time64 != SYS_futex
   // Userspace knows about the new time64 syscalls, so it's possible that
   // userspace has also updated timespec to use a 64-bit tv_sec.
-  // The SYS_futex and SYS_clock_gettime syscalls still use the old definition
-  // of timespec where tv_sec is 32 bits, so define a type that matches that.
+  // The SYS_futex syscall still uses the old definition of timespec
+  // where tv_sec is 32 bits, so define a type that matches that.
   struct syscall_timespec { long tv_sec; long tv_nsec; };
 #else
   using syscall_timespec = ::timespec;
@@ -234,11 +234,10 @@ namespace
 
        // We only get to here if futex_clock_monotonic_unavailable was
        // true or has just been set to true.
+       struct timespec ts;
 #ifdef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL
-       syscall_timespec ts;
        syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts);
 #else
-       struct timespec ts;
        clock_gettime(CLOCK_MONOTONIC, &ts);
 #endif