vppinfra: preserve total_cpu_time across clock freq adjustment
[vpp.git] / src / vppinfra / time.h
index 288922d..b2d7492 100644 (file)
@@ -56,6 +56,8 @@ typedef struct
      from clock cycles into seconds. */
   f64 seconds_per_clock;
 
+  f64 round_to_units;
+
   /* Time stamp of call to clib_time_init call. */
   u64 init_cpu_time;
 
@@ -114,6 +116,16 @@ clib_cpu_time_now (void)
   return (u64) lo + ((u64) hi2 << (u64) 32);
 }
 
+#elif defined (__aarch64__)
+always_inline u64
+clib_cpu_time_now (void)
+{
+  u64 vct;
+  /* User access to cntvct_el0 is enabled in Linux kernel since 3.12. */
+  asm volatile ("mrs %0, cntvct_el0":"=r" (vct));
+  return vct;
+}
+
 #elif defined (__arm__)
 #if defined(__ARM_ARCH_8A__)
 always_inline u64
@@ -164,16 +176,14 @@ clib_cpu_time_now (void)
   return ((u64) h << 32) | l;
 }
 
-#elif defined (__aarch64__)
+#elif defined(_mips) && __mips == 64
+
 always_inline u64
 clib_cpu_time_now (void)
 {
-  u64 tsc;
-
-  /* Works on Cavium ThunderX. Other platforms: YMMV */
-  asm volatile ("mrs %0, cntvct_el0":"=r" (tsc));
-
-  return tsc;
+  u64 result;
+  asm volatile ("rdhwr %0,$31\n":"=r" (result));
+  return result;
 }
 
 #else
@@ -183,21 +193,33 @@ clib_cpu_time_now (void)
 
 void clib_time_verify_frequency (clib_time_t * c);
 
+/* Define it as the type returned by clib_time_now */
+typedef f64 clib_time_type_t;
+typedef u64 clib_us_time_t;
+
+#define CLIB_US_TIME_PERIOD (1e-6)
+#define CLIB_US_TIME_FREQ (1.0/CLIB_US_TIME_PERIOD)
+
 always_inline f64
 clib_time_now_internal (clib_time_t * c, u64 n)
 {
   u64 l = c->last_cpu_time;
   u64 t = c->total_cpu_time;
+  f64 rv;
   t += n - l;
   c->total_cpu_time = t;
   c->last_cpu_time = n;
+  rv = t * c->seconds_per_clock;
   if (PREDICT_FALSE
       ((c->last_cpu_time -
        c->last_verify_cpu_time) >> c->log2_clocks_per_frequency_verify))
     clib_time_verify_frequency (c);
-  return t * c->seconds_per_clock;
+  return rv;
 }
 
+/* Maximum f64 value as max clib_time */
+#define CLIB_TIME_MAX (1.7976931348623157e+308)
+
 always_inline f64
 clib_time_now (clib_time_t * c)
 {
@@ -226,10 +248,14 @@ void clib_time_init (clib_time_t * c);
 always_inline f64
 unix_time_now (void)
 {
+  struct timespec ts;
+#ifdef __MACH__
+  clock_gettime (CLOCK_REALTIME, &ts);
+#else
   /* clock_gettime without indirect syscall uses GLIBC wrappers which
      we don't want.  Just the bare metal, please. */
-  struct timespec ts;
   syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
+#endif
   return ts.tv_sec + 1e-9 * ts.tv_nsec;
 }
 
@@ -238,7 +264,11 @@ always_inline u64
 unix_time_now_nsec (void)
 {
   struct timespec ts;
+#ifdef __MACH__
+  clock_gettime (CLOCK_REALTIME, &ts);
+#else
   syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
+#endif
   return 1e9 * ts.tv_sec + ts.tv_nsec;
 }
 
@@ -246,7 +276,11 @@ always_inline void
 unix_time_now_nsec_fraction (u32 * sec, u32 * nsec)
 {
   struct timespec ts;
+#ifdef __MACH__
+  clock_gettime (CLOCK_REALTIME, &ts);
+#else
   syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
+#endif
   *sec = ts.tv_sec;
   *nsec = ts.tv_nsec;
 }