[Chrono][Darwin] Make steady_clock use CLOCK_UPTIME_RAW

Use CLOCK_UPTIME_RAW in case clock_gettime is available on Darwin.

On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able
to time functions in the nanosecond range. Thus, they are the only
acceptable implementations of steady_clock.

Differential Revision: https://reviews.llvm.org/D27429

rdar://problem/29449467

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@291466 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bruno Cardoso Lopes
2017-01-09 19:21:48 +00:00
parent 7d32d2f5a1
commit ac7fc6cf28

View File

@@ -12,6 +12,28 @@
#include "system_error" // __throw_system_error #include "system_error" // __throw_system_error
#include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME #include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME
#if (__APPLE__)
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200
#define _LIBCXX_USE_CLOCK_GETTIME
#endif
#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__)
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 100000
#define _LIBCXX_USE_CLOCK_GETTIME
#endif
#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__)
#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 100000
#define _LIBCXX_USE_CLOCK_GETTIME
#endif
#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__)
#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 30000
#define _LIBCXX_USE_CLOCK_GETTIME
#endif
#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__
#else
#define _LIBCXX_USE_CLOCK_GETTIME
#endif // __APPLE__
#if defined(_LIBCPP_WIN32API) #if defined(_LIBCPP_WIN32API)
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define VC_EXTRA_LEAN #define VC_EXTRA_LEAN
@@ -70,16 +92,16 @@ system_clock::now() _NOEXCEPT
static_cast<__int64>(ft.dwLowDateTime)}; static_cast<__int64>(ft.dwLowDateTime)};
return time_point(duration_cast<duration>(d - nt_to_unix_epoch)); return time_point(duration_cast<duration>(d - nt_to_unix_epoch));
#else #else
#ifdef CLOCK_REALTIME #if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
struct timespec tp; struct timespec tp;
if (0 != clock_gettime(CLOCK_REALTIME, &tp)) if (0 != clock_gettime(CLOCK_REALTIME, &tp))
__throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
#else // !CLOCK_REALTIME #else
timeval tv; timeval tv;
gettimeofday(&tv, 0); gettimeofday(&tv, 0);
return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
#endif // CLOCK_REALTIME #endif // _LIBCXX_USE_CLOCK_GETTIME && CLOCK_REALTIME
#endif #endif
} }
@@ -106,6 +128,18 @@ const bool steady_clock::is_steady;
#if defined(__APPLE__) #if defined(__APPLE__)
// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW
#if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
struct timespec tp;
if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp))
__throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed");
return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
}
#else
// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of // mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom // nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
// are run time constants supplied by the OS. This clock has no relationship // are run time constants supplied by the OS. This clock has no relationship
@@ -157,6 +191,7 @@ steady_clock::now() _NOEXCEPT
static FP fp = init_steady_clock(); static FP fp = init_steady_clock();
return time_point(duration(fp())); return time_point(duration(fp()));
} }
#endif // defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
#elif defined(_LIBCPP_WIN32API) #elif defined(_LIBCPP_WIN32API)
@@ -175,6 +210,13 @@ steady_clock::now() _NOEXCEPT
#elif defined(CLOCK_MONOTONIC) #elif defined(CLOCK_MONOTONIC)
// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to
// time functions in the nanosecond range. Thus, they are the only acceptable
// implementations of steady_clock.
#ifdef __APPLE__
#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms"
#endif
steady_clock::time_point steady_clock::time_point
steady_clock::now() _NOEXCEPT steady_clock::now() _NOEXCEPT
{ {