Index: include/__threading_support =================================================================== --- include/__threading_support +++ include/__threading_support @@ -13,7 +13,9 @@ #include <__config> #include -#include +#include +#include +#include #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER #pragma GCC system_header @@ -42,8 +44,48 @@ #pragma weak pthread_create // Do not create libpthread dependency #endif +# include // 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(CLOCK_REALTIME) || !defined(_LIBCXX_USE_CLOCK_GETTIME) +#include // for gettimeofday and timeval +#endif // !defined(CLOCK_REALTIME) + +#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) +#if __APPLE__ +#include // mach_absolute_time, mach_timebase_info_data_t +#elif !defined(CLOCK_MONOTONIC) +#error "Monotonic clock not implemented" +#endif +#endif + #elif defined(_LIBCPP_HAS_THREAD_API_WIN32) +#define WIN32_LEAN_AND_MEAN +#define VC_EXTRA_LEAN #include +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 +#include +#endif #include #include #endif @@ -119,6 +161,17 @@ #define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI #endif +// Clocks +_LIBCPP_THREAD_ABI_VISIBILITY +chrono::system_clock::time_point __libcpp_clock_system_now(); + +// steady_clock::now() on __APPLE__ is implemented in chrono.cpp in a way +// that cannot be externalized easily. +#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(__APPLE__) +_LIBCPP_THREAD_ABI_VISIBILITY +chrono::steady_clock::time_point __libcpp_clock_steady_now(); +#endif + // Mutex _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); @@ -221,6 +274,41 @@ #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +// Clocks +chrono::system_clock::time_point __libcpp_clock_system_now() +{ +using namespace chrono; +#if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) + struct timespec __tp; + if (0 != clock_gettime(CLOCK_REALTIME, &__tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); + return system_clock::time_point(seconds(__tp.tv_sec) + + microseconds(__tp.tv_nsec / 1000)); +#else + timeval __tv; + gettimeofday(&__tv, 0); + return system_clock::time_point(seconds(__tv.tv_sec) + + microseconds(__tv.tv_usec)); +#endif // _LIBCXX_USE_CLOCK_GETTIME && CLOCK_REALTIME +} + +#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(__APPLE__) +chrono::steady_clock::time_point __libcpp_clock_steady_now() +{ +using namespace chrono; +#if defined(CLOCK_MONOTONIC) + struct timespec __tp; + if (0 != clock_gettime(CLOCK_MONOTONIC, &__tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); + return steady_clock::time_point(seconds(__tp.tv_sec) + + nanoseconds(__tp.tv_nsec)); +#else +#error "Monotonic clock not implemented" +#endif +} +#endif + +// Mutex int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { pthread_mutexattr_t attr; @@ -429,6 +517,53 @@ #elif defined(_LIBCPP_HAS_THREAD_API_WIN32) +// Clocks +chrono::system_clock::time_point __libcpp_clock_system_now() +{ + using namespace chrono; + // FILETIME is in 100ns units + using filetime_duration = + _VSTD::chrono::duration<__int64, + _VSTD::ratio_multiply<_VSTD::ratio<100, 1>, + nanoseconds::period>>; + + // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970. + static _LIBCPP_CONSTEXPR const seconds __nt_to_unix_epoch{11644473600}; + + FILETIME __ft; +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + GetSystemTimePreciseAsFileTime(&__ft); +#else + GetSystemTimeAsFileTime(&__ft); +#endif +#else + GetSystemTimeAsFileTime(&__ft); +#endif + + filetime_duration __d{(static_cast<__int64>(__ft.dwHighDateTime) << 32) | + static_cast<__int64>(__ft.dwLowDateTime)}; + return system_clock::time_point( + duration_cast(__d - __nt_to_unix_epoch) + ); +} + +#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK +chrono::steady_clock::time_point __libcpp_clock_steady_now() +{ + using namespace chrono; + static LARGE_INTEGER __freq; + static BOOL __initialized = FALSE; + if (!__initialized) + __initialized = QueryPerformanceFrequency(&__freq); // always succceeds + + LARGE_INTEGER __counter; + QueryPerformanceCounter(&__counter); + return steady_clock::time_point(duration(__counter.QuadPart * nano::den / + __freq.QuadPart)); +} +#endif + // Mutex int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { Index: src/chrono.cpp =================================================================== --- src/chrono.cpp +++ src/chrono.cpp @@ -10,50 +10,7 @@ #include "chrono" #include "cerrno" // errno #include "system_error" // __throw_system_error -#include // 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) -#define WIN32_LEAN_AND_MEAN -#define VC_EXTRA_LEAN -#include -#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 -#include -#endif -#else -#if !defined(CLOCK_REALTIME) || !defined(_LIBCXX_USE_CLOCK_GETTIME) -#include // for gettimeofday and timeval -#endif // !defined(CLOCK_REALTIME) -#endif // defined(_LIBCPP_WIN32API) - -#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) -#if __APPLE__ -#include // mach_absolute_time, mach_timebase_info_data_t -#elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC) -#error "Monotonic clock not implemented" -#endif -#endif +#include "__threading_support" _LIBCPP_BEGIN_NAMESPACE_STD @@ -67,42 +24,7 @@ system_clock::time_point system_clock::now() _NOEXCEPT { -#if defined(_LIBCPP_WIN32API) - // FILETIME is in 100ns units - using filetime_duration = - _VSTD::chrono::duration<__int64, - _VSTD::ratio_multiply<_VSTD::ratio<100, 1>, - nanoseconds::period>>; - - // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970. - static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600}; - - FILETIME ft; -#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - GetSystemTimePreciseAsFileTime(&ft); -#else - GetSystemTimeAsFileTime(&ft); -#endif -#else - GetSystemTimeAsFileTime(&ft); -#endif - - filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) | - static_cast<__int64>(ft.dwLowDateTime)}; - return time_point(duration_cast(d - nt_to_unix_epoch)); -#else -#if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) - struct timespec tp; - if (0 != clock_gettime(CLOCK_REALTIME, &tp)) - __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); - return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); -#else - timeval tv; - gettimeofday(&tv, 0); - return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); -#endif // _LIBCXX_USE_CLOCK_GETTIME && CLOCK_REALTIME -#endif + return __libcpp_clock_system_now(); } time_t @@ -193,42 +115,15 @@ } #endif // defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) -#elif defined(_LIBCPP_WIN32API) - -steady_clock::time_point -steady_clock::now() _NOEXCEPT -{ - static LARGE_INTEGER freq; - static BOOL initialized = FALSE; - if (!initialized) - initialized = QueryPerformanceFrequency(&freq); // always succceeds - - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart)); -} - -#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 +#else steady_clock::time_point steady_clock::now() _NOEXCEPT { - struct timespec tp; - if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) - __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); - return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); + return __libcpp_clock_steady_now(); } -#else -#error "Monotonic clock not implemented" -#endif +#endif // __APPLE__ #endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK