security/sandbox/chromium/base/time/time_win.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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.
     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.  Using timeBeginPeriod(1) is a requirement in order to make our
    33 // message loop waits have the same resolution that our time measurements
    34 // do.  Otherwise, WaitForSingleObject(..., 1) will no less than 15ms when
    35 // there is nothing else to waken the Wait.
    37 #include "base/time/time.h"
    39 #pragma comment(lib, "winmm.lib")
    40 #include <windows.h>
    41 #include <mmsystem.h>
    43 #include "base/basictypes.h"
    44 #include "base/cpu.h"
    45 #include "base/logging.h"
    46 #include "base/memory/singleton.h"
    47 #include "base/synchronization/lock.h"
    49 using base::Time;
    50 using base::TimeDelta;
    51 using base::TimeTicks;
    53 namespace {
    55 // From MSDN, FILETIME "Contains a 64-bit value representing the number of
    56 // 100-nanosecond intervals since January 1, 1601 (UTC)."
    57 int64 FileTimeToMicroseconds(const FILETIME& ft) {
    58   // Need to bit_cast to fix alignment, then divide by 10 to convert
    59   // 100-nanoseconds to milliseconds. This only works on little-endian
    60   // machines.
    61   return bit_cast<int64, FILETIME>(ft) / 10;
    62 }
    64 void MicrosecondsToFileTime(int64 us, FILETIME* ft) {
    65   DCHECK_GE(us, 0LL) << "Time is less than 0, negative values are not "
    66       "representable in FILETIME";
    68   // Multiply by 10 to convert milliseconds to 100-nanoseconds. Bit_cast will
    69   // handle alignment problems. This only works on little-endian machines.
    70   *ft = bit_cast<FILETIME, int64>(us * 10);
    71 }
    73 int64 CurrentWallclockMicroseconds() {
    74   FILETIME ft;
    75   ::GetSystemTimeAsFileTime(&ft);
    76   return FileTimeToMicroseconds(ft);
    77 }
    79 // Time between resampling the un-granular clock for this API.  60 seconds.
    80 const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond;
    82 int64 initial_time = 0;
    83 TimeTicks initial_ticks;
    85 void InitializeClock() {
    86   initial_ticks = TimeTicks::Now();
    87   initial_time = CurrentWallclockMicroseconds();
    88 }
    90 }  // namespace
    92 // Time -----------------------------------------------------------------------
    94 // The internal representation of Time uses FILETIME, whose epoch is 1601-01-01
    95 // 00:00:00 UTC.  ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the
    96 // number of leap year days between 1601 and 1970: (1970-1601)/4 excluding
    97 // 1700, 1800, and 1900.
    98 // static
    99 const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000);
   101 bool Time::high_resolution_timer_enabled_ = false;
   102 int Time::high_resolution_timer_activated_ = 0;
   104 // static
   105 Time Time::Now() {
   106   if (initial_time == 0)
   107     InitializeClock();
   109   // We implement time using the high-resolution timers so that we can get
   110   // timeouts which are smaller than 10-15ms.  If we just used
   111   // CurrentWallclockMicroseconds(), we'd have the less-granular timer.
   112   //
   113   // To make this work, we initialize the clock (initial_time) and the
   114   // counter (initial_ctr).  To compute the initial time, we can check
   115   // the number of ticks that have elapsed, and compute the delta.
   116   //
   117   // To avoid any drift, we periodically resync the counters to the system
   118   // clock.
   119   while (true) {
   120     TimeTicks ticks = TimeTicks::Now();
   122     // Calculate the time elapsed since we started our timer
   123     TimeDelta elapsed = ticks - initial_ticks;
   125     // Check if enough time has elapsed that we need to resync the clock.
   126     if (elapsed.InMilliseconds() > kMaxMillisecondsToAvoidDrift) {
   127       InitializeClock();
   128       continue;
   129     }
   131     return Time(elapsed + Time(initial_time));
   132   }
   133 }
   135 // static
   136 Time Time::NowFromSystemTime() {
   137   // Force resync.
   138   InitializeClock();
   139   return Time(initial_time);
   140 }
   142 // static
   143 Time Time::FromFileTime(FILETIME ft) {
   144   if (bit_cast<int64, FILETIME>(ft) == 0)
   145     return Time();
   146   if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() &&
   147       ft.dwLowDateTime == std::numeric_limits<DWORD>::max())
   148     return Max();
   149   return Time(FileTimeToMicroseconds(ft));
   150 }
   152 FILETIME Time::ToFileTime() const {
   153   if (is_null())
   154     return bit_cast<FILETIME, int64>(0);
   155   if (is_max()) {
   156     FILETIME result;
   157     result.dwHighDateTime = std::numeric_limits<DWORD>::max();
   158     result.dwLowDateTime = std::numeric_limits<DWORD>::max();
   159     return result;
   160   }
   161   FILETIME utc_ft;
   162   MicrosecondsToFileTime(us_, &utc_ft);
   163   return utc_ft;
   164 }
   166 // static
   167 void Time::EnableHighResolutionTimer(bool enable) {
   168   // Test for single-threaded access.
   169   static PlatformThreadId my_thread = PlatformThread::CurrentId();
   170   DCHECK(PlatformThread::CurrentId() == my_thread);
   172   if (high_resolution_timer_enabled_ == enable)
   173     return;
   175   high_resolution_timer_enabled_ = enable;
   176 }
   178 // static
   179 bool Time::ActivateHighResolutionTimer(bool activating) {
   180   if (!high_resolution_timer_enabled_ && activating)
   181     return false;
   183   // Using anything other than 1ms makes timers granular
   184   // to that interval.
   185   const int kMinTimerIntervalMs = 1;
   186   MMRESULT result;
   187   if (activating) {
   188     result = timeBeginPeriod(kMinTimerIntervalMs);
   189     high_resolution_timer_activated_++;
   190   } else {
   191     result = timeEndPeriod(kMinTimerIntervalMs);
   192     high_resolution_timer_activated_--;
   193   }
   194   return result == TIMERR_NOERROR;
   195 }
   197 // static
   198 bool Time::IsHighResolutionTimerInUse() {
   199   // Note:  we should track the high_resolution_timer_activated_ value
   200   // under a lock if we want it to be accurate in a system with multiple
   201   // message loops.  We don't do that - because we don't want to take the
   202   // expense of a lock for this.  We *only* track this value so that unit
   203   // tests can see if the high resolution timer is on or off.
   204   return high_resolution_timer_enabled_ &&
   205       high_resolution_timer_activated_ > 0;
   206 }
   208 // static
   209 Time Time::FromExploded(bool is_local, const Exploded& exploded) {
   210   // Create the system struct representing our exploded time. It will either be
   211   // in local time or UTC.
   212   SYSTEMTIME st;
   213   st.wYear = exploded.year;
   214   st.wMonth = exploded.month;
   215   st.wDayOfWeek = exploded.day_of_week;
   216   st.wDay = exploded.day_of_month;
   217   st.wHour = exploded.hour;
   218   st.wMinute = exploded.minute;
   219   st.wSecond = exploded.second;
   220   st.wMilliseconds = exploded.millisecond;
   222   FILETIME ft;
   223   bool success = true;
   224   // Ensure that it's in UTC.
   225   if (is_local) {
   226     SYSTEMTIME utc_st;
   227     success = TzSpecificLocalTimeToSystemTime(NULL, &st, &utc_st) &&
   228               SystemTimeToFileTime(&utc_st, &ft);
   229   } else {
   230     success = !!SystemTimeToFileTime(&st, &ft);
   231   }
   233   if (!success) {
   234     NOTREACHED() << "Unable to convert time";
   235     return Time(0);
   236   }
   237   return Time(FileTimeToMicroseconds(ft));
   238 }
   240 void Time::Explode(bool is_local, Exploded* exploded) const {
   241   if (us_ < 0LL) {
   242     // We are not able to convert it to FILETIME.
   243     ZeroMemory(exploded, sizeof(*exploded));
   244     return;
   245   }
   247   // FILETIME in UTC.
   248   FILETIME utc_ft;
   249   MicrosecondsToFileTime(us_, &utc_ft);
   251   // FILETIME in local time if necessary.
   252   bool success = true;
   253   // FILETIME in SYSTEMTIME (exploded).
   254   SYSTEMTIME st;
   255   if (is_local) {
   256     SYSTEMTIME utc_st;
   257     // We don't use FileTimeToLocalFileTime here, since it uses the current
   258     // settings for the time zone and daylight saving time. Therefore, if it is
   259     // daylight saving time, it will take daylight saving time into account,
   260     // even if the time you are converting is in standard time.
   261     success = FileTimeToSystemTime(&utc_ft, &utc_st) &&
   262               SystemTimeToTzSpecificLocalTime(NULL, &utc_st, &st);
   263   } else {
   264     success = !!FileTimeToSystemTime(&utc_ft, &st);
   265   }
   267   if (!success) {
   268     NOTREACHED() << "Unable to convert time, don't know why";
   269     ZeroMemory(exploded, sizeof(*exploded));
   270     return;
   271   }
   273   exploded->year = st.wYear;
   274   exploded->month = st.wMonth;
   275   exploded->day_of_week = st.wDayOfWeek;
   276   exploded->day_of_month = st.wDay;
   277   exploded->hour = st.wHour;
   278   exploded->minute = st.wMinute;
   279   exploded->second = st.wSecond;
   280   exploded->millisecond = st.wMilliseconds;
   281 }
   283 // TimeTicks ------------------------------------------------------------------
   284 namespace {
   286 // We define a wrapper to adapt between the __stdcall and __cdecl call of the
   287 // mock function, and to avoid a static constructor.  Assigning an import to a
   288 // function pointer directly would require setup code to fetch from the IAT.
   289 DWORD timeGetTimeWrapper() {
   290   return timeGetTime();
   291 }
   293 DWORD (*tick_function)(void) = &timeGetTimeWrapper;
   295 // Accumulation of time lost due to rollover (in milliseconds).
   296 int64 rollover_ms = 0;
   298 // The last timeGetTime value we saw, to detect rollover.
   299 DWORD last_seen_now = 0;
   301 // Lock protecting rollover_ms and last_seen_now.
   302 // Note: this is a global object, and we usually avoid these. However, the time
   303 // code is low-level, and we don't want to use Singletons here (it would be too
   304 // easy to use a Singleton without even knowing it, and that may lead to many
   305 // gotchas). Its impact on startup time should be negligible due to low-level
   306 // nature of time code.
   307 base::Lock rollover_lock;
   309 // We use timeGetTime() to implement TimeTicks::Now().  This can be problematic
   310 // because it returns the number of milliseconds since Windows has started,
   311 // which will roll over the 32-bit value every ~49 days.  We try to track
   312 // rollover ourselves, which works if TimeTicks::Now() is called at least every
   313 // 49 days.
   314 TimeDelta RolloverProtectedNow() {
   315   base::AutoLock locked(rollover_lock);
   316   // We should hold the lock while calling tick_function to make sure that
   317   // we keep last_seen_now stay correctly in sync.
   318   DWORD now = tick_function();
   319   if (now < last_seen_now)
   320     rollover_ms += 0x100000000I64;  // ~49.7 days.
   321   last_seen_now = now;
   322   return TimeDelta::FromMilliseconds(now + rollover_ms);
   323 }
   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 }
   331 // Overview of time counters:
   332 // (1) CPU cycle counter. (Retrieved via RDTSC)
   333 // The CPU counter provides the highest resolution time stamp and is the least
   334 // expensive to retrieve. However, the CPU counter is unreliable and should not
   335 // be used in production. Its biggest issue is that it is per processor and it
   336 // is not synchronized between processors. Also, on some computers, the counters
   337 // will change frequency due to thermal and power changes, and stop in some
   338 // states.
   339 //
   340 // (2) QueryPerformanceCounter (QPC). The QPC counter provides a high-
   341 // resolution (100 nanoseconds) time stamp but is comparatively more expensive
   342 // to retrieve. What QueryPerformanceCounter actually does is up to the HAL.
   343 // (with some help from ACPI).
   344 // According to http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx
   345 // in the worst case, it gets the counter from the rollover interrupt on the
   346 // programmable interrupt timer. In best cases, the HAL may conclude that the
   347 // RDTSC counter runs at a constant frequency, then it uses that instead. On
   348 // multiprocessor machines, it will try to verify the values returned from
   349 // RDTSC on each processor are consistent with each other, and apply a handful
   350 // of workarounds for known buggy hardware. In other words, QPC is supposed to
   351 // give consistent result on a multiprocessor computer, but it is unreliable in
   352 // reality due to bugs in BIOS or HAL on some, especially old computers.
   353 // With recent updates on HAL and newer BIOS, QPC is getting more reliable but
   354 // it should be used with caution.
   355 //
   356 // (3) System time. The system time provides a low-resolution (typically 10ms
   357 // to 55 milliseconds) time stamp but is comparatively less expensive to
   358 // retrieve and more reliable.
   359 class HighResNowSingleton {
   360  public:
   361   static HighResNowSingleton* GetInstance() {
   362     return Singleton<HighResNowSingleton>::get();
   363   }
   365   bool IsUsingHighResClock() {
   366     return ticks_per_second_ != 0.0;
   367   }
   369   void DisableHighResClock() {
   370     ticks_per_second_ = 0.0;
   371   }
   373   TimeDelta Now() {
   374     if (IsUsingHighResClock())
   375       return TimeDelta::FromMicroseconds(UnreliableNow());
   377     // Just fallback to the slower clock.
   378     return RolloverProtectedNow();
   379   }
   381   int64 GetQPCDriftMicroseconds() {
   382     if (!IsUsingHighResClock())
   383       return 0;
   384     return abs((UnreliableNow() - ReliableNow()) - skew_);
   385   }
   387   int64 QPCValueToMicroseconds(LONGLONG qpc_value) {
   388     if (!ticks_per_second_)
   389       return 0;
   391     // Intentionally calculate microseconds in a round about manner to avoid
   392     // overflow and precision issues. Think twice before simplifying!
   393     int64 whole_seconds = qpc_value / ticks_per_second_;
   394     int64 leftover_ticks = qpc_value % ticks_per_second_;
   395     int64 microseconds = (whole_seconds * Time::kMicrosecondsPerSecond) +
   396                          ((leftover_ticks * Time::kMicrosecondsPerSecond) /
   397                           ticks_per_second_);
   398     return microseconds;
   399   }
   401  private:
   402   HighResNowSingleton()
   403     : ticks_per_second_(0),
   404       skew_(0) {
   405     InitializeClock();
   407     base::CPU cpu;
   408     if (IsBuggyAthlon(cpu))
   409       DisableHighResClock();
   410   }
   412   // Synchronize the QPC clock with GetSystemTimeAsFileTime.
   413   void InitializeClock() {
   414     LARGE_INTEGER ticks_per_sec = {0};
   415     if (!QueryPerformanceFrequency(&ticks_per_sec))
   416       return;  // Broken, we don't guarantee this function works.
   417     ticks_per_second_ = ticks_per_sec.QuadPart;
   419     skew_ = UnreliableNow() - ReliableNow();
   420   }
   422   // Get the number of microseconds since boot in an unreliable fashion.
   423   int64 UnreliableNow() {
   424     LARGE_INTEGER now;
   425     QueryPerformanceCounter(&now);
   426     return QPCValueToMicroseconds(now.QuadPart);
   427   }
   429   // Get the number of microseconds since boot in a reliable fashion.
   430   int64 ReliableNow() {
   431     return RolloverProtectedNow().InMicroseconds();
   432   }
   434   int64 ticks_per_second_;  // 0 indicates QPF failed and we're broken.
   435   int64 skew_;  // Skew between lo-res and hi-res clocks (for debugging).
   437   friend struct DefaultSingletonTraits<HighResNowSingleton>;
   438 };
   440 TimeDelta HighResNowWrapper() {
   441   return HighResNowSingleton::GetInstance()->Now();
   442 }
   444 typedef TimeDelta (*NowFunction)(void);
   445 NowFunction now_function = RolloverProtectedNow;
   447 bool CPUReliablySupportsHighResTime() {
   448   base::CPU cpu;
   449   if (!cpu.has_non_stop_time_stamp_counter())
   450     return false;
   452   if (IsBuggyAthlon(cpu))
   453     return false;
   455   return true;
   456 }
   458 }  // namespace
   460 // static
   461 TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction(
   462     TickFunctionType ticker) {
   463   base::AutoLock locked(rollover_lock);
   464   TickFunctionType old = tick_function;
   465   tick_function = ticker;
   466   rollover_ms = 0;
   467   last_seen_now = 0;
   468   return old;
   469 }
   471 // static
   472 bool TimeTicks::SetNowIsHighResNowIfSupported() {
   473   if (!CPUReliablySupportsHighResTime()) {
   474     return false;
   475   }
   477   now_function = HighResNowWrapper;
   478   return true;
   479 }
   481 // static
   482 TimeTicks TimeTicks::Now() {
   483   return TimeTicks() + now_function();
   484 }
   486 // static
   487 TimeTicks TimeTicks::HighResNow() {
   488   return TimeTicks() + HighResNowSingleton::GetInstance()->Now();
   489 }
   491 // static
   492 TimeTicks TimeTicks::ThreadNow() {
   493   NOTREACHED();
   494   return TimeTicks();
   495 }
   497 // static
   498 TimeTicks TimeTicks::NowFromSystemTraceTime() {
   499   return HighResNow();
   500 }
   502 // static
   503 int64 TimeTicks::GetQPCDriftMicroseconds() {
   504   return HighResNowSingleton::GetInstance()->GetQPCDriftMicroseconds();
   505 }
   507 // static
   508 TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
   509   return TimeTicks(
   510       HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value));
   511 }
   513 // static
   514 bool TimeTicks::IsHighResClockWorking() {
   515   return HighResNowSingleton::GetInstance()->IsUsingHighResClock();
   516 }
   518 TimeTicks TimeTicks::UnprotectedNow() {
   519   if (now_function == HighResNowWrapper) {
   520     return Now();
   521   } else {
   522     return TimeTicks() + TimeDelta::FromMilliseconds(timeGetTime());
   523   }
   524 }
   526 // TimeDelta ------------------------------------------------------------------
   528 // static
   529 TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
   530   return TimeDelta(
   531       HighResNowSingleton::GetInstance()->QPCValueToMicroseconds(qpc_value));
   532 }

mercurial