15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows Timer Primer 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A good article: http://www.ddj.com/windows/184416651 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The default windows timer, GetSystemTimeAsFileTime is not very precise. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is only good to ~15.5ms. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// QueryPerformanceCounter is the logical choice for a high-precision timer. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// However, it is known to be buggy on some hardware. Specifically, it can 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sometimes "jump". On laptops, QPC can also be very expensive to call. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It's 3-4x slower than timeGetTime() on desktops, but can be 10x slower 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on laptops. A unittest exists which will show the relative cost of various 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// timers on any system. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The next logical choice is timeGetTime(). timeGetTime has a precision of 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1ms, but only if you call APIs (timeBeginPeriod()) which affect all other 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// applications on the system. By default, precision is only 15.5ms. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Unfortunately, we don't want to call timeBeginPeriod because we don't 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// want to affect other applications. Further, on mobile platforms, use of 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// faster multimedia timers can hurt battery life. See the intel 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// article about this here: 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://softwarecommunity.intel.com/articles/eng/1086.htm 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To work around all this, we're going to generally use timeGetTime(). We 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will only increase the system-wide timer if we're not running on battery 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// power. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "winmm.lib") 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mmsystem.h> 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/cpu.h" 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/lazy_instance.h" 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/logging.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// From MSDN, FILETIME "Contains a 64-bit value representing the number of 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 100-nanosecond intervals since January 1, 1601 (UTC)." 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 FileTimeToMicroseconds(const FILETIME& ft) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to bit_cast to fix alignment, then divide by 10 to convert 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 100-nanoseconds to milliseconds. This only works on little-endian 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // machines. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bit_cast<int64, FILETIME>(ft) / 10; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MicrosecondsToFileTime(int64 us, FILETIME* ft) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(us, 0LL) << "Time is less than 0, negative values are not " 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "representable in FILETIME"; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Multiply by 10 to convert milliseconds to 100-nanoseconds. Bit_cast will 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handle alignment problems. This only works on little-endian machines. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ft = bit_cast<FILETIME, int64>(us * 10); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 CurrentWallclockMicroseconds() { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILETIME ft; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetSystemTimeAsFileTime(&ft); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FileTimeToMicroseconds(ft); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Time between resampling the un-granular clock for this API. 60 seconds. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 initial_time = 0; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeTicks initial_ticks; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitializeClock() { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_ticks = TimeTicks::Now(); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_time = CurrentWallclockMicroseconds(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The two values that ActivateHighResolutionTimer uses to set the systemwide 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// timer interrupt frequency on Windows. It controls how precise timers are 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// but also has a big impact on battery life. 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kMinTimerIntervalHighResMs = 1; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kMinTimerIntervalLowResMs = 4; 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool g_high_res_timer_enabled = false; 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// How many times the high resolution timer has been called. 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciuint32_t g_high_res_timer_count = 0; 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The lock to control access to the above two variables. 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibase::LazyInstance<base::Lock>::Leaky g_high_res_lock = 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LAZY_INSTANCE_INITIALIZER; 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Time ----------------------------------------------------------------------- 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The internal representation of Time uses FILETIME, whose epoch is 1601-01-01 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 00:00:00 UTC. ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// number of leap year days between 1601 and 1970: (1970-1601)/4 excluding 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1700, 1800, and 1900. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Time Time::Now() { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initial_time == 0) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeClock(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We implement time using the high-resolution timers so that we can get 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // timeouts which are smaller than 10-15ms. If we just used 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CurrentWallclockMicroseconds(), we'd have the less-granular timer. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To make this work, we initialize the clock (initial_time) and the 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // counter (initial_ctr). To compute the initial time, we can check 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the number of ticks that have elapsed, and compute the delta. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To avoid any drift, we periodically resync the counters to the system 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clock. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks ticks = TimeTicks::Now(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate the time elapsed since we started our timer 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta elapsed = ticks - initial_ticks; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if enough time has elapsed that we need to resync the clock. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (elapsed.InMilliseconds() > kMaxMillisecondsToAvoidDrift) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeClock(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Time(elapsed + Time(initial_time)); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Time Time::NowFromSystemTime() { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force resync. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeClock(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Time(initial_time); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Time Time::FromFileTime(FILETIME ft) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bit_cast<int64, FILETIME>(ft) == 0) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Time(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() && 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ft.dwLowDateTime == std::numeric_limits<DWORD>::max()) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Max(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Time(FileTimeToMicroseconds(ft)); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FILETIME Time::ToFileTime() const { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_null()) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bit_cast<FILETIME, int64>(0); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_max()) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILETIME result; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.dwHighDateTime = std::numeric_limits<DWORD>::max(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.dwLowDateTime = std::numeric_limits<DWORD>::max(); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILETIME utc_ft; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MicrosecondsToFileTime(us_, &utc_ft); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return utc_ft; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Time::EnableHighResolutionTimer(bool enable) { 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::AutoLock lock(g_high_res_lock.Get()); 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (g_high_res_timer_enabled == enable) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_high_res_timer_enabled = enable; 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!g_high_res_timer_count) 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Since g_high_res_timer_count != 0, an ActivateHighResolutionTimer(true) 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // was called which called timeBeginPeriod with g_high_res_timer_enabled 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // with a value which is the opposite of |enable|. With that information we 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // call timeEndPeriod with the same value used in timeBeginPeriod and 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // therefore undo the period effect. 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (enable) { 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timeEndPeriod(kMinTimerIntervalLowResMs); 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timeBeginPeriod(kMinTimerIntervalHighResMs); 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timeEndPeriod(kMinTimerIntervalHighResMs); 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timeBeginPeriod(kMinTimerIntervalLowResMs); 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Time::ActivateHighResolutionTimer(bool activating) { 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We only do work on the transition from zero to one or one to zero so we 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // can easily undo the effect (if necessary) when EnableHighResolutionTimer is 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // called. 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const uint32_t max = std::numeric_limits<uint32_t>::max(); 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::AutoLock lock(g_high_res_lock.Get()); 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : kMinTimerIntervalLowResMs; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (activating) { 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(g_high_res_timer_count != max); 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++g_high_res_timer_count; 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (g_high_res_timer_count == 1) 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timeBeginPeriod(period); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(g_high_res_timer_count != 0); 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci --g_high_res_timer_count; 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (g_high_res_timer_count == 0) 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timeEndPeriod(period); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return (period == kMinTimerIntervalHighResMs); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Time::IsHighResolutionTimerInUse() { 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::AutoLock lock(g_high_res_lock.Get()); 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return g_high_res_timer_enabled && g_high_res_timer_count > 0; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Time Time::FromExploded(bool is_local, const Exploded& exploded) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the system struct representing our exploded time. It will either be 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in local time or UTC. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SYSTEMTIME st; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) st.wYear = exploded.year; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) st.wMonth = exploded.month; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) st.wDayOfWeek = exploded.day_of_week; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) st.wDay = exploded.day_of_month; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) st.wHour = exploded.hour; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) st.wMinute = exploded.minute; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) st.wSecond = exploded.second; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) st.wMilliseconds = exploded.millisecond; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILETIME ft; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = true; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that it's in UTC. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_local) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SYSTEMTIME utc_st; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = TzSpecificLocalTimeToSystemTime(NULL, &st, &utc_st) && 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SystemTimeToFileTime(&utc_st, &ft); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = !!SystemTimeToFileTime(&st, &ft); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!success) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unable to convert time"; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Time(0); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Time(FileTimeToMicroseconds(ft)); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Time::Explode(bool is_local, Exploded* exploded) const { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (us_ < 0LL) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are not able to convert it to FILETIME. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZeroMemory(exploded, sizeof(*exploded)); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FILETIME in UTC. 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILETIME utc_ft; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MicrosecondsToFileTime(us_, &utc_ft); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FILETIME in local time if necessary. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = true; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FILETIME in SYSTEMTIME (exploded). 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SYSTEMTIME st = {0}; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_local) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SYSTEMTIME utc_st; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't use FileTimeToLocalFileTime here, since it uses the current 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // settings for the time zone and daylight saving time. Therefore, if it is 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // daylight saving time, it will take daylight saving time into account, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // even if the time you are converting is in standard time. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = FileTimeToSystemTime(&utc_ft, &utc_st) && 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SystemTimeToTzSpecificLocalTime(NULL, &utc_st, &st); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = !!FileTimeToSystemTime(&utc_ft, &st); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!success) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unable to convert time, don't know why"; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZeroMemory(exploded, sizeof(*exploded)); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exploded->year = st.wYear; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exploded->month = st.wMonth; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exploded->day_of_week = st.wDayOfWeek; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exploded->day_of_month = st.wDay; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exploded->hour = st.wHour; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exploded->minute = st.wMinute; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exploded->second = st.wSecond; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exploded->millisecond = st.wMilliseconds; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TimeTicks ------------------------------------------------------------------ 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We define a wrapper to adapt between the __stdcall and __cdecl call of the 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mock function, and to avoid a static constructor. Assigning an import to a 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function pointer directly would require setup code to fetch from the IAT. 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD timeGetTimeWrapper() { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return timeGetTime(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD (*tick_function)(void) = &timeGetTimeWrapper; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Accumulation of time lost due to rollover (in milliseconds). 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 rollover_ms = 0; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The last timeGetTime value we saw, to detect rollover. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD last_seen_now = 0; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Lock protecting rollover_ms and last_seen_now. 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: this is a global object, and we usually avoid these. However, the time 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// code is low-level, and we don't want to use Singletons here (it would be too 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// easy to use a Singleton without even knowing it, and that may lead to many 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gotchas). Its impact on startup time should be negligible due to low-level 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// nature of time code. 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Lock rollover_lock; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use timeGetTime() to implement TimeTicks::Now(). This can be problematic 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// because it returns the number of milliseconds since Windows has started, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which will roll over the 32-bit value every ~49 days. We try to track 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// rollover ourselves, which works if TimeTicks::Now() is called at least every 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 49 days. 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeDelta RolloverProtectedNow() { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock locked(rollover_lock); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should hold the lock while calling tick_function to make sure that 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we keep last_seen_now stay correctly in sync. 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD now = tick_function(); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (now < last_seen_now) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rollover_ms += 0x100000000I64; // ~49.7 days. 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_seen_now = now; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TimeDelta::FromMilliseconds(now + rollover_ms); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool IsBuggyAthlon(const base::CPU& cpu) { 34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is 34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // unreliable. Fallback to low-res clock. 34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15; 34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Overview of time counters: 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (1) CPU cycle counter. (Retrieved via RDTSC) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The CPU counter provides the highest resolution time stamp and is the least 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expensive to retrieve. However, the CPU counter is unreliable and should not 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be used in production. Its biggest issue is that it is per processor and it 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is not synchronized between processors. Also, on some computers, the counters 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will change frequency due to thermal and power changes, and stop in some 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// states. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high- 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resolution (100 nanoseconds) time stamp but is comparatively more expensive 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to retrieve. What QueryPerformanceCounter actually does is up to the HAL. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (with some help from ACPI). 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// According to http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the worst case, it gets the counter from the rollover interrupt on the 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// programmable interrupt timer. In best cases, the HAL may conclude that the 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RDTSC counter runs at a constant frequency, then it uses that instead. On 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multiprocessor machines, it will try to verify the values returned from 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RDTSC on each processor are consistent with each other, and apply a handful 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of workarounds for known buggy hardware. In other words, QPC is supposed to 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// give consistent result on a multiprocessor computer, but it is unreliable in 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reality due to bugs in BIOS or HAL on some, especially old computers. 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// With recent updates on HAL and newer BIOS, QPC is getting more reliable but 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it should be used with caution. 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (3) System time. The system time provides a low-resolution (typically 10ms 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to 55 milliseconds) time stamp but is comparatively less expensive to 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// retrieve and more reliable. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HighResNowSingleton { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) HighResNowSingleton() 3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : ticks_per_second_(0), 3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci skew_(0) { 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CPU cpu; 383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (IsBuggyAthlon(cpu)) 3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Synchronize the QPC clock with GetSystemTimeAsFileTime. 3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LARGE_INTEGER ticks_per_sec = {0}; 3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!QueryPerformanceFrequency(&ticks_per_sec)) 3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; // QPC is not available. 3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ticks_per_second_ = ticks_per_sec.QuadPart; 3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci skew_ = UnreliableNow() - ReliableNow(); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool IsUsingHighResClock() { 3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return ticks_per_second_ != 0; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta Now() { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsUsingHighResClock()) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TimeDelta::FromMicroseconds(UnreliableNow()); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Just fallback to the slower clock. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RolloverProtectedNow(); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 GetQPCDriftMicroseconds() { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsUsingHighResClock()) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return abs((UnreliableNow() - ReliableNow()) - skew_); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 QPCValueToMicroseconds(LONGLONG qpc_value) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ticks_per_second_) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If the QPC Value is below the overflow threshold, we proceed with 4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // simple multiply and divide. 4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (qpc_value < Time::kQPCOverflowThreshold) 4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return qpc_value * Time::kMicrosecondsPerSecond / ticks_per_second_; 4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Otherwise, calculate microseconds in a round about manner to avoid 4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // overflow and precision issues. 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 whole_seconds = qpc_value / ticks_per_second_; 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int64 leftover_ticks = qpc_value - (whole_seconds * ticks_per_second_); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 microseconds = (whole_seconds * Time::kMicrosecondsPerSecond) + 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((leftover_ticks * Time::kMicrosecondsPerSecond) / 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ticks_per_second_); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return microseconds; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the number of microseconds since boot in an unreliable fashion. 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 UnreliableNow() { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LARGE_INTEGER now; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryPerformanceCounter(&now); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return QPCValueToMicroseconds(now.QuadPart); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the number of microseconds since boot in a reliable fashion. 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 ReliableNow() { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RolloverProtectedNow().InMicroseconds(); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 ticks_per_second_; // 0 indicates QPF failed and we're broken. 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 skew_; // Skew between lo-res and hi-res clocks (for debugging). 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static base::LazyInstance<HighResNowSingleton>::Leaky 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) leaky_high_res_now_singleton = LAZY_INSTANCE_INITIALIZER; 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)HighResNowSingleton* GetHighResNowSingleton() { 451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return leaky_high_res_now_singleton.Pointer(); 452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TimeDelta HighResNowWrapper() { 455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return GetHighResNowSingleton()->Now(); 45658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 45758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 45858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)typedef TimeDelta (*NowFunction)(void); 45958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 46058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool CPUReliablySupportsHighResTime() { 46158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::CPU cpu; 4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!cpu.has_non_stop_time_stamp_counter() || 4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) !GetHighResNowSingleton()->IsUsingHighResClock()) 46458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 46558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 46658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (IsBuggyAthlon(cpu)) 46758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 46858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 46958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return true; 47058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 47158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTimeDelta InitialNowFunction(); 4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivolatile NowFunction now_function = InitialNowFunction; 4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTimeDelta InitialNowFunction() { 4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!CPUReliablySupportsHighResTime()) { 4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci InterlockedExchangePointer( 4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci reinterpret_cast<void* volatile*>(&now_function), 4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &RolloverProtectedNow); 4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return RolloverProtectedNow(); 4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci InterlockedExchangePointer( 4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci reinterpret_cast<void* volatile*>(&now_function), 4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &HighResNowWrapper); 4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return HighResNowWrapper(); 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction( 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TickFunctionType ticker) { 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock locked(rollover_lock); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TickFunctionType old = tick_function; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick_function = ticker; 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rollover_ms = 0; 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_seen_now = 0; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return old; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeTicks TimeTicks::Now() { 50458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return TimeTicks() + now_function(); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeTicks TimeTicks::HighResNow() { 509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return TimeTicks() + HighResNowWrapper(); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool TimeTicks::IsHighResNowFastAndReliable() { 5144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return CPUReliablySupportsHighResTime(); 5154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static 518a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TimeTicks TimeTicks::ThreadNow() { 519a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) NOTREACHED(); 520a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return TimeTicks(); 521a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 523a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeTicks TimeTicks::NowFromSystemTraceTime() { 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HighResNow(); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 TimeTicks::GetQPCDriftMicroseconds() { 530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return GetHighResNowSingleton()->GetQPCDriftMicroseconds(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { 535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return TimeTicks(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value)); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TimeTicks::IsHighResClockWorking() { 540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return GetHighResNowSingleton()->IsUsingHighResClock(); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TimeTicks TimeTicks::UnprotectedNow() { 54458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (now_function == HighResNowWrapper) { 54558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return Now(); 54658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 54758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return TimeTicks() + TimeDelta::FromMilliseconds(timeGetTime()); 54858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 54958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 55058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TimeDelta ------------------------------------------------------------------ 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { 555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return TimeDelta(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value)); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 557