Index: base/time/time_win.cc |
diff --git a/base/time/time_win.cc b/base/time/time_win.cc |
index 5fa899d1f97f69be69d1df65ba854565d7240b53..86cbde86082911be318ca432f97c05a4dd197969 100644 |
--- a/base/time/time_win.cc |
+++ b/base/time/time_win.cc |
@@ -79,10 +79,22 @@ int64 CurrentWallclockMicroseconds() { |
// Time between resampling the un-granular clock for this API. 60 seconds. |
const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; |
-int64 initial_time = 0; |
+// The ticks at initialization. |
TimeTicks initial_ticks; |
+// The time at initialization. |
+int64 initial_time = 0; |
+ |
+// Lock protecting initial_time and initial_ticks. |
+// Note: this is a global object, and we usually avoid these. However, the time |
+// code is low-level, and we don't want to use Singletons here (it would be too |
Nico
2014/08/15 23:17:38
(fwiw, on linux or mac, "low-level" isn't an excus
willchan no longer on Chromium
2014/08/15 23:20:19
This is very true. But what's the alternative? Do
|
+// easy to use a Singleton without even knowing it, and that may lead to many |
+// gotchas). Its impact on startup time should be negligible due to low-level |
+// nature of time code. |
+base::Lock initialize_clock_lock; |
+ |
void InitializeClock() { |
+ base::AutoLock locked(initialize_clock_lock); |
M-A Ruel
2014/08/16 00:40:14
Because I'm a nice guy, here's the code you actual
|
initial_ticks = TimeTicks::Now(); |
initial_time = CurrentWallclockMicroseconds(); |
} |
@@ -119,8 +131,16 @@ Time Time::Now() { |
while (true) { |
TimeTicks ticks = TimeTicks::Now(); |
+ int64 start_time = 0; |
+ TimeTicks start_ticks; |
+ { |
+ base::AutoLock locked(initialize_clock_lock); |
+ start_time = initial_time; |
+ start_ticks = initial_ticks; |
+ } |
+ |
// Calculate the time elapsed since we started our timer |
- TimeDelta elapsed = ticks - initial_ticks; |
+ TimeDelta elapsed = ticks - start_ticks; |
// Check if enough time has elapsed that we need to resync the clock. |
if (elapsed.InMilliseconds() > kMaxMillisecondsToAvoidDrift) { |
@@ -128,7 +148,7 @@ Time Time::Now() { |
continue; |
} |
- return Time(elapsed + Time(initial_time)); |
+ return Time(elapsed + Time(start_time)); |
} |
} |
@@ -359,21 +379,24 @@ bool IsBuggyAthlon(const base::CPU& cpu) { |
class HighResNowSingleton { |
public: |
HighResNowSingleton() |
- : ticks_per_second_(0), |
- skew_(0) { |
- InitializeClock(); |
+ : ticks_per_second_(0), |
+ skew_(0) { |
base::CPU cpu; |
if (IsBuggyAthlon(cpu)) |
- DisableHighResClock(); |
- } |
+ return; |
- bool IsUsingHighResClock() { |
- return ticks_per_second_ != 0.0; |
+ // Synchronize the QPC clock with GetSystemTimeAsFileTime. |
+ LARGE_INTEGER ticks_per_sec = {0}; |
+ if (!QueryPerformanceFrequency(&ticks_per_sec)) |
+ return; // QPC is not available. |
+ ticks_per_second_ = ticks_per_sec.QuadPart; |
+ |
+ skew_ = UnreliableNow() - ReliableNow(); |
} |
- void DisableHighResClock() { |
- ticks_per_second_ = 0.0; |
+ bool IsUsingHighResClock() { |
+ return ticks_per_second_ != 0; |
} |
TimeDelta Now() { |
@@ -408,16 +431,6 @@ class HighResNowSingleton { |
} |
private: |
- // Synchronize the QPC clock with GetSystemTimeAsFileTime. |
- void InitializeClock() { |
- LARGE_INTEGER ticks_per_sec = {0}; |
- if (!QueryPerformanceFrequency(&ticks_per_sec)) |
- return; // Broken, we don't guarantee this function works. |
- ticks_per_second_ = ticks_per_sec.QuadPart; |
- |
- skew_ = UnreliableNow() - ReliableNow(); |
- } |
- |
// Get the number of microseconds since boot in an unreliable fashion. |
int64 UnreliableNow() { |
LARGE_INTEGER now; |
@@ -480,6 +493,7 @@ bool TimeTicks::SetNowIsHighResNowIfSupported() { |
} |
now_function = HighResNowWrapper; |
+ InitializeClock(); |
return true; |
} |