Browse Source

HPCC-14571 Add support for power8 equivalent to RDTSC

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 9 years ago
parent
commit
2ba288cbf4
2 changed files with 44 additions and 10 deletions
  1. 12 10
      system/jlib/jdebug.cpp
  2. 32 0
      system/jlib/jdebug.hpp

+ 12 - 10
system/jlib/jdebug.cpp

@@ -300,7 +300,7 @@ double getCycleToNanoScale()
 
 #else
 
-#if defined(_ARCH_X86_) || defined(_ARCH_X86_64_)
+#if defined(HAS_GOOD_CYCLE_COUNTER)
 static bool useRDTSC = _USE_RDTSC;
 #endif
 static double cycleToNanoScale;
@@ -309,9 +309,6 @@ static double cycleToMilliScale;
 
 void calibrate_timing()
 {
-    cycleToNanoScale = 1.0;
-    cycleToMicroScale = 1.0;
-    cycleToMilliScale = 1.0;
 #if defined(_ARCH_X86_) || defined(_ARCH_X86_64_)
     if (useRDTSC) {
         unsigned long eax;
@@ -334,6 +331,9 @@ void calibrate_timing()
         if ((edx&0x10)==0)
             useRDTSC = false;
     }
+#endif
+
+#if defined(HAS_GOOD_CYCLE_COUNTER)
     if (useRDTSC) {
         unsigned startu = usTick();
         cycle_t start = getTSC();
@@ -358,6 +358,8 @@ void calibrate_timing()
     }
 #endif
     cycleToNanoScale = 1.0;
+    cycleToMicroScale = 1.0;
+    cycleToMilliScale = 1.0;
 }
 
 
@@ -367,7 +369,7 @@ static bool use_gettimeofday=false;
 #endif
 cycle_t jlib_decl get_cycles_now()
 {
-#if defined(_ARCH_X86_) || defined(_ARCH_X86_64_)
+#if defined(HAS_GOOD_CYCLE_COUNTER)
     if (useRDTSC)
         return getTSC();
 #endif
@@ -390,19 +392,19 @@ cycle_t jlib_decl get_cycles_now()
 
 __int64 jlib_decl cycle_to_nanosec(cycle_t cycles)
 {
-#if defined(_ARCH_X86_) || defined(_ARCH_X86_64_)
+#if defined(HAS_GOOD_CYCLE_COUNTER)
     if (useRDTSC)
         return (__int64)((double)cycles * cycleToNanoScale);
+#endif
 #ifdef __APPLE__
     return cycles * (uint64_t) timebase_info.numer / (uint64_t)timebase_info.denom;
 #endif
-#endif
     return cycles;
 }
 
 __int64 jlib_decl cycle_to_microsec(cycle_t cycles)
 {
-#if defined(_ARCH_X86_) || defined(_ARCH_X86_64_)
+#if defined(HAS_GOOD_CYCLE_COUNTER)
     if (useRDTSC)
         return (__int64)((double)cycles * cycleToMicroScale);
 #endif
@@ -411,7 +413,7 @@ __int64 jlib_decl cycle_to_microsec(cycle_t cycles)
 
 __int64 jlib_decl cycle_to_millisec(cycle_t cycles)
 {
-#if defined(_ARCH_X86_) || defined(_ARCH_X86_64_)
+#if defined(HAS_GOOD_CYCLE_COUNTER)
     if (useRDTSC)
         return (__int64)((double)cycles * cycleToMilliScale);
 #endif
@@ -420,7 +422,7 @@ __int64 jlib_decl cycle_to_millisec(cycle_t cycles)
 
 cycle_t nanosec_to_cycle(__int64 ns)
 {
-#if defined(_ARCH_X86_) || defined(_ARCH_X86_64_)
+#if defined(HAS_GOOD_CYCLE_COUNTER)
     if (useRDTSC)
         return (__int64)((double)ns / cycleToNanoScale);
 #endif

+ 32 - 0
system/jlib/jdebug.hpp

@@ -54,6 +54,38 @@ inline __int64 getTSC()
 inline cycle_t getTSC() { return __rdtsc(); }
 #endif // WIN32
 
+#elif defined(_ARCH_PPC)
+
+#define HAS_GOOD_CYCLE_COUNTER
+
+static inline cycle_t getTSC()
+{
+    int64_t result;
+#ifdef _ARCH_PPC64
+    /*
+        This reads timebase in one 64bit go.  Does *not* include a workaround for the cell (see 
+        http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html)
+    */
+    __asm__ volatile(
+        "mftb    %0"
+        : "=r" (result));
+#else
+    /*
+        Read the high 32bits of the timer, then the lower, and repeat if high order has changed in the meantime.  See
+        http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html
+    */
+    unsigned long dummy;
+    __asm__ volatile(
+        "mfspr   %1,269\n\t"  /* mftbu */
+        "mfspr   %L0,268\n\t" /* mftb */
+        "mfspr   %0,269\n\t"  /* mftbu */
+        "cmpw    %0,%1\n\t"   /* check if the high order word has chanegd */
+        "bne     $-16"
+        : "=r" (result), "=r" (dummy));
+#endif
+    return result;
+}
+
 #else
 // ARMFIX: cycle-count is not always available in user mode
 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0338g/Bihbeabc.html