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

Side by Side Diff: base/time/time_win.cc

Issue 16896018: Enable high resolution time for TimeTicks::Now on Windows Canary (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rename (retry) Created 7 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
« no previous file with comments | « base/time/time.h ('k') | chrome/browser/chrome_browser_main_win.cc » ('j') | 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 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 base::AutoLock locked(rollover_lock); 315 base::AutoLock locked(rollover_lock);
316 // We should hold the lock while calling tick_function to make sure that 316 // We should hold the lock while calling tick_function to make sure that
317 // we keep last_seen_now stay correctly in sync. 317 // we keep last_seen_now stay correctly in sync.
318 DWORD now = tick_function(); 318 DWORD now = tick_function();
319 if (now < last_seen_now) 319 if (now < last_seen_now)
320 rollover_ms += 0x100000000I64; // ~49.7 days. 320 rollover_ms += 0x100000000I64; // ~49.7 days.
321 last_seen_now = now; 321 last_seen_now = now;
322 return TimeDelta::FromMilliseconds(now + rollover_ms); 322 return TimeDelta::FromMilliseconds(now + rollover_ms);
323 } 323 }
324 324
325 bool IsBuggyAthlon(const base::CPU& cpu) {
326 // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is
327 // unreliable. Fallback to low-res clock.
328 return cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15;
329 }
330
325 // Overview of time counters: 331 // Overview of time counters:
326 // (1) CPU cycle counter. (Retrieved via RDTSC) 332 // (1) CPU cycle counter. (Retrieved via RDTSC)
327 // The CPU counter provides the highest resolution time stamp and is the least 333 // The CPU counter provides the highest resolution time stamp and is the least
328 // expensive to retrieve. However, the CPU counter is unreliable and should not 334 // expensive to retrieve. However, the CPU counter is unreliable and should not
329 // be used in production. Its biggest issue is that it is per processor and it 335 // be used in production. Its biggest issue is that it is per processor and it
330 // is not synchronized between processors. Also, on some computers, the counters 336 // is not synchronized between processors. Also, on some computers, the counters
331 // will change frequency due to thermal and power changes, and stop in some 337 // will change frequency due to thermal and power changes, and stop in some
332 // states. 338 // states.
333 // 339 //
334 // (2) QueryPerformanceCounter (QPC). The QPC counter provides a high- 340 // (2) QueryPerformanceCounter (QPC). The QPC counter provides a high-
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 ticks_per_second_); 397 ticks_per_second_);
392 return microseconds; 398 return microseconds;
393 } 399 }
394 400
395 private: 401 private:
396 HighResNowSingleton() 402 HighResNowSingleton()
397 : ticks_per_second_(0), 403 : ticks_per_second_(0),
398 skew_(0) { 404 skew_(0) {
399 InitializeClock(); 405 InitializeClock();
400 406
401 // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is
402 // unreliable. Fallback to low-res clock.
403 base::CPU cpu; 407 base::CPU cpu;
404 if (cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15) 408 if (IsBuggyAthlon(cpu))
405 DisableHighResClock(); 409 DisableHighResClock();
406 } 410 }
407 411
408 // Synchronize the QPC clock with GetSystemTimeAsFileTime. 412 // Synchronize the QPC clock with GetSystemTimeAsFileTime.
409 void InitializeClock() { 413 void InitializeClock() {
410 LARGE_INTEGER ticks_per_sec = {0}; 414 LARGE_INTEGER ticks_per_sec = {0};
411 if (!QueryPerformanceFrequency(&ticks_per_sec)) 415 if (!QueryPerformanceFrequency(&ticks_per_sec))
412 return; // Broken, we don't guarantee this function works. 416 return; // Broken, we don't guarantee this function works.
413 ticks_per_second_ = ticks_per_sec.QuadPart; 417 ticks_per_second_ = ticks_per_sec.QuadPart;
414 418
(...skipping 11 matching lines...) Expand all
426 int64 ReliableNow() { 430 int64 ReliableNow() {
427 return RolloverProtectedNow().InMicroseconds(); 431 return RolloverProtectedNow().InMicroseconds();
428 } 432 }
429 433
430 int64 ticks_per_second_; // 0 indicates QPF failed and we're broken. 434 int64 ticks_per_second_; // 0 indicates QPF failed and we're broken.
431 int64 skew_; // Skew between lo-res and hi-res clocks (for debugging). 435 int64 skew_; // Skew between lo-res and hi-res clocks (for debugging).
432 436
433 friend struct DefaultSingletonTraits<HighResNowSingleton>; 437 friend struct DefaultSingletonTraits<HighResNowSingleton>;
434 }; 438 };
435 439
440 TimeDelta HighResNowWrapper() {
441 return HighResNowSingleton::GetInstance()->Now();
442 }
443
444 typedef TimeDelta (*NowFunction)(void);
445 NowFunction now_function = RolloverProtectedNow;
446
447 bool CPUReliablySupportsHighResTime() {
448 base::CPU cpu;
449 if (!cpu.has_non_stop_time_stamp_counter())
450 return false;
451
452 if (IsBuggyAthlon(cpu))
453 return false;
454
455 return true;
456 }
457
436 } // namespace 458 } // namespace
437 459
438 // static 460 // static
439 TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction( 461 TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction(
440 TickFunctionType ticker) { 462 TickFunctionType ticker) {
441 base::AutoLock locked(rollover_lock); 463 base::AutoLock locked(rollover_lock);
442 TickFunctionType old = tick_function; 464 TickFunctionType old = tick_function;
443 tick_function = ticker; 465 tick_function = ticker;
444 rollover_ms = 0; 466 rollover_ms = 0;
445 last_seen_now = 0; 467 last_seen_now = 0;
446 return old; 468 return old;
447 } 469 }
448 470
449 // static 471 // static
472 bool TimeTicks::SetNowIsHighResNowIfSupported() {
473 if (!CPUReliablySupportsHighResTime()) {
474 return false;
475 }
476
477 now_function = HighResNowWrapper;
478 return true;
479 }
480
481 // static
450 TimeTicks TimeTicks::Now() { 482 TimeTicks TimeTicks::Now() {
451 return TimeTicks() + RolloverProtectedNow(); 483 return TimeTicks() + now_function();
452 } 484 }
453 485
454 // static 486 // static
455 TimeTicks TimeTicks::HighResNow() { 487 TimeTicks TimeTicks::HighResNow() {
456 return TimeTicks() + HighResNowSingleton::GetInstance()->Now(); 488 return TimeTicks() + HighResNowSingleton::GetInstance()->Now();
457 } 489 }
458 490
459 // static 491 // static
460 TimeTicks TimeTicks::ThreadNow() { 492 TimeTicks TimeTicks::ThreadNow() {
461 NOTREACHED(); 493 NOTREACHED();
(...skipping 14 matching lines...) Expand all
476 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { 508 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
477 return TimeTicks( 509 return TimeTicks(
478 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value)); 510 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value));
479 } 511 }
480 512
481 // static 513 // static
482 bool TimeTicks::IsHighResClockWorking() { 514 bool TimeTicks::IsHighResClockWorking() {
483 return HighResNowSingleton::GetInstance()->IsUsingHighResClock(); 515 return HighResNowSingleton::GetInstance()->IsUsingHighResClock();
484 } 516 }
485 517
518 TimeTicks TimeTicks::UnprotectedNow() {
519 if (now_function == HighResNowWrapper) {
520 return Now();
521 } else {
522 return TimeTicks() + TimeDelta::FromMilliseconds(timeGetTime());
523 }
524 }
525
486 // TimeDelta ------------------------------------------------------------------ 526 // TimeDelta ------------------------------------------------------------------
487 527
488 // static 528 // static
489 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { 529 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
490 return TimeDelta( 530 return TimeDelta(
491 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value)); 531 HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value));
492 } 532 }
OLDNEW
« no previous file with comments | « base/time/time.h ('k') | chrome/browser/chrome_browser_main_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698