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 46 using base::Time; 47 using base::TimeDelta; 48 using base::TimeTicks; 49 50 namespace { 51 52 // From MSDN, FILETIME "Contains a 64-bit value representing the number of 53 // 100-nanosecond intervals since January 1, 1601 (UTC)." 54 int64 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 61 void 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 70 int64 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. 77 const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; 78 79 int64 initial_time = 0; 80 TimeTicks initial_ticks; 81 82 void 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. 90 const int kMinTimerIntervalHighResMs = 1; 91 const int kMinTimerIntervalLowResMs = 4; 92 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. 93 bool g_high_res_timer_enabled = false; 94 // How many times the high resolution timer has been called. 95 uint32_t g_high_res_timer_count = 0; 96 // The lock to control access to the above two variables. 97 base::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 109 const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000); 110 111 // static 112 Time 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 143 Time Time::NowFromSystemTime() { 144 // Force resync. 145 InitializeClock(); 146 return Time(initial_time); 147 } 148 149 // static 150 Time 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 159 FILETIME 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 174 void 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 196 bool 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 220 bool 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 226 Time 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 257 void 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 ------------------------------------------------------------------ 301 namespace { 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. 306 DWORD timeGetTimeWrapper() { 307 return timeGetTime(); 308 } 309 310 DWORD (*tick_function)(void) = &timeGetTimeWrapper; 311 312 // Accumulation of time lost due to rollover (in milliseconds). 313 int64 rollover_ms = 0; 314 315 // The last timeGetTime value we saw, to detect rollover. 316 DWORD 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. 324 base::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. 331 TimeDelta 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 342 bool 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. 376 class 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 447 static base::LazyInstance<HighResNowSingleton>::Leaky 448 leaky_high_res_now_singleton = LAZY_INSTANCE_INITIALIZER; 449 450 HighResNowSingleton* GetHighResNowSingleton() { 451 return leaky_high_res_now_singleton.Pointer(); 452 } 453 454 TimeDelta HighResNowWrapper() { 455 return GetHighResNowSingleton()->Now(); 456 } 457 458 typedef TimeDelta (*NowFunction)(void); 459 460 bool 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 472 TimeDelta InitialNowFunction(); 473 474 volatile NowFunction now_function = InitialNowFunction; 475 476 TimeDelta 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 492 TimeTicks::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 503 TimeTicks TimeTicks::Now() { 504 return TimeTicks() + now_function(); 505 } 506 507 // static 508 TimeTicks TimeTicks::HighResNow() { 509 return TimeTicks() + HighResNowWrapper(); 510 } 511 512 // static 513 bool TimeTicks::IsHighResNowFastAndReliable() { 514 return CPUReliablySupportsHighResTime(); 515 } 516 517 // static 518 TimeTicks TimeTicks::ThreadNow() { 519 NOTREACHED(); 520 return TimeTicks(); 521 } 522 523 // static 524 TimeTicks TimeTicks::NowFromSystemTraceTime() { 525 return HighResNow(); 526 } 527 528 // static 529 int64 TimeTicks::GetQPCDriftMicroseconds() { 530 return GetHighResNowSingleton()->GetQPCDriftMicroseconds(); 531 } 532 533 // static 534 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { 535 return TimeTicks(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value)); 536 } 537 538 // static 539 bool TimeTicks::IsHighResClockWorking() { 540 return GetHighResNowSingleton()->IsUsingHighResClock(); 541 } 542 543 TimeTicks 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 554 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { 555 return TimeDelta(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value)); 556 } 557