diff options
Diffstat (limited to 'src/vppinfra')
-rw-r--r-- | src/vppinfra/time.c | 17 | ||||
-rw-r--r-- | src/vppinfra/time.h | 4 |
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 */ |