Bug 784859 - Part 1: Use QueryPerformanceCounter directly if the machine has a stable TSC; r=bbondy
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 06 Sep 2012 11:01:06 -0400
changeset 104646 d291e2674dc6
parent 104645 a2db0bc00598
child 104647 2a8acb221714
push id14615
push usereakhgari@mozilla.com
push date2012-09-08 18:13 +0000
treeherdermozilla-inbound@d4a8c7efef04 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbondy
bugs784859
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 784859 - Part 1: Use QueryPerformanceCounter directly if the machine has a stable TSC; r=bbondy
xpcom/ds/TimeStamp_windows.cpp
--- a/xpcom/ds/TimeStamp_windows.cpp
+++ b/xpcom/ds/TimeStamp_windows.cpp
@@ -19,16 +19,35 @@
 #include "nsThreadUtils.h"
 #include "nsAutoPtr.h"
 #include <pratom.h>
 #include <windows.h>
 
 #include "prlog.h"
 #include <stdio.h>
 
+#include <intrin.h>
+
+static bool
+HasStableTSC()
+{
+  int regs[4];
+
+  // detect if the Advanced Power Management feature is supported
+  __cpuid(regs, 0x80000000);
+  if (regs[0] < 0x80000007)
+          return false;
+
+  __cpuid(regs, 0x80000007);
+  // if bit 8 is set than TSC will run at a constant rate
+  // in all ACPI P-state, C-states and T-states
+  return regs[3] & (1 << 8);
+}
+
+
 #if defined(PR_LOGGING)
 // Log module for mozilla::TimeStamp for Windows logging...
 //
 // To enable logging (see prlog.h for full details):
 //
 //    set NSPR_LOG_MODULES=TimeStampWindows:5
 //    set NSPR_LOG_FILE=nspr.log
 //
@@ -42,16 +61,18 @@
 
 // Estimate of the smallest duration of time we can measure.
 static volatile ULONGLONG sResolution;
 static volatile ULONGLONG sResolutionSigDigs;
 static const double   kNsPerSecd  = 1000000000.0;
 static const LONGLONG kNsPerSec   = 1000000000;
 static const LONGLONG kNsPerMillisec = 1000000;
 
+static bool sHasStableTSC = false;
+
 
 // ----------------------------------------------------------------------------
 // Global constants
 // ----------------------------------------------------------------------------
 
 // After this time we always recalibrate the skew.
 //
 // On most platforms QPC and GTC have not quit the same slope, so after some
@@ -595,26 +616,31 @@ TimeStamp::Startup()
 
   ULONGLONG qpc = PerformanceCounter();
   sLastCalibrated = TickCount64(::GetTickCount());
   sSkew = qpc - ms2mt(sLastCalibrated);
 
   InitThresholds();
   InitResolution();
 
+  sHasStableTSC = HasStableTSC();
+
   LOG(("TimeStamp: initial skew is %1.2fms", mt2ms_d(sSkew)));
 
   return NS_OK;
 }
 
 void
 TimeStamp::Shutdown()
 {
   DeleteCriticalSection(&sTimeStampLock);
 }
 
 TimeStamp
 TimeStamp::Now()
 {
+  if (sHasStableTSC) {
+    return TimeStamp(uint64_t(PerformanceCounter()));
+  }
   return TimeStamp(uint64_t(CalibratedPerformanceCounter()));
 }
 
 } // namespace mozilla