| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 |  | 
 | // Windows Timer Primer | 
 | // | 
 | // A good article:  http://www.ddj.com/windows/184416651 | 
 | // A good mozilla bug:  http://bugzilla.mozilla.org/show_bug.cgi?id=363258 | 
 | // | 
 | // The default windows timer, GetSystemTimeAsFileTime is not very precise. | 
 | // It is only good to ~15.5ms. | 
 | // | 
 | // QueryPerformanceCounter is the logical choice for a high-precision timer. | 
 | // However, it is known to be buggy on some hardware.  Specifically, it can | 
 | // sometimes "jump".  On laptops, QPC can also be very expensive to call. | 
 | // It's 3-4x slower than timeGetTime() on desktops, but can be 10x slower | 
 | // on laptops.  A unittest exists which will show the relative cost of various | 
 | // timers on any system. | 
 | // | 
 | // The next logical choice is timeGetTime().  timeGetTime has a precision of | 
 | // 1ms, but only if you call APIs (timeBeginPeriod()) which affect all other | 
 | // applications on the system.  By default, precision is only 15.5ms. | 
 | // Unfortunately, we don't want to call timeBeginPeriod because we don't | 
 | // want to affect other applications.  Further, on mobile platforms, use of | 
 | // faster multimedia timers can hurt battery life.  See the intel | 
 | // article about this here: | 
 | // http://softwarecommunity.intel.com/articles/eng/1086.htm | 
 | // | 
 | // To work around all this, we're going to generally use timeGetTime().  We | 
 | // will only increase the system-wide timer if we're not running on battery | 
 | // power. | 
 |  | 
 | #include "base/time/time.h" | 
 |  | 
 | #include <windows.h> | 
 | #include <mmsystem.h> | 
 | #include <stdint.h> | 
 |  | 
 | #include "base/atomicops.h" | 
 | #include "base/bit_cast.h" | 
 | #include "base/cpu.h" | 
 | #include "base/logging.h" | 
 | #include "base/synchronization/lock.h" | 
 | #include "base/threading/platform_thread.h" | 
 | #include "base/time/time_override.h" | 
 |  | 
 | namespace base { | 
 |  | 
 | namespace { | 
 |  | 
 | // From MSDN, FILETIME "Contains a 64-bit value representing the number of | 
 | // 100-nanosecond intervals since January 1, 1601 (UTC)." | 
 | int64_t FileTimeToMicroseconds(const FILETIME& ft) { | 
 |   // Need to bit_cast to fix alignment, then divide by 10 to convert | 
 |   // 100-nanoseconds to microseconds. This only works on little-endian | 
 |   // machines. | 
 |   return bit_cast<int64_t, FILETIME>(ft) / 10; | 
 | } | 
 |  | 
 | void MicrosecondsToFileTime(int64_t us, FILETIME* ft) { | 
 |   DCHECK_GE(us, 0LL) << "Time is less than 0, negative values are not " | 
 |       "representable in FILETIME"; | 
 |  | 
 |   // Multiply by 10 to convert microseconds to 100-nanoseconds. Bit_cast will | 
 |   // handle alignment problems. This only works on little-endian machines. | 
 |   *ft = bit_cast<FILETIME, int64_t>(us * 10); | 
 | } | 
 |  | 
 | int64_t CurrentWallclockMicroseconds() { | 
 |   FILETIME ft; | 
 |   ::GetSystemTimeAsFileTime(&ft); | 
 |   return FileTimeToMicroseconds(ft); | 
 | } | 
 |  | 
 | // Time between resampling the un-granular clock for this API. | 
 | constexpr TimeDelta kMaxTimeToAvoidDrift = TimeDelta::FromSeconds(60); | 
 |  | 
 | int64_t g_initial_time = 0; | 
 | TimeTicks g_initial_ticks; | 
 |  | 
 | void InitializeClock() { | 
 |   g_initial_ticks = subtle::TimeTicksNowIgnoringOverride(); | 
 |   g_initial_time = CurrentWallclockMicroseconds(); | 
 | } | 
 |  | 
 | // The two values that ActivateHighResolutionTimer uses to set the systemwide | 
 | // timer interrupt frequency on Windows. It controls how precise timers are | 
 | // but also has a big impact on battery life. | 
 | const int kMinTimerIntervalHighResMs = 1; | 
 | const int kMinTimerIntervalLowResMs = 4; | 
 | // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. | 
 | bool g_high_res_timer_enabled = false; | 
 | // How many times the high resolution timer has been called. | 
 | uint32_t g_high_res_timer_count = 0; | 
 | // Start time of the high resolution timer usage monitoring. This is needed | 
 | // to calculate the usage as percentage of the total elapsed time. | 
 | TimeTicks g_high_res_timer_usage_start; | 
 | // The cumulative time the high resolution timer has been in use since | 
 | // |g_high_res_timer_usage_start| moment. | 
 | TimeDelta g_high_res_timer_usage; | 
 | // Timestamp of the last activation change of the high resolution timer. This | 
 | // is used to calculate the cumulative usage. | 
 | TimeTicks g_high_res_timer_last_activation; | 
 | // The lock to control access to the above two variables. | 
 | Lock* GetHighResLock() { | 
 |   static auto* lock = new Lock(); | 
 |   return lock; | 
 | } | 
 |  | 
 | // Returns the current value of the performance counter. | 
 | uint64_t QPCNowRaw() { | 
 |   LARGE_INTEGER perf_counter_now = {}; | 
 |   // According to the MSDN documentation for QueryPerformanceCounter(), this | 
 |   // will never fail on systems that run XP or later. | 
 |   // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx | 
 |   ::QueryPerformanceCounter(&perf_counter_now); | 
 |   return perf_counter_now.QuadPart; | 
 | } | 
 |  | 
 | bool SafeConvertToWord(int in, WORD* out) { | 
 |   CheckedNumeric<WORD> result = in; | 
 |   *out = result.ValueOrDefault(std::numeric_limits<WORD>::max()); | 
 |   return result.IsValid(); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | // Time ----------------------------------------------------------------------- | 
 |  | 
 | namespace subtle { | 
 | Time TimeNowIgnoringOverride() { | 
 |   if (g_initial_time == 0) | 
 |     InitializeClock(); | 
 |  | 
 |   // We implement time using the high-resolution timers so that we can get | 
 |   // timeouts which are smaller than 10-15ms.  If we just used | 
 |   // CurrentWallclockMicroseconds(), we'd have the less-granular timer. | 
 |   // | 
 |   // To make this work, we initialize the clock (g_initial_time) and the | 
 |   // counter (initial_ctr).  To compute the initial time, we can check | 
 |   // the number of ticks that have elapsed, and compute the delta. | 
 |   // | 
 |   // To avoid any drift, we periodically resync the counters to the system | 
 |   // clock. | 
 |   while (true) { | 
 |     TimeTicks ticks = TimeTicksNowIgnoringOverride(); | 
 |  | 
 |     // Calculate the time elapsed since we started our timer | 
 |     TimeDelta elapsed = ticks - g_initial_ticks; | 
 |  | 
 |     // Check if enough time has elapsed that we need to resync the clock. | 
 |     if (elapsed > kMaxTimeToAvoidDrift) { | 
 |       InitializeClock(); | 
 |       continue; | 
 |     } | 
 |  | 
 |     return Time() + elapsed + TimeDelta::FromMicroseconds(g_initial_time); | 
 |   } | 
 | } | 
 |  | 
 | Time TimeNowFromSystemTimeIgnoringOverride() { | 
 |   // Force resync. | 
 |   InitializeClock(); | 
 |   return Time() + TimeDelta::FromMicroseconds(g_initial_time); | 
 | } | 
 | }  // namespace subtle | 
 |  | 
 | // static | 
 | Time Time::FromFileTime(FILETIME ft) { | 
 |   if (bit_cast<int64_t, FILETIME>(ft) == 0) | 
 |     return Time(); | 
 |   if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() && | 
 |       ft.dwLowDateTime == std::numeric_limits<DWORD>::max()) | 
 |     return Max(); | 
 |   return Time(FileTimeToMicroseconds(ft)); | 
 | } | 
 |  | 
 | FILETIME Time::ToFileTime() const { | 
 |   if (is_null()) | 
 |     return bit_cast<FILETIME, int64_t>(0); | 
 |   if (is_max()) { | 
 |     FILETIME result; | 
 |     result.dwHighDateTime = std::numeric_limits<DWORD>::max(); | 
 |     result.dwLowDateTime = std::numeric_limits<DWORD>::max(); | 
 |     return result; | 
 |   } | 
 |   FILETIME utc_ft; | 
 |   MicrosecondsToFileTime(us_, &utc_ft); | 
 |   return utc_ft; | 
 | } | 
 |  | 
 | // static | 
 | void Time::EnableHighResolutionTimer(bool enable) { | 
 |   AutoLock lock(*GetHighResLock()); | 
 |   if (g_high_res_timer_enabled == enable) | 
 |     return; | 
 |   g_high_res_timer_enabled = enable; | 
 |   if (!g_high_res_timer_count) | 
 |     return; | 
 |   // Since g_high_res_timer_count != 0, an ActivateHighResolutionTimer(true) | 
 |   // was called which called timeBeginPeriod with g_high_res_timer_enabled | 
 |   // with a value which is the opposite of |enable|. With that information we | 
 |   // call timeEndPeriod with the same value used in timeBeginPeriod and | 
 |   // therefore undo the period effect. | 
 |   if (enable) { | 
 |     timeEndPeriod(kMinTimerIntervalLowResMs); | 
 |     timeBeginPeriod(kMinTimerIntervalHighResMs); | 
 |   } else { | 
 |     timeEndPeriod(kMinTimerIntervalHighResMs); | 
 |     timeBeginPeriod(kMinTimerIntervalLowResMs); | 
 |   } | 
 | } | 
 |  | 
 | // static | 
 | bool Time::ActivateHighResolutionTimer(bool activating) { | 
 |   // We only do work on the transition from zero to one or one to zero so we | 
 |   // can easily undo the effect (if necessary) when EnableHighResolutionTimer is | 
 |   // called. | 
 |   const uint32_t max = std::numeric_limits<uint32_t>::max(); | 
 |  | 
 |   AutoLock lock(*GetHighResLock()); | 
 |   UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs | 
 |                                          : kMinTimerIntervalLowResMs; | 
 |   if (activating) { | 
 |     DCHECK_NE(g_high_res_timer_count, max); | 
 |     ++g_high_res_timer_count; | 
 |     if (g_high_res_timer_count == 1) { | 
 |       g_high_res_timer_last_activation = subtle::TimeTicksNowIgnoringOverride(); | 
 |       timeBeginPeriod(period); | 
 |     } | 
 |   } else { | 
 |     DCHECK_NE(g_high_res_timer_count, 0u); | 
 |     --g_high_res_timer_count; | 
 |     if (g_high_res_timer_count == 0) { | 
 |       g_high_res_timer_usage += subtle::TimeTicksNowIgnoringOverride() - | 
 |                                 g_high_res_timer_last_activation; | 
 |       timeEndPeriod(period); | 
 |     } | 
 |   } | 
 |   return (period == kMinTimerIntervalHighResMs); | 
 | } | 
 |  | 
 | // static | 
 | bool Time::IsHighResolutionTimerInUse() { | 
 |   AutoLock lock(*GetHighResLock()); | 
 |   return g_high_res_timer_enabled && g_high_res_timer_count > 0; | 
 | } | 
 |  | 
 | // static | 
 | void Time::ResetHighResolutionTimerUsage() { | 
 |   AutoLock lock(*GetHighResLock()); | 
 |   g_high_res_timer_usage = TimeDelta(); | 
 |   g_high_res_timer_usage_start = subtle::TimeTicksNowIgnoringOverride(); | 
 |   if (g_high_res_timer_count > 0) | 
 |     g_high_res_timer_last_activation = g_high_res_timer_usage_start; | 
 | } | 
 |  | 
 | // static | 
 | double Time::GetHighResolutionTimerUsage() { | 
 |   AutoLock lock(*GetHighResLock()); | 
 |   TimeTicks now = subtle::TimeTicksNowIgnoringOverride(); | 
 |   TimeDelta elapsed_time = now - g_high_res_timer_usage_start; | 
 |   if (elapsed_time.is_zero()) { | 
 |     // This is unexpected but possible if TimeTicks resolution is low and | 
 |     // GetHighResolutionTimerUsage() is called promptly after | 
 |     // ResetHighResolutionTimerUsage(). | 
 |     return 0.0; | 
 |   } | 
 |   TimeDelta used_time = g_high_res_timer_usage; | 
 |   if (g_high_res_timer_count > 0) { | 
 |     // If currently activated add the remainder of time since the last | 
 |     // activation. | 
 |     used_time += now - g_high_res_timer_last_activation; | 
 |   } | 
 |   return used_time.InMillisecondsF() / elapsed_time.InMillisecondsF() * 100; | 
 | } | 
 |  | 
 | // static | 
 | bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { | 
 |   // Create the system struct representing our exploded time. It will either be | 
 |   // in local time or UTC.If casting from int to WORD results in overflow, | 
 |   // fail and return Time(0). | 
 |   SYSTEMTIME st; | 
 |   if (!SafeConvertToWord(exploded.year, &st.wYear) || | 
 |       !SafeConvertToWord(exploded.month, &st.wMonth) || | 
 |       !SafeConvertToWord(exploded.day_of_week, &st.wDayOfWeek) || | 
 |       !SafeConvertToWord(exploded.day_of_month, &st.wDay) || | 
 |       !SafeConvertToWord(exploded.hour, &st.wHour) || | 
 |       !SafeConvertToWord(exploded.minute, &st.wMinute) || | 
 |       !SafeConvertToWord(exploded.second, &st.wSecond) || | 
 |       !SafeConvertToWord(exploded.millisecond, &st.wMilliseconds)) { | 
 |     *time = Time(0); | 
 |     return false; | 
 |   } | 
 |  | 
 |   FILETIME ft; | 
 |   bool success = true; | 
 |   // Ensure that it's in UTC. | 
 |   if (is_local) { | 
 |     SYSTEMTIME utc_st; | 
 |     success = TzSpecificLocalTimeToSystemTime(nullptr, &st, &utc_st) && | 
 |               SystemTimeToFileTime(&utc_st, &ft); | 
 |   } else { | 
 |     success = !!SystemTimeToFileTime(&st, &ft); | 
 |   } | 
 |  | 
 |   if (!success) { | 
 |     *time = Time(0); | 
 |     return false; | 
 |   } | 
 |  | 
 |   *time = Time(FileTimeToMicroseconds(ft)); | 
 |   return true; | 
 | } | 
 |  | 
 | void Time::Explode(bool is_local, Exploded* exploded) const { | 
 |   if (us_ < 0LL) { | 
 |     // We are not able to convert it to FILETIME. | 
 |     ZeroMemory(exploded, sizeof(*exploded)); | 
 |     return; | 
 |   } | 
 |  | 
 |   // FILETIME in UTC. | 
 |   FILETIME utc_ft; | 
 |   MicrosecondsToFileTime(us_, &utc_ft); | 
 |  | 
 |   // FILETIME in local time if necessary. | 
 |   bool success = true; | 
 |   // FILETIME in SYSTEMTIME (exploded). | 
 |   SYSTEMTIME st = {0}; | 
 |   if (is_local) { | 
 |     SYSTEMTIME utc_st; | 
 |     // We don't use FileTimeToLocalFileTime here, since it uses the current | 
 |     // settings for the time zone and daylight saving time. Therefore, if it is | 
 |     // daylight saving time, it will take daylight saving time into account, | 
 |     // even if the time you are converting is in standard time. | 
 |     success = FileTimeToSystemTime(&utc_ft, &utc_st) && | 
 |               SystemTimeToTzSpecificLocalTime(nullptr, &utc_st, &st); | 
 |   } else { | 
 |     success = !!FileTimeToSystemTime(&utc_ft, &st); | 
 |   } | 
 |  | 
 |   if (!success) { | 
 |     NOTREACHED() << "Unable to convert time, don't know why"; | 
 |     ZeroMemory(exploded, sizeof(*exploded)); | 
 |     return; | 
 |   } | 
 |  | 
 |   exploded->year = st.wYear; | 
 |   exploded->month = st.wMonth; | 
 |   exploded->day_of_week = st.wDayOfWeek; | 
 |   exploded->day_of_month = st.wDay; | 
 |   exploded->hour = st.wHour; | 
 |   exploded->minute = st.wMinute; | 
 |   exploded->second = st.wSecond; | 
 |   exploded->millisecond = st.wMilliseconds; | 
 | } | 
 |  | 
 | // TimeTicks ------------------------------------------------------------------ | 
 |  | 
 | namespace { | 
 |  | 
 | // We define a wrapper to adapt between the __stdcall and __cdecl call of the | 
 | // mock function, and to avoid a static constructor.  Assigning an import to a | 
 | // function pointer directly would require setup code to fetch from the IAT. | 
 | DWORD timeGetTimeWrapper() { | 
 |   return timeGetTime(); | 
 | } | 
 |  | 
 | DWORD (*g_tick_function)(void) = &timeGetTimeWrapper; | 
 |  | 
 | // A structure holding the most significant bits of "last seen" and a | 
 | // "rollover" counter. | 
 | union LastTimeAndRolloversState { | 
 |   // The state as a single 32-bit opaque value. | 
 |   subtle::Atomic32 as_opaque_32; | 
 |  | 
 |   // The state as usable values. | 
 |   struct { | 
 |     // The top 8-bits of the "last" time. This is enough to check for rollovers | 
 |     // and the small bit-size means fewer CompareAndSwap operations to store | 
 |     // changes in state, which in turn makes for fewer retries. | 
 |     uint8_t last_8; | 
 |     // A count of the number of detected rollovers. Using this as bits 47-32 | 
 |     // of the upper half of a 64-bit value results in a 48-bit tick counter. | 
 |     // This extends the total rollover period from about 49 days to about 8800 | 
 |     // years while still allowing it to be stored with last_8 in a single | 
 |     // 32-bit value. | 
 |     uint16_t rollovers; | 
 |   } as_values; | 
 | }; | 
 | subtle::Atomic32 g_last_time_and_rollovers = 0; | 
 | static_assert( | 
 |     sizeof(LastTimeAndRolloversState) <= sizeof(g_last_time_and_rollovers), | 
 |     "LastTimeAndRolloversState does not fit in a single atomic word"); | 
 |  | 
 | // We use timeGetTime() to implement TimeTicks::Now().  This can be problematic | 
 | // because it returns the number of milliseconds since Windows has started, | 
 | // which will roll over the 32-bit value every ~49 days.  We try to track | 
 | // rollover ourselves, which works if TimeTicks::Now() is called at least every | 
 | // 48.8 days (not 49 days because only changes in the top 8 bits get noticed). | 
 | TimeTicks RolloverProtectedNow() { | 
 |   LastTimeAndRolloversState state; | 
 |   DWORD now;  // DWORD is always unsigned 32 bits. | 
 |  | 
 |   while (true) { | 
 |     // Fetch the "now" and "last" tick values, updating "last" with "now" and | 
 |     // incrementing the "rollovers" counter if the tick-value has wrapped back | 
 |     // around. Atomic operations ensure that both "last" and "rollovers" are | 
 |     // always updated together. | 
 |     int32_t original = subtle::Acquire_Load(&g_last_time_and_rollovers); | 
 |     state.as_opaque_32 = original; | 
 |     now = g_tick_function(); | 
 |     uint8_t now_8 = static_cast<uint8_t>(now >> 24); | 
 |     if (now_8 < state.as_values.last_8) | 
 |       ++state.as_values.rollovers; | 
 |     state.as_values.last_8 = now_8; | 
 |  | 
 |     // If the state hasn't changed, exit the loop. | 
 |     if (state.as_opaque_32 == original) | 
 |       break; | 
 |  | 
 |     // Save the changed state. If the existing value is unchanged from the | 
 |     // original, exit the loop. | 
 |     int32_t check = subtle::Release_CompareAndSwap( | 
 |         &g_last_time_and_rollovers, original, state.as_opaque_32); | 
 |     if (check == original) | 
 |       break; | 
 |  | 
 |     // Another thread has done something in between so retry from the top. | 
 |   } | 
 |  | 
 |   return TimeTicks() + | 
 |          TimeDelta::FromMilliseconds( | 
 |              now + (static_cast<uint64_t>(state.as_values.rollovers) << 32)); | 
 | } | 
 |  | 
 | // Discussion of tick counter options on Windows: | 
 | // | 
 | // (1) CPU cycle counter. (Retrieved via RDTSC) | 
 | // The CPU counter provides the highest resolution time stamp and is the least | 
 | // expensive to retrieve. However, on older CPUs, two issues can affect its | 
 | // reliability: First it is maintained per processor and not synchronized | 
 | // between processors. Also, the counters will change frequency due to thermal | 
 | // and power changes, and stop in some states. | 
 | // | 
 | // (2) QueryPerformanceCounter (QPC). The QPC counter provides a high- | 
 | // resolution (<1 microsecond) time stamp. On most hardware running today, it | 
 | // auto-detects and uses the constant-rate RDTSC counter to provide extremely | 
 | // efficient and reliable time stamps. | 
 | // | 
 | // On older CPUs where RDTSC is unreliable, it falls back to using more | 
 | // expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI | 
 | // PM timer, and can involve system calls; and all this is up to the HAL (with | 
 | // some help from ACPI). According to | 
 | // http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the | 
 | // worst case, it gets the counter from the rollover interrupt on the | 
 | // programmable interrupt timer. In best cases, the HAL may conclude that the | 
 | // RDTSC counter runs at a constant frequency, then it uses that instead. On | 
 | // multiprocessor machines, it will try to verify the values returned from | 
 | // RDTSC on each processor are consistent with each other, and apply a handful | 
 | // of workarounds for known buggy hardware. In other words, QPC is supposed to | 
 | // give consistent results on a multiprocessor computer, but for older CPUs it | 
 | // can be unreliable due bugs in BIOS or HAL. | 
 | // | 
 | // (3) System time. The system time provides a low-resolution (from ~1 to ~15.6 | 
 | // milliseconds) time stamp but is comparatively less expensive to retrieve and | 
 | // more reliable. Time::EnableHighResolutionTimer() and | 
 | // Time::ActivateHighResolutionTimer() can be called to alter the resolution of | 
 | // this timer; and also other Windows applications can alter it, affecting this | 
 | // one. | 
 |  | 
 | TimeTicks InitialNowFunction(); | 
 |  | 
 | // See "threading notes" in InitializeNowFunctionPointer() for details on how | 
 | // concurrent reads/writes to these globals has been made safe. | 
 | TimeTicksNowFunction g_time_ticks_now_ignoring_override_function = | 
 |     &InitialNowFunction; | 
 | int64_t g_qpc_ticks_per_second = 0; | 
 |  | 
 | // As of January 2015, use of <atomic> is forbidden in Chromium code. This is | 
 | // what std::atomic_thread_fence does on Windows on all Intel architectures when | 
 | // the memory_order argument is anything but std::memory_order_seq_cst: | 
 | #define ATOMIC_THREAD_FENCE(memory_order) _ReadWriteBarrier(); | 
 |  | 
 | TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) { | 
 |   // Ensure that the assignment to |g_qpc_ticks_per_second|, made in | 
 |   // InitializeNowFunctionPointer(), has happened by this point. | 
 |   ATOMIC_THREAD_FENCE(memory_order_acquire); | 
 |  | 
 |   DCHECK_GT(g_qpc_ticks_per_second, 0); | 
 |  | 
 |   // If the QPC Value is below the overflow threshold, we proceed with | 
 |   // simple multiply and divide. | 
 |   if (qpc_value < Time::kQPCOverflowThreshold) { | 
 |     return TimeDelta::FromMicroseconds( | 
 |         qpc_value * Time::kMicrosecondsPerSecond / g_qpc_ticks_per_second); | 
 |   } | 
 |   // Otherwise, calculate microseconds in a round about manner to avoid | 
 |   // overflow and precision issues. | 
 |   int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second; | 
 |   int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second); | 
 |   return TimeDelta::FromMicroseconds( | 
 |       (whole_seconds * Time::kMicrosecondsPerSecond) + | 
 |       ((leftover_ticks * Time::kMicrosecondsPerSecond) / | 
 |        g_qpc_ticks_per_second)); | 
 | } | 
 |  | 
 | TimeTicks QPCNow() { | 
 |   return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw()); | 
 | } | 
 |  | 
 | bool IsBuggyAthlon(const CPU& cpu) { | 
 |   // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is unreliable. | 
 |   return cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15; | 
 | } | 
 |  | 
 | void InitializeNowFunctionPointer() { | 
 |   LARGE_INTEGER ticks_per_sec = {}; | 
 |   if (!QueryPerformanceFrequency(&ticks_per_sec)) | 
 |     ticks_per_sec.QuadPart = 0; | 
 |  | 
 |   // If Windows cannot provide a QPC implementation, TimeTicks::Now() must use | 
 |   // the low-resolution clock. | 
 |   // | 
 |   // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now() | 
 |   // will still use the low-resolution clock. A CPU lacking a non-stop time | 
 |   // counter will cause Windows to provide an alternate QPC implementation that | 
 |   // works, but is expensive to use. Certain Athlon CPUs are known to make the | 
 |   // QPC implementation unreliable. | 
 |   // | 
 |   // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015, | 
 |   // ~72% of users fall within this category. | 
 |   TimeTicksNowFunction now_function; | 
 |   CPU cpu; | 
 |   if (ticks_per_sec.QuadPart <= 0 || | 
 |       !cpu.has_non_stop_time_stamp_counter() || IsBuggyAthlon(cpu)) { | 
 |     now_function = &RolloverProtectedNow; | 
 |   } else { | 
 |     now_function = &QPCNow; | 
 |   } | 
 |  | 
 |   // Threading note 1: In an unlikely race condition, it's possible for two or | 
 |   // more threads to enter InitializeNowFunctionPointer() in parallel. This is | 
 |   // not a problem since all threads should end up writing out the same values | 
 |   // to the global variables. | 
 |   // | 
 |   // Threading note 2: A release fence is placed here to ensure, from the | 
 |   // perspective of other threads using the function pointers, that the | 
 |   // assignment to |g_qpc_ticks_per_second| happens before the function pointers | 
 |   // are changed. | 
 |   g_qpc_ticks_per_second = ticks_per_sec.QuadPart; | 
 |   ATOMIC_THREAD_FENCE(memory_order_release); | 
 |   // Also set g_time_ticks_now_function to avoid the additional indirection via | 
 |   // TimeTicksNowIgnoringOverride() for future calls to TimeTicks::Now(). But | 
 |   // g_time_ticks_now_function may have already be overridden. | 
 |   if (internal::g_time_ticks_now_function == | 
 |       &subtle::TimeTicksNowIgnoringOverride) { | 
 |     internal::g_time_ticks_now_function = now_function; | 
 |   } | 
 |   g_time_ticks_now_ignoring_override_function = now_function; | 
 | } | 
 |  | 
 | TimeTicks InitialNowFunction() { | 
 |   InitializeNowFunctionPointer(); | 
 |   return g_time_ticks_now_ignoring_override_function(); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | // static | 
 | TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction( | 
 |     TickFunctionType ticker) { | 
 |   TickFunctionType old = g_tick_function; | 
 |   g_tick_function = ticker; | 
 |   subtle::NoBarrier_Store(&g_last_time_and_rollovers, 0); | 
 |   return old; | 
 | } | 
 |  | 
 | namespace subtle { | 
 | TimeTicks TimeTicksNowIgnoringOverride() { | 
 |   return g_time_ticks_now_ignoring_override_function(); | 
 | } | 
 | }  // namespace subtle | 
 |  | 
 | // static | 
 | bool TimeTicks::IsHighResolution() { | 
 |   if (g_time_ticks_now_ignoring_override_function == &InitialNowFunction) | 
 |     InitializeNowFunctionPointer(); | 
 |   return g_time_ticks_now_ignoring_override_function == &QPCNow; | 
 | } | 
 |  | 
 | // static | 
 | bool TimeTicks::IsConsistentAcrossProcesses() { | 
 |   // According to Windows documentation [1] QPC is consistent post-Windows | 
 |   // Vista. So if we are using QPC then we are consistent which is the same as | 
 |   // being high resolution. | 
 |   // | 
 |   // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx | 
 |   // | 
 |   // "In general, the performance counter results are consistent across all | 
 |   // processors in multi-core and multi-processor systems, even when measured on | 
 |   // different threads or processes. Here are some exceptions to this rule: | 
 |   // - Pre-Windows Vista operating systems that run on certain processors might | 
 |   // violate this consistency because of one of these reasons: | 
 |   //     1. The hardware processors have a non-invariant TSC and the BIOS | 
 |   //     doesn't indicate this condition correctly. | 
 |   //     2. The TSC synchronization algorithm that was used wasn't suitable for | 
 |   //     systems with large numbers of processors." | 
 |   return IsHighResolution(); | 
 | } | 
 |  | 
 | // static | 
 | TimeTicks::Clock TimeTicks::GetClock() { | 
 |   return IsHighResolution() ? | 
 |       Clock::WIN_QPC : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME; | 
 | } | 
 |  | 
 | // ThreadTicks ---------------------------------------------------------------- | 
 |  | 
 | namespace subtle { | 
 | ThreadTicks ThreadTicksNowIgnoringOverride() { | 
 |   return ThreadTicks::GetForThread(PlatformThread::CurrentHandle()); | 
 | } | 
 | }  // namespace subtle | 
 |  | 
 | // static | 
 | ThreadTicks ThreadTicks::GetForThread( | 
 |     const PlatformThreadHandle& thread_handle) { | 
 |   DCHECK(IsSupported()); | 
 |  | 
 |   // Get the number of TSC ticks used by the current thread. | 
 |   ULONG64 thread_cycle_time = 0; | 
 |   ::QueryThreadCycleTime(thread_handle.platform_handle(), &thread_cycle_time); | 
 |  | 
 |   // Get the frequency of the TSC. | 
 |   double tsc_ticks_per_second = TSCTicksPerSecond(); | 
 |   if (tsc_ticks_per_second == 0) | 
 |     return ThreadTicks(); | 
 |  | 
 |   // Return the CPU time of the current thread. | 
 |   double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second; | 
 |   return ThreadTicks( | 
 |       static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond)); | 
 | } | 
 |  | 
 | // static | 
 | bool ThreadTicks::IsSupportedWin() { | 
 |   static bool is_supported = | 
 |       CPU().has_non_stop_time_stamp_counter() && !IsBuggyAthlon(CPU()); | 
 |   return is_supported; | 
 | } | 
 |  | 
 | // static | 
 | void ThreadTicks::WaitUntilInitializedWin() { | 
 |   while (TSCTicksPerSecond() == 0) | 
 |     ::Sleep(10); | 
 | } | 
 |  | 
 | double ThreadTicks::TSCTicksPerSecond() { | 
 |   DCHECK(IsSupported()); | 
 |  | 
 |   // The value returned by QueryPerformanceFrequency() cannot be used as the TSC | 
 |   // frequency, because there is no guarantee that the TSC frequency is equal to | 
 |   // the performance counter frequency. | 
 |  | 
 |   // The TSC frequency is cached in a static variable because it takes some time | 
 |   // to compute it. | 
 |   static double tsc_ticks_per_second = 0; | 
 |   if (tsc_ticks_per_second != 0) | 
 |     return tsc_ticks_per_second; | 
 |  | 
 |   // Increase the thread priority to reduces the chances of having a context | 
 |   // switch during a reading of the TSC and the performance counter. | 
 |   int previous_priority = ::GetThreadPriority(::GetCurrentThread()); | 
 |   ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST); | 
 |  | 
 |   // The first time that this function is called, make an initial reading of the | 
 |   // TSC and the performance counter. | 
 |   static const uint64_t tsc_initial = __rdtsc(); | 
 |   static const uint64_t perf_counter_initial = QPCNowRaw(); | 
 |  | 
 |   // Make a another reading of the TSC and the performance counter every time | 
 |   // that this function is called. | 
 |   uint64_t tsc_now = __rdtsc(); | 
 |   uint64_t perf_counter_now = QPCNowRaw(); | 
 |  | 
 |   // Reset the thread priority. | 
 |   ::SetThreadPriority(::GetCurrentThread(), previous_priority); | 
 |  | 
 |   // Make sure that at least 50 ms elapsed between the 2 readings. The first | 
 |   // time that this function is called, we don't expect this to be the case. | 
 |   // Note: The longer the elapsed time between the 2 readings is, the more | 
 |   //   accurate the computed TSC frequency will be. The 50 ms value was | 
 |   //   chosen because local benchmarks show that it allows us to get a | 
 |   //   stddev of less than 1 tick/us between multiple runs. | 
 |   // Note: According to the MSDN documentation for QueryPerformanceFrequency(), | 
 |   //   this will never fail on systems that run XP or later. | 
 |   //   https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx | 
 |   LARGE_INTEGER perf_counter_frequency = {}; | 
 |   ::QueryPerformanceFrequency(&perf_counter_frequency); | 
 |   DCHECK_GE(perf_counter_now, perf_counter_initial); | 
 |   uint64_t perf_counter_ticks = perf_counter_now - perf_counter_initial; | 
 |   double elapsed_time_seconds = | 
 |       perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart); | 
 |  | 
 |   static constexpr double kMinimumEvaluationPeriodSeconds = 0.05; | 
 |   if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds) | 
 |     return 0; | 
 |  | 
 |   // Compute the frequency of the TSC. | 
 |   DCHECK_GE(tsc_now, tsc_initial); | 
 |   uint64_t tsc_ticks = tsc_now - tsc_initial; | 
 |   tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds; | 
 |  | 
 |   return tsc_ticks_per_second; | 
 | } | 
 |  | 
 | // static | 
 | TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { | 
 |   return TimeTicks() + QPCValueToTimeDelta(qpc_value); | 
 | } | 
 |  | 
 | // TimeDelta ------------------------------------------------------------------ | 
 |  | 
 | // static | 
 | TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { | 
 |   return QPCValueToTimeDelta(qpc_value); | 
 | } | 
 |  | 
 | // static | 
 | TimeDelta TimeDelta::FromFileTime(FILETIME ft) { | 
 |   return TimeDelta::FromMicroseconds(FileTimeToMicroseconds(ft)); | 
 | } | 
 |  | 
 | }  // namespace base |