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
3// found in the LICENSE file.
4
5
6// Windows Timer Primer
7//
8// A good article:  http://www.ddj.com/windows/184416651
9// A good mozilla bug:  http://bugzilla.mozilla.org/show_bug.cgi?id=363258
10//
11// The default windows timer, GetSystemTimeAsFileTime is not very precise.
12// It is only good to ~15.5ms.
13//
14// QueryPerformanceCounter is the logical choice for a high-precision timer.
15// However, it is known to be buggy on some hardware.  Specifically, it can
16// sometimes "jump".  On laptops, QPC can also be very expensive to call.
17// It's 3-4x slower than timeGetTime() on desktops, but can be 10x slower
18// on laptops.  A unittest exists which will show the relative cost of various
19// timers on any system.
20//
21// The next logical choice is timeGetTime().  timeGetTime has a precision of
22// 1ms, but only if you call APIs (timeBeginPeriod()) which affect all other
23// applications on the system.  By default, precision is only 15.5ms.
24// Unfortunately, we don't want to call timeBeginPeriod because we don't
25// want to affect other applications.  Further, on mobile platforms, use of
26// faster multimedia timers can hurt battery life.  See the intel
27// article about this here:
28// http://softwarecommunity.intel.com/articles/eng/1086.htm
29//
30// To work around all this, we're going to generally use timeGetTime().  We
31// will only increase the system-wide timer if we're not running on battery
32// power.
33
34#include "base/time/time.h"
35
36#pragma comment(lib, "winmm.lib")
37#include <windows.h>
38#include <mmsystem.h>
39
40#include "base/basictypes.h"
41#include "base/cpu.h"
42#include "base/lazy_instance.h"
43#include "base/logging.h"
44#include "base/synchronization/lock.h"
45
46using base::Time;
47using base::TimeDelta;
48using base::TimeTicks;
49
50namespace {
51
52// From MSDN, FILETIME "Contains a 64-bit value representing the number of
53// 100-nanosecond intervals since January 1, 1601 (UTC)."
54int64 FileTimeToMicroseconds(const FILETIME& ft) {
55  // Need to bit_cast to fix alignment, then divide by 10 to convert
56  // 100-nanoseconds to milliseconds. This only works on little-endian
57  // machines.
58  return bit_cast<int64, FILETIME>(ft) / 10;
59}
60
61void MicrosecondsToFileTime(int64 us, FILETIME* ft) {
62  DCHECK_GE(us, 0LL) << "Time is less than 0, negative values are not "
63      "representable in FILETIME";
64
65  // Multiply by 10 to convert milliseconds to 100-nanoseconds. Bit_cast will
66  // handle alignment problems. This only works on little-endian machines.
67  *ft = bit_cast<FILETIME, int64>(us * 10);
68}
69
70int64 CurrentWallclockMicroseconds() {
71  FILETIME ft;
72  ::GetSystemTimeAsFileTime(&ft);
73  return FileTimeToMicroseconds(ft);
74}
75
76// Time between resampling the un-granular clock for this API.  60 seconds.
77const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond;
78
79int64 initial_time = 0;
80TimeTicks initial_ticks;
81
82void InitializeClock() {
83  initial_ticks = TimeTicks::Now();
84  initial_time = CurrentWallclockMicroseconds();
85}
86
87// The two values that ActivateHighResolutionTimer uses to set the systemwide
88// timer interrupt frequency on Windows. It controls how precise timers are
89// but also has a big impact on battery life.
90const int kMinTimerIntervalHighResMs = 1;
91const int kMinTimerIntervalLowResMs = 4;
92// Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active.
93bool g_high_res_timer_enabled = false;
94// How many times the high resolution timer has been called.
95uint32_t g_high_res_timer_count = 0;
96// The lock to control access to the above two variables.
97base::LazyInstance<base::Lock>::Leaky g_high_res_lock =
98    LAZY_INSTANCE_INITIALIZER;
99
100}  // namespace
101
102// Time -----------------------------------------------------------------------
103
104// The internal representation of Time uses FILETIME, whose epoch is 1601-01-01
105// 00:00:00 UTC.  ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the
106// number of leap year days between 1601 and 1970: (1970-1601)/4 excluding
107// 1700, 1800, and 1900.
108// static
109const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000);
110
111// static
112Time Time::Now() {
113  if (initial_time == 0)
114    InitializeClock();
115
116  // We implement time using the high-resolution timers so that we can get
117  // timeouts which are smaller than 10-15ms.  If we just used
118  // CurrentWallclockMicroseconds(), we'd have the less-granular timer.
119  //
120  // To make this work, we initialize the clock (initial_time) and the
121  // counter (initial_ctr).  To compute the initial time, we can check
122  // the number of ticks that have elapsed, and compute the delta.
123  //
124  // To avoid any drift, we periodically resync the counters to the system
125  // clock.
126  while (true) {
127    TimeTicks ticks = TimeTicks::Now();
128
129    // Calculate the time elapsed since we started our timer
130    TimeDelta elapsed = ticks - initial_ticks;
131
132    // Check if enough time has elapsed that we need to resync the clock.
133    if (elapsed.InMilliseconds() > kMaxMillisecondsToAvoidDrift) {
134      InitializeClock();
135      continue;
136    }
137
138    return Time(elapsed + Time(initial_time));
139  }
140}
141
142// static
143Time Time::NowFromSystemTime() {
144  // Force resync.
145  InitializeClock();
146  return Time(initial_time);
147}
148
149// static
150Time Time::FromFileTime(FILETIME ft) {
151  if (bit_cast<int64, FILETIME>(ft) == 0)
152    return Time();
153  if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() &&
154      ft.dwLowDateTime == std::numeric_limits<DWORD>::max())
155    return Max();
156  return Time(FileTimeToMicroseconds(ft));
157}
158
159FILETIME Time::ToFileTime() const {
160  if (is_null())
161    return bit_cast<FILETIME, int64>(0);
162  if (is_max()) {
163    FILETIME result;
164    result.dwHighDateTime = std::numeric_limits<DWORD>::max();
165    result.dwLowDateTime = std::numeric_limits<DWORD>::max();
166    return result;
167  }
168  FILETIME utc_ft;
169  MicrosecondsToFileTime(us_, &utc_ft);
170  return utc_ft;
171}
172
173// static
174void Time::EnableHighResolutionTimer(bool enable) {
175  base::AutoLock lock(g_high_res_lock.Get());
176  if (g_high_res_timer_enabled == enable)
177    return;
178  g_high_res_timer_enabled = enable;
179  if (!g_high_res_timer_count)
180    return;
181  // Since g_high_res_timer_count != 0, an ActivateHighResolutionTimer(true)
182  // was called which called timeBeginPeriod with g_high_res_timer_enabled
183  // with a value which is the opposite of |enable|. With that information we
184  // call timeEndPeriod with the same value used in timeBeginPeriod and
185  // therefore undo the period effect.
186  if (enable) {
187    timeEndPeriod(kMinTimerIntervalLowResMs);
188    timeBeginPeriod(kMinTimerIntervalHighResMs);
189  } else {
190    timeEndPeriod(kMinTimerIntervalHighResMs);
191    timeBeginPeriod(kMinTimerIntervalLowResMs);
192  }
193}
194
195// static
196bool Time::ActivateHighResolutionTimer(bool activating) {
197  // We only do work on the transition from zero to one or one to zero so we
198  // can easily undo the effect (if necessary) when EnableHighResolutionTimer is
199  // called.
200  const uint32_t max = std::numeric_limits<uint32_t>::max();
201
202  base::AutoLock lock(g_high_res_lock.Get());
203  UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs
204                                         : kMinTimerIntervalLowResMs;
205  if (activating) {
206    DCHECK(g_high_res_timer_count != max);
207    ++g_high_res_timer_count;
208    if (g_high_res_timer_count == 1)
209      timeBeginPeriod(period);
210  } else {
211    DCHECK(g_high_res_timer_count != 0);
212    --g_high_res_timer_count;
213    if (g_high_res_timer_count == 0)
214      timeEndPeriod(period);
215  }
216  return (period == kMinTimerIntervalHighResMs);
217}
218
219// static
220bool Time::IsHighResolutionTimerInUse() {
221  base::AutoLock lock(g_high_res_lock.Get());
222  return g_high_res_timer_enabled && g_high_res_timer_count > 0;
223}
224
225// static
226Time Time::FromExploded(bool is_local, const Exploded& exploded) {
227  // Create the system struct representing our exploded time. It will either be
228  // in local time or UTC.
229  SYSTEMTIME st;
230  st.wYear = exploded.year;
231  st.wMonth = exploded.month;
232  st.wDayOfWeek = exploded.day_of_week;
233  st.wDay = exploded.day_of_month;
234  st.wHour = exploded.hour;
235  st.wMinute = exploded.minute;
236  st.wSecond = exploded.second;
237  st.wMilliseconds = exploded.millisecond;
238
239  FILETIME ft;
240  bool success = true;
241  // Ensure that it's in UTC.
242  if (is_local) {
243    SYSTEMTIME utc_st;
244    success = TzSpecificLocalTimeToSystemTime(NULL, &st, &utc_st) &&
245              SystemTimeToFileTime(&utc_st, &ft);
246  } else {
247    success = !!SystemTimeToFileTime(&st, &ft);
248  }
249
250  if (!success) {
251    NOTREACHED() << "Unable to convert time";
252    return Time(0);
253  }
254  return Time(FileTimeToMicroseconds(ft));
255}
256
257void Time::Explode(bool is_local, Exploded* exploded) const {
258  if (us_ < 0LL) {
259    // We are not able to convert it to FILETIME.
260    ZeroMemory(exploded, sizeof(*exploded));
261    return;
262  }
263
264  // FILETIME in UTC.
265  FILETIME utc_ft;
266  MicrosecondsToFileTime(us_, &utc_ft);
267
268  // FILETIME in local time if necessary.
269  bool success = true;
270  // FILETIME in SYSTEMTIME (exploded).
271  SYSTEMTIME st = {0};
272  if (is_local) {
273    SYSTEMTIME utc_st;
274    // We don't use FileTimeToLocalFileTime here, since it uses the current
275    // settings for the time zone and daylight saving time. Therefore, if it is
276    // daylight saving time, it will take daylight saving time into account,
277    // even if the time you are converting is in standard time.
278    success = FileTimeToSystemTime(&utc_ft, &utc_st) &&
279              SystemTimeToTzSpecificLocalTime(NULL, &utc_st, &st);
280  } else {
281    success = !!FileTimeToSystemTime(&utc_ft, &st);
282  }
283
284  if (!success) {
285    NOTREACHED() << "Unable to convert time, don't know why";
286    ZeroMemory(exploded, sizeof(*exploded));
287    return;
288  }
289
290  exploded->year = st.wYear;
291  exploded->month = st.wMonth;
292  exploded->day_of_week = st.wDayOfWeek;
293  exploded->day_of_month = st.wDay;
294  exploded->hour = st.wHour;
295  exploded->minute = st.wMinute;
296  exploded->second = st.wSecond;
297  exploded->millisecond = st.wMilliseconds;
298}
299
300// TimeTicks ------------------------------------------------------------------
301namespace {
302
303// We define a wrapper to adapt between the __stdcall and __cdecl call of the
304// mock function, and to avoid a static constructor.  Assigning an import to a
305// function pointer directly would require setup code to fetch from the IAT.
306DWORD timeGetTimeWrapper() {
307  return timeGetTime();
308}
309
310DWORD (*tick_function)(void) = &timeGetTimeWrapper;
311
312// Accumulation of time lost due to rollover (in milliseconds).
313int64 rollover_ms = 0;
314
315// The last timeGetTime value we saw, to detect rollover.
316DWORD last_seen_now = 0;
317
318// Lock protecting rollover_ms and last_seen_now.
319// Note: this is a global object, and we usually avoid these. However, the time
320// code is low-level, and we don't want to use Singletons here (it would be too
321// easy to use a Singleton without even knowing it, and that may lead to many
322// gotchas). Its impact on startup time should be negligible due to low-level
323// nature of time code.
324base::Lock rollover_lock;
325
326// We use timeGetTime() to implement TimeTicks::Now().  This can be problematic
327// because it returns the number of milliseconds since Windows has started,
328// which will roll over the 32-bit value every ~49 days.  We try to track
329// rollover ourselves, which works if TimeTicks::Now() is called at least every
330// 49 days.
331TimeDelta RolloverProtectedNow() {
332  base::AutoLock locked(rollover_lock);
333  // We should hold the lock while calling tick_function to make sure that
334  // we keep last_seen_now stay correctly in sync.
335  DWORD now = tick_function();
336  if (now < last_seen_now)
337    rollover_ms += 0x100000000I64;  // ~49.7 days.
338  last_seen_now = now;
339  return TimeDelta::FromMilliseconds(now + rollover_ms);
340}
341
342bool IsBuggyAthlon(const base::CPU& cpu) {
343  // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is
344  // unreliable.  Fallback to low-res clock.
345  return cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15;
346}
347
348// Overview of time counters:
349// (1) CPU cycle counter. (Retrieved via RDTSC)
350// The CPU counter provides the highest resolution time stamp and is the least
351// expensive to retrieve. However, the CPU counter is unreliable and should not
352// be used in production. Its biggest issue is that it is per processor and it
353// is not synchronized between processors. Also, on some computers, the counters
354// will change frequency due to thermal and power changes, and stop in some
355// states.
356//
357// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high-
358// resolution (100 nanoseconds) time stamp but is comparatively more expensive
359// to retrieve. What QueryPerformanceCounter actually does is up to the HAL.
360// (with some help from ACPI).
361// According to http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx
362// in the worst case, it gets the counter from the rollover interrupt on the
363// programmable interrupt timer. In best cases, the HAL may conclude that the
364// RDTSC counter runs at a constant frequency, then it uses that instead. On
365// multiprocessor machines, it will try to verify the values returned from
366// RDTSC on each processor are consistent with each other, and apply a handful
367// of workarounds for known buggy hardware. In other words, QPC is supposed to
368// give consistent result on a multiprocessor computer, but it is unreliable in
369// reality due to bugs in BIOS or HAL on some, especially old computers.
370// With recent updates on HAL and newer BIOS, QPC is getting more reliable but
371// it should be used with caution.
372//
373// (3) System time. The system time provides a low-resolution (typically 10ms
374// to 55 milliseconds) time stamp but is comparatively less expensive to
375// retrieve and more reliable.
376class HighResNowSingleton {
377 public:
378  HighResNowSingleton()
379      : ticks_per_second_(0),
380        skew_(0) {
381
382    base::CPU cpu;
383    if (IsBuggyAthlon(cpu))
384      return;
385
386    // Synchronize the QPC clock with GetSystemTimeAsFileTime.
387    LARGE_INTEGER ticks_per_sec = {0};
388    if (!QueryPerformanceFrequency(&ticks_per_sec))
389      return; // QPC is not available.
390    ticks_per_second_ = ticks_per_sec.QuadPart;
391
392    skew_ = UnreliableNow() - ReliableNow();
393  }
394
395  bool IsUsingHighResClock() {
396    return ticks_per_second_ != 0;
397  }
398
399  TimeDelta Now() {
400    if (IsUsingHighResClock())
401      return TimeDelta::FromMicroseconds(UnreliableNow());
402
403    // Just fallback to the slower clock.
404    return RolloverProtectedNow();
405  }
406
407  int64 GetQPCDriftMicroseconds() {
408    if (!IsUsingHighResClock())
409      return 0;
410    return abs((UnreliableNow() - ReliableNow()) - skew_);
411  }
412
413  int64 QPCValueToMicroseconds(LONGLONG qpc_value) {
414    if (!ticks_per_second_)
415      return 0;
416    // If the QPC Value is below the overflow threshold, we proceed with
417    // simple multiply and divide.
418    if (qpc_value < Time::kQPCOverflowThreshold)
419      return qpc_value * Time::kMicrosecondsPerSecond / ticks_per_second_;
420    // Otherwise, calculate microseconds in a round about manner to avoid
421    // overflow and precision issues.
422    int64 whole_seconds = qpc_value / ticks_per_second_;
423    int64 leftover_ticks = qpc_value - (whole_seconds * ticks_per_second_);
424    int64 microseconds = (whole_seconds * Time::kMicrosecondsPerSecond) +
425                         ((leftover_ticks * Time::kMicrosecondsPerSecond) /
426                          ticks_per_second_);
427    return microseconds;
428  }
429
430 private:
431  // Get the number of microseconds since boot in an unreliable fashion.
432  int64 UnreliableNow() {
433    LARGE_INTEGER now;
434    QueryPerformanceCounter(&now);
435    return QPCValueToMicroseconds(now.QuadPart);
436  }
437
438  // Get the number of microseconds since boot in a reliable fashion.
439  int64 ReliableNow() {
440    return RolloverProtectedNow().InMicroseconds();
441  }
442
443  int64 ticks_per_second_;  // 0 indicates QPF failed and we're broken.
444  int64 skew_;  // Skew between lo-res and hi-res clocks (for debugging).
445};
446
447static base::LazyInstance<HighResNowSingleton>::Leaky
448    leaky_high_res_now_singleton = LAZY_INSTANCE_INITIALIZER;
449
450HighResNowSingleton* GetHighResNowSingleton() {
451  return leaky_high_res_now_singleton.Pointer();
452}
453
454TimeDelta HighResNowWrapper() {
455  return GetHighResNowSingleton()->Now();
456}
457
458typedef TimeDelta (*NowFunction)(void);
459
460bool CPUReliablySupportsHighResTime() {
461  base::CPU cpu;
462  if (!cpu.has_non_stop_time_stamp_counter() ||
463      !GetHighResNowSingleton()->IsUsingHighResClock())
464    return false;
465
466  if (IsBuggyAthlon(cpu))
467    return false;
468
469  return true;
470}
471
472TimeDelta InitialNowFunction();
473
474volatile NowFunction now_function = InitialNowFunction;
475
476TimeDelta InitialNowFunction() {
477  if (!CPUReliablySupportsHighResTime()) {
478    InterlockedExchangePointer(
479        reinterpret_cast<void* volatile*>(&now_function),
480        &RolloverProtectedNow);
481    return RolloverProtectedNow();
482  }
483  InterlockedExchangePointer(
484        reinterpret_cast<void* volatile*>(&now_function),
485        &HighResNowWrapper);
486  return HighResNowWrapper();
487}
488
489}  // namespace
490
491// static
492TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction(
493    TickFunctionType ticker) {
494  base::AutoLock locked(rollover_lock);
495  TickFunctionType old = tick_function;
496  tick_function = ticker;
497  rollover_ms = 0;
498  last_seen_now = 0;
499  return old;
500}
501
502// static
503TimeTicks TimeTicks::Now() {
504  return TimeTicks() + now_function();
505}
506
507// static
508TimeTicks TimeTicks::HighResNow() {
509  return TimeTicks() + HighResNowWrapper();
510}
511
512// static
513bool TimeTicks::IsHighResNowFastAndReliable() {
514  return CPUReliablySupportsHighResTime();
515}
516
517// static
518TimeTicks TimeTicks::ThreadNow() {
519  NOTREACHED();
520  return TimeTicks();
521}
522
523// static
524TimeTicks TimeTicks::NowFromSystemTraceTime() {
525  return HighResNow();
526}
527
528// static
529int64 TimeTicks::GetQPCDriftMicroseconds() {
530  return GetHighResNowSingleton()->GetQPCDriftMicroseconds();
531}
532
533// static
534TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
535  return TimeTicks(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value));
536}
537
538// static
539bool TimeTicks::IsHighResClockWorking() {
540  return GetHighResNowSingleton()->IsUsingHighResClock();
541}
542
543TimeTicks TimeTicks::UnprotectedNow() {
544  if (now_function == HighResNowWrapper) {
545    return Now();
546  } else {
547    return TimeTicks() + TimeDelta::FromMilliseconds(timeGetTime());
548  }
549}
550
551// TimeDelta ------------------------------------------------------------------
552
553// static
554TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
555  return TimeDelta(GetHighResNowSingleton()->QPCValueToMicroseconds(qpc_value));
556}
557