summaryrefslogtreecommitdiffstats
path: root/src/vlib
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2020-05-26 13:12:17 +0000
committerAndrew Yourtchenko <ayourtch@gmail.com>2020-06-12 08:22:58 +0000
commit4f3db90a6f6640cd4e9e5a80769b9bd8c07fd558 (patch)
tree2c601bb41ed24bb732165a5210916dc77d0314fc /src/vlib
parent3aab9be7511d64c5f094225e55572c466ccf4b80 (diff)
fib: IPv6 lookup data structure MP safe when prefixes change (VPP-1881)
Type: fix adding routes should be MP safe. When new prefixes with differrent prefix lengths are added, adjust the sorted list in an MP safe way. Change-Id: Ib73a3c84d01eb86d17f8e79ea2bd2505dd9afb3d Signed-off-by: Neale Ranns <nranns@cisco.com> (cherry picked from commit aecb10b97fa97b215c415ceaa3cac4c97204922f)
Diffstat (limited to 'src/vlib')
-rw-r--r--src/vlib/main.h2
-rw-r--r--src/vlib/threads.c47
-rw-r--r--src/vlib/threads.h5
3 files changed, 53 insertions, 1 deletions
diff --git a/src/vlib/main.h b/src/vlib/main.h
index 20b8b464e34..a2ed9ba69f9 100644
--- a/src/vlib/main.h
+++ b/src/vlib/main.h
@@ -96,7 +96,7 @@ typedef struct vlib_main_t
u64 cpu_time_main_loop_start;
/* Incremented once for each main loop. */
- u32 main_loop_count;
+ volatile u32 main_loop_count;
/* Count of vectors processed this main loop. */
u32 main_loop_vectors_processed;
diff --git a/src/vlib/threads.c b/src/vlib/threads.c
index 07e1d79cf4c..26b9e7f8d56 100644
--- a/src/vlib/threads.c
+++ b/src/vlib/threads.c
@@ -1390,6 +1390,18 @@ vlib_worker_thread_initial_barrier_sync_and_release (vlib_main_t * vm)
*vlib_worker_threads->wait_at_barrier = 0;
}
+/**
+ * Return true if the wroker thread barrier is held
+ */
+u8
+vlib_worker_thread_barrier_held (void)
+{
+ if (vec_len (vlib_mains) < 2)
+ return (1);
+
+ return (*vlib_worker_threads->wait_at_barrier == 1);
+}
+
void
vlib_worker_thread_barrier_sync_int (vlib_main_t * vm, const char *func_name)
{
@@ -1586,6 +1598,41 @@ vlib_worker_thread_barrier_release (vlib_main_t * vm)
}
+/**
+ * Wait until each of the workers has been once around the track
+ */
+void
+vlib_worker_wait_one_loop (void)
+{
+ ASSERT (vlib_get_thread_index () == 0);
+
+ if (vec_len (vlib_mains) < 2)
+ return;
+
+ if (vlib_worker_thread_barrier_held ())
+ return;
+
+ u32 *counts = 0;
+ u32 ii;
+
+ vec_validate (counts, vec_len (vlib_mains) - 1);
+
+ /* record the current loop counts */
+ vec_foreach_index (ii, vlib_mains)
+ counts[ii] = vlib_mains[ii]->main_loop_count;
+
+ /* spin until each changes, apart from the main thread, or we'd be
+ * a while */
+ for (ii = 1; ii < vec_len (counts); ii++)
+ {
+ while (counts[ii] == vlib_mains[ii]->main_loop_count)
+ CLIB_PAUSE ();
+ }
+
+ vec_free (counts);
+ return;
+}
+
/*
* Check the frame queue to see if any frames are available.
* If so, pull the packets off the frames and put them to
diff --git a/src/vlib/threads.h b/src/vlib/threads.h
index 312323c096d..2088c5b8b7a 100644
--- a/src/vlib/threads.h
+++ b/src/vlib/threads.h
@@ -206,8 +206,13 @@ u32 vlib_frame_queue_main_init (u32 node_index, u32 frame_queue_nelts);
void vlib_worker_thread_barrier_sync_int (vlib_main_t * vm,
const char *func_name);
void vlib_worker_thread_barrier_release (vlib_main_t * vm);
+u8 vlib_worker_thread_barrier_held (void);
void vlib_worker_thread_initial_barrier_sync_and_release (vlib_main_t * vm);
void vlib_worker_thread_node_refork (void);
+/**
+ * Wait until each of the workers has been once around the track
+ */
+void vlib_worker_wait_one_loop (void);
static_always_inline uword
vlib_get_thread_index (void)