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 22 matching lines...) Expand all Loading... |
33 | 33 |
34 #include "base/time/time.h" | 34 #include "base/time/time.h" |
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/atomicops.h" | 40 #include "base/atomicops.h" |
41 #include "base/bit_cast.h" | 41 #include "base/bit_cast.h" |
42 #include "base/cpu.h" | 42 #include "base/cpu.h" |
43 #include "base/lazy_instance.h" | |
44 #include "base/logging.h" | 43 #include "base/logging.h" |
45 #include "base/synchronization/lock.h" | 44 #include "base/synchronization/lock.h" |
46 #include "base/threading/platform_thread.h" | 45 #include "base/threading/platform_thread.h" |
47 | 46 |
48 using base::ThreadTicks; | 47 using base::ThreadTicks; |
49 using base::Time; | 48 using base::Time; |
50 using base::TimeDelta; | 49 using base::TimeDelta; |
51 using base::TimeTicks; | 50 using base::TimeTicks; |
52 | 51 |
53 namespace { | 52 namespace { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 // The two values that ActivateHighResolutionTimer uses to set the systemwide | 89 // The two values that ActivateHighResolutionTimer uses to set the systemwide |
91 // timer interrupt frequency on Windows. It controls how precise timers are | 90 // timer interrupt frequency on Windows. It controls how precise timers are |
92 // but also has a big impact on battery life. | 91 // but also has a big impact on battery life. |
93 const int kMinTimerIntervalHighResMs = 1; | 92 const int kMinTimerIntervalHighResMs = 1; |
94 const int kMinTimerIntervalLowResMs = 4; | 93 const int kMinTimerIntervalLowResMs = 4; |
95 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. | 94 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. |
96 bool g_high_res_timer_enabled = false; | 95 bool g_high_res_timer_enabled = false; |
97 // How many times the high resolution timer has been called. | 96 // How many times the high resolution timer has been called. |
98 uint32_t g_high_res_timer_count = 0; | 97 uint32_t g_high_res_timer_count = 0; |
99 // The lock to control access to the above two variables. | 98 // The lock to control access to the above two variables. |
100 base::LazyInstance<base::Lock>::Leaky g_high_res_lock = | 99 base::Lock* GetHighResLock() { |
101 LAZY_INSTANCE_INITIALIZER; | 100 static auto lock = new base::Lock(); |
| 101 return lock; |
| 102 } |
102 | 103 |
103 // Returns the current value of the performance counter. | 104 // Returns the current value of the performance counter. |
104 uint64_t QPCNowRaw() { | 105 uint64_t QPCNowRaw() { |
105 LARGE_INTEGER perf_counter_now = {}; | 106 LARGE_INTEGER perf_counter_now = {}; |
106 // According to the MSDN documentation for QueryPerformanceCounter(), this | 107 // According to the MSDN documentation for QueryPerformanceCounter(), this |
107 // will never fail on systems that run XP or later. | 108 // will never fail on systems that run XP or later. |
108 // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx | 109 // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx |
109 ::QueryPerformanceCounter(&perf_counter_now); | 110 ::QueryPerformanceCounter(&perf_counter_now); |
110 return perf_counter_now.QuadPart; | 111 return perf_counter_now.QuadPart; |
111 } | 112 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 result.dwLowDateTime = std::numeric_limits<DWORD>::max(); | 185 result.dwLowDateTime = std::numeric_limits<DWORD>::max(); |
185 return result; | 186 return result; |
186 } | 187 } |
187 FILETIME utc_ft; | 188 FILETIME utc_ft; |
188 MicrosecondsToFileTime(us_, &utc_ft); | 189 MicrosecondsToFileTime(us_, &utc_ft); |
189 return utc_ft; | 190 return utc_ft; |
190 } | 191 } |
191 | 192 |
192 // static | 193 // static |
193 void Time::EnableHighResolutionTimer(bool enable) { | 194 void Time::EnableHighResolutionTimer(bool enable) { |
194 base::AutoLock lock(g_high_res_lock.Get()); | 195 base::AutoLock lock(*GetHighResLock()); |
195 if (g_high_res_timer_enabled == enable) | 196 if (g_high_res_timer_enabled == enable) |
196 return; | 197 return; |
197 g_high_res_timer_enabled = enable; | 198 g_high_res_timer_enabled = enable; |
198 if (!g_high_res_timer_count) | 199 if (!g_high_res_timer_count) |
199 return; | 200 return; |
200 // Since g_high_res_timer_count != 0, an ActivateHighResolutionTimer(true) | 201 // Since g_high_res_timer_count != 0, an ActivateHighResolutionTimer(true) |
201 // was called which called timeBeginPeriod with g_high_res_timer_enabled | 202 // was called which called timeBeginPeriod with g_high_res_timer_enabled |
202 // with a value which is the opposite of |enable|. With that information we | 203 // with a value which is the opposite of |enable|. With that information we |
203 // call timeEndPeriod with the same value used in timeBeginPeriod and | 204 // call timeEndPeriod with the same value used in timeBeginPeriod and |
204 // therefore undo the period effect. | 205 // therefore undo the period effect. |
205 if (enable) { | 206 if (enable) { |
206 timeEndPeriod(kMinTimerIntervalLowResMs); | 207 timeEndPeriod(kMinTimerIntervalLowResMs); |
207 timeBeginPeriod(kMinTimerIntervalHighResMs); | 208 timeBeginPeriod(kMinTimerIntervalHighResMs); |
208 } else { | 209 } else { |
209 timeEndPeriod(kMinTimerIntervalHighResMs); | 210 timeEndPeriod(kMinTimerIntervalHighResMs); |
210 timeBeginPeriod(kMinTimerIntervalLowResMs); | 211 timeBeginPeriod(kMinTimerIntervalLowResMs); |
211 } | 212 } |
212 } | 213 } |
213 | 214 |
214 // static | 215 // static |
215 bool Time::ActivateHighResolutionTimer(bool activating) { | 216 bool Time::ActivateHighResolutionTimer(bool activating) { |
216 // We only do work on the transition from zero to one or one to zero so we | 217 // We only do work on the transition from zero to one or one to zero so we |
217 // can easily undo the effect (if necessary) when EnableHighResolutionTimer is | 218 // can easily undo the effect (if necessary) when EnableHighResolutionTimer is |
218 // called. | 219 // called. |
219 const uint32_t max = std::numeric_limits<uint32_t>::max(); | 220 const uint32_t max = std::numeric_limits<uint32_t>::max(); |
220 | 221 |
221 base::AutoLock lock(g_high_res_lock.Get()); | 222 base::AutoLock lock(*GetHighResLock()); |
222 UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs | 223 UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs |
223 : kMinTimerIntervalLowResMs; | 224 : kMinTimerIntervalLowResMs; |
224 if (activating) { | 225 if (activating) { |
225 DCHECK_NE(g_high_res_timer_count, max); | 226 DCHECK_NE(g_high_res_timer_count, max); |
226 ++g_high_res_timer_count; | 227 ++g_high_res_timer_count; |
227 if (g_high_res_timer_count == 1) | 228 if (g_high_res_timer_count == 1) |
228 timeBeginPeriod(period); | 229 timeBeginPeriod(period); |
229 } else { | 230 } else { |
230 DCHECK_NE(g_high_res_timer_count, 0u); | 231 DCHECK_NE(g_high_res_timer_count, 0u); |
231 --g_high_res_timer_count; | 232 --g_high_res_timer_count; |
232 if (g_high_res_timer_count == 0) | 233 if (g_high_res_timer_count == 0) |
233 timeEndPeriod(period); | 234 timeEndPeriod(period); |
234 } | 235 } |
235 return (period == kMinTimerIntervalHighResMs); | 236 return (period == kMinTimerIntervalHighResMs); |
236 } | 237 } |
237 | 238 |
238 // static | 239 // static |
239 bool Time::IsHighResolutionTimerInUse() { | 240 bool Time::IsHighResolutionTimerInUse() { |
240 base::AutoLock lock(g_high_res_lock.Get()); | 241 base::AutoLock lock(*GetHighResLock()); |
241 return g_high_res_timer_enabled && g_high_res_timer_count > 0; | 242 return g_high_res_timer_enabled && g_high_res_timer_count > 0; |
242 } | 243 } |
243 | 244 |
244 // static | 245 // static |
245 bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { | 246 bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { |
246 // Create the system struct representing our exploded time. It will either be | 247 // Create the system struct representing our exploded time. It will either be |
247 // in local time or UTC.If casting from int to WORD results in overflow, | 248 // in local time or UTC.If casting from int to WORD results in overflow, |
248 // fail and return Time(0). | 249 // fail and return Time(0). |
249 SYSTEMTIME st; | 250 SYSTEMTIME st; |
250 if (!SafeConvertToWord(exploded.year, &st.wYear) || | 251 if (!SafeConvertToWord(exploded.year, &st.wYear) || |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { | 675 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { |
675 return TimeTicks() + QPCValueToTimeDelta(qpc_value); | 676 return TimeTicks() + QPCValueToTimeDelta(qpc_value); |
676 } | 677 } |
677 | 678 |
678 // TimeDelta ------------------------------------------------------------------ | 679 // TimeDelta ------------------------------------------------------------------ |
679 | 680 |
680 // static | 681 // static |
681 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { | 682 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { |
682 return QPCValueToTimeDelta(qpc_value); | 683 return QPCValueToTimeDelta(qpc_value); |
683 } | 684 } |
OLD | NEW |