xref: /aosp_15_r20/external/cronet/base/time/time_win.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 
6 // Windows Timer Primer
7 //
8 // A good article:  http://www.ddj.com/windows/184416651
9 // A good mozilla bug:  http://bugzilla.mozilla.org/show_bug.cgi?id=363258
10 //
11 // The default windows timer, GetSystemTimeAsFileTime is not very precise.
12 // It is only good to ~15.5ms.
13 //
14 // QueryPerformanceCounter is the logical choice for a high-precision timer.
15 // However, it is known to be buggy on some hardware.  Specifically, it can
16 // sometimes "jump".  On laptops, QPC can also be very expensive to call.
17 // It's 3-4x slower than timeGetTime() on desktops, but can be 10x slower
18 // on laptops.  A unittest exists which will show the relative cost of various
19 // timers on any system.
20 //
21 // The next logical choice is timeGetTime().  timeGetTime has a precision of
22 // 1ms, but only if you call APIs (timeBeginPeriod()) which affect all other
23 // applications on the system.  By default, precision is only 15.5ms.
24 // Unfortunately, we don't want to call timeBeginPeriod because we don't
25 // want to affect other applications.  Further, on mobile platforms, use of
26 // faster multimedia timers can hurt battery life.  See the intel
27 // article about this here:
28 // http://softwarecommunity.intel.com/articles/eng/1086.htm
29 //
30 // To work around all this, we're going to generally use timeGetTime().  We
31 // will only increase the system-wide timer if we're not running on battery
32 // power.
33 
34 #include "base/time/time.h"
35 
36 #include <windows.h>
37 
38 #include <mmsystem.h>
39 #include <stdint.h>
40 #include <windows.foundation.h>
41 
42 #include <atomic>
43 #include <ostream>
44 
45 #include "base/bit_cast.h"
46 #include "base/check_op.h"
47 #include "base/cpu.h"
48 #include "base/notreached.h"
49 #include "base/synchronization/lock.h"
50 #include "base/threading/platform_thread.h"
51 #include "base/time/time_override.h"
52 #include "build/build_config.h"
53 
54 namespace base {
55 
56 namespace {
57 
58 // From MSDN, FILETIME "Contains a 64-bit value representing the number of
59 // 100-nanosecond intervals since January 1, 1601 (UTC)."
FileTimeToMicroseconds(const FILETIME & ft)60 int64_t FileTimeToMicroseconds(const FILETIME& ft) {
61   // Need to bit_cast to fix alignment, then divide by 10 to convert
62   // 100-nanoseconds to microseconds. This only works on little-endian
63   // machines.
64   return bit_cast<int64_t, FILETIME>(ft) / 10;
65 }
66 
CanConvertToFileTime(int64_t us)67 bool CanConvertToFileTime(int64_t us) {
68   return us >= 0 && us <= (std::numeric_limits<int64_t>::max() / 10);
69 }
70 
MicrosecondsToFileTime(int64_t us)71 FILETIME MicrosecondsToFileTime(int64_t us) {
72   DCHECK(CanConvertToFileTime(us)) << "Out-of-range: Cannot convert " << us
73                                    << " microseconds to FILETIME units.";
74 
75   // Multiply by 10 to convert microseconds to 100-nanoseconds. Bit_cast will
76   // handle alignment problems. This only works on little-endian machines.
77   return bit_cast<FILETIME, int64_t>(us * 10);
78 }
79 
CurrentWallclockMicroseconds()80 int64_t CurrentWallclockMicroseconds() {
81   FILETIME ft;
82   ::GetSystemTimeAsFileTime(&ft);
83   return FileTimeToMicroseconds(ft);
84 }
85 
86 // Time between resampling the un-granular clock for this API.
87 constexpr TimeDelta kMaxTimeToAvoidDrift = Seconds(60);
88 
89 int64_t g_initial_time = 0;
90 TimeTicks g_initial_ticks;
91 
InitializeClock()92 void InitializeClock() {
93   g_initial_ticks = subtle::TimeTicksNowIgnoringOverride();
94   g_initial_time = CurrentWallclockMicroseconds();
95 }
96 
97 // Track the last value passed to timeBeginPeriod so that we can cancel that
98 // call by calling timeEndPeriod with the same value. A value of zero means that
99 // the timer frequency is not currently raised.
100 UINT g_last_interval_requested_ms = 0;
101 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active.
102 // For most purposes this could also be named g_is_on_ac_power.
103 bool g_high_res_timer_enabled = false;
104 // How many times the high resolution timer has been called.
105 uint32_t g_high_res_timer_count = 0;
106 // Start time of the high resolution timer usage monitoring. This is needed
107 // to calculate the usage as percentage of the total elapsed time.
108 TimeTicks g_high_res_timer_usage_start;
109 // The cumulative time the high resolution timer has been in use since
110 // |g_high_res_timer_usage_start| moment.
111 TimeDelta g_high_res_timer_usage;
112 // Timestamp of the last activation change of the high resolution timer. This
113 // is used to calculate the cumulative usage.
114 TimeTicks g_high_res_timer_last_activation;
115 // The lock to control access to the above set of variables.
GetHighResLock()116 Lock* GetHighResLock() {
117   static auto* lock = new Lock();
118   return lock;
119 }
120 
121 // The two values that ActivateHighResolutionTimer uses to set the systemwide
122 // timer interrupt frequency on Windows. These control how precise timers are
123 // but also have a big impact on battery life.
124 
125 // Used when a faster timer has been requested (g_high_res_timer_count > 0) and
126 // the computer is running on AC power (plugged in) so that it's okay to go to
127 // the highest frequency.
128 constexpr UINT kMinTimerIntervalHighResMs = 1;
129 
130 // Used when a faster timer has been requested (g_high_res_timer_count > 0) and
131 // the computer is running on DC power (battery) so that we don't want to raise
132 // the timer frequency as much.
133 constexpr UINT kMinTimerIntervalLowResMs = 8;
134 
135 // Calculate the desired timer interrupt interval. Note that zero means that the
136 // system default should be used.
GetIntervalMs()137 UINT GetIntervalMs() {
138   if (!g_high_res_timer_count)
139     return 0;  // Use the default, typically 15.625
140   if (g_high_res_timer_enabled)
141     return kMinTimerIntervalHighResMs;
142   return kMinTimerIntervalLowResMs;
143 }
144 
145 // Compare the currently requested timer interrupt interval to the last interval
146 // requested and update if necessary (by cancelling the old request and making a
147 // new request). If there is no change then do nothing.
UpdateTimerIntervalLocked()148 void UpdateTimerIntervalLocked() {
149   UINT new_interval = GetIntervalMs();
150   if (new_interval == g_last_interval_requested_ms)
151     return;
152   if (g_last_interval_requested_ms) {
153     // Record how long the timer interrupt frequency was raised.
154     g_high_res_timer_usage += subtle::TimeTicksNowIgnoringOverride() -
155                               g_high_res_timer_last_activation;
156     // Reset the timer interrupt back to the default.
157     timeEndPeriod(g_last_interval_requested_ms);
158   }
159   g_last_interval_requested_ms = new_interval;
160   if (g_last_interval_requested_ms) {
161     // Record when the timer interrupt was raised.
162     g_high_res_timer_last_activation = subtle::TimeTicksNowIgnoringOverride();
163     timeBeginPeriod(g_last_interval_requested_ms);
164   }
165 }
166 
167 // Returns the current value of the performance counter.
QPCNowRaw()168 int64_t QPCNowRaw() {
169   LARGE_INTEGER perf_counter_now = {};
170   // According to the MSDN documentation for QueryPerformanceCounter(), this
171   // will never fail on systems that run XP or later.
172   // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx
173   ::QueryPerformanceCounter(&perf_counter_now);
174   return perf_counter_now.QuadPart;
175 }
176 
SafeConvertToWord(int in,WORD * out)177 bool SafeConvertToWord(int in, WORD* out) {
178   CheckedNumeric<WORD> result = in;
179   *out = result.ValueOrDefault(std::numeric_limits<WORD>::max());
180   return result.IsValid();
181 }
182 
183 }  // namespace
184 
185 // Time -----------------------------------------------------------------------
186 
187 namespace subtle {
TimeNowIgnoringOverride()188 Time TimeNowIgnoringOverride() {
189   if (g_initial_time == 0)
190     InitializeClock();
191 
192   // We implement time using the high-resolution timers so that we can get
193   // timeouts which are smaller than 10-15ms.  If we just used
194   // CurrentWallclockMicroseconds(), we'd have the less-granular timer.
195   //
196   // To make this work, we initialize the clock (g_initial_time) and the
197   // counter (initial_ctr).  To compute the initial time, we can check
198   // the number of ticks that have elapsed, and compute the delta.
199   //
200   // To avoid any drift, we periodically resync the counters to the system
201   // clock.
202   while (true) {
203     TimeTicks ticks = TimeTicksNowIgnoringOverride();
204 
205     // Calculate the time elapsed since we started our timer
206     TimeDelta elapsed = ticks - g_initial_ticks;
207 
208     // Check if enough time has elapsed that we need to resync the clock.
209     if (elapsed > kMaxTimeToAvoidDrift) {
210       InitializeClock();
211       continue;
212     }
213 
214     return Time() + elapsed + Microseconds(g_initial_time);
215   }
216 }
217 
TimeNowFromSystemTimeIgnoringOverride()218 Time TimeNowFromSystemTimeIgnoringOverride() {
219   // Force resync.
220   InitializeClock();
221   return Time() + Microseconds(g_initial_time);
222 }
223 }  // namespace subtle
224 
225 // static
FromFileTime(FILETIME ft)226 Time Time::FromFileTime(FILETIME ft) {
227   if (bit_cast<int64_t, FILETIME>(ft) == 0)
228     return Time();
229   if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() &&
230       ft.dwLowDateTime == std::numeric_limits<DWORD>::max())
231     return Max();
232   return Time(FileTimeToMicroseconds(ft));
233 }
234 
ToFileTime() const235 FILETIME Time::ToFileTime() const {
236   if (is_null())
237     return bit_cast<FILETIME, int64_t>(0);
238   if (is_max()) {
239     FILETIME result;
240     result.dwHighDateTime = std::numeric_limits<DWORD>::max();
241     result.dwLowDateTime = std::numeric_limits<DWORD>::max();
242     return result;
243   }
244   return MicrosecondsToFileTime(us_);
245 }
246 
247 // static
248 // Enable raising of the system-global timer interrupt frequency to 1 kHz (when
249 // enable is true, which happens when on AC power) or some lower frequency when
250 // on battery power (when enable is false). If the g_high_res_timer_enabled
251 // setting hasn't actually changed or if if there are no outstanding requests
252 // (if g_high_res_timer_count is zero) then do nothing.
253 // TL;DR - call this when going from AC to DC power or vice-versa.
EnableHighResolutionTimer(bool enable)254 void Time::EnableHighResolutionTimer(bool enable) {
255   AutoLock lock(*GetHighResLock());
256   g_high_res_timer_enabled = enable;
257   UpdateTimerIntervalLocked();
258 }
259 
260 // static
261 // Request that the system-global Windows timer interrupt frequency be raised.
262 // How high the frequency is raised depends on the system's power state and
263 // possibly other options.
264 // TL;DR - call this at the beginning and end of a time period where you want
265 // higher frequency timer interrupts. Each call with activating=true must be
266 // paired with a subsequent activating=false call.
ActivateHighResolutionTimer(bool activating)267 bool Time::ActivateHighResolutionTimer(bool activating) {
268   // We only do work on the transition from zero to one or one to zero so we
269   // can easily undo the effect (if necessary) when EnableHighResolutionTimer is
270   // called.
271   const uint32_t max = std::numeric_limits<uint32_t>::max();
272 
273   AutoLock lock(*GetHighResLock());
274   if (activating) {
275     DCHECK_NE(g_high_res_timer_count, max);
276     ++g_high_res_timer_count;
277   } else {
278     DCHECK_NE(g_high_res_timer_count, 0u);
279     --g_high_res_timer_count;
280   }
281   UpdateTimerIntervalLocked();
282   return true;
283 }
284 
285 // static
286 // See if the timer interrupt interval has been set to the lowest value.
IsHighResolutionTimerInUse()287 bool Time::IsHighResolutionTimerInUse() {
288   AutoLock lock(*GetHighResLock());
289   return g_last_interval_requested_ms == kMinTimerIntervalHighResMs;
290 }
291 
292 // static
ResetHighResolutionTimerUsage()293 void Time::ResetHighResolutionTimerUsage() {
294   AutoLock lock(*GetHighResLock());
295   g_high_res_timer_usage = TimeDelta();
296   g_high_res_timer_usage_start = subtle::TimeTicksNowIgnoringOverride();
297   if (g_high_res_timer_count > 0)
298     g_high_res_timer_last_activation = g_high_res_timer_usage_start;
299 }
300 
301 // static
GetHighResolutionTimerUsage()302 double Time::GetHighResolutionTimerUsage() {
303   AutoLock lock(*GetHighResLock());
304   TimeTicks now = subtle::TimeTicksNowIgnoringOverride();
305   TimeDelta elapsed_time = now - g_high_res_timer_usage_start;
306   if (elapsed_time.is_zero()) {
307     // This is unexpected but possible if TimeTicks resolution is low and
308     // GetHighResolutionTimerUsage() is called promptly after
309     // ResetHighResolutionTimerUsage().
310     return 0.0;
311   }
312   TimeDelta used_time = g_high_res_timer_usage;
313   if (g_high_res_timer_count > 0) {
314     // If currently activated add the remainder of time since the last
315     // activation.
316     used_time += now - g_high_res_timer_last_activation;
317   }
318   return used_time / elapsed_time * 100;
319 }
320 
321 // static
FromExploded(bool is_local,const Exploded & exploded,Time * time)322 bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
323   // Create the system struct representing our exploded time. It will either be
324   // in local time or UTC.If casting from int to WORD results in overflow,
325   // fail and return Time(0).
326   SYSTEMTIME st;
327   if (!SafeConvertToWord(exploded.year, &st.wYear) ||
328       !SafeConvertToWord(exploded.month, &st.wMonth) ||
329       !SafeConvertToWord(exploded.day_of_week, &st.wDayOfWeek) ||
330       !SafeConvertToWord(exploded.day_of_month, &st.wDay) ||
331       !SafeConvertToWord(exploded.hour, &st.wHour) ||
332       !SafeConvertToWord(exploded.minute, &st.wMinute) ||
333       !SafeConvertToWord(exploded.second, &st.wSecond) ||
334       !SafeConvertToWord(exploded.millisecond, &st.wMilliseconds)) {
335     *time = Time(0);
336     return false;
337   }
338 
339   FILETIME ft;
340   bool success = true;
341   // Ensure that it's in UTC.
342   if (is_local) {
343     SYSTEMTIME utc_st;
344     success = TzSpecificLocalTimeToSystemTime(nullptr, &st, &utc_st) &&
345               SystemTimeToFileTime(&utc_st, &ft);
346   } else {
347     success = !!SystemTimeToFileTime(&st, &ft);
348   }
349 
350   *time = Time(success ? FileTimeToMicroseconds(ft) : 0);
351   return success;
352 }
353 
Explode(bool is_local,Exploded * exploded) const354 void Time::Explode(bool is_local, Exploded* exploded) const {
355   if (!CanConvertToFileTime(us_)) {
356     // We are not able to convert it to FILETIME.
357     ZeroMemory(exploded, sizeof(*exploded));
358     return;
359   }
360 
361   const FILETIME utc_ft = MicrosecondsToFileTime(us_);
362 
363   // FILETIME in local time if necessary.
364   bool success = true;
365   // FILETIME in SYSTEMTIME (exploded).
366   SYSTEMTIME st = {0};
367   if (is_local) {
368     SYSTEMTIME utc_st;
369     // We don't use FileTimeToLocalFileTime here, since it uses the current
370     // settings for the time zone and daylight saving time. Therefore, if it is
371     // daylight saving time, it will take daylight saving time into account,
372     // even if the time you are converting is in standard time.
373     success = FileTimeToSystemTime(&utc_ft, &utc_st) &&
374               SystemTimeToTzSpecificLocalTime(nullptr, &utc_st, &st);
375   } else {
376     success = !!FileTimeToSystemTime(&utc_ft, &st);
377   }
378 
379   if (!success) {
380     ZeroMemory(exploded, sizeof(*exploded));
381     return;
382   }
383 
384   exploded->year = st.wYear;
385   exploded->month = st.wMonth;
386   exploded->day_of_week = st.wDayOfWeek;
387   exploded->day_of_month = st.wDay;
388   exploded->hour = st.wHour;
389   exploded->minute = st.wMinute;
390   exploded->second = st.wSecond;
391   exploded->millisecond = st.wMilliseconds;
392 }
393 
394 // TimeTicks ------------------------------------------------------------------
395 
396 namespace {
397 
398 // We define a wrapper to adapt between the __stdcall and __cdecl call of the
399 // mock function, and to avoid a static constructor.  Assigning an import to a
400 // function pointer directly would require setup code to fetch from the IAT.
timeGetTimeWrapper()401 DWORD timeGetTimeWrapper() {
402   return timeGetTime();
403 }
404 
405 DWORD (*g_tick_function)(void) = &timeGetTimeWrapper;
406 
407 // A structure holding the most significant bits of "last seen" and a
408 // "rollover" counter.
409 union LastTimeAndRolloversState {
410   // The state as a single 32-bit opaque value.
411   std::atomic<int32_t> as_opaque_32{0};
412 
413   // The state as usable values.
414   struct {
415     // The top 8-bits of the "last" time. This is enough to check for rollovers
416     // and the small bit-size means fewer CompareAndSwap operations to store
417     // changes in state, which in turn makes for fewer retries.
418     uint8_t last_8;
419     // A count of the number of detected rollovers. Using this as bits 47-32
420     // of the upper half of a 64-bit value results in a 48-bit tick counter.
421     // This extends the total rollover period from about 49 days to about 8800
422     // years while still allowing it to be stored with last_8 in a single
423     // 32-bit value.
424     uint16_t rollovers;
425   } as_values;
426 };
427 std::atomic<int32_t> g_last_time_and_rollovers = 0;
428 static_assert(
429     sizeof(LastTimeAndRolloversState) <= sizeof(g_last_time_and_rollovers),
430     "LastTimeAndRolloversState does not fit in a single atomic word");
431 
432 // We use timeGetTime() to implement TimeTicks::Now().  This can be problematic
433 // because it returns the number of milliseconds since Windows has started,
434 // which will roll over the 32-bit value every ~49 days.  We try to track
435 // rollover ourselves, which works if TimeTicks::Now() is called at least every
436 // 48.8 days (not 49 days because only changes in the top 8 bits get noticed).
RolloverProtectedNow()437 TimeTicks RolloverProtectedNow() {
438   LastTimeAndRolloversState state;
439   DWORD now;  // DWORD is always unsigned 32 bits.
440 
441   while (true) {
442     // Fetch the "now" and "last" tick values, updating "last" with "now" and
443     // incrementing the "rollovers" counter if the tick-value has wrapped back
444     // around. Atomic operations ensure that both "last" and "rollovers" are
445     // always updated together.
446     int32_t original =
447         g_last_time_and_rollovers.load(std::memory_order_acquire);
448     state.as_opaque_32 = original;
449     now = g_tick_function();
450     uint8_t now_8 = static_cast<uint8_t>(now >> 24);
451     if (now_8 < state.as_values.last_8)
452       ++state.as_values.rollovers;
453     state.as_values.last_8 = now_8;
454 
455     // If the state hasn't changed, exit the loop.
456     if (state.as_opaque_32 == original)
457       break;
458 
459     // Save the changed state. If the existing value is unchanged from the
460     // original so that the operation is successful. Exit the loop.
461     bool success = g_last_time_and_rollovers.compare_exchange_strong(
462         original, state.as_opaque_32, std::memory_order_release);
463     if (success)
464       break;
465 
466     // Another thread has done something in between so retry from the top.
467   }
468 
469   return TimeTicks() +
470          Milliseconds(now +
471                       (static_cast<uint64_t>(state.as_values.rollovers) << 32));
472 }
473 
474 // Discussion of tick counter options on Windows:
475 //
476 // (1) CPU cycle counter. (Retrieved via RDTSC)
477 // The CPU counter provides the highest resolution time stamp and is the least
478 // expensive to retrieve. However, on older CPUs, two issues can affect its
479 // reliability: First it is maintained per processor and not synchronized
480 // between processors. Also, the counters will change frequency due to thermal
481 // and power changes, and stop in some states.
482 //
483 // (2) QueryPerformanceCounter (QPC). The QPC counter provides a high-
484 // resolution (<1 microsecond) time stamp. On most hardware running today, it
485 // auto-detects and uses the constant-rate RDTSC counter to provide extremely
486 // efficient and reliable time stamps.
487 //
488 // On older CPUs where RDTSC is unreliable, it falls back to using more
489 // expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI
490 // PM timer, and can involve system calls; and all this is up to the HAL (with
491 // some help from ACPI). According to
492 // http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the
493 // worst case, it gets the counter from the rollover interrupt on the
494 // programmable interrupt timer. In best cases, the HAL may conclude that the
495 // RDTSC counter runs at a constant frequency, then it uses that instead. On
496 // multiprocessor machines, it will try to verify the values returned from
497 // RDTSC on each processor are consistent with each other, and apply a handful
498 // of workarounds for known buggy hardware. In other words, QPC is supposed to
499 // give consistent results on a multiprocessor computer, but for older CPUs it
500 // can be unreliable due bugs in BIOS or HAL.
501 //
502 // (3) System time. The system time provides a low-resolution (from ~1 to ~15.6
503 // milliseconds) time stamp but is comparatively less expensive to retrieve and
504 // more reliable. Time::EnableHighResolutionTimer() and
505 // Time::ActivateHighResolutionTimer() can be called to alter the resolution of
506 // this timer; and also other Windows applications can alter it, affecting this
507 // one.
508 
509 TimeTicks InitialNowFunction();
510 
511 // See "threading notes" in InitializeNowFunctionPointer() for details on how
512 // concurrent reads/writes to these globals has been made safe.
513 std::atomic<TimeTicksNowFunction> g_time_ticks_now_ignoring_override_function{
514     &InitialNowFunction};
515 int64_t g_qpc_ticks_per_second = 0;
516 
QPCValueToTimeDelta(LONGLONG qpc_value)517 TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) {
518   // Ensure that the assignment to |g_qpc_ticks_per_second|, made in
519   // InitializeNowFunctionPointer(), has happened by this point.
520   std::atomic_thread_fence(std::memory_order_acquire);
521 
522   DCHECK_GT(g_qpc_ticks_per_second, 0);
523 
524   // If the QPC Value is below the overflow threshold, we proceed with
525   // simple multiply and divide.
526   if (qpc_value < Time::kQPCOverflowThreshold) {
527     return Microseconds(qpc_value * Time::kMicrosecondsPerSecond /
528                         g_qpc_ticks_per_second);
529   }
530   // Otherwise, calculate microseconds in a round about manner to avoid
531   // overflow and precision issues.
532   int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second;
533   int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second);
534   return Microseconds((whole_seconds * Time::kMicrosecondsPerSecond) +
535                       ((leftover_ticks * Time::kMicrosecondsPerSecond) /
536                        g_qpc_ticks_per_second));
537 }
538 
QPCNow()539 TimeTicks QPCNow() {
540   return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw());
541 }
542 
InitializeNowFunctionPointer()543 void InitializeNowFunctionPointer() {
544   LARGE_INTEGER ticks_per_sec = {};
545   if (!QueryPerformanceFrequency(&ticks_per_sec))
546     ticks_per_sec.QuadPart = 0;
547 
548   // If Windows cannot provide a QPC implementation, TimeTicks::Now() must use
549   // the low-resolution clock.
550   //
551   // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now()
552   // will still use the low-resolution clock. A CPU lacking a non-stop time
553   // counter will cause Windows to provide an alternate QPC implementation that
554   // works, but is expensive to use.
555   //
556   // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015,
557   // ~72% of users fall within this category.
558   CPU cpu;
559   const TimeTicksNowFunction now_function =
560       (ticks_per_sec.QuadPart <= 0 || !cpu.has_non_stop_time_stamp_counter())
561           ? &RolloverProtectedNow
562           : &QPCNow;
563 
564   // Threading note 1: In an unlikely race condition, it's possible for two or
565   // more threads to enter InitializeNowFunctionPointer() in parallel. This is
566   // not a problem since all threads end up writing out the same values
567   // to the global variables, and those variable being atomic are safe to read
568   // from other threads.
569   //
570   // Threading note 2: A release fence is placed here to ensure, from the
571   // perspective of other threads using the function pointers, that the
572   // assignment to |g_qpc_ticks_per_second| happens before the function pointers
573   // are changed.
574   g_qpc_ticks_per_second = ticks_per_sec.QuadPart;
575   std::atomic_thread_fence(std::memory_order_release);
576   // Also set g_time_ticks_now_function to avoid the additional indirection via
577   // TimeTicksNowIgnoringOverride() for future calls to TimeTicks::Now(), only
578   // if it wasn't already overridden to a different value. memory_order_relaxed
579   // is sufficient since an explicit fence was inserted above.
580   base::TimeTicksNowFunction initial_time_ticks_now_function =
581       &subtle::TimeTicksNowIgnoringOverride;
582   internal::g_time_ticks_now_function.compare_exchange_strong(
583       initial_time_ticks_now_function, now_function, std::memory_order_relaxed);
584   g_time_ticks_now_ignoring_override_function.store(now_function,
585                                                     std::memory_order_relaxed);
586 }
587 
InitialNowFunction()588 TimeTicks InitialNowFunction() {
589   InitializeNowFunctionPointer();
590   return g_time_ticks_now_ignoring_override_function.load(
591       std::memory_order_relaxed)();
592 }
593 
594 }  // namespace
595 
596 // static
SetMockTickFunction(TickFunctionType ticker)597 TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction(
598     TickFunctionType ticker) {
599   TickFunctionType old = g_tick_function;
600   g_tick_function = ticker;
601   g_last_time_and_rollovers.store(0, std::memory_order_relaxed);
602   return old;
603 }
604 
605 namespace subtle {
TimeTicksNowIgnoringOverride()606 TimeTicks TimeTicksNowIgnoringOverride() {
607   return g_time_ticks_now_ignoring_override_function.load(
608       std::memory_order_relaxed)();
609 }
610 }  // namespace subtle
611 
612 // static
IsHighResolution()613 bool TimeTicks::IsHighResolution() {
614   if (g_time_ticks_now_ignoring_override_function == &InitialNowFunction)
615     InitializeNowFunctionPointer();
616   return g_time_ticks_now_ignoring_override_function == &QPCNow;
617 }
618 
619 // static
IsConsistentAcrossProcesses()620 bool TimeTicks::IsConsistentAcrossProcesses() {
621   // According to Windows documentation [1] QPC is consistent post-Windows
622   // Vista. So if we are using QPC then we are consistent which is the same as
623   // being high resolution.
624   //
625   // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
626   //
627   // "In general, the performance counter results are consistent across all
628   // processors in multi-core and multi-processor systems, even when measured on
629   // different threads or processes. Here are some exceptions to this rule:
630   // - Pre-Windows Vista operating systems that run on certain processors might
631   // violate this consistency because of one of these reasons:
632   //     1. The hardware processors have a non-invariant TSC and the BIOS
633   //     doesn't indicate this condition correctly.
634   //     2. The TSC synchronization algorithm that was used wasn't suitable for
635   //     systems with large numbers of processors."
636   return IsHighResolution();
637 }
638 
639 // static
GetClock()640 TimeTicks::Clock TimeTicks::GetClock() {
641   return IsHighResolution() ? Clock::WIN_QPC
642                             : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME;
643 }
644 
645 // LiveTicks ------------------------------------------------------------------
646 
647 namespace subtle {
LiveTicksNowIgnoringOverride()648 LiveTicks LiveTicksNowIgnoringOverride() {
649   ULONGLONG unbiased_interrupt_time;
650   QueryUnbiasedInterruptTimePrecise(&unbiased_interrupt_time);
651   // QueryUnbiasedInterruptTimePrecise gets the interrupt time in system time
652   // units of 100 nanoseconds.
653   return LiveTicks() + Nanoseconds(unbiased_interrupt_time * 100);
654 }
655 }  // namespace subtle
656 
657 // ThreadTicks ----------------------------------------------------------------
658 
659 namespace subtle {
ThreadTicksNowIgnoringOverride()660 ThreadTicks ThreadTicksNowIgnoringOverride() {
661   return ThreadTicks::GetForThread(PlatformThread::CurrentHandle());
662 }
663 }  // namespace subtle
664 
665 // static
GetForThread(const PlatformThreadHandle & thread_handle)666 ThreadTicks ThreadTicks::GetForThread(
667     const PlatformThreadHandle& thread_handle) {
668   DCHECK(IsSupported());
669 
670 #if defined(ARCH_CPU_ARM64)
671   // QueryThreadCycleTime versus TSCTicksPerSecond doesn't have much relation to
672   // actual elapsed time on Windows on Arm, because QueryThreadCycleTime is
673   // backed by the actual number of CPU cycles executed, rather than a
674   // constant-rate timer like Intel. To work around this, use GetThreadTimes
675   // (which isn't as accurate but is meaningful as a measure of elapsed
676   // per-thread time).
677   FILETIME creation_time, exit_time, kernel_time, user_time;
678   ::GetThreadTimes(thread_handle.platform_handle(), &creation_time, &exit_time,
679                    &kernel_time, &user_time);
680 
681   const int64_t us = FileTimeToMicroseconds(user_time);
682 #else
683   // Get the number of TSC ticks used by the current thread.
684   ULONG64 thread_cycle_time = 0;
685   ::QueryThreadCycleTime(thread_handle.platform_handle(), &thread_cycle_time);
686 
687   // Get the frequency of the TSC.
688   const double tsc_ticks_per_second = time_internal::TSCTicksPerSecond();
689   if (tsc_ticks_per_second == 0)
690     return ThreadTicks();
691 
692   // Return the CPU time of the current thread.
693   const double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second;
694   const int64_t us =
695       static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond);
696 #endif
697 
698   return ThreadTicks(us);
699 }
700 
701 // static
IsSupportedWin()702 bool ThreadTicks::IsSupportedWin() {
703 #if defined(ARCH_CPU_ARM64)
704   // The Arm implementation does not use QueryThreadCycleTime and therefore does
705   // not care about the time stamp counter.
706   return true;
707 #else
708   return time_internal::HasConstantRateTSC();
709 #endif
710 }
711 
712 // static
WaitUntilInitializedWin()713 void ThreadTicks::WaitUntilInitializedWin() {
714 #if !defined(ARCH_CPU_ARM64)
715   while (time_internal::TSCTicksPerSecond() == 0)
716     ::Sleep(10);
717 #endif
718 }
719 
720 // static
FromQPCValue(LONGLONG qpc_value)721 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
722   return TimeTicks() + QPCValueToTimeDelta(qpc_value);
723 }
724 
725 // TimeDelta ------------------------------------------------------------------
726 
727 // static
FromQPCValue(LONGLONG qpc_value)728 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
729   return QPCValueToTimeDelta(qpc_value);
730 }
731 
732 // static
FromFileTime(FILETIME ft)733 TimeDelta TimeDelta::FromFileTime(FILETIME ft) {
734   return Microseconds(FileTimeToMicroseconds(ft));
735 }
736 
737 // static
FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt)738 TimeDelta TimeDelta::FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt) {
739   // UniversalTime is 100 ns intervals since January 1, 1601 (UTC)
740   return Microseconds(dt.UniversalTime / 10);
741 }
742 
ToWinrtDateTime() const743 ABI::Windows::Foundation::DateTime TimeDelta::ToWinrtDateTime() const {
744   ABI::Windows::Foundation::DateTime date_time;
745   date_time.UniversalTime = InMicroseconds() * 10;
746   return date_time;
747 }
748 
749 // static
FromWinrtTimeSpan(ABI::Windows::Foundation::TimeSpan ts)750 TimeDelta TimeDelta::FromWinrtTimeSpan(ABI::Windows::Foundation::TimeSpan ts) {
751   // Duration is 100 ns intervals
752   return Microseconds(ts.Duration / 10);
753 }
754 
ToWinrtTimeSpan() const755 ABI::Windows::Foundation::TimeSpan TimeDelta::ToWinrtTimeSpan() const {
756   ABI::Windows::Foundation::TimeSpan time_span;
757   time_span.Duration = InMicroseconds() * 10;
758   return time_span;
759 }
760 
761 #if !defined(ARCH_CPU_ARM64)
762 namespace time_internal {
763 
HasConstantRateTSC()764 bool HasConstantRateTSC() {
765   static bool is_supported = CPU().has_non_stop_time_stamp_counter();
766   return is_supported;
767 }
768 
TSCTicksPerSecond()769 double TSCTicksPerSecond() {
770   DCHECK(HasConstantRateTSC());
771   // The value returned by QueryPerformanceFrequency() cannot be used as the TSC
772   // frequency, because there is no guarantee that the TSC frequency is equal to
773   // the performance counter frequency.
774   // The TSC frequency is cached in a static variable because it takes some time
775   // to compute it.
776   static double tsc_ticks_per_second = 0;
777   if (tsc_ticks_per_second != 0)
778     return tsc_ticks_per_second;
779 
780   // Increase the thread priority to reduces the chances of having a context
781   // switch during a reading of the TSC and the performance counter.
782   const int previous_priority = ::GetThreadPriority(::GetCurrentThread());
783   ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
784 
785   // The first time that this function is called, make an initial reading of the
786   // TSC and the performance counter.
787 
788   static const uint64_t tsc_initial = __rdtsc();
789   static const int64_t perf_counter_initial = QPCNowRaw();
790 
791   // Make a another reading of the TSC and the performance counter every time
792   // that this function is called.
793   const uint64_t tsc_now = __rdtsc();
794   const int64_t perf_counter_now = QPCNowRaw();
795 
796   // Reset the thread priority.
797   ::SetThreadPriority(::GetCurrentThread(), previous_priority);
798 
799   // Make sure that at least 50 ms elapsed between the 2 readings. The first
800   // time that this function is called, we don't expect this to be the case.
801   // Note: The longer the elapsed time between the 2 readings is, the more
802   //   accurate the computed TSC frequency will be. The 50 ms value was
803   //   chosen because local benchmarks show that it allows us to get a
804   //   stddev of less than 1 tick/us between multiple runs.
805   // Note: According to the MSDN documentation for QueryPerformanceFrequency(),
806   //   this will never fail on systems that run XP or later.
807   //   https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx
808   LARGE_INTEGER perf_counter_frequency = {};
809   ::QueryPerformanceFrequency(&perf_counter_frequency);
810   DCHECK_GE(perf_counter_now, perf_counter_initial);
811   const int64_t perf_counter_ticks = perf_counter_now - perf_counter_initial;
812   const double elapsed_time_seconds =
813       perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart);
814 
815   constexpr double kMinimumEvaluationPeriodSeconds = 0.05;
816   if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds)
817     return 0;
818 
819   // Compute the frequency of the TSC.
820   DCHECK_GE(tsc_now, tsc_initial);
821   const uint64_t tsc_ticks = tsc_now - tsc_initial;
822   tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds;
823 
824   return tsc_ticks_per_second;
825 }
826 
827 }  // namespace time_internal
828 #endif  // defined(ARCH_CPU_ARM64)
829 
830 }  // namespace base
831