rmaprath created this revision.

These implementations depend heavily on the underlying platform. It would be 
good to put them behind a porting function within the threading API as quite a 
bit of threading functionality depend on the clocks.

The `steady_clock::now()` implementation was difficult to pluck out for 
`__APPLE__` because it uses some static functions within the library sources.

I have tested these changes on linux, I will test them on Windows and Mac 
before committing (if this gets approved).


https://reviews.llvm.org/D29818

Files:
  include/__threading_support
  src/chrono.cpp

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 <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)
-#define WIN32_LEAN_AND_MEAN
-#define VC_EXTRA_LEAN
-#include <Windows.h>
-#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
-#include <winapifamily.h>
-#endif
-#else
-#if !defined(CLOCK_REALTIME) || !defined(_LIBCXX_USE_CLOCK_GETTIME)
-#include <sys/time.h>        // for gettimeofday and timeval
-#endif // !defined(CLOCK_REALTIME)
-#endif // defined(_LIBCPP_WIN32API)
-
-#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK)
-#if __APPLE__
-#include <mach/mach_time.h>  // 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<duration>(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
 
Index: include/__threading_support
===================================================================
--- include/__threading_support
+++ include/__threading_support
@@ -13,7 +13,9 @@
 
 #include <__config>
 #include <chrono>
-#include <errno.h>
+#include <cerrno>
+#include <cstdint>
+#include <system_error>
 
 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
 #pragma GCC system_header
@@ -39,8 +41,48 @@
 #pragma weak pthread_create // Do not create libpthread dependency
 #endif
 
+# 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(CLOCK_REALTIME) || !defined(_LIBCXX_USE_CLOCK_GETTIME)
+#include <sys/time.h>        // for gettimeofday and timeval
+#endif // !defined(CLOCK_REALTIME)
+
+#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK)
+#if __APPLE__
+#include <mach/mach_time.h>  // 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 <Windows.h>
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
+#include <winapifamily.h>
+#endif
 #include <process.h>
 #include <fibersapi.h>
 #endif
@@ -116,6 +158,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);
@@ -218,6 +271,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;
@@ -426,6 +514,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<duration>(__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)
 {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to