aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vppinfra/time.c17
-rw-r--r--src/vppinfra/time.h4
2 files changed, 17 insertions, 4 deletions
diff --git a/src/vppinfra/time.c b/src/vppinfra/time.c
index dee50024975..bfc48ce0671 100644
--- a/src/vppinfra/time.c
+++ b/src/vppinfra/time.c
@@ -198,6 +198,7 @@ clib_time_verify_frequency (clib_time_t * c)
f64 dtr_max;
u64 dtc = c->last_cpu_time - c->last_verify_cpu_time;
f64 new_clocks_per_second, delta;
+ f64 save_total_cpu_time_in_seconds;
c->last_verify_cpu_time = c->last_cpu_time;
c->last_verify_reference_time = now_reference;
@@ -239,10 +240,12 @@ clib_time_verify_frequency (clib_time_t * c)
flt_round_nearest ((f64) dtc / (dtr * c->round_to_units))
* c->round_to_units;
+ /* Compute abs(rate change) */
delta = new_clocks_per_second - c->clocks_per_second;
if (delta < 0.0)
delta = -delta;
+ /* If rate change > 1%, reject it and try again */
if (PREDICT_FALSE ((delta / c->clocks_per_second) > .01))
{
clib_warning ("Rejecting large frequency change of %.2f%%",
@@ -251,11 +254,19 @@ clib_time_verify_frequency (clib_time_t * c)
return;
}
- c->clocks_per_second =
- flt_round_nearest ((f64) dtc / (dtr * c->round_to_units))
- * c->round_to_units;
+ /* Save total cpu time in seconds */
+ save_total_cpu_time_in_seconds = c->total_cpu_time * c->seconds_per_clock;
+
+ /* Recalculate clock rate */
+ c->clocks_per_second = new_clocks_per_second;
c->seconds_per_clock = 1 / c->clocks_per_second;
+ /*
+ * Restore total cpu time in seconds. Otherwise, if c->clocks_per_second
+ * has decreased, time may appear to flow backwards.
+ */
+ c->total_cpu_time = save_total_cpu_time_in_seconds * c->clocks_per_second;
+
/* Double time between verifies; max at 64 secs ~ 1 minute. */
if (c->log2_clocks_per_frequency_verify < c->log2_clocks_per_second + 6)
c->log2_clocks_per_frequency_verify += 1;
diff --git a/src/vppinfra/time.h b/src/vppinfra/time.h
index ae738db1307..b2d749256d3 100644
--- a/src/vppinfra/time.h
+++ b/src/vppinfra/time.h
@@ -205,14 +205,16 @@ 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 */