time_win.cc (31913B)
1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 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 #include <windows.foundation.h> 37 #include <windows.h> 38 39 #include <mmsystem.h> 40 #include <stdint.h> 41 42 #include <atomic> 43 #include <ostream> 44 45 #include "base/bit_cast.h" 46 #include "base/check_op.h" 47 #include "base/cpu.h" 48 #include "base/notreached.h" 49 #include "base/synchronization/lock.h" 50 #include "base/threading/platform_thread.h" 51 #include "base/time/time_override.h" 52 #include "build/build_config.h" 53 54 namespace base { 55 56 namespace { 57 58 // From MSDN, FILETIME "Contains a 64-bit value representing the number of 59 // 100-nanosecond intervals since January 1, 1601 (UTC)." 60 int64_t FileTimeToMicroseconds(const FILETIME& ft) { 61 // Need to bit_cast to fix alignment, then divide by 10 to convert 62 // 100-nanoseconds to microseconds. This only works on little-endian 63 // machines. 64 return bit_cast<int64_t, FILETIME>(ft) / 10; 65 } 66 67 bool CanConvertToFileTime(int64_t us) { 68 return us >= 0 && us <= (std::numeric_limits<int64_t>::max() / 10); 69 } 70 71 FILETIME MicrosecondsToFileTime(int64_t us) { 72 DCHECK(CanConvertToFileTime(us)) << "Out-of-range: Cannot convert " << us 73 << " microseconds to FILETIME units."; 74 75 // Multiply by 10 to convert microseconds to 100-nanoseconds. Bit_cast will 76 // handle alignment problems. This only works on little-endian machines. 77 return bit_cast<FILETIME, int64_t>(us * 10); 78 } 79 80 int64_t CurrentWallclockMicroseconds() { 81 FILETIME ft; 82 ::GetSystemTimeAsFileTime(&ft); 83 return FileTimeToMicroseconds(ft); 84 } 85 86 // Time between resampling the un-granular clock for this API. 87 constexpr TimeDelta kMaxTimeToAvoidDrift = Seconds(60); 88 89 int64_t g_initial_time = 0; 90 TimeTicks g_initial_ticks; 91 92 void InitializeClock() { 93 g_initial_ticks = subtle::TimeTicksNowIgnoringOverride(); 94 g_initial_time = CurrentWallclockMicroseconds(); 95 } 96 97 // Track the last value passed to timeBeginPeriod so that we can cancel that 98 // call by calling timeEndPeriod with the same value. A value of zero means that 99 // the timer frequency is not currently raised. 100 UINT g_last_interval_requested_ms = 0; 101 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. 102 // For most purposes this could also be named g_is_on_ac_power. 103 bool g_high_res_timer_enabled = false; 104 // How many times the high resolution timer has been called. 105 uint32_t g_high_res_timer_count = 0; 106 // Start time of the high resolution timer usage monitoring. This is needed 107 // to calculate the usage as percentage of the total elapsed time. 108 TimeTicks g_high_res_timer_usage_start; 109 // The cumulative time the high resolution timer has been in use since 110 // |g_high_res_timer_usage_start| moment. 111 TimeDelta g_high_res_timer_usage; 112 // Timestamp of the last activation change of the high resolution timer. This 113 // is used to calculate the cumulative usage. 114 TimeTicks g_high_res_timer_last_activation; 115 // The lock to control access to the above set of variables. 116 Lock* GetHighResLock() { 117 static auto* lock = new Lock(); 118 return lock; 119 } 120 121 // The two values that ActivateHighResolutionTimer uses to set the systemwide 122 // timer interrupt frequency on Windows. These control how precise timers are 123 // but also have a big impact on battery life. 124 125 // Used when a faster timer has been requested (g_high_res_timer_count > 0) and 126 // the computer is running on AC power (plugged in) so that it's okay to go to 127 // the highest frequency. 128 constexpr UINT kMinTimerIntervalHighResMs = 1; 129 130 // Used when a faster timer has been requested (g_high_res_timer_count > 0) and 131 // the computer is running on DC power (battery) so that we don't want to raise 132 // the timer frequency as much. 133 constexpr UINT kMinTimerIntervalLowResMs = 8; 134 135 // Calculate the desired timer interrupt interval. Note that zero means that the 136 // system default should be used. 137 UINT GetIntervalMs() { 138 if (!g_high_res_timer_count) 139 return 0; // Use the default, typically 15.625 140 if (g_high_res_timer_enabled) 141 return kMinTimerIntervalHighResMs; 142 return kMinTimerIntervalLowResMs; 143 } 144 145 // Compare the currently requested timer interrupt interval to the last interval 146 // requested and update if necessary (by cancelling the old request and making a 147 // new request). If there is no change then do nothing. 148 void UpdateTimerIntervalLocked() { 149 UINT new_interval = GetIntervalMs(); 150 if (new_interval == g_last_interval_requested_ms) 151 return; 152 if (g_last_interval_requested_ms) { 153 // Record how long the timer interrupt frequency was raised. 154 g_high_res_timer_usage += subtle::TimeTicksNowIgnoringOverride() - 155 g_high_res_timer_last_activation; 156 // Reset the timer interrupt back to the default. 157 timeEndPeriod(g_last_interval_requested_ms); 158 } 159 g_last_interval_requested_ms = new_interval; 160 if (g_last_interval_requested_ms) { 161 // Record when the timer interrupt was raised. 162 g_high_res_timer_last_activation = subtle::TimeTicksNowIgnoringOverride(); 163 timeBeginPeriod(g_last_interval_requested_ms); 164 } 165 } 166 167 // Returns the current value of the performance counter. 168 int64_t QPCNowRaw() { 169 LARGE_INTEGER perf_counter_now = {}; 170 // According to the MSDN documentation for QueryPerformanceCounter(), this 171 // will never fail on systems that run XP or later. 172 // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx 173 ::QueryPerformanceCounter(&perf_counter_now); 174 return perf_counter_now.QuadPart; 175 } 176 177 bool SafeConvertToWord(int in, WORD* out) { 178 CheckedNumeric<WORD> result = in; 179 *out = result.ValueOrDefault(std::numeric_limits<WORD>::max()); 180 return result.IsValid(); 181 } 182 183 } // namespace 184 185 // Time ----------------------------------------------------------------------- 186 187 namespace subtle { 188 Time TimeNowIgnoringOverride() { 189 if (g_initial_time == 0) 190 InitializeClock(); 191 192 // We implement time using the high-resolution timers so that we can get 193 // timeouts which are smaller than 10-15ms. If we just used 194 // CurrentWallclockMicroseconds(), we'd have the less-granular timer. 195 // 196 // To make this work, we initialize the clock (g_initial_time) and the 197 // counter (initial_ctr). To compute the initial time, we can check 198 // the number of ticks that have elapsed, and compute the delta. 199 // 200 // To avoid any drift, we periodically resync the counters to the system 201 // clock. 202 while (true) { 203 TimeTicks ticks = TimeTicksNowIgnoringOverride(); 204 205 // Calculate the time elapsed since we started our timer 206 TimeDelta elapsed = ticks - g_initial_ticks; 207 208 // Check if enough time has elapsed that we need to resync the clock. 209 if (elapsed > kMaxTimeToAvoidDrift) { 210 InitializeClock(); 211 continue; 212 } 213 214 return Time() + elapsed + Microseconds(g_initial_time); 215 } 216 } 217 218 Time TimeNowFromSystemTimeIgnoringOverride() { 219 // Force resync. 220 InitializeClock(); 221 return Time() + Microseconds(g_initial_time); 222 } 223 } // namespace subtle 224 225 // static 226 Time Time::FromFileTime(FILETIME ft) { 227 if (bit_cast<int64_t, FILETIME>(ft) == 0) 228 return Time(); 229 if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() && 230 ft.dwLowDateTime == std::numeric_limits<DWORD>::max()) 231 return Max(); 232 return Time(FileTimeToMicroseconds(ft)); 233 } 234 235 FILETIME Time::ToFileTime() const { 236 if (is_null()) 237 return bit_cast<FILETIME, int64_t>(0); 238 if (is_max()) { 239 FILETIME result; 240 result.dwHighDateTime = std::numeric_limits<DWORD>::max(); 241 result.dwLowDateTime = std::numeric_limits<DWORD>::max(); 242 return result; 243 } 244 return MicrosecondsToFileTime(us_); 245 } 246 247 // static 248 // Enable raising of the system-global timer interrupt frequency to 1 kHz (when 249 // enable is true, which happens when on AC power) or some lower frequency when 250 // on battery power (when enable is false). If the g_high_res_timer_enabled 251 // setting hasn't actually changed or if if there are no outstanding requests 252 // (if g_high_res_timer_count is zero) then do nothing. 253 // TL;DR - call this when going from AC to DC power or vice-versa. 254 void Time::EnableHighResolutionTimer(bool enable) { 255 AutoLock lock(*GetHighResLock()); 256 g_high_res_timer_enabled = enable; 257 UpdateTimerIntervalLocked(); 258 } 259 260 // static 261 // Request that the system-global Windows timer interrupt frequency be raised. 262 // How high the frequency is raised depends on the system's power state and 263 // possibly other options. 264 // TL;DR - call this at the beginning and end of a time period where you want 265 // higher frequency timer interrupts. Each call with activating=true must be 266 // paired with a subsequent activating=false call. 267 bool Time::ActivateHighResolutionTimer(bool activating) { 268 // We only do work on the transition from zero to one or one to zero so we 269 // can easily undo the effect (if necessary) when EnableHighResolutionTimer is 270 // called. 271 const uint32_t max = std::numeric_limits<uint32_t>::max(); 272 273 AutoLock lock(*GetHighResLock()); 274 if (activating) { 275 DCHECK_NE(g_high_res_timer_count, max); 276 ++g_high_res_timer_count; 277 } else { 278 DCHECK_NE(g_high_res_timer_count, 0u); 279 --g_high_res_timer_count; 280 } 281 UpdateTimerIntervalLocked(); 282 return true; 283 } 284 285 // static 286 // See if the timer interrupt interval has been set to the lowest value. 287 bool Time::IsHighResolutionTimerInUse() { 288 AutoLock lock(*GetHighResLock()); 289 return g_last_interval_requested_ms == kMinTimerIntervalHighResMs; 290 } 291 292 // static 293 void Time::ResetHighResolutionTimerUsage() { 294 AutoLock lock(*GetHighResLock()); 295 g_high_res_timer_usage = TimeDelta(); 296 g_high_res_timer_usage_start = subtle::TimeTicksNowIgnoringOverride(); 297 if (g_high_res_timer_count > 0) 298 g_high_res_timer_last_activation = g_high_res_timer_usage_start; 299 } 300 301 // static 302 double Time::GetHighResolutionTimerUsage() { 303 AutoLock lock(*GetHighResLock()); 304 TimeTicks now = subtle::TimeTicksNowIgnoringOverride(); 305 TimeDelta elapsed_time = now - g_high_res_timer_usage_start; 306 if (elapsed_time.is_zero()) { 307 // This is unexpected but possible if TimeTicks resolution is low and 308 // GetHighResolutionTimerUsage() is called promptly after 309 // ResetHighResolutionTimerUsage(). 310 return 0.0; 311 } 312 TimeDelta used_time = g_high_res_timer_usage; 313 if (g_high_res_timer_count > 0) { 314 // If currently activated add the remainder of time since the last 315 // activation. 316 used_time += now - g_high_res_timer_last_activation; 317 } 318 return used_time / elapsed_time * 100; 319 } 320 321 // static 322 bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { 323 // Create the system struct representing our exploded time. It will either be 324 // in local time or UTC.If casting from int to WORD results in overflow, 325 // fail and return Time(0). 326 SYSTEMTIME st; 327 if (!SafeConvertToWord(exploded.year, &st.wYear) || 328 !SafeConvertToWord(exploded.month, &st.wMonth) || 329 !SafeConvertToWord(exploded.day_of_week, &st.wDayOfWeek) || 330 !SafeConvertToWord(exploded.day_of_month, &st.wDay) || 331 !SafeConvertToWord(exploded.hour, &st.wHour) || 332 !SafeConvertToWord(exploded.minute, &st.wMinute) || 333 !SafeConvertToWord(exploded.second, &st.wSecond) || 334 !SafeConvertToWord(exploded.millisecond, &st.wMilliseconds)) { 335 *time = Time(0); 336 return false; 337 } 338 339 FILETIME ft; 340 bool success = true; 341 // Ensure that it's in UTC. 342 if (is_local) { 343 SYSTEMTIME utc_st; 344 success = TzSpecificLocalTimeToSystemTime(nullptr, &st, &utc_st) && 345 SystemTimeToFileTime(&utc_st, &ft); 346 } else { 347 success = !!SystemTimeToFileTime(&st, &ft); 348 } 349 350 *time = Time(success ? FileTimeToMicroseconds(ft) : 0); 351 return success; 352 } 353 354 void Time::Explode(bool is_local, Exploded* exploded) const { 355 if (!CanConvertToFileTime(us_)) { 356 // We are not able to convert it to FILETIME. 357 ZeroMemory(exploded, sizeof(*exploded)); 358 return; 359 } 360 361 const FILETIME utc_ft = MicrosecondsToFileTime(us_); 362 363 // FILETIME in local time if necessary. 364 bool success = true; 365 // FILETIME in SYSTEMTIME (exploded). 366 SYSTEMTIME st = {0}; 367 if (is_local) { 368 SYSTEMTIME utc_st; 369 // We don't use FileTimeToLocalFileTime here, since it uses the current 370 // settings for the time zone and daylight saving time. Therefore, if it is 371 // daylight saving time, it will take daylight saving time into account, 372 // even if the time you are converting is in standard time. 373 success = FileTimeToSystemTime(&utc_ft, &utc_st) && 374 SystemTimeToTzSpecificLocalTime(nullptr, &utc_st, &st); 375 } else { 376 success = !!FileTimeToSystemTime(&utc_ft, &st); 377 } 378 379 if (!success) { 380 ZeroMemory(exploded, sizeof(*exploded)); 381 return; 382 } 383 384 exploded->year = st.wYear; 385 exploded->month = st.wMonth; 386 exploded->day_of_week = st.wDayOfWeek; 387 exploded->day_of_month = st.wDay; 388 exploded->hour = st.wHour; 389 exploded->minute = st.wMinute; 390 exploded->second = st.wSecond; 391 exploded->millisecond = st.wMilliseconds; 392 } 393 394 // TimeTicks ------------------------------------------------------------------ 395 396 namespace { 397 398 // We define a wrapper to adapt between the __stdcall and __cdecl call of the 399 // mock function, and to avoid a static constructor. Assigning an import to a 400 // function pointer directly would require setup code to fetch from the IAT. 401 DWORD timeGetTimeWrapper() { 402 return timeGetTime(); 403 } 404 405 DWORD (*g_tick_function)(void) = &timeGetTimeWrapper; 406 407 // A structure holding the most significant bits of "last seen" and a 408 // "rollover" counter. 409 union LastTimeAndRolloversState { 410 // The state as a single 32-bit opaque value. 411 std::atomic<int32_t> as_opaque_32{0}; 412 413 // The state as usable values. 414 struct { 415 // The top 8-bits of the "last" time. This is enough to check for rollovers 416 // and the small bit-size means fewer CompareAndSwap operations to store 417 // changes in state, which in turn makes for fewer retries. 418 uint8_t last_8; 419 // A count of the number of detected rollovers. Using this as bits 47-32 420 // of the upper half of a 64-bit value results in a 48-bit tick counter. 421 // This extends the total rollover period from about 49 days to about 8800 422 // years while still allowing it to be stored with last_8 in a single 423 // 32-bit value. 424 uint16_t rollovers; 425 } as_values; 426 }; 427 std::atomic<int32_t> g_last_time_and_rollovers = 0; 428 static_assert( 429 sizeof(LastTimeAndRolloversState) <= sizeof(g_last_time_and_rollovers), 430 "LastTimeAndRolloversState does not fit in a single atomic word"); 431 432 // We use timeGetTime() to implement TimeTicks::Now(). This can be problematic 433 // because it returns the number of milliseconds since Windows has started, 434 // which will roll over the 32-bit value every ~49 days. We try to track 435 // rollover ourselves, which works if TimeTicks::Now() is called at least every 436 // 48.8 days (not 49 days because only changes in the top 8 bits get noticed). 437 TimeTicks RolloverProtectedNow() { 438 LastTimeAndRolloversState state; 439 DWORD now; // DWORD is always unsigned 32 bits. 440 441 while (true) { 442 // Fetch the "now" and "last" tick values, updating "last" with "now" and 443 // incrementing the "rollovers" counter if the tick-value has wrapped back 444 // around. Atomic operations ensure that both "last" and "rollovers" are 445 // always updated together. 446 int32_t original = 447 g_last_time_and_rollovers.load(std::memory_order_acquire); 448 state.as_opaque_32 = original; 449 now = g_tick_function(); 450 uint8_t now_8 = static_cast<uint8_t>(now >> 24); 451 if (now_8 < state.as_values.last_8) 452 ++state.as_values.rollovers; 453 state.as_values.last_8 = now_8; 454 455 // If the state hasn't changed, exit the loop. 456 if (state.as_opaque_32 == original) 457 break; 458 459 // Save the changed state. If the existing value is unchanged from the 460 // original so that the operation is successful. Exit the loop. 461 bool success = g_last_time_and_rollovers.compare_exchange_strong( 462 original, state.as_opaque_32, std::memory_order_release); 463 if (success) 464 break; 465 466 // Another thread has done something in between so retry from the top. 467 } 468 469 return TimeTicks() + 470 Milliseconds(now + 471 (static_cast<uint64_t>(state.as_values.rollovers) << 32)); 472 } 473 474 // Discussion of tick counter options on Windows: 475 // 476 // (1) CPU cycle counter. (Retrieved via RDTSC) 477 // The CPU counter provides the highest resolution time stamp and is the least 478 // expensive to retrieve. However, on older CPUs, two issues can affect its 479 // reliability: First it is maintained per processor and not synchronized 480 // between processors. Also, the counters will change frequency due to thermal 481 // and power changes, and stop in some states. 482 // 483 // (2) QueryPerformanceCounter (QPC). The QPC counter provides a high- 484 // resolution (<1 microsecond) time stamp. On most hardware running today, it 485 // auto-detects and uses the constant-rate RDTSC counter to provide extremely 486 // efficient and reliable time stamps. 487 // 488 // On older CPUs where RDTSC is unreliable, it falls back to using more 489 // expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI 490 // PM timer, and can involve system calls; and all this is up to the HAL (with 491 // some help from ACPI). According to 492 // http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the 493 // worst case, it gets the counter from the rollover interrupt on the 494 // programmable interrupt timer. In best cases, the HAL may conclude that the 495 // RDTSC counter runs at a constant frequency, then it uses that instead. On 496 // multiprocessor machines, it will try to verify the values returned from 497 // RDTSC on each processor are consistent with each other, and apply a handful 498 // of workarounds for known buggy hardware. In other words, QPC is supposed to 499 // give consistent results on a multiprocessor computer, but for older CPUs it 500 // can be unreliable due bugs in BIOS or HAL. 501 // 502 // (3) System time. The system time provides a low-resolution (from ~1 to ~15.6 503 // milliseconds) time stamp but is comparatively less expensive to retrieve and 504 // more reliable. Time::EnableHighResolutionTimer() and 505 // Time::ActivateHighResolutionTimer() can be called to alter the resolution of 506 // this timer; and also other Windows applications can alter it, affecting this 507 // one. 508 509 TimeTicks InitialNowFunction(); 510 511 // See "threading notes" in InitializeNowFunctionPointer() for details on how 512 // concurrent reads/writes to these globals has been made safe. 513 std::atomic<TimeTicksNowFunction> g_time_ticks_now_ignoring_override_function{ 514 &InitialNowFunction}; 515 int64_t g_qpc_ticks_per_second = 0; 516 517 TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) { 518 // Ensure that the assignment to |g_qpc_ticks_per_second|, made in 519 // InitializeNowFunctionPointer(), has happened by this point. 520 std::atomic_thread_fence(std::memory_order_acquire); 521 522 DCHECK_GT(g_qpc_ticks_per_second, 0); 523 524 // If the QPC Value is below the overflow threshold, we proceed with 525 // simple multiply and divide. 526 if (qpc_value < Time::kQPCOverflowThreshold) { 527 return Microseconds(qpc_value * Time::kMicrosecondsPerSecond / 528 g_qpc_ticks_per_second); 529 } 530 // Otherwise, calculate microseconds in a round about manner to avoid 531 // overflow and precision issues. 532 int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second; 533 int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second); 534 return Microseconds((whole_seconds * Time::kMicrosecondsPerSecond) + 535 ((leftover_ticks * Time::kMicrosecondsPerSecond) / 536 g_qpc_ticks_per_second)); 537 } 538 539 TimeTicks QPCNow() { 540 return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw()); 541 } 542 543 void InitializeNowFunctionPointer() { 544 LARGE_INTEGER ticks_per_sec = {}; 545 if (!QueryPerformanceFrequency(&ticks_per_sec)) 546 ticks_per_sec.QuadPart = 0; 547 548 // If Windows cannot provide a QPC implementation, TimeTicks::Now() must use 549 // the low-resolution clock. 550 // 551 // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now() 552 // will still use the low-resolution clock. A CPU lacking a non-stop time 553 // counter will cause Windows to provide an alternate QPC implementation that 554 // works, but is expensive to use. 555 // 556 // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015, 557 // ~72% of users fall within this category. 558 CPU cpu; 559 const TimeTicksNowFunction now_function = 560 (ticks_per_sec.QuadPart <= 0 || !cpu.has_non_stop_time_stamp_counter()) 561 ? &RolloverProtectedNow 562 : &QPCNow; 563 564 // Threading note 1: In an unlikely race condition, it's possible for two or 565 // more threads to enter InitializeNowFunctionPointer() in parallel. This is 566 // not a problem since all threads end up writing out the same values 567 // to the global variables, and those variable being atomic are safe to read 568 // from other threads. 569 // 570 // Threading note 2: A release fence is placed here to ensure, from the 571 // perspective of other threads using the function pointers, that the 572 // assignment to |g_qpc_ticks_per_second| happens before the function pointers 573 // are changed. 574 g_qpc_ticks_per_second = ticks_per_sec.QuadPart; 575 std::atomic_thread_fence(std::memory_order_release); 576 // Also set g_time_ticks_now_function to avoid the additional indirection via 577 // TimeTicksNowIgnoringOverride() for future calls to TimeTicks::Now(), only 578 // if it wasn't already overridden to a different value. memory_order_relaxed 579 // is sufficient since an explicit fence was inserted above. 580 base::TimeTicksNowFunction initial_time_ticks_now_function = 581 &subtle::TimeTicksNowIgnoringOverride; 582 internal::g_time_ticks_now_function.compare_exchange_strong( 583 initial_time_ticks_now_function, now_function, std::memory_order_relaxed); 584 g_time_ticks_now_ignoring_override_function.store(now_function, 585 std::memory_order_relaxed); 586 } 587 588 TimeTicks InitialNowFunction() { 589 InitializeNowFunctionPointer(); 590 return g_time_ticks_now_ignoring_override_function.load( 591 std::memory_order_relaxed)(); 592 } 593 594 } // namespace 595 596 // static 597 TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction( 598 TickFunctionType ticker) { 599 TickFunctionType old = g_tick_function; 600 g_tick_function = ticker; 601 g_last_time_and_rollovers.store(0, std::memory_order_relaxed); 602 return old; 603 } 604 605 namespace subtle { 606 TimeTicks TimeTicksNowIgnoringOverride() { 607 return g_time_ticks_now_ignoring_override_function.load( 608 std::memory_order_relaxed)(); 609 } 610 } // namespace subtle 611 612 // static 613 bool TimeTicks::IsHighResolution() { 614 if (g_time_ticks_now_ignoring_override_function == &InitialNowFunction) 615 InitializeNowFunctionPointer(); 616 return g_time_ticks_now_ignoring_override_function == &QPCNow; 617 } 618 619 // static 620 bool TimeTicks::IsConsistentAcrossProcesses() { 621 // According to Windows documentation [1] QPC is consistent post-Windows 622 // Vista. So if we are using QPC then we are consistent which is the same as 623 // being high resolution. 624 // 625 // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx 626 // 627 // "In general, the performance counter results are consistent across all 628 // processors in multi-core and multi-processor systems, even when measured on 629 // different threads or processes. Here are some exceptions to this rule: 630 // - Pre-Windows Vista operating systems that run on certain processors might 631 // violate this consistency because of one of these reasons: 632 // 1. The hardware processors have a non-invariant TSC and the BIOS 633 // doesn't indicate this condition correctly. 634 // 2. The TSC synchronization algorithm that was used wasn't suitable for 635 // systems with large numbers of processors." 636 return IsHighResolution(); 637 } 638 639 // static 640 TimeTicks::Clock TimeTicks::GetClock() { 641 return IsHighResolution() ? Clock::WIN_QPC 642 : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME; 643 } 644 645 // LiveTicks ------------------------------------------------------------------ 646 647 #if !defined(MOZ_SANDBOX) 648 namespace subtle { 649 LiveTicks LiveTicksNowIgnoringOverride() { 650 ULONGLONG unbiased_interrupt_time; 651 QueryUnbiasedInterruptTimePrecise(&unbiased_interrupt_time); 652 // QueryUnbiasedInterruptTimePrecise gets the interrupt time in system time 653 // units of 100 nanoseconds. 654 return LiveTicks() + Nanoseconds(unbiased_interrupt_time * 100); 655 } 656 } // namespace subtle 657 #endif 658 659 // ThreadTicks ---------------------------------------------------------------- 660 661 namespace subtle { 662 ThreadTicks ThreadTicksNowIgnoringOverride() { 663 return ThreadTicks::GetForThread(PlatformThread::CurrentHandle()); 664 } 665 } // namespace subtle 666 667 // static 668 ThreadTicks ThreadTicks::GetForThread( 669 const PlatformThreadHandle& thread_handle) { 670 DCHECK(IsSupported()); 671 672 #if defined(ARCH_CPU_ARM64) 673 // QueryThreadCycleTime versus TSCTicksPerSecond doesn't have much relation to 674 // actual elapsed time on Windows on Arm, because QueryThreadCycleTime is 675 // backed by the actual number of CPU cycles executed, rather than a 676 // constant-rate timer like Intel. To work around this, use GetThreadTimes 677 // (which isn't as accurate but is meaningful as a measure of elapsed 678 // per-thread time). 679 FILETIME creation_time, exit_time, kernel_time, user_time; 680 ::GetThreadTimes(thread_handle.platform_handle(), &creation_time, &exit_time, 681 &kernel_time, &user_time); 682 683 const int64_t us = FileTimeToMicroseconds(user_time); 684 #else 685 // Get the number of TSC ticks used by the current thread. 686 ULONG64 thread_cycle_time = 0; 687 ::QueryThreadCycleTime(thread_handle.platform_handle(), &thread_cycle_time); 688 689 // Get the frequency of the TSC. 690 const double tsc_ticks_per_second = time_internal::TSCTicksPerSecond(); 691 if (tsc_ticks_per_second == 0) 692 return ThreadTicks(); 693 694 // Return the CPU time of the current thread. 695 const double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second; 696 const int64_t us = 697 static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond); 698 #endif 699 700 return ThreadTicks(us); 701 } 702 703 // static 704 bool ThreadTicks::IsSupportedWin() { 705 #if defined(ARCH_CPU_ARM64) 706 // The Arm implementation does not use QueryThreadCycleTime and therefore does 707 // not care about the time stamp counter. 708 return true; 709 #else 710 return time_internal::HasConstantRateTSC(); 711 #endif 712 } 713 714 // static 715 void ThreadTicks::WaitUntilInitializedWin() { 716 #if !defined(ARCH_CPU_ARM64) 717 while (time_internal::TSCTicksPerSecond() == 0) 718 ::Sleep(10); 719 #endif 720 } 721 722 // static 723 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { 724 return TimeTicks() + QPCValueToTimeDelta(qpc_value); 725 } 726 727 // TimeDelta ------------------------------------------------------------------ 728 729 // static 730 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { 731 return QPCValueToTimeDelta(qpc_value); 732 } 733 734 // static 735 TimeDelta TimeDelta::FromFileTime(FILETIME ft) { 736 return Microseconds(FileTimeToMicroseconds(ft)); 737 } 738 739 // static 740 TimeDelta TimeDelta::FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt) { 741 // UniversalTime is 100 ns intervals since January 1, 1601 (UTC) 742 return Microseconds(dt.UniversalTime / 10); 743 } 744 745 ABI::Windows::Foundation::DateTime TimeDelta::ToWinrtDateTime() const { 746 ABI::Windows::Foundation::DateTime date_time; 747 date_time.UniversalTime = InMicroseconds() * 10; 748 return date_time; 749 } 750 751 // static 752 TimeDelta TimeDelta::FromWinrtTimeSpan(ABI::Windows::Foundation::TimeSpan ts) { 753 // Duration is 100 ns intervals 754 return Microseconds(ts.Duration / 10); 755 } 756 757 ABI::Windows::Foundation::TimeSpan TimeDelta::ToWinrtTimeSpan() const { 758 ABI::Windows::Foundation::TimeSpan time_span; 759 time_span.Duration = InMicroseconds() * 10; 760 return time_span; 761 } 762 763 #if !defined(ARCH_CPU_ARM64) 764 namespace time_internal { 765 766 bool HasConstantRateTSC() { 767 static bool is_supported = CPU().has_non_stop_time_stamp_counter(); 768 return is_supported; 769 } 770 771 double TSCTicksPerSecond() { 772 DCHECK(HasConstantRateTSC()); 773 // The value returned by QueryPerformanceFrequency() cannot be used as the TSC 774 // frequency, because there is no guarantee that the TSC frequency is equal to 775 // the performance counter frequency. 776 // The TSC frequency is cached in a static variable because it takes some time 777 // to compute it. 778 static double tsc_ticks_per_second = 0; 779 if (tsc_ticks_per_second != 0) 780 return tsc_ticks_per_second; 781 782 // Increase the thread priority to reduces the chances of having a context 783 // switch during a reading of the TSC and the performance counter. 784 const int previous_priority = ::GetThreadPriority(::GetCurrentThread()); 785 ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST); 786 787 // The first time that this function is called, make an initial reading of the 788 // TSC and the performance counter. 789 790 static const uint64_t tsc_initial = __rdtsc(); 791 static const int64_t perf_counter_initial = QPCNowRaw(); 792 793 // Make a another reading of the TSC and the performance counter every time 794 // that this function is called. 795 const uint64_t tsc_now = __rdtsc(); 796 const int64_t perf_counter_now = QPCNowRaw(); 797 798 // Reset the thread priority. 799 ::SetThreadPriority(::GetCurrentThread(), previous_priority); 800 801 // Make sure that at least 50 ms elapsed between the 2 readings. The first 802 // time that this function is called, we don't expect this to be the case. 803 // Note: The longer the elapsed time between the 2 readings is, the more 804 // accurate the computed TSC frequency will be. The 50 ms value was 805 // chosen because local benchmarks show that it allows us to get a 806 // stddev of less than 1 tick/us between multiple runs. 807 // Note: According to the MSDN documentation for QueryPerformanceFrequency(), 808 // this will never fail on systems that run XP or later. 809 // https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx 810 LARGE_INTEGER perf_counter_frequency = {}; 811 ::QueryPerformanceFrequency(&perf_counter_frequency); 812 DCHECK_GE(perf_counter_now, perf_counter_initial); 813 const int64_t perf_counter_ticks = perf_counter_now - perf_counter_initial; 814 const double elapsed_time_seconds = 815 perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart); 816 817 constexpr double kMinimumEvaluationPeriodSeconds = 0.05; 818 if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds) 819 return 0; 820 821 // Compute the frequency of the TSC. 822 DCHECK_GE(tsc_now, tsc_initial); 823 const uint64_t tsc_ticks = tsc_now - tsc_initial; 824 tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds; 825 826 return tsc_ticks_per_second; 827 } 828 829 } // namespace time_internal 830 #endif // defined(ARCH_CPU_ARM64) 831 832 } // namespace base