• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Windows Timer Primer
6 //
7 // A good article:  http://www.ddj.com/windows/184416651
8 // A good mozilla bug:  http://bugzilla.mozilla.org/show_bug.cgi?id=363258
9 //
10 // The default windows timer, GetSystemTimePreciseAsFileTime is quite precise.
11 // However it is not always fast on some hardware and is slower than the
12 // performance counters.
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   ::GetSystemTimePreciseAsFileTime(&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 likely are smaller than those if we just used
194   // CurrentWallclockMicroseconds().
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 9 September 2024,
557   // ~97% 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 
TimeTicksLowResolutionNowIgnoringOverride()611 TimeTicks TimeTicksLowResolutionNowIgnoringOverride() {
612   return RolloverProtectedNow();
613 }
614 }  // namespace subtle
615 
616 // static
IsHighResolution()617 bool TimeTicks::IsHighResolution() {
618   if (g_time_ticks_now_ignoring_override_function == &InitialNowFunction)
619     InitializeNowFunctionPointer();
620   return g_time_ticks_now_ignoring_override_function == &QPCNow;
621 }
622 
623 // static
IsConsistentAcrossProcesses()624 bool TimeTicks::IsConsistentAcrossProcesses() {
625   // According to Windows documentation [1] QPC is consistent post-Windows
626   // Vista. So if we are using QPC then we are consistent which is the same as
627   // being high resolution.
628   //
629   // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
630   //
631   // "In general, the performance counter results are consistent across all
632   // processors in multi-core and multi-processor systems, even when measured on
633   // different threads or processes. Here are some exceptions to this rule:
634   // - Pre-Windows Vista operating systems that run on certain processors might
635   // violate this consistency because of one of these reasons:
636   //     1. The hardware processors have a non-invariant TSC and the BIOS
637   //     doesn't indicate this condition correctly.
638   //     2. The TSC synchronization algorithm that was used wasn't suitable for
639   //     systems with large numbers of processors."
640   return IsHighResolution();
641 }
642 
643 // static
GetClock()644 TimeTicks::Clock TimeTicks::GetClock() {
645   return IsHighResolution() ? Clock::WIN_QPC
646                             : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME;
647 }
648 
649 // LiveTicks ------------------------------------------------------------------
650 
651 namespace subtle {
LiveTicksNowIgnoringOverride()652 LiveTicks LiveTicksNowIgnoringOverride() {
653   ULONGLONG unbiased_interrupt_time;
654   QueryUnbiasedInterruptTimePrecise(&unbiased_interrupt_time);
655   // QueryUnbiasedInterruptTimePrecise gets the interrupt time in system time
656   // units of 100 nanoseconds.
657   return LiveTicks() + Nanoseconds(unbiased_interrupt_time * 100);
658 }
659 }  // namespace subtle
660 
661 // ThreadTicks ----------------------------------------------------------------
662 
663 namespace subtle {
ThreadTicksNowIgnoringOverride()664 ThreadTicks ThreadTicksNowIgnoringOverride() {
665   return ThreadTicks::GetForThread(PlatformThread::CurrentHandle());
666 }
667 }  // namespace subtle
668 
669 // static
GetForThread(const PlatformThreadHandle & thread_handle)670 ThreadTicks ThreadTicks::GetForThread(
671     const PlatformThreadHandle& thread_handle) {
672   DCHECK(IsSupported());
673 
674 #if defined(ARCH_CPU_ARM64)
675   // QueryThreadCycleTime versus TSCTicksPerSecond doesn't have much relation to
676   // actual elapsed time on Windows on Arm, because QueryThreadCycleTime is
677   // backed by the actual number of CPU cycles executed, rather than a
678   // constant-rate timer like Intel. To work around this, use GetThreadTimes
679   // (which isn't as accurate but is meaningful as a measure of elapsed
680   // per-thread time).
681   FILETIME creation_time, exit_time, kernel_time, user_time;
682   ::GetThreadTimes(thread_handle.platform_handle(), &creation_time, &exit_time,
683                    &kernel_time, &user_time);
684 
685   const int64_t us = FileTimeToMicroseconds(user_time);
686 #else
687   // Get the number of TSC ticks used by the current thread.
688   ULONG64 thread_cycle_time = 0;
689   ::QueryThreadCycleTime(thread_handle.platform_handle(), &thread_cycle_time);
690 
691   // Get the frequency of the TSC.
692   const double tsc_ticks_per_second = time_internal::TSCTicksPerSecond();
693   if (tsc_ticks_per_second == 0)
694     return ThreadTicks();
695 
696   // Return the CPU time of the current thread.
697   const double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second;
698   const int64_t us =
699       static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond);
700 #endif
701 
702   return ThreadTicks(us);
703 }
704 
705 // static
IsSupportedWin()706 bool ThreadTicks::IsSupportedWin() {
707 #if defined(ARCH_CPU_ARM64)
708   // The Arm implementation does not use QueryThreadCycleTime and therefore does
709   // not care about the time stamp counter.
710   return true;
711 #else
712   return time_internal::HasConstantRateTSC();
713 #endif
714 }
715 
716 // static
WaitUntilInitializedWin()717 void ThreadTicks::WaitUntilInitializedWin() {
718 #if !defined(ARCH_CPU_ARM64)
719   while (time_internal::TSCTicksPerSecond() == 0)
720     ::Sleep(10);
721 #endif
722 }
723 
724 // static
FromQPCValue(LONGLONG qpc_value)725 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
726   return TimeTicks() + QPCValueToTimeDelta(qpc_value);
727 }
728 
729 // TimeDelta ------------------------------------------------------------------
730 
731 // static
FromQPCValue(LONGLONG qpc_value)732 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
733   return QPCValueToTimeDelta(qpc_value);
734 }
735 
736 // static
FromFileTime(FILETIME ft)737 TimeDelta TimeDelta::FromFileTime(FILETIME ft) {
738   return Microseconds(FileTimeToMicroseconds(ft));
739 }
740 
741 // static
FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt)742 TimeDelta TimeDelta::FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt) {
743   // UniversalTime is 100 ns intervals since January 1, 1601 (UTC)
744   return Microseconds(dt.UniversalTime / 10);
745 }
746 
ToWinrtDateTime() const747 ABI::Windows::Foundation::DateTime TimeDelta::ToWinrtDateTime() const {
748   ABI::Windows::Foundation::DateTime date_time;
749   date_time.UniversalTime = InMicroseconds() * 10;
750   return date_time;
751 }
752 
753 // static
FromWinrtTimeSpan(ABI::Windows::Foundation::TimeSpan ts)754 TimeDelta TimeDelta::FromWinrtTimeSpan(ABI::Windows::Foundation::TimeSpan ts) {
755   // Duration is 100 ns intervals
756   return Microseconds(ts.Duration / 10);
757 }
758 
ToWinrtTimeSpan() const759 ABI::Windows::Foundation::TimeSpan TimeDelta::ToWinrtTimeSpan() const {
760   ABI::Windows::Foundation::TimeSpan time_span;
761   time_span.Duration = InMicroseconds() * 10;
762   return time_span;
763 }
764 
765 #if !defined(ARCH_CPU_ARM64)
766 namespace time_internal {
767 
HasConstantRateTSC()768 bool HasConstantRateTSC() {
769   static bool is_supported = CPU().has_non_stop_time_stamp_counter();
770   return is_supported;
771 }
772 
TSCTicksPerSecond()773 double TSCTicksPerSecond() {
774   DCHECK(HasConstantRateTSC());
775   // The value returned by QueryPerformanceFrequency() cannot be used as the TSC
776   // frequency, because there is no guarantee that the TSC frequency is equal to
777   // the performance counter frequency.
778   // The TSC frequency is cached in a static variable because it takes some time
779   // to compute it.
780   static double tsc_ticks_per_second = 0;
781   if (tsc_ticks_per_second != 0)
782     return tsc_ticks_per_second;
783 
784   // Increase the thread priority to reduces the chances of having a context
785   // switch during a reading of the TSC and the performance counter.
786   const int previous_priority = ::GetThreadPriority(::GetCurrentThread());
787   ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
788 
789   // The first time that this function is called, make an initial reading of the
790   // TSC and the performance counter.
791 
792   static const uint64_t tsc_initial = __rdtsc();
793   static const int64_t perf_counter_initial = QPCNowRaw();
794 
795   // Make a another reading of the TSC and the performance counter every time
796   // that this function is called.
797   const uint64_t tsc_now = __rdtsc();
798   const int64_t perf_counter_now = QPCNowRaw();
799 
800   // Reset the thread priority.
801   ::SetThreadPriority(::GetCurrentThread(), previous_priority);
802 
803   // Make sure that at least 50 ms elapsed between the 2 readings. The first
804   // time that this function is called, we don't expect this to be the case.
805   // Note: The longer the elapsed time between the 2 readings is, the more
806   //   accurate the computed TSC frequency will be. The 50 ms value was
807   //   chosen because local benchmarks show that it allows us to get a
808   //   stddev of less than 1 tick/us between multiple runs.
809   // Note: According to the MSDN documentation for QueryPerformanceFrequency(),
810   //   this will never fail on systems that run XP or later.
811   //   https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx
812   LARGE_INTEGER perf_counter_frequency = {};
813   ::QueryPerformanceFrequency(&perf_counter_frequency);
814   DCHECK_GE(perf_counter_now, perf_counter_initial);
815   const int64_t perf_counter_ticks = perf_counter_now - perf_counter_initial;
816   const double elapsed_time_seconds =
817       perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart);
818 
819   constexpr double kMinimumEvaluationPeriodSeconds = 0.05;
820   if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds)
821     return 0;
822 
823   // Compute the frequency of the TSC.
824   DCHECK_GE(tsc_now, tsc_initial);
825   const uint64_t tsc_ticks = tsc_now - tsc_initial;
826   tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds;
827 
828   return tsc_ticks_per_second;
829 }
830 
831 }  // namespace time_internal
832 #endif  // defined(ARCH_CPU_ARM64)
833 
834 }  // namespace base
835