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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 | 88 |
89 // The two values that ActivateHighResolutionTimer uses to set the systemwide | 89 // The two values that ActivateHighResolutionTimer uses to set the systemwide |
90 // timer interrupt frequency on Windows. It controls how precise timers are | 90 // timer interrupt frequency on Windows. It controls how precise timers are |
91 // but also has a big impact on battery life. | 91 // but also has a big impact on battery life. |
92 const int kMinTimerIntervalHighResMs = 1; | 92 const int kMinTimerIntervalHighResMs = 1; |
93 const int kMinTimerIntervalLowResMs = 4; | 93 const int kMinTimerIntervalLowResMs = 4; |
94 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. | 94 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. |
95 bool g_high_res_timer_enabled = false; | 95 bool g_high_res_timer_enabled = false; |
96 // How many times the high resolution timer has been called. | 96 // How many times the high resolution timer has been called. |
97 uint32_t g_high_res_timer_count = 0; | 97 uint32_t g_high_res_timer_count = 0; |
| 98 // Start time of the high resolution timer usage monitoring. This is needed |
| 99 // to calculate the usage as percentage of the total elapsed time. |
| 100 TimeTicks g_high_res_timer_usage_start; |
| 101 // The cumulative time the high resolution timer has been in use since |
| 102 // |g_high_res_timer_usage_start| moment. |
| 103 TimeDelta g_high_res_timer_usage; |
| 104 // Timestamp of the last activation change of the high resolution timer. This |
| 105 // is used to calculate the cumulative usage. |
| 106 TimeTicks g_high_res_timer_last_activation; |
98 // The lock to control access to the above two variables. | 107 // The lock to control access to the above two variables. |
99 base::Lock* GetHighResLock() { | 108 base::Lock* GetHighResLock() { |
100 static auto* lock = new base::Lock(); | 109 static auto* lock = new base::Lock(); |
101 return lock; | 110 return lock; |
102 } | 111 } |
103 | 112 |
104 // Returns the current value of the performance counter. | 113 // Returns the current value of the performance counter. |
105 uint64_t QPCNowRaw() { | 114 uint64_t QPCNowRaw() { |
106 LARGE_INTEGER perf_counter_now = {}; | 115 LARGE_INTEGER perf_counter_now = {}; |
107 // According to the MSDN documentation for QueryPerformanceCounter(), this | 116 // According to the MSDN documentation for QueryPerformanceCounter(), this |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 // can easily undo the effect (if necessary) when EnableHighResolutionTimer is | 220 // can easily undo the effect (if necessary) when EnableHighResolutionTimer is |
212 // called. | 221 // called. |
213 const uint32_t max = std::numeric_limits<uint32_t>::max(); | 222 const uint32_t max = std::numeric_limits<uint32_t>::max(); |
214 | 223 |
215 base::AutoLock lock(*GetHighResLock()); | 224 base::AutoLock lock(*GetHighResLock()); |
216 UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs | 225 UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs |
217 : kMinTimerIntervalLowResMs; | 226 : kMinTimerIntervalLowResMs; |
218 if (activating) { | 227 if (activating) { |
219 DCHECK_NE(g_high_res_timer_count, max); | 228 DCHECK_NE(g_high_res_timer_count, max); |
220 ++g_high_res_timer_count; | 229 ++g_high_res_timer_count; |
221 if (g_high_res_timer_count == 1) | 230 if (g_high_res_timer_count == 1) { |
| 231 g_high_res_timer_last_activation = TimeTicks::Now(); |
222 timeBeginPeriod(period); | 232 timeBeginPeriod(period); |
| 233 } |
223 } else { | 234 } else { |
224 DCHECK_NE(g_high_res_timer_count, 0u); | 235 DCHECK_NE(g_high_res_timer_count, 0u); |
225 --g_high_res_timer_count; | 236 --g_high_res_timer_count; |
226 if (g_high_res_timer_count == 0) | 237 if (g_high_res_timer_count == 0) { |
| 238 g_high_res_timer_usage += |
| 239 TimeTicks::Now() - g_high_res_timer_last_activation; |
227 timeEndPeriod(period); | 240 timeEndPeriod(period); |
| 241 } |
228 } | 242 } |
229 return (period == kMinTimerIntervalHighResMs); | 243 return (period == kMinTimerIntervalHighResMs); |
230 } | 244 } |
231 | 245 |
232 // static | 246 // static |
233 bool Time::IsHighResolutionTimerInUse() { | 247 bool Time::IsHighResolutionTimerInUse() { |
234 base::AutoLock lock(*GetHighResLock()); | 248 base::AutoLock lock(*GetHighResLock()); |
235 return g_high_res_timer_enabled && g_high_res_timer_count > 0; | 249 return g_high_res_timer_enabled && g_high_res_timer_count > 0; |
236 } | 250 } |
237 | 251 |
238 // static | 252 // static |
| 253 void Time::ResetHighResolutionTimerUsage() { |
| 254 base::AutoLock lock(*GetHighResLock()); |
| 255 g_high_res_timer_usage = TimeDelta(); |
| 256 g_high_res_timer_usage_start = TimeTicks::Now(); |
| 257 if (g_high_res_timer_count > 0) |
| 258 g_high_res_timer_last_activation = g_high_res_timer_usage_start; |
| 259 } |
| 260 |
| 261 // static |
| 262 double Time::GetHighResolutionTimerUsage() { |
| 263 base::AutoLock lock(*GetHighResLock()); |
| 264 TimeTicks now = TimeTicks::Now(); |
| 265 TimeDelta elapsed_time = now - g_high_res_timer_usage_start; |
| 266 if (elapsed_time.is_zero()) { |
| 267 // This is unexpected but possible if TimeTicks resolution is low and |
| 268 // GetHighResolutionTimerUsage() is called promptly after |
| 269 // ResetHighResolutionTimerUsage(). |
| 270 return 0.0; |
| 271 } |
| 272 TimeDelta used_time = g_high_res_timer_usage; |
| 273 if (g_high_res_timer_count > 0) { |
| 274 // If currently activated add the remainder of time since the last |
| 275 // activation. |
| 276 used_time += now - g_high_res_timer_last_activation; |
| 277 } |
| 278 return used_time.InMillisecondsF() / elapsed_time.InMillisecondsF() * 100; |
| 279 } |
| 280 |
| 281 // static |
239 bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { | 282 bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { |
240 // Create the system struct representing our exploded time. It will either be | 283 // Create the system struct representing our exploded time. It will either be |
241 // in local time or UTC.If casting from int to WORD results in overflow, | 284 // in local time or UTC.If casting from int to WORD results in overflow, |
242 // fail and return Time(0). | 285 // fail and return Time(0). |
243 SYSTEMTIME st; | 286 SYSTEMTIME st; |
244 if (!SafeConvertToWord(exploded.year, &st.wYear) || | 287 if (!SafeConvertToWord(exploded.year, &st.wYear) || |
245 !SafeConvertToWord(exploded.month, &st.wMonth) || | 288 !SafeConvertToWord(exploded.month, &st.wMonth) || |
246 !SafeConvertToWord(exploded.day_of_week, &st.wDayOfWeek) || | 289 !SafeConvertToWord(exploded.day_of_week, &st.wDayOfWeek) || |
247 !SafeConvertToWord(exploded.day_of_month, &st.wDay) || | 290 !SafeConvertToWord(exploded.day_of_month, &st.wDay) || |
248 !SafeConvertToWord(exploded.hour, &st.wHour) || | 291 !SafeConvertToWord(exploded.hour, &st.wHour) || |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { | 711 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { |
669 return TimeTicks() + QPCValueToTimeDelta(qpc_value); | 712 return TimeTicks() + QPCValueToTimeDelta(qpc_value); |
670 } | 713 } |
671 | 714 |
672 // TimeDelta ------------------------------------------------------------------ | 715 // TimeDelta ------------------------------------------------------------------ |
673 | 716 |
674 // static | 717 // static |
675 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { | 718 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { |
676 return QPCValueToTimeDelta(qpc_value); | 719 return QPCValueToTimeDelta(qpc_value); |
677 } | 720 } |
OLD | NEW |