vppinfra: fix corner cases in tw_timer_expire 29/25729/3
authorDave Barach <dave@barachs.net>
Sun, 8 Mar 2020 12:27:19 +0000 (08:27 -0400)
committerJohn Lo <loj@cisco.com>
Mon, 9 Mar 2020 20:55:37 +0000 (20:55 +0000)
Type: fix

Signed-off-by: Dave Barach <dave@barachs.net>
Change-Id: I4b3ff6e9c8e1d76037b168aeab36dcb5b4482260

src/vppinfra/tw_timer_template.c

index af2b75a..6b005fd 100644 (file)
@@ -513,7 +513,7 @@ static inline
   u32 slow_wheel_index __attribute__ ((unused));
   u32 glacier_wheel_index __attribute__ ((unused));
 
-  /* Shouldn't happen */
+  /* Called too soon to process new timer expirations? */
   if (PREDICT_FALSE (now < tw->next_run_time))
     return callback_vector_arg;
 
@@ -525,6 +525,27 @@ static inline
   /* Remember when we ran, compute next runtime */
   tw->next_run_time = (now + tw->timer_interval);
 
+  /* First call, or time jumped backwards? */
+  if (PREDICT_FALSE
+      ((tw->last_run_time == 0.0) || (now <= tw->last_run_time)))
+    {
+      tw->last_run_time = now;
+      return callback_vector_arg;
+    }
+
+  /*
+   * Refuse to do anything if we're about to process way too many slots.
+   * Should never come anywhere close to happening, with the possible exception
+   * of cases involving a large forward jump in the timebase.
+   */
+  if (nticks > (1 << (TW_RING_SHIFT + 1)))
+    {
+      clib_warning ("Excessive nticks %u at %.6f last run %.6f",
+                   nticks, now, tw->last_run_time);
+      tw->last_run_time = now;
+      return callback_vector_arg;
+    }
+
   if (callback_vector_arg == 0)
     {
       _vec_len (tw->expired_timer_handles) = 0;