Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: base/time_win.cc

Issue 10843038: Add native QPC to base::Time* conversion on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix typo and remove unnecessary comment Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/time.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 0;
377
378 // Intentionally calculate microseconds in a round about manner to avoid
379 // overflow and precision issues. Think twice before simplifying!
380 int64 whole_seconds = qpc_value / ticks_per_second_;
381 int64 leftover_ticks = qpc_value % ticks_per_second_;
382 int64 microseconds = (whole_seconds * Time::kMicrosecondsPerSecond) +
383 ((leftover_ticks * Time::kMicrosecondsPerSecond) /
384 ticks_per_second_);
385 return microseconds;
386 }
387
374 private: 388 private:
375 HighResNowSingleton() 389 HighResNowSingleton()
376 : ticks_per_microsecond_(0.0), 390 : ticks_per_second_(0),
377 skew_(0) { 391 skew_(0) {
378 InitializeClock(); 392 InitializeClock();
379 393
380 // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is 394 // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is
381 // unreliable. Fallback to low-res clock. 395 // unreliable. Fallback to low-res clock.
382 base::CPU cpu; 396 base::CPU cpu;
383 if (cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15) 397 if (cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15)
384 DisableHighResClock(); 398 DisableHighResClock();
385 } 399 }
386 400
387 // Synchronize the QPC clock with GetSystemTimeAsFileTime. 401 // Synchronize the QPC clock with GetSystemTimeAsFileTime.
388 void InitializeClock() { 402 void InitializeClock() {
389 LARGE_INTEGER ticks_per_sec = {0}; 403 LARGE_INTEGER ticks_per_sec = {0};
390 if (!QueryPerformanceFrequency(&ticks_per_sec)) 404 if (!QueryPerformanceFrequency(&ticks_per_sec))
391 return; // Broken, we don't guarantee this function works. 405 return; // Broken, we don't guarantee this function works.
392 ticks_per_microsecond_ = static_cast<float>(ticks_per_sec.QuadPart) / 406 ticks_per_second_ = ticks_per_sec.QuadPart;
393 static_cast<float>(Time::kMicrosecondsPerSecond);
394 407
395 skew_ = UnreliableNow() - ReliableNow(); 408 skew_ = UnreliableNow() - ReliableNow();
396 } 409 }
397 410
398 // Get the number of microseconds since boot in an unreliable fashion. 411 // Get the number of microseconds since boot in an unreliable fashion.
399 int64 UnreliableNow() { 412 int64 UnreliableNow() {
400 LARGE_INTEGER now; 413 LARGE_INTEGER now;
401 QueryPerformanceCounter(&now); 414 QueryPerformanceCounter(&now);
402 return static_cast<int64>(now.QuadPart / ticks_per_microsecond_); 415 return QPCValueToMicroseconds(now.QuadPart);
403 } 416 }
404 417
405 // Get the number of microseconds since boot in a reliable fashion. 418 // Get the number of microseconds since boot in a reliable fashion.
406 int64 ReliableNow() { 419 int64 ReliableNow() {
407 return RolloverProtectedNow().InMicroseconds(); 420 return RolloverProtectedNow().InMicroseconds();
408 } 421 }
409 422
410 // Cached clock frequency -> microseconds. This assumes that the clock 423 int64 ticks_per_second_; // 0 indicates QPF failed and we're broken.
411 // 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.
413 int64 skew_; // Skew between lo-res and hi-res clocks (for debugging). 424 int64 skew_; // Skew between lo-res and hi-res clocks (for debugging).
414 425
415 friend struct DefaultSingletonTraits<HighResNowSingleton>; 426 friend struct DefaultSingletonTraits<HighResNowSingleton>;
416 }; 427 };
417 428
418 } // namespace 429 } // namespace
419 430
420 // static 431 // static
421 TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction( 432 TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction(
422 TickFunctionType ticker) { 433 TickFunctionType ticker) {
(...skipping 16 matching lines...) Expand all
439 TimeTicks TimeTicks::NowFromSystemTraceTime() { 450 TimeTicks TimeTicks::NowFromSystemTraceTime() {
440 return HighResNow(); 451 return HighResNow();
441 } 452 }
442 453
443 // static 454 // static
444 int64 TimeTicks::GetQPCDriftMicroseconds() { 455 int64 TimeTicks::GetQPCDriftMicroseconds() {
445 return HighResNowSingleton::GetInstance()->GetQPCDriftMicroseconds(); 456 return HighResNowSingleton::GetInstance()->GetQPCDriftMicroseconds();
446 } 457 }
447 458
448 // static 459 // static
460 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
461 return TimeTicks(
462 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value));
463 }
464
465 // static
449 bool TimeTicks::IsHighResClockWorking() { 466 bool TimeTicks::IsHighResClockWorking() {
450 return HighResNowSingleton::GetInstance()->IsUsingHighResClock(); 467 return HighResNowSingleton::GetInstance()->IsUsingHighResClock();
451 } 468 }
469
470 // TimeDelta ------------------------------------------------------------------
471
472 // static
473 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
474 return TimeDelta(
475 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value));
476 }
OLDNEW
« no previous file with comments | « base/time.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698