• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===------------------------- chrono.cpp ---------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "chrono"
11 #include "cerrno"        // errno
12 #include "system_error"  // __throw_system_error
13 #include <time.h>        // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME
14 
15 #if (__APPLE__)
16 #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
17 #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200
18 #define _LIBCXX_USE_CLOCK_GETTIME
19 #endif
20 #elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__)
21 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 100000
22 #define _LIBCXX_USE_CLOCK_GETTIME
23 #endif
24 #elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__)
25 #if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 100000
26 #define _LIBCXX_USE_CLOCK_GETTIME
27 #endif
28 #elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__)
29 #if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 30000
30 #define _LIBCXX_USE_CLOCK_GETTIME
31 #endif
32 #endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__
33 #else
34 #define _LIBCXX_USE_CLOCK_GETTIME
35 #endif // __APPLE__
36 
37 #if defined(_LIBCPP_WIN32API)
38 #define WIN32_LEAN_AND_MEAN
39 #define VC_EXTRA_LEAN
40 #include <Windows.h>
41 #if _WIN32_WINNT >= _WIN32_WINNT_WIN8
42 #include <winapifamily.h>
43 #endif
44 #else
45 #if !defined(CLOCK_REALTIME) || !defined(_LIBCXX_USE_CLOCK_GETTIME)
46 #include <sys/time.h>        // for gettimeofday and timeval
47 #endif // !defined(CLOCK_REALTIME)
48 #endif // defined(_LIBCPP_WIN32API)
49 
50 #if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK)
51 #if __APPLE__
52 #include <mach/mach_time.h>  // mach_absolute_time, mach_timebase_info_data_t
53 #elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC)
54 #error "Monotonic clock not implemented"
55 #endif
56 #endif
57 
58 _LIBCPP_BEGIN_NAMESPACE_STD
59 
60 namespace chrono
61 {
62 
63 // system_clock
64 
65 const bool system_clock::is_steady;
66 
67 system_clock::time_point
now()68 system_clock::now() _NOEXCEPT
69 {
70 #if defined(_LIBCPP_WIN32API)
71   // FILETIME is in 100ns units
72   using filetime_duration =
73       _VSTD::chrono::duration<__int64,
74                               _VSTD::ratio_multiply<_VSTD::ratio<100, 1>,
75                                                     nanoseconds::period>>;
76 
77   // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970.
78   static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600};
79 
80   FILETIME ft;
81 #if _WIN32_WINNT >= _WIN32_WINNT_WIN8
82 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
83   GetSystemTimePreciseAsFileTime(&ft);
84 #else
85   GetSystemTimeAsFileTime(&ft);
86 #endif
87 #else
88   GetSystemTimeAsFileTime(&ft);
89 #endif
90 
91   filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) |
92                        static_cast<__int64>(ft.dwLowDateTime)};
93   return time_point(duration_cast<duration>(d - nt_to_unix_epoch));
94 #else
95 #if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
96     struct timespec tp;
97     if (0 != clock_gettime(CLOCK_REALTIME, &tp))
98         __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
99     return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
100 #else
101     timeval tv;
102     gettimeofday(&tv, 0);
103     return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
104 #endif // _LIBCXX_USE_CLOCK_GETTIME && CLOCK_REALTIME
105 #endif
106 }
107 
108 time_t
to_time_t(const time_point & t)109 system_clock::to_time_t(const time_point& t) _NOEXCEPT
110 {
111     return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
112 }
113 
114 system_clock::time_point
from_time_t(time_t t)115 system_clock::from_time_t(time_t t) _NOEXCEPT
116 {
117     return system_clock::time_point(seconds(t));
118 }
119 
120 #ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK
121 // steady_clock
122 //
123 // Warning:  If this is not truly steady, then it is non-conforming.  It is
124 //  better for it to not exist and have the rest of libc++ use system_clock
125 //  instead.
126 
127 const bool steady_clock::is_steady;
128 
129 #if defined(__APPLE__)
130 
131 // Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW
132 #if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
133 steady_clock::time_point
now()134 steady_clock::now() _NOEXCEPT
135 {
136     struct timespec tp;
137     if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp))
138         __throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed");
139     return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
140 }
141 
142 #else
143 //   mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
144 //   nanoseconds since the computer booted up.  MachInfo.numer and MachInfo.denom
145 //   are run time constants supplied by the OS.  This clock has no relationship
146 //   to the Gregorian calendar.  It's main use is as a high resolution timer.
147 
148 // MachInfo.numer / MachInfo.denom is often 1 on the latest equipment.  Specialize
149 //   for that case as an optimization.
150 
151 static
152 steady_clock::rep
steady_simplified()153 steady_simplified()
154 {
155     return static_cast<steady_clock::rep>(mach_absolute_time());
156 }
157 
158 static
159 double
compute_steady_factor()160 compute_steady_factor()
161 {
162     mach_timebase_info_data_t MachInfo;
163     mach_timebase_info(&MachInfo);
164     return static_cast<double>(MachInfo.numer) / MachInfo.denom;
165 }
166 
167 static
168 steady_clock::rep
steady_full()169 steady_full()
170 {
171     static const double factor = compute_steady_factor();
172     return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
173 }
174 
175 typedef steady_clock::rep (*FP)();
176 
177 static
178 FP
init_steady_clock()179 init_steady_clock()
180 {
181     mach_timebase_info_data_t MachInfo;
182     mach_timebase_info(&MachInfo);
183     if (MachInfo.numer == MachInfo.denom)
184         return &steady_simplified;
185     return &steady_full;
186 }
187 
188 steady_clock::time_point
now()189 steady_clock::now() _NOEXCEPT
190 {
191     static FP fp = init_steady_clock();
192     return time_point(duration(fp()));
193 }
194 #endif // defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
195 
196 #elif defined(_LIBCPP_WIN32API)
197 
198 steady_clock::time_point
now()199 steady_clock::now() _NOEXCEPT
200 {
201   static LARGE_INTEGER freq;
202   static BOOL initialized = FALSE;
203   if (!initialized)
204     initialized = QueryPerformanceFrequency(&freq); // always succceeds
205 
206   LARGE_INTEGER counter;
207   QueryPerformanceCounter(&counter);
208   return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart));
209 }
210 
211 #elif defined(CLOCK_MONOTONIC)
212 
213 // On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to
214 // time functions in the nanosecond range. Thus, they are the only acceptable
215 // implementations of steady_clock.
216 #ifdef __APPLE__
217 #error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms"
218 #endif
219 
220 steady_clock::time_point
now()221 steady_clock::now() _NOEXCEPT
222 {
223     struct timespec tp;
224     if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
225         __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
226     return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
227 }
228 
229 #else
230 #error "Monotonic clock not implemented"
231 #endif
232 
233 #endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK
234 
235 }
236 
237 _LIBCPP_END_NAMESPACE_STD
238