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

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

Issue 1824673002: time: Add a static TimeTicks method that returns the underlying clock (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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
« base/time/time.h ('K') | « base/time/time_posix.cc ('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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; 79 const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond;
80 80
81 int64_t initial_time = 0; 81 int64_t initial_time = 0;
82 TimeTicks initial_ticks; 82 TimeTicks initial_ticks;
83 83
84 void InitializeClock() { 84 void InitializeClock() {
85 initial_ticks = TimeTicks::Now(); 85 initial_ticks = TimeTicks::Now();
86 initial_time = CurrentWallclockMicroseconds(); 86 initial_time = CurrentWallclockMicroseconds();
87 } 87 }
88 88
89 const char* kTimeGetTimeClockId = "WIN_ROLLOVER_PROTECTED_TIME_GET_TIME_MICROS";
90 const char* kQPCClockId = "WIN_QPC_MICROS";
91
89 // The two values that ActivateHighResolutionTimer uses to set the systemwide 92 // The two values that ActivateHighResolutionTimer uses to set the systemwide
90 // timer interrupt frequency on Windows. It controls how precise timers are 93 // timer interrupt frequency on Windows. It controls how precise timers are
91 // but also has a big impact on battery life. 94 // but also has a big impact on battery life.
92 const int kMinTimerIntervalHighResMs = 1; 95 const int kMinTimerIntervalHighResMs = 1;
93 const int kMinTimerIntervalLowResMs = 4; 96 const int kMinTimerIntervalLowResMs = 4;
94 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. 97 // Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active.
95 bool g_high_res_timer_enabled = false; 98 bool g_high_res_timer_enabled = false;
96 // How many times the high resolution timer has been called. 99 // How many times the high resolution timer has been called.
97 uint32_t g_high_res_timer_count = 0; 100 uint32_t g_high_res_timer_count = 0;
98 // The lock to control access to the above two variables. 101 // The lock to control access to the above two variables.
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 // this timer; and also other Windows applications can alter it, affecting this 399 // this timer; and also other Windows applications can alter it, affecting this
397 // one. 400 // one.
398 401
399 using NowFunction = TimeDelta (*)(void); 402 using NowFunction = TimeDelta (*)(void);
400 403
401 TimeDelta InitialNowFunction(); 404 TimeDelta InitialNowFunction();
402 405
403 // See "threading notes" in InitializeNowFunctionPointer() for details on how 406 // See "threading notes" in InitializeNowFunctionPointer() for details on how
404 // concurrent reads/writes to these globals has been made safe. 407 // concurrent reads/writes to these globals has been made safe.
405 NowFunction g_now_function = &InitialNowFunction; 408 NowFunction g_now_function = &InitialNowFunction;
409 const char* g_now_clock_id = "";
410
406 int64_t g_qpc_ticks_per_second = 0; 411 int64_t g_qpc_ticks_per_second = 0;
407 412
408 // As of January 2015, use of <atomic> is forbidden in Chromium code. This is 413 // As of January 2015, use of <atomic> is forbidden in Chromium code. This is
409 // what std::atomic_thread_fence does on Windows on all Intel architectures when 414 // what std::atomic_thread_fence does on Windows on all Intel architectures when
410 // the memory_order argument is anything but std::memory_order_seq_cst: 415 // the memory_order argument is anything but std::memory_order_seq_cst:
411 #define ATOMIC_THREAD_FENCE(memory_order) _ReadWriteBarrier(); 416 #define ATOMIC_THREAD_FENCE(memory_order) _ReadWriteBarrier();
412 417
413 TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) { 418 TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) {
414 // Ensure that the assignment to |g_qpc_ticks_per_second|, made in 419 // Ensure that the assignment to |g_qpc_ticks_per_second|, made in
415 // InitializeNowFunctionPointer(), has happened by this point. 420 // InitializeNowFunctionPointer(), has happened by this point.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 // 457 //
453 // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now() 458 // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now()
454 // will still use the low-resolution clock. A CPU lacking a non-stop time 459 // will still use the low-resolution clock. A CPU lacking a non-stop time
455 // counter will cause Windows to provide an alternate QPC implementation that 460 // counter will cause Windows to provide an alternate QPC implementation that
456 // works, but is expensive to use. Certain Athlon CPUs are known to make the 461 // works, but is expensive to use. Certain Athlon CPUs are known to make the
457 // QPC implementation unreliable. 462 // QPC implementation unreliable.
458 // 463 //
459 // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015, 464 // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015,
460 // ~72% of users fall within this category. 465 // ~72% of users fall within this category.
461 NowFunction now_function; 466 NowFunction now_function;
467 const char* now_clock_id;
462 base::CPU cpu; 468 base::CPU cpu;
463 if (ticks_per_sec.QuadPart <= 0 || 469 if (ticks_per_sec.QuadPart <= 0 ||
464 !cpu.has_non_stop_time_stamp_counter() || IsBuggyAthlon(cpu)) { 470 !cpu.has_non_stop_time_stamp_counter() || IsBuggyAthlon(cpu)) {
465 now_function = &RolloverProtectedNow; 471 now_function = &RolloverProtectedNow;
472 now_clock_id = kTimeGetTimeClockId;
466 } else { 473 } else {
467 now_function = &QPCNow; 474 now_function = &QPCNow;
475 now_clock_id = kQPCClockId;
468 } 476 }
469 477
470 // Threading note 1: In an unlikely race condition, it's possible for two or 478 // Threading note 1: In an unlikely race condition, it's possible for two or
471 // more threads to enter InitializeNowFunctionPointer() in parallel. This is 479 // more threads to enter InitializeNowFunctionPointer() in parallel. This is
472 // not a problem since all threads should end up writing out the same values 480 // not a problem since all threads should end up writing out the same values
473 // to the global variables. 481 // to the global variables.
474 // 482 //
475 // Threading note 2: A release fence is placed here to ensure, from the 483 // Threading note 2: A release fence is placed here to ensure, from the
476 // perspective of other threads using the function pointers, that the 484 // perspective of other threads using the function pointers, that the
477 // assignment to |g_qpc_ticks_per_second| happens before the function pointers 485 // assignment to |g_qpc_ticks_per_second| happens before the function pointers
478 // are changed. 486 // are changed.
479 g_qpc_ticks_per_second = ticks_per_sec.QuadPart; 487 g_qpc_ticks_per_second = ticks_per_sec.QuadPart;
480 ATOMIC_THREAD_FENCE(memory_order_release); 488 ATOMIC_THREAD_FENCE(memory_order_release);
481 g_now_function = now_function; 489 g_now_function = now_function;
490 g_now_clock_id = now_clock_id;
danakj 2016/03/26 00:40:33 Why is this after the fence?
charliea (OOO until 10-5) 2016/03/28 15:40:51 I'm not sure, but if the above comment is any indi
danakj 2016/03/28 17:53:50 Yeah, I stared at this for a while, and AFAICT the
charliea (OOO until 10-5) 2016/03/28 21:07:36 Done.
482 } 491 }
483 492
484 TimeDelta InitialNowFunction() { 493 TimeDelta InitialNowFunction() {
485 InitializeNowFunctionPointer(); 494 InitializeNowFunctionPointer();
486 return g_now_function(); 495 return g_now_function();
487 } 496 }
488 497
489 } // namespace 498 } // namespace
490 499
491 // static 500 // static
(...skipping 13 matching lines...) Expand all
505 } 514 }
506 515
507 // static 516 // static
508 bool TimeTicks::IsHighResolution() { 517 bool TimeTicks::IsHighResolution() {
509 if (g_now_function == &InitialNowFunction) 518 if (g_now_function == &InitialNowFunction)
510 InitializeNowFunctionPointer(); 519 InitializeNowFunctionPointer();
511 return g_now_function == &QPCNow; 520 return g_now_function == &QPCNow;
512 } 521 }
513 522
514 // static 523 // static
524 std::string TimeTicks::ClockId() {
525 if (g_now_function == &InitialNowFunction)
526 InitializeNowFunctionPointer();
527 return g_now_clock_id;
528 }
529
530 // static
515 ThreadTicks ThreadTicks::Now() { 531 ThreadTicks ThreadTicks::Now() {
516 DCHECK(IsSupported()); 532 DCHECK(IsSupported());
517 533
518 // Get the number of TSC ticks used by the current thread. 534 // Get the number of TSC ticks used by the current thread.
519 ULONG64 thread_cycle_time = 0; 535 ULONG64 thread_cycle_time = 0;
520 GetQueryThreadCycleTimeFunction()(::GetCurrentThread(), &thread_cycle_time); 536 GetQueryThreadCycleTimeFunction()(::GetCurrentThread(), &thread_cycle_time);
521 537
522 // Get the frequency of the TSC. 538 // Get the frequency of the TSC.
523 double tsc_ticks_per_second = TSCTicksPerSecond(); 539 double tsc_ticks_per_second = TSCTicksPerSecond();
524 if (tsc_ticks_per_second == 0) 540 if (tsc_ticks_per_second == 0)
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { 623 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
608 return TimeTicks() + QPCValueToTimeDelta(qpc_value); 624 return TimeTicks() + QPCValueToTimeDelta(qpc_value);
609 } 625 }
610 626
611 // TimeDelta ------------------------------------------------------------------ 627 // TimeDelta ------------------------------------------------------------------
612 628
613 // static 629 // static
614 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { 630 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
615 return QPCValueToTimeDelta(qpc_value); 631 return QPCValueToTimeDelta(qpc_value);
616 } 632 }
OLDNEW
« base/time/time.h ('K') | « base/time/time_posix.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698