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.
This commit is contained in:
Jonathan Wakely 2020-11-17 16:13:02 +00:00
parent 61ef34c503
commit 1e3e6c700f
4 changed files with 70 additions and 28 deletions

View 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

View File

@ -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

View File

@ -35,17 +35,6 @@
#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)

View 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