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 24 matching lines...) Expand all Loading... |
35 | 35 |
36 #include <windows.h> | 36 #include <windows.h> |
37 #include <mmsystem.h> | 37 #include <mmsystem.h> |
38 #include <stdint.h> | 38 #include <stdint.h> |
39 | 39 |
40 #include "base/bit_cast.h" | 40 #include "base/bit_cast.h" |
41 #include "base/cpu.h" | 41 #include "base/cpu.h" |
42 #include "base/lazy_instance.h" | 42 #include "base/lazy_instance.h" |
43 #include "base/logging.h" | 43 #include "base/logging.h" |
44 #include "base/synchronization/lock.h" | 44 #include "base/synchronization/lock.h" |
| 45 #include "base/threading/platform_thread.h" |
45 | 46 |
46 using base::ThreadTicks; | 47 using base::ThreadTicks; |
47 using base::Time; | 48 using base::Time; |
48 using base::TimeDelta; | 49 using base::TimeDelta; |
49 using base::TimeTicks; | 50 using base::TimeTicks; |
50 | 51 |
51 namespace { | 52 namespace { |
52 | 53 |
53 // From MSDN, FILETIME "Contains a 64-bit value representing the number of | 54 // From MSDN, FILETIME "Contains a 64-bit value representing the number of |
54 // 100-nanosecond intervals since January 1, 1601 (UTC)." | 55 // 100-nanosecond intervals since January 1, 1601 (UTC)." |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 const int kMinTimerIntervalHighResMs = 1; | 92 const int kMinTimerIntervalHighResMs = 1; |
92 const int kMinTimerIntervalLowResMs = 4; | 93 const int kMinTimerIntervalLowResMs = 4; |
93 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. | 94 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. |
94 bool g_high_res_timer_enabled = false; | 95 bool g_high_res_timer_enabled = false; |
95 // How many times the high resolution timer has been called. | 96 // How many times the high resolution timer has been called. |
96 uint32_t g_high_res_timer_count = 0; | 97 uint32_t g_high_res_timer_count = 0; |
97 // The lock to control access to the above two variables. | 98 // The lock to control access to the above two variables. |
98 base::LazyInstance<base::Lock>::Leaky g_high_res_lock = | 99 base::LazyInstance<base::Lock>::Leaky g_high_res_lock = |
99 LAZY_INSTANCE_INITIALIZER; | 100 LAZY_INSTANCE_INITIALIZER; |
100 | 101 |
101 // Returns a pointer to the QueryThreadCycleTime() function from Windows. | |
102 // Can't statically link to it because it is not available on XP. | |
103 using QueryThreadCycleTimePtr = decltype(::QueryThreadCycleTime)*; | |
104 QueryThreadCycleTimePtr GetQueryThreadCycleTimeFunction() { | |
105 static const QueryThreadCycleTimePtr query_thread_cycle_time_fn = | |
106 reinterpret_cast<QueryThreadCycleTimePtr>(::GetProcAddress( | |
107 ::GetModuleHandle(L"kernel32.dll"), "QueryThreadCycleTime")); | |
108 return query_thread_cycle_time_fn; | |
109 } | |
110 | |
111 // Returns the current value of the performance counter. | 102 // Returns the current value of the performance counter. |
112 uint64_t QPCNowRaw() { | 103 uint64_t QPCNowRaw() { |
113 LARGE_INTEGER perf_counter_now = {}; | 104 LARGE_INTEGER perf_counter_now = {}; |
114 // According to the MSDN documentation for QueryPerformanceCounter(), this | 105 // According to the MSDN documentation for QueryPerformanceCounter(), this |
115 // will never fail on systems that run XP or later. | 106 // will never fail on systems that run XP or later. |
116 // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx | 107 // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx |
117 ::QueryPerformanceCounter(&perf_counter_now); | 108 ::QueryPerformanceCounter(&perf_counter_now); |
118 return perf_counter_now.QuadPart; | 109 return perf_counter_now.QuadPart; |
119 } | 110 } |
120 | 111 |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 } | 502 } |
512 | 503 |
513 // static | 504 // static |
514 TimeTicks::Clock TimeTicks::GetClock() { | 505 TimeTicks::Clock TimeTicks::GetClock() { |
515 return IsHighResolution() ? | 506 return IsHighResolution() ? |
516 Clock::WIN_QPC : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME; | 507 Clock::WIN_QPC : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME; |
517 } | 508 } |
518 | 509 |
519 // static | 510 // static |
520 ThreadTicks ThreadTicks::Now() { | 511 ThreadTicks ThreadTicks::Now() { |
| 512 return ThreadTicks::GetForThread(PlatformThread::CurrentHandle()); |
| 513 } |
| 514 |
| 515 // static |
| 516 ThreadTicks ThreadTicks::GetForThread( |
| 517 const base::PlatformThreadHandle& thread_handle) { |
521 DCHECK(IsSupported()); | 518 DCHECK(IsSupported()); |
522 | 519 |
523 // Get the number of TSC ticks used by the current thread. | 520 // Get the number of TSC ticks used by the current thread. |
524 ULONG64 thread_cycle_time = 0; | 521 ULONG64 thread_cycle_time = 0; |
525 GetQueryThreadCycleTimeFunction()(::GetCurrentThread(), &thread_cycle_time); | 522 ::QueryThreadCycleTime(thread_handle.platform_handle(), &thread_cycle_time); |
526 | 523 |
527 // Get the frequency of the TSC. | 524 // Get the frequency of the TSC. |
528 double tsc_ticks_per_second = TSCTicksPerSecond(); | 525 double tsc_ticks_per_second = TSCTicksPerSecond(); |
529 if (tsc_ticks_per_second == 0) | 526 if (tsc_ticks_per_second == 0) |
530 return ThreadTicks(); | 527 return ThreadTicks(); |
531 | 528 |
532 // Return the CPU time of the current thread. | 529 // Return the CPU time of the current thread. |
533 double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second; | 530 double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second; |
534 return ThreadTicks( | 531 return ThreadTicks( |
535 static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond)); | 532 static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond)); |
536 } | 533 } |
537 | 534 |
538 // static | 535 // static |
539 bool ThreadTicks::IsSupportedWin() { | 536 bool ThreadTicks::IsSupportedWin() { |
540 static bool is_supported = GetQueryThreadCycleTimeFunction() && | 537 static bool is_supported = base::CPU().has_non_stop_time_stamp_counter() && |
541 base::CPU().has_non_stop_time_stamp_counter() && | |
542 !IsBuggyAthlon(base::CPU()); | 538 !IsBuggyAthlon(base::CPU()); |
543 return is_supported; | 539 return is_supported; |
544 } | 540 } |
545 | 541 |
546 // static | 542 // static |
547 void ThreadTicks::WaitUntilInitializedWin() { | 543 void ThreadTicks::WaitUntilInitializedWin() { |
548 while (TSCTicksPerSecond() == 0) | 544 while (TSCTicksPerSecond() == 0) |
549 ::Sleep(10); | 545 ::Sleep(10); |
550 } | 546 } |
551 | 547 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { | 608 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { |
613 return TimeTicks() + QPCValueToTimeDelta(qpc_value); | 609 return TimeTicks() + QPCValueToTimeDelta(qpc_value); |
614 } | 610 } |
615 | 611 |
616 // TimeDelta ------------------------------------------------------------------ | 612 // TimeDelta ------------------------------------------------------------------ |
617 | 613 |
618 // static | 614 // static |
619 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { | 615 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { |
620 return QPCValueToTimeDelta(qpc_value); | 616 return QPCValueToTimeDelta(qpc_value); |
621 } | 617 } |
OLD | NEW |