From 1e3e6c700f04fe6992b9077541e434172c1cbdae Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 17 Nov 2020 16:13:02 +0000 Subject: [PATCH] libstdc++: Revert changes for SYS_clock_gettime64 [PR 93421] 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 | 29 +++++++++++++++++--- libstdc++-v3/configure | 45 ++++++++++++++++++++++++++++---- libstdc++-v3/src/c++11/chrono.cc | 17 ++---------- libstdc++-v3/src/c++11/futex.cc | 7 +++-- 4 files changed, 70 insertions(+), 28 deletions(-) diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 650d63ab3d7..486347b34d9 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -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 + #include + ], + [#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 diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 1997c1fce4a..d9ed414cc77 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -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 + #include + +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 diff --git a/libstdc++-v3/src/c++11/chrono.cc b/libstdc++-v3/src/c++11/chrono.cc index f10be7d8c07..723f3002d11 100644 --- a/libstdc++-v3/src/c++11/chrono.cc +++ b/libstdc++-v3/src/c++11/chrono.cc @@ -35,17 +35,6 @@ #ifdef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL #include #include - -# 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) diff --git a/libstdc++-v3/src/c++11/futex.cc b/libstdc++-v3/src/c++11/futex.cc index 9adfb898b4f..33e2097e19c 100644 --- a/libstdc++-v3/src/c++11/futex.cc +++ b/libstdc++-v3/src/c++11/futex.cc @@ -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 -- 2.30.2