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 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
337 // (3) System time. The system time provides a low-resolution (typically 10ms | 337 // (3) System time. The system time provides a low-resolution (typically 10ms |
338 // to 55 milliseconds) time stamp but is comparatively less expensive to | 338 // to 55 milliseconds) time stamp but is comparatively less expensive to |
339 // retrieve and more reliable. | 339 // retrieve and more reliable. |
340 class HighResNowSingleton { | 340 class HighResNowSingleton { |
341 public: | 341 public: |
342 static HighResNowSingleton* GetInstance() { | 342 static HighResNowSingleton* GetInstance() { |
343 return Singleton<HighResNowSingleton>::get(); | 343 return Singleton<HighResNowSingleton>::get(); |
344 } | 344 } |
345 | 345 |
346 bool IsUsingHighResClock() { | 346 bool IsUsingHighResClock() { |
347 return ticks_per_microsecond_ != 0.0; | 347 return ticks_per_second_ != 0.0; |
348 } | 348 } |
349 | 349 |
350 void DisableHighResClock() { | 350 void DisableHighResClock() { |
351 ticks_per_microsecond_ = 0.0; | 351 ticks_per_second_ = 0.0; |
352 } | 352 } |
353 | 353 |
354 TimeDelta Now() { | 354 TimeDelta Now() { |
355 if (IsUsingHighResClock()) | 355 if (IsUsingHighResClock()) |
356 return TimeDelta::FromMicroseconds(UnreliableNow()); | 356 return TimeDelta::FromMicroseconds(UnreliableNow()); |
357 | 357 |
358 // Just fallback to the slower clock. | 358 // Just fallback to the slower clock. |
359 return RolloverProtectedNow(); | 359 return RolloverProtectedNow(); |
360 } | 360 } |
361 | 361 |
362 int64 GetQPCDriftMicroseconds() { | 362 int64 GetQPCDriftMicroseconds() { |
363 if (!IsUsingHighResClock()) | 363 if (!IsUsingHighResClock()) |
364 return 0; | 364 return 0; |
365 | 365 |
366 // The static_cast<long> is needed as a hint to VS 2008 to tell it | 366 // The static_cast<long> is needed as a hint to VS 2008 to tell it |
367 // which version of abs() to use. Other compilers don't seem to | 367 // which version of abs() to use. Other compilers don't seem to |
368 // need it, including VS 2010, but to keep code identical we use it | 368 // need it, including VS 2010, but to keep code identical we use it |
369 // everywhere. | 369 // everywhere. |
370 // TODO(joi): Remove the hint if/when we no longer support VS 2008. | 370 // TODO(joi): Remove the hint if/when we no longer support VS 2008. |
371 return abs(static_cast<long>((UnreliableNow() - ReliableNow()) - skew_)); | 371 return abs(static_cast<long>((UnreliableNow() - ReliableNow()) - skew_)); |
372 } | 372 } |
373 | 373 |
374 int64 QPCValueToMicroseconds(LONGLONG qpc_value) { | |
375 if (ticks_per_second_) | |
376 return qpc_value * Time::kMicrosecondsPerSecond / ticks_per_second_; | |
jar (doing other things)
2012/08/02 03:13:20
nit: 2 character indent from start of "if"
| |
377 return 0; | |
378 } | |
379 | |
374 private: | 380 private: |
375 HighResNowSingleton() | 381 HighResNowSingleton() |
376 : ticks_per_microsecond_(0.0), | 382 : ticks_per_second_(0), |
jbates
2012/08/02 03:10:34
what's the reason for changing to per_second? seem
brianderson
2012/08/02 19:04:14
Using ticks per second, we are dividing by the act
| |
377 skew_(0) { | 383 skew_(0) { |
378 InitializeClock(); | 384 InitializeClock(); |
379 | 385 |
380 // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is | 386 // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is |
381 // unreliable. Fallback to low-res clock. | 387 // unreliable. Fallback to low-res clock. |
382 base::CPU cpu; | 388 base::CPU cpu; |
383 if (cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15) | 389 if (cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15) |
384 DisableHighResClock(); | 390 DisableHighResClock(); |
385 } | 391 } |
386 | 392 |
387 // Synchronize the QPC clock with GetSystemTimeAsFileTime. | 393 // Synchronize the QPC clock with GetSystemTimeAsFileTime. |
388 void InitializeClock() { | 394 void InitializeClock() { |
389 LARGE_INTEGER ticks_per_sec = {0}; | 395 LARGE_INTEGER ticks_per_sec = {0}; |
390 if (!QueryPerformanceFrequency(&ticks_per_sec)) | 396 if (!QueryPerformanceFrequency(&ticks_per_sec)) |
391 return; // Broken, we don't guarantee this function works. | 397 return; // Broken, we don't guarantee this function works. |
392 ticks_per_microsecond_ = static_cast<float>(ticks_per_sec.QuadPart) / | 398 ticks_per_second_ = ticks_per_sec.QuadPart; |
393 static_cast<float>(Time::kMicrosecondsPerSecond); | |
394 | 399 |
395 skew_ = UnreliableNow() - ReliableNow(); | 400 skew_ = UnreliableNow() - ReliableNow(); |
396 } | 401 } |
397 | 402 |
398 // Get the number of microseconds since boot in an unreliable fashion. | 403 // Get the number of microseconds since boot in an unreliable fashion. |
399 int64 UnreliableNow() { | 404 int64 UnreliableNow() { |
400 LARGE_INTEGER now; | 405 LARGE_INTEGER now; |
401 QueryPerformanceCounter(&now); | 406 QueryPerformanceCounter(&now); |
402 return static_cast<int64>(now.QuadPart / ticks_per_microsecond_); | 407 return now.QuadPart * Time::kMicrosecondsPerSecond / ticks_per_second_; |
jar (doing other things)
2012/08/02 03:13:20
I think this is going to work ok (working with int
| |
403 } | 408 } |
404 | 409 |
405 // Get the number of microseconds since boot in a reliable fashion. | 410 // Get the number of microseconds since boot in a reliable fashion. |
406 int64 ReliableNow() { | 411 int64 ReliableNow() { |
407 return RolloverProtectedNow().InMicroseconds(); | 412 return RolloverProtectedNow().InMicroseconds(); |
408 } | 413 } |
409 | 414 |
410 // Cached clock frequency -> microseconds. This assumes that the clock | 415 // Cached clock frequency -> microseconds. This assumes that the clock |
jar (doing other things)
2012/08/02 03:13:20
Comment should be changed or removed.
| |
411 // frequency is faster than one microsecond (which is 1MHz, should be OK). | 416 // frequency is faster than one microsecond (which is 1MHz, should be OK). |
412 float ticks_per_microsecond_; // 0 indicates QPF failed and we're broken. | 417 int64 ticks_per_second_; // 0 indicates QPF failed and we're broken. |
413 int64 skew_; // Skew between lo-res and hi-res clocks (for debugging). | 418 int64 skew_; // Skew between lo-res and hi-res clocks (for debugging). |
414 | 419 |
415 friend struct DefaultSingletonTraits<HighResNowSingleton>; | 420 friend struct DefaultSingletonTraits<HighResNowSingleton>; |
416 }; | 421 }; |
417 | 422 |
418 } // namespace | 423 } // namespace |
419 | 424 |
420 // static | 425 // static |
421 TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction( | 426 TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction( |
422 TickFunctionType ticker) { | 427 TickFunctionType ticker) { |
(...skipping 16 matching lines...) Expand all Loading... | |
439 TimeTicks TimeTicks::NowFromSystemTraceTime() { | 444 TimeTicks TimeTicks::NowFromSystemTraceTime() { |
440 return HighResNow(); | 445 return HighResNow(); |
441 } | 446 } |
442 | 447 |
443 // static | 448 // static |
444 int64 TimeTicks::GetQPCDriftMicroseconds() { | 449 int64 TimeTicks::GetQPCDriftMicroseconds() { |
445 return HighResNowSingleton::GetInstance()->GetQPCDriftMicroseconds(); | 450 return HighResNowSingleton::GetInstance()->GetQPCDriftMicroseconds(); |
446 } | 451 } |
447 | 452 |
448 // static | 453 // static |
454 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { | |
455 return TimeTicks( | |
456 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value)); | |
457 } | |
458 | |
459 // static | |
449 bool TimeTicks::IsHighResClockWorking() { | 460 bool TimeTicks::IsHighResClockWorking() { |
450 return HighResNowSingleton::GetInstance()->IsUsingHighResClock(); | 461 return HighResNowSingleton::GetInstance()->IsUsingHighResClock(); |
451 } | 462 } |
463 | |
464 // TimeDelta ------------------------------------------------------------------ | |
465 | |
466 // static | |
467 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { | |
468 return TimeDelta( | |
469 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value)); | |
470 } | |
OLD | NEW |