1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5 6// Windows Timer Primer 7// 8// A good article: http://www.ddj.com/windows/184416651 9// A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258 10// 11// The default windows timer, GetSystemTimeAsFileTime is not very precise. 12// It is only good to ~15.5ms. 13// 14// QueryPerformanceCounter is the logical choice for a high-precision timer. 15// However, it is known to be buggy on some hardware. Specifically, it can 16// sometimes "jump". On laptops, QPC can also be very expensive to call. 17// It's 3-4x slower than timeGetTime() on desktops, but can be 10x slower 18// on laptops. A unittest exists which will show the relative cost of various 19// timers on any system. 20// 21// The next logical choice is timeGetTime(). timeGetTime has a precision of 22// 1ms, but only if you call APIs (timeBeginPeriod()) which affect all other 23// applications on the system. By default, precision is only 15.5ms. 24// Unfortunately, we don't want to call timeBeginPeriod because we don't 25// want to affect other applications. Further, on mobile platforms, use of 26// faster multimedia timers can hurt battery life. See the intel 27// article about this here: 28// http://softwarecommunity.intel.com/articles/eng/1086.htm 29// 30// To work around all this, we're going to generally use timeGetTime(). We 31// will only increase the system-wide timer if we're not running on battery 32// power. 33 34#include "base/time/time.h" 35 36#pragma comment(lib, "winmm.lib") 37#include <windows.h> 38#include <mmsystem.h> 39 40#include "base/basictypes.h" 41#include "base/cpu.h" 42#include "base/lazy_instance.h" 43#include "base/logging.h" 44#include "base/synchronization/lock.h" 45 46using base::Time; 47using base::TimeDelta; 48using base::TimeTicks; 49 50namespace { 51 52// From MSDN, FILETIME "Contains a 64-bit value representing the number of 53// 100-nanosecond intervals since January 1, 1601 (UTC)." 54int64 FileTimeToMicroseconds(const FILETIME& ft) { 55 // Need to bit_cast to fix alignment, then divide by 10 to convert 56 // 100-nanoseconds to milliseconds. This only works on little-endian 57 // machines. 58 return bit_cast<int64, FILETIME>(ft) / 10; 59} 60 61void MicrosecondsToFileTime(int64 us, FILETIME* ft) { 62 DCHECK_GE(us, 0LL) << "Time is less than 0, negative values are not " 63 "representable in FILETIME"; 64 65 // Multiply by 10 to convert milliseconds to 100-nanoseconds. Bit_cast will 66 // handle alignment problems. This only works on little-endian machines. 67 *ft = bit_cast<FILETIME, int64>(us * 10); 68} 69 70int64 CurrentWallclockMicroseconds() { 71 FILETIME ft; 72 ::GetSystemTimeAsFileTime(&ft); 73 return FileTimeToMicroseconds(ft); 74} 75 76// Time between resampling the un-granular clock for this API. 60 seconds. 77const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; 78 79int64 initial_time = 0; 80TimeTicks initial_ticks; 81 82void InitializeClock() { 83 initial_ticks = TimeTicks::Now(); 84 initial_time = CurrentWallclockMicroseconds(); 85} 86 87// The two values that ActivateHighResolutionTimer uses to set the systemwide 88// timer interrupt frequency on Windows. It controls how precise timers are 89// but also has a big impact on battery life. 90const int kMinTimerIntervalHighResMs = 1; 91const int kMinTimerIntervalLowResMs = 4; 92// Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. 93bool g_high_res_timer_enabled = false; 94// How many times the high resolution timer has been called. 95uint32_t g_high_res_timer_count = 0; 96// The lock to control access to the above two variables. 97base::LazyInstance<base::Lock>::Leaky g_high_res_lock = 98 LAZY_INSTANCE_INITIALIZER; 99 100} // namespace 101 102// Time ----------------------------------------------------------------------- 103 104// The internal representation of Time uses FILETIME, whose epoch is 1601-01-01 105// 00:00:00 UTC. ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the 106// number of leap year days between 1601 and 1970: (1970-1601)/4 excluding 107// 1700, 1800, and 1900. 108// static 109const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000); 110 111// static 112Time Time::Now() { 113 if (initial_time == 0) 114 InitializeClock(); 115 116 // We implement time using the high-resolution timers so that we can get 117 // timeouts which are smaller than 10-15ms. If we just used 118 // CurrentWallclockMicroseconds(), we'd have the less-granular timer. 119 // 120 // To make this work, we initialize the clock (initial_time) and the 121 // counter (initial_ctr). To compute the initial time, we can check 122 // the number of ticks that have elapsed, and compute the delta. 123 // 124 // To avoid any drift, we periodically resync the counters to the system 125 // clock. 126 while (true) { 127 TimeTicks ticks = TimeTicks::Now(); 128 129 // Calculate the time elapsed since we started our timer 130 TimeDelta elapsed = ticks - initial_ticks; 131 132 // Check if enough time has elapsed that we need to resync the clock. 133 if (elapsed.InMilliseconds() > kMaxMillisecondsToAvoidDrift) { 134 InitializeClock(); 135 continue; 136 } 137 138 return Time(elapsed + Time(initial_time)); 139 } 140} 141 142// static 143Time Time::NowFromSystemTime() { 144 // Force resync. 145 InitializeClock(); 146 return Time(initial_time); 147} 148 149// static 150Time Time::FromFileTime(FILETIME ft) { 151 if (bit_cast<int64, FILETIME>(ft) == 0) 152 return Time(); 153 if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() && 154 ft.dwLowDateTime == std::numeric_limits<DWORD>::max()) 155 return Max(); 156 return Time(FileTimeToMicroseconds(ft)); 157} 158 159FILETIME Time::ToFileTime() const { 160 if (is_null()) 161 return bit_cast<FILETIME, int64>(0); 162 if (is_max()) { 163 FILETIME result; 164 result.dwHighDateTime = std::numeric_limits<DWORD>::max(); 165 result.dwLowDateTime = std::numeric_limits<DWORD>::max(); 166 return result; 167 } 168 FILETIME utc_ft; 169 MicrosecondsToFileTime(us_, &utc_ft); 170 return utc_ft; 171} 172 173// static 174void Time::EnableHighResolutionTimer(bool enable) { 175 base::AutoLock lock(g_high_res_lock.Get()); 176 if (g_high_res_timer_enabled == enable) 177 return; 178 g_high_res_timer_enabled = enable; 179 if (!g_high_res_timer_count) 180 return; 181 // Since g_high_res_timer_count != 0, an ActivateHighResolutionTimer(true) 182 // was called which called timeBeginPeriod with g_high_res_timer_enabled 183 // with a value which is the opposite of |enable|. With that information we 184 // call timeEndPeriod with the same value used in timeBeginPeriod and 185 // therefore undo the period effect. 186 if (enable) { 187 timeEndPeriod(kMinTimerIntervalLowResMs); 188 timeBeginPeriod(kMinTimerIntervalHighResMs); 189 } else { 190 timeEndPeriod(kMinTimerIntervalHighResMs); 191 timeBeginPeriod(kMinTimerIntervalLowResMs); 192 } 193} 194 195// static 196bool Time::ActivateHighResolutionTimer(bool activating) { 197 // We only do work on the transition from zero to one or one to zero so we 198 // can easily undo the effect (if necessary) when EnableHighResolutionTimer is 199 // called. 200 const uint32_t max = std::numeric_limits<uint32_t>::max(); 201 202 base::AutoLock lock(g_high_res_lock.Get()); 203 UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs 204 : kMinTimerIntervalLowResMs; 205 if (activating) { 206 DCHECK(g_high_res_timer_count != max); 207 ++g_high_res_timer_count; 208 if (g_high_res_timer_count == 1) 209 timeBeginPeriod(period); 210 } else { 211 DCHECK(g_high_res_timer_count != 0); 212 --g_high_res_timer_count; 213 if (g_high_res_timer_count == 0) 214 timeEndPeriod(period); 215 } 216 return (period == kMinTimerIntervalHighResMs); 217} 218 219// static 220bool Time::IsHighResolutionTimerInUse() { 221 base::AutoLock lock(g_high_res_lock.Get()); 222 return g_high_res_timer_enabled && g_high_res_timer_count > 0; 223} 224 225// static 226Time Time::FromExploded(bool is_local, const Exploded& exploded) { 227 // Create the system struct representing our exploded time. It will either be 228 // in local time or UTC. 229 SYSTEMTIME st; 230 st.wYear = exploded.year; 231 st.wMonth = exploded.month; 232 st.wDayOfWeek = exploded.day_of_week; 233 st.wDay = exploded.day_of_month; 234 st.wHour = exploded.hour; 235 st.wMinute = exploded.minute; 236 st.wSecond = exploded.second; 237 st.wMilliseconds = exploded.millisecond; 238 239 FILETIME ft; 240 bool success = true; 241 // Ensure that it's in UTC. 242 if (is_local) { 243 SYSTEMTIME utc_st; 244 success = TzSpecificLocalTimeToSystemTime(NULL, &st, &utc_st) && 245 SystemTimeToFileTime(&utc_st, &ft); 246 } else { 247 success = !!SystemTimeToFileTime(&st, &ft); 248 } 249 250 if (!success) { 251 NOTREACHED() << "Unable to convert time"; 252 return Time(0); 253 } 254 return Time(FileTimeToMicroseconds(ft)); 255} 256 257void Time::Explode(bool is_local, Exploded* exploded) const { 258 if (us_ < 0LL) { 259 // We are not able to convert it to FILETIME. 260 ZeroMemory(exploded, sizeof(*exploded)); 261 return; 262 } 263 264 // FILETIME in UTC. 265 FILETIME utc_ft; 266 MicrosecondsToFileTime(us_, &utc_ft); 267 268 // FILETIME in local time if necessary. 269 bool success = true; 270 // FILETIME in SYSTEMTIME (exploded). 271 SYSTEMTIME st = {0}; 272 if (is_local) { 273 SYSTEMTIME utc_st; 274 // We don't use FileTimeToLocalFileTime here, since it uses the current 275 // settings for the time zone and daylight saving time. Therefore, if it is 276 // daylight saving time, it will take daylight saving time into account, 277 // even if the time you are converting is in standard time. 278 success = FileTimeToSystemTime(&utc_ft, &utc_st) && 279 SystemTimeToTzSpecificLocalTime(NULL, &utc_st, &st); 280 } else { 281 success = !!FileTimeToSystemTime(&utc_ft, &st); 282 } 283 284 if (!success) { 285 NOTREACHED() << "Unable to convert time, don't know why"; 286 ZeroMemory(exploded, sizeof(*exploded)); 287 return; 288 } 289 290 exploded->year = st.wYear; 291 exploded->month = st.wMonth; 292 exploded->day_of_week = st.wDayOfWeek; 293 exploded->day_of_month = st.wDay; 294 exploded->hour = st.wHour; 295 exploded->minute = st.wMinute; 296 exploded->second = st.wSecond; 297 exploded->millisecond = st.wMilliseconds; 298} 299 300// TimeTicks ------------------------------------------------------------------ 301namespace { 302 303// We define a wrapper to adapt between the __stdcall and __cdecl call of the 304// mock function, and to avoid a static constructor. Assigning an import to a 305// function pointer directly would require setup code to fetch from the IAT. 306DWORD timeGetTimeWrapper() { 307 return timeGetTime(); 308} 309 310DWORD (*tick_function)(void) = &timeGetTimeWrapper; 311 312// Accumulation of time lost due to rollover (in milliseconds). 313int64 rollover_ms = 0; 314 315// The last timeGetTime value we saw, to detect rollover. 316DWORD last_seen_now = 0; 317 318// Lock protecting rollover_ms and last_seen_now. 319// Note: this is a global object, and we usually avoid these. However, the time 320// code is low-level, and we don't want to use Singletons here (it would be too 321// easy to use a Singleton without even knowing it, and that may lead to many 322// gotchas). Its impact on startup time should be negligible due to low-level 323// nature of time code. 324base::Lock rollover_lock; 325 326// We use timeGetTime() to implement TimeTicks::Now(). This can be problematic 327// because it returns the number of milliseconds since Windows has started, 328// which will roll over the 32-bit value every ~49 days. We try to track 329// rollover ourselves, which works if TimeTicks::Now() is called at least every 330// 49 days. 331TimeDelta RolloverProtectedNow() { 332 base::AutoLock locked(rollover_lock); 333 // We should hold the lock while calling tick_function to make sure that 334 // we keep last_seen_now stay correctly in sync. 335 DWORD now = tick_function(); 336 if (now < last_seen_now) 337 rollover_ms += 0x100000000I64; // ~49.7 days. 338 last_seen_now = now; 339 return TimeDelta::FromMilliseconds(now + rollover_ms); 340} 341 342bool IsBuggyAthlon(const base::CPU& cpu) { 343 // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is 344 // unreliable. Fallback to low-res clock. 345 return cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15; 346} 347 348// Overview of time counters: 349// (1) CPU cycle counter. (Retrieved via RDTSC) 350// The CPU counter provides the highest resolution time stamp and is the least 351// expensive to retrieve. However, the CPU counter is unreliable and should not 352// be used in production. Its biggest issue is that it is per processor and it 353// is not synchronized between processors. Also, on some computers, the counters 354// will change frequency due to thermal and power changes, and stop in some 355// states. 356// 357// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high- 358// resolution (100 nanoseconds) time stamp but is comparatively more expensive 359// to retrieve. What QueryPerformanceCounter actually does is up to the HAL. 360// (with some help from ACPI). 361// According to http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx 362// in the worst case, it gets the counter from the rollover interrupt on the 363// programmable interrupt timer. In best cases, the HAL may conclude that the 364// RDTSC counter runs at a constant frequency, then it uses that instead. On 365// multiprocessor machines, it will try to verify the values returned from 366// RDTSC on each processor are consistent with each other, and apply a handful 367// of workarounds for known buggy hardware. In other words, QPC is supposed to 368// give consistent result on a multiprocessor computer, but it is unreliable in 369// reality due to bugs in BIOS or HAL on some, especially old computers. 370// With recent updates on HAL and newer BIOS, QPC is getting more reliable but 371// it should be used with caution. 372// 373// (3) System time. The system time provides a low-resolution (typically 10ms 374// to 55 milliseconds) time stamp but is comparatively less expensive to 375// retrieve and more reliable. 376class HighResNowSingleton { 377 public: 378 HighResNowSingleton() 379 : ticks_per_second_(0), 380 skew_(0) { 381 382 base::CPU cpu; 383 if (IsBuggyAthlon(cpu)) 384 return; 385 386 // Synchronize the QPC clock with GetSystemTimeAsFileTime. 387 LARGE_INTEGER ticks_per_sec = {0}; 388 if (!QueryPerformanceFrequency(&ticks_per_sec)) 389 return; // QPC is not available. 390 ticks_per_second_ = ticks_per_sec.QuadPart; 391 392 skew_ = UnreliableNow() - ReliableNow(); 393 } 394 395 bool IsUsingHighResClock() { 396 return ticks_per_second_ != 0; 397 } 398 399 TimeDelta Now() { 400 if (IsUsingHighResClock()) 401 return TimeDelta::FromMicroseconds(UnreliableNow()); 402 403 // Just fallback to the slower clock. 404 return RolloverProtectedNow(); 405 } 406 407 int64 GetQPCDriftMicroseconds() { 408 if (!IsUsingHighResClock()) 409 return 0; 410 return abs((UnreliableNow() - ReliableNow()) - skew_); 411 } 412 413 int64 QPCValueToMicroseconds(LONGLONG qpc_value) { 414 if (!ticks_per_second_) 415 return 0; 416 // If the QPC Value is below the overflow threshold, we proceed with 417 // simple multiply and divide. 418 if (qpc_value < Time::kQPCOverflowThreshold) 419 return qpc_value * Time::kMicrosecondsPerSecond / ticks_per_second_; 420 // Otherwise, calculate microseconds in a round about manner to avoid 421 // overflow and precision issues. 422 int64 whole_seconds = qpc_value / ticks_per_second_; 423 int64 leftover_ticks = qpc_value - (whole_seconds * ticks_per_second_); 424 int64 microseconds = (whole_seconds * Time::kMicrosecondsPerSecond) + 425 ((leftover_ticks * Time::kMicrosecondsPerSecond) / 426 ticks_per_second_); 427 return microseconds; 428 } 429 430 private: 431 // Get the number of microseconds since boot in an unreliable fashion. 432 int64 UnreliableNow() { 433 LARGE_INTEGER now; 434 QueryPerformanceCounter(&now); 435 return QPCValueToMicroseconds(now.QuadPart); 436 } 437 438 // Get the number of microseconds since boot in a reliable fashion. 439 int64 ReliableNow() { 440 return RolloverProtectedNow().InMicroseconds(); 441 } 442 443 int64 ticks_per_second_; // 0 indicates QPF failed and we're broken. 444 int64 skew_; // Skew between lo-res and hi-res clocks (for debugging). 445}; 446 447static base::LazyInstance<HighResNowSingleton>::Leaky 448 leaky_high_res_now_singleton = LAZY_INSTANCE_INITIALIZER; 449 450HighResNowSingleton* GetHighResNowSingleton() { 451 return leaky_high_res_now_singleton.Pointer(); 452} 453 454TimeDelta HighResNowWrapper() { 455 return GetHighResNowSingleton()->Now(); 456} 457 458typedef TimeDelta (*NowFunction)(void); 459 460bool CPUReliablySupportsHighResTime() { 461 base::CPU cpu; 462 if (!cpu.has_non_stop_time_stamp_counter() || 463 !GetHighResNowSingleton()->IsUsingHighResClock()) 464 return false; 465 466 if (IsBuggyAthlon(cpu)) 467 return false; 468 469 return true; 470} 471 472TimeDelta InitialNowFunction(); 473 474volatile NowFunction now_function = InitialNowFunction; 475 476TimeDelta InitialNowFunction() { 477 if (!CPUReliablySupportsHighResTime()) { 478 InterlockedExchangePointer( 479 reinterpret_cast<void* volatile*>(&now_function), 480 &RolloverProtectedNow); 481 return RolloverProtectedNow(); 482 } 483 InterlockedExchangePointer( 484 reinterpret_cast<void* volatile*>(&now_function), 485 &HighResNowWrapper); 486 return HighResNowWrapper(); 487} 488 489} // namespace 490 491// static 492TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction( 493 TickFunctionType ticker) { 494 base::AutoLock locked(rollover_lock); 495 TickFunctionType old = tick_function; 496 tick_function = ticker; 497 rollover_ms = 0; 498 last_seen_now = 0; 499 return old; 500} 501 502// static 503TimeTicks TimeTicks::Now() { 504 return TimeTicks() + now_function(); 505} 506 507// static 508TimeTicks TimeTicks::HighResNow() { 509 return TimeTicks() + HighResNowWrapper(); 510} 511 512// static 513bool TimeTicks::IsHighResNowFastAndReliable() { 514 return CPUReliablySupportsHighResTime(); 515} 516 517// static 518TimeTicks TimeTicks::ThreadNow() { 519 NOTREACHED(); 520 return TimeTicks(); 521} 522 523// static 524TimeTicks TimeTicks::NowFromSystemTraceTime() { 525 return HighResNow(); 526} 527 528// static 529int64 TimeTicks::GetQPCDriftMicroseconds() { 530 return GetHighResNowSingleton()->GetQPCDriftMicroseconds(); 531} 532 533// static 534TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { 535 return TimeTicks(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value)); 536} 537 538// static 539bool TimeTicks::IsHighResClockWorking() { 540 return GetHighResNowSingleton()->IsUsingHighResClock(); 541} 542 543TimeTicks TimeTicks::UnprotectedNow() { 544 if (now_function == HighResNowWrapper) { 545 return Now(); 546 } else { 547 return TimeTicks() + TimeDelta::FromMilliseconds(timeGetTime()); 548 } 549} 550 551// TimeDelta ------------------------------------------------------------------ 552 553// static 554TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { 555 return TimeDelta(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value)); 556} 557