diff options
author | Neale Ranns <nranns@cisco.com> | 2020-05-26 13:12:17 +0000 |
---|---|---|
committer | Andrew Yourtchenko <ayourtch@gmail.com> | 2020-05-27 16:26:34 +0000 |
commit | aecb10b97fa97b215c415ceaa3cac4c97204922f (patch) | |
tree | b729a39bb1356554d61aeab6d2e6acd5c20ced13 /src/vlib | |
parent | af3022f0e88e07a62f1f6c3ec8e121e0d4de427f (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>
Diffstat (limited to 'src/vlib')
-rw-r--r-- | src/vlib/main.h | 2 | ||||
-rw-r--r-- | src/vlib/threads.c | 47 | ||||
-rw-r--r-- | src/vlib/threads.h | 5 |
3 files changed, 53 insertions, 1 deletions
diff --git a/src/vlib/main.h b/src/vlib/main.h index d6b2d1f875f..49604e6f513 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 2f141f10d05..aebcb346f68 100644 --- a/src/vlib/threads.c +++ b/src/vlib/threads.c @@ -1434,6 +1434,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) { @@ -1630,6 +1642,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 c1188cea933..b5841ccc2e3 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) |