vlib: make vlib_node_interrupt_pending(...) thread safe
authorDamjan Marion <damarion@cisco.com>
Tue, 28 Mar 2017 12:16:15 +0000 (14:16 +0200)
committerDave Barach <openvpp@barachs.net>
Tue, 4 Apr 2017 14:40:22 +0000 (14:40 +0000)
Change-Id: I24577bd32ae23fbe8515cc8d960eab5448ce3b5c
Signed-off-by: Damjan Marion <damarion@cisco.com>
src/vlib/main.c
src/vlib/node.h
src/vlib/node_funcs.h

index a272686..b22203f 100644 (file)
@@ -1414,6 +1414,7 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
   uword i;
   u64 cpu_time_now;
   vlib_frame_queue_main_t *fqm;
+  u32 *last_node_runtime_indices = 0;
 
   /* Initialize pending node vector. */
   if (is_main)
@@ -1442,8 +1443,13 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
       vec_alloc (nm->data_from_advancing_timing_wheel, 32);
     }
 
-  /* Pre-allocate expired nodes. */
+  /* Pre-allocate interupt runtime indices and lock. */
   vec_alloc (nm->pending_interrupt_node_runtime_indices, 32);
+  vec_alloc (last_node_runtime_indices, 32);
+  if (!is_main)
+    clib_spinlock_init (&nm->pending_interrupt_lock);
+
+  /* Pre-allocate expired nodes. */
   if (!nm->polling_threshold_vector_length)
     nm->polling_threshold_vector_length = 10;
   if (!nm->interrupt_threshold_vector_length)
@@ -1505,13 +1511,20 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
        uword i;
        if (l > 0)
          {
-           _vec_len (nm->pending_interrupt_node_runtime_indices) = 0;
+           u32 *tmp;
+           if (!is_main)
+             clib_spinlock_lock (&nm->pending_interrupt_lock);
+           tmp = nm->pending_interrupt_node_runtime_indices;
+           nm->pending_interrupt_node_runtime_indices =
+             last_node_runtime_indices;
+           last_node_runtime_indices = tmp;
+           _vec_len (last_node_runtime_indices) = 0;
+           if (!is_main)
+             clib_spinlock_unlock (&nm->pending_interrupt_lock);
            for (i = 0; i < l; i++)
              {
                n = vec_elt_at_index (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT],
-                                     nm->
-                                     pending_interrupt_node_runtime_indices
-                                     [i]);
+                                     last_node_runtime_indices[i]);
                cpu_time_now =
                  dispatch_node (vm, n, VLIB_NODE_TYPE_INPUT,
                                 VLIB_NODE_STATE_INTERRUPT,
index 2a532cc..fc7e7da 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <vppinfra/cpu.h>
 #include <vppinfra/longjmp.h>
+#include <vppinfra/lock.h>
 #include <vppinfra/timing_wheel.h>
 #include <vlib/trace.h>                /* for vlib_trace_filter_t */
 
@@ -644,6 +645,7 @@ typedef struct
 
   /* Node runtime indices for input nodes with pending interrupts. */
   u32 *pending_interrupt_node_runtime_indices;
+  clib_spinlock_t pending_interrupt_lock;
 
   /* Input nodes are switched from/to interrupt to/from polling mode
      when average vector length goes above/below polling/interrupt
index 8ccfc43..1f7d94e 100644 (file)
@@ -183,7 +183,9 @@ vlib_node_set_interrupt_pending (vlib_main_t * vm, u32 node_index)
   vlib_node_main_t *nm = &vm->node_main;
   vlib_node_t *n = vec_elt (nm->nodes, node_index);
   ASSERT (n->type == VLIB_NODE_TYPE_INPUT);
+  clib_spinlock_lock_if_init (&nm->pending_interrupt_lock);
   vec_add1 (nm->pending_interrupt_node_runtime_indices, n->runtime_index);
+  clib_spinlock_unlock_if_init (&nm->pending_interrupt_lock);
 }
 
 always_inline vlib_process_t *