| 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 |