summaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/session/segment_manager.c36
1 files changed, 32 insertions, 4 deletions
diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c
index 65f3f08370e..8441d54e92c 100644
--- a/src/vnet/session/segment_manager.c
+++ b/src/vnet/session/segment_manager.c
@@ -469,7 +469,8 @@ segment_manager_free (segment_manager_t * sm)
segment_manager_main_t *smm = &sm_main;
fifo_segment_t *fifo_segment;
- ASSERT (!segment_manager_has_fifos (sm)
+ ASSERT (vlib_get_thread_index () == 0
+ && !segment_manager_has_fifos (sm)
&& segment_manager_app_detached (sm));
if (sm->flags & SEG_MANAGER_F_DETACHED_LISTENER)
@@ -495,9 +496,38 @@ segment_manager_free (segment_manager_t * sm)
pool_put (smm->segment_managers, sm);
}
+static void
+sm_free_w_index_helper (void *arg)
+{
+ u32 sm_index = *(u32 *) arg;
+ segment_manager_t *sm;
+
+ ASSERT (vlib_get_thread_index () == 0);
+
+ if ((sm = segment_manager_get_if_valid (sm_index)))
+ segment_manager_free (sm);
+}
+
+static void
+segment_manager_free_safe (segment_manager_t * sm)
+{
+ if (!vlib_thread_is_main_w_barrier ())
+ {
+ u32 sm_index = segment_manager_index (sm);
+ vlib_rpc_call_main_thread (sm_free_w_index_helper, (u8 *) & sm_index,
+ sizeof (sm_index));
+ }
+ else
+ {
+ segment_manager_free (sm);
+ }
+}
+
void
segment_manager_init_free (segment_manager_t * sm)
{
+ ASSERT (vlib_get_thread_index () == 0);
+
segment_manager_app_detach (sm);
if (segment_manager_has_fifos (sm))
segment_manager_del_sessions (sm);
@@ -785,9 +815,7 @@ segment_manager_dealloc_fifos (svm_fifo_t * rx_fifo, svm_fifo_t * tx_fifo)
/* Remove segment manager if no sessions and detached from app */
if (segment_manager_app_detached (sm)
&& !segment_manager_has_fifos (sm))
- {
- segment_manager_free (sm);
- }
+ segment_manager_free_safe (sm);
}
else
segment_manager_segment_reader_unlock (sm);