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 104648 d291e2674dc6
parent 104646 a2db0bc00598
child 104649 2a8acb221714
push id23436
push userryanvm@gmail.com
push date2012-09-09 01:10 +0000
treeherdermozilla-central@f31d1aa89848 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbondy
bugs784859
milestone18.0a1
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