+void
+segment_manager_cleanup_detached_listener (segment_manager_t * sm)
+{
+ app_worker_t *app_wrk;
+
+ app_wrk = app_worker_get_if_valid (sm->app_wrk_index);
+ if (!app_wrk)
+ return;
+
+ app_worker_del_detached_sm (app_wrk, segment_manager_index (sm));
+}
+
+/**
+ * Cleanup segment manager.
+ */
+void
+segment_manager_free (segment_manager_t * sm)
+{
+ segment_manager_main_t *smm = &sm_main;
+ fifo_segment_t *fifo_segment;
+
+ ASSERT (vlib_get_thread_index () == 0
+ && !segment_manager_has_fifos (sm)
+ && segment_manager_app_detached (sm));
+
+ if (sm->flags & SEG_MANAGER_F_DETACHED_LISTENER)
+ segment_manager_cleanup_detached_listener (sm);
+
+ /* If we have empty preallocated segments that haven't been removed, remove
+ * them now. Apart from that, the first segment in the first segment manager
+ * is not removed when all fifos are removed. It can only be removed when
+ * the manager is explicitly deleted/detached by the app. */
+ clib_rwlock_writer_lock (&sm->segments_rwlock);
+
+ /* *INDENT-OFF* */
+ pool_foreach (fifo_segment, sm->segments) {
+ segment_manager_del_segment (sm, fifo_segment);
+ }
+ /* *INDENT-ON* */
+
+ pool_free (sm->segments);
+ clib_rwlock_writer_unlock (&sm->segments_rwlock);
+
+ clib_rwlock_free (&sm->segments_rwlock);
+ if (CLIB_DEBUG)
+ clib_memset (sm, 0xfe, sizeof (*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);
+ else
+ {
+ ASSERT (!sm->first_is_protected || segment_manager_app_detached (sm));
+ segment_manager_free (sm);
+ }
+}
+
+segment_manager_t *
+segment_manager_get (u32 index)
+{
+ return pool_elt_at_index (sm_main.segment_managers, index);
+}
+
+segment_manager_t *
+segment_manager_get_if_valid (u32 index)
+{
+ if (pool_is_free_index (sm_main.segment_managers, index))
+ return 0;
+ return pool_elt_at_index (sm_main.segment_managers, index);
+}
+
+u32
+segment_manager_index (segment_manager_t * sm)
+{
+ return sm - sm_main.segment_managers;
+}
+