| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 | 5 |
| 6 // Windows Timer Primer | 6 // Windows Timer Primer |
| 7 // | 7 // |
| 8 // A good article: http://www.ddj.com/windows/184416651 | 8 // A good article: http://www.ddj.com/windows/184416651 |
| 9 // A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258 | 9 // A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258 |
| 10 // | 10 // |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 LastTimeAndRolloversState state; | 369 LastTimeAndRolloversState state; |
| 370 DWORD now; // DWORD is always unsigned 32 bits. | 370 DWORD now; // DWORD is always unsigned 32 bits. |
| 371 | 371 |
| 372 while (true) { | 372 while (true) { |
| 373 // Fetch the "now" and "last" tick values, updating "last" with "now" and | 373 // Fetch the "now" and "last" tick values, updating "last" with "now" and |
| 374 // incrementing the "rollovers" counter if the tick-value has wrapped back | 374 // incrementing the "rollovers" counter if the tick-value has wrapped back |
| 375 // around. Atomic operations ensure that both "last" and "rollovers" are | 375 // around. Atomic operations ensure that both "last" and "rollovers" are |
| 376 // always updated together. | 376 // always updated together. |
| 377 int32_t original = base::subtle::Acquire_Load(&g_last_time_and_rollovers); | 377 int32_t original = base::subtle::Acquire_Load(&g_last_time_and_rollovers); |
| 378 state.as_opaque_32 = original; | 378 state.as_opaque_32 = original; |
| 379 now = g_tick_function(); | 379 now = g_tick_function() & ~0xF; |
| 380 uint8_t now_8 = static_cast<uint8_t>(now >> 24); | 380 uint8_t now_8 = static_cast<uint8_t>(now >> 24); |
| 381 if (now_8 < state.as_values.last_8) | 381 if (now_8 < state.as_values.last_8) |
| 382 ++state.as_values.rollovers; | 382 ++state.as_values.rollovers; |
| 383 state.as_values.last_8 = now_8; | 383 state.as_values.last_8 = now_8; |
| 384 | 384 |
| 385 // If the state hasn't changed, exit the loop. | 385 // If the state hasn't changed, exit the loop. |
| 386 if (state.as_opaque_32 == original) | 386 if (state.as_opaque_32 == original) |
| 387 break; | 387 break; |
| 388 | 388 |
| 389 // Save the changed state. If the existing value is unchanged from the | 389 // Save the changed state. If the existing value is unchanged from the |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now() | 492 // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now() |
| 493 // will still use the low-resolution clock. A CPU lacking a non-stop time | 493 // will still use the low-resolution clock. A CPU lacking a non-stop time |
| 494 // counter will cause Windows to provide an alternate QPC implementation that | 494 // counter will cause Windows to provide an alternate QPC implementation that |
| 495 // works, but is expensive to use. Certain Athlon CPUs are known to make the | 495 // works, but is expensive to use. Certain Athlon CPUs are known to make the |
| 496 // QPC implementation unreliable. | 496 // QPC implementation unreliable. |
| 497 // | 497 // |
| 498 // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015, | 498 // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015, |
| 499 // ~72% of users fall within this category. | 499 // ~72% of users fall within this category. |
| 500 NowFunction now_function; | 500 NowFunction now_function; |
| 501 base::CPU cpu; | 501 base::CPU cpu; |
| 502 if (ticks_per_sec.QuadPart <= 0 || | 502 if (true || ticks_per_sec.QuadPart <= 0 || |
| 503 !cpu.has_non_stop_time_stamp_counter() || IsBuggyAthlon(cpu)) { | 503 !cpu.has_non_stop_time_stamp_counter() || IsBuggyAthlon(cpu)) { |
| 504 now_function = &RolloverProtectedNow; | 504 now_function = &RolloverProtectedNow; |
| 505 } else { | 505 } else { |
| 506 now_function = &QPCNow; | 506 now_function = &QPCNow; |
| 507 } | 507 } |
| 508 | 508 |
| 509 // Threading note 1: In an unlikely race condition, it's possible for two or | 509 // Threading note 1: In an unlikely race condition, it's possible for two or |
| 510 // more threads to enter InitializeNowFunctionPointer() in parallel. This is | 510 // more threads to enter InitializeNowFunctionPointer() in parallel. This is |
| 511 // not a problem since all threads should end up writing out the same values | 511 // not a problem since all threads should end up writing out the same values |
| 512 // to the global variables. | 512 // to the global variables. |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { | 675 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { |
| 676 return TimeTicks() + QPCValueToTimeDelta(qpc_value); | 676 return TimeTicks() + QPCValueToTimeDelta(qpc_value); |
| 677 } | 677 } |
| 678 | 678 |
| 679 // TimeDelta ------------------------------------------------------------------ | 679 // TimeDelta ------------------------------------------------------------------ |
| 680 | 680 |
| 681 // static | 681 // static |
| 682 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { | 682 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { |
| 683 return QPCValueToTimeDelta(qpc_value); | 683 return QPCValueToTimeDelta(qpc_value); |
| 684 } | 684 } |
| OLD | NEW |