tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TimeStamp_windows.cpp (4558B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/DynamicallyLinkedFunctionPtr.h"
      8 #include "mozilla/TimeStamp.h"
      9 #include <intrin.h>
     10 #include <windows.h>
     11 
     12 // Historical note: We used to sample both QueryPerformanceCounter (QPC) and
     13 // GetTickCount (GTC) timestamps in the past, as very early implementations of
     14 // QPC were buggy. We had heuristics to determine if QPC is unreliable and
     15 // would have switched to GTC in case, which could cause unexpected time
     16 // travels between QPC and GPC values when that occured.
     17 //
     18 // Since Windows 8 together with the then modern CPUs, QPC became both reliable
     19 // and almost as fast as GTC timestamps and provides a much higher resolution.
     20 // QPC in general exists long enough even on older systems than Windows 8, such
     21 // that we can just always rely on it, as we do in rust.
     22 
     23 // ----------------------------------------------------------------------------
     24 // Global variables, not changing at runtime
     25 // ----------------------------------------------------------------------------
     26 
     27 // Result of QueryPerformanceFrequency, set only once on startup.
     28 static double sTicksPerSecd;
     29 static double sTicksPerMsd;
     30 
     31 // ----------------------------------------------------------------------------
     32 // Useful constants
     33 // ----------------------------------------------------------------------------
     34 
     35 static constexpr double kMsPerSecd = 1000.0;
     36 
     37 namespace mozilla {
     38 
     39 // Result is in ticks.
     40 static inline ULONGLONG PerformanceCounter() {
     41  LARGE_INTEGER pc;
     42  MOZ_ALWAYS_TRUE(::QueryPerformanceCounter(&pc));
     43  return pc.QuadPart;
     44 }
     45 
     46 static void InitConstants() {
     47  // Query the frequency from QPC and rely on it for all values.
     48  // Note: The resolution used to be sampled based on a loop of QPC calls.
     49  // While it is true that on most systems we cannot expect to subsequently
     50  // sample QPC values as fast as the QPC frequency, we still will get that
     51  // as resolution of the sampled values, that is we have 1 tick resolution.
     52  LARGE_INTEGER freq;
     53  bool hasQPC = ::QueryPerformanceFrequency(&freq);
     54  MOZ_RELEASE_ASSERT(hasQPC);
     55  sTicksPerSecd = double(freq.QuadPart);
     56  sTicksPerMsd = sTicksPerSecd / kMsPerSecd;
     57 }
     58 
     59 // ----------------------------------------------------------------------------
     60 // TimeDuration and TimeStamp implementation
     61 // ----------------------------------------------------------------------------
     62 
     63 MFBT_API double BaseTimeDurationPlatformUtils::ToSeconds(int64_t aTicks) {
     64  return double(aTicks) / sTicksPerSecd;
     65 }
     66 
     67 MFBT_API int64_t
     68 BaseTimeDurationPlatformUtils::TicksFromMilliseconds(double aMilliseconds) {
     69  double result = sTicksPerMsd * aMilliseconds;
     70  // NOTE: this MUST be a >= test, because int64_t(double(INT64_MAX))
     71  // overflows and gives INT64_MIN.
     72  if (result >= double(INT64_MAX)) {
     73    return INT64_MAX;
     74  }
     75  if (result <= double(INT64_MIN)) {
     76    return INT64_MIN;
     77  }
     78 
     79  return (int64_t)result;
     80 }
     81 
     82 // Note that we init early enough during startup such that we are supposed to
     83 // not yet have started other threads which could try to use us.
     84 static bool gInitialized = false;
     85 
     86 MFBT_API void TimeStamp::Startup() {
     87  if (gInitialized) {
     88    return;
     89  }
     90  InitConstants();
     91  gInitialized = true;
     92 }
     93 
     94 MFBT_API void TimeStamp::Shutdown() {}
     95 
     96 MFBT_API TimeStamp TimeStamp::Now(bool aHighResolution) {
     97  MOZ_ASSERT(gInitialized);
     98  return TimeStamp((TimeStampValue)PerformanceCounter());
     99 }
    100 
    101 // Computes and returns the process uptime in microseconds.
    102 // Returns 0 if an error was encountered.
    103 
    104 MFBT_API uint64_t TimeStamp::ComputeProcessUptime() {
    105  FILETIME start, foo, bar, baz;
    106  bool success = GetProcessTimes(GetCurrentProcess(), &start, &foo, &bar, &baz);
    107  if (!success) {
    108    return 0;
    109  }
    110 
    111  static const StaticDynamicallyLinkedFunctionPtr<void(WINAPI*)(LPFILETIME)>
    112      pGetSystemTimePreciseAsFileTime(L"kernel32.dll",
    113                                      "GetSystemTimePreciseAsFileTime");
    114 
    115  FILETIME now;
    116  if (pGetSystemTimePreciseAsFileTime) {
    117    pGetSystemTimePreciseAsFileTime(&now);
    118  } else {
    119    GetSystemTimeAsFileTime(&now);
    120  }
    121 
    122  ULARGE_INTEGER startUsec = {{start.dwLowDateTime, start.dwHighDateTime}};
    123  ULARGE_INTEGER nowUsec = {{now.dwLowDateTime, now.dwHighDateTime}};
    124 
    125  return (nowUsec.QuadPart - startUsec.QuadPart) / 10ULL;
    126 }
    127 
    128 }  // namespace mozilla