vcl: improve shutdown()
[vpp.git] / src / vcl / vcl_locked.c
index 5011461..ea22bcd 100644 (file)
@@ -38,6 +38,7 @@ typedef struct vcl_locked_session_
 
 typedef struct vls_worker_
 {
+  clib_rwlock_t sh_to_vlsh_table_lock; /** valid for multithread workers */
   vcl_locked_session_t *vls_pool;
   uword *session_handle_to_vlsh_table;
   u32 wrk_index;
@@ -50,7 +51,6 @@ typedef struct vls_local_
   pthread_mutex_t vls_mt_mq_mlock;
   pthread_mutex_t vls_mt_spool_mlock;
   volatile u8 select_mp_check;
-  volatile u8 epoll_mp_check;
 } vls_process_local_t;
 
 static vls_process_local_t vls_local;
@@ -312,6 +312,8 @@ vls_worker_alloc (void)
   vls_worker_t *wrk;
 
   pool_get_zero (vlsm->workers, wrk);
+  if (vls_mt_wrk_supported ())
+    clib_rwlock_init (&wrk->sh_to_vlsh_table_lock);
   wrk->wrk_index = vcl_get_worker_index ();
 }
 
@@ -319,6 +321,8 @@ static void
 vls_worker_free (vls_worker_t * wrk)
 {
   hash_free (wrk->session_handle_to_vlsh_table);
+  if (vls_mt_wrk_supported ())
+    clib_rwlock_free (&wrk->sh_to_vlsh_table_lock);
   pool_free (wrk->vls_pool);
   pool_put (vlsm->workers, wrk);
 }
@@ -331,6 +335,37 @@ vls_worker_get (u32 wrk_index)
   return pool_elt_at_index (vlsm->workers, wrk_index);
 }
 
+static void
+vls_sh_to_vlsh_table_add (vls_worker_t *wrk, vcl_session_handle_t sh, u32 vlsh)
+{
+  if (vls_mt_wrk_supported ())
+    clib_rwlock_writer_lock (&wrk->sh_to_vlsh_table_lock);
+  hash_set (wrk->session_handle_to_vlsh_table, sh, vlsh);
+  if (vls_mt_wrk_supported ())
+    clib_rwlock_writer_unlock (&wrk->sh_to_vlsh_table_lock);
+}
+
+static void
+vls_sh_to_vlsh_table_del (vls_worker_t *wrk, vcl_session_handle_t sh)
+{
+  if (vls_mt_wrk_supported ())
+    clib_rwlock_writer_lock (&wrk->sh_to_vlsh_table_lock);
+  hash_unset (wrk->session_handle_to_vlsh_table, sh);
+  if (vls_mt_wrk_supported ())
+    clib_rwlock_writer_unlock (&wrk->sh_to_vlsh_table_lock);
+}
+
+static uword *
+vls_sh_to_vlsh_table_get (vls_worker_t *wrk, vcl_session_handle_t sh)
+{
+  if (vls_mt_wrk_supported ())
+    clib_rwlock_reader_lock (&wrk->sh_to_vlsh_table_lock);
+  uword *vlshp = hash_get (wrk->session_handle_to_vlsh_table, sh);
+  if (vls_mt_wrk_supported ())
+    clib_rwlock_reader_unlock (&wrk->sh_to_vlsh_table_lock);
+  return vlshp;
+}
+
 static vls_handle_t
 vls_alloc (vcl_session_handle_t sh)
 {
@@ -344,7 +379,7 @@ vls_alloc (vcl_session_handle_t sh)
   vls->worker_index = vppcom_session_worker (sh);
   vls->vls_index = vls - wrk->vls_pool;
   vls->shared_data_index = ~0;
-  hash_set (wrk->session_handle_to_vlsh_table, sh, vls->vls_index);
+  vls_sh_to_vlsh_table_add (wrk, sh, vls->vls_index);
   if (vls_mt_wrk_supported ())
     {
       hash_set (vls->vcl_wrk_index_to_session_index, vls->worker_index,
@@ -372,8 +407,8 @@ vls_free (vcl_locked_session_t * vls)
   vls_worker_t *wrk = vls_worker_get_current ();
 
   ASSERT (vls != 0);
-  hash_unset (wrk->session_handle_to_vlsh_table,
-             vcl_session_handle_from_index (vls->session_index));
+  vls_sh_to_vlsh_table_del (
+    wrk, vcl_session_handle_from_index (vls->session_index));
   clib_spinlock_free (&vls->lock);
   pool_put (wrk->vls_pool, vls);
 }
@@ -452,10 +487,10 @@ vls_handle_t
 vls_si_wi_to_vlsh (u32 session_index, u32 vcl_wrk_index)
 {
   vls_worker_t *wrk = vls_worker_get_current ();
-  uword *vlshp;
-  vlshp = hash_get (wrk->session_handle_to_vlsh_table,
-                   vcl_session_handle_from_wrk_session_index (session_index,
-                                                              vcl_wrk_index));
+  uword *vlshp = vls_sh_to_vlsh_table_get (
+    wrk,
+    vcl_session_handle_from_wrk_session_index (session_index, vcl_wrk_index));
+
   return vlshp ? *vlshp : VLS_INVALID_HANDLE;
 }
 
@@ -861,6 +896,7 @@ vls_mt_session_migrate (vcl_locked_session_t *vls)
 {
   u32 wrk_index = vcl_get_worker_index ();
   vcl_worker_t *wrk;
+  vls_worker_t *vls_wrk = vls_worker_get_current ();
   u32 src_sid, sid, vls_index, own_vcl_wrk_index;
   vcl_session_t *session;
   uword *p;
@@ -945,6 +981,8 @@ vls_mt_session_migrate (vcl_locked_session_t *vls)
   vls->worker_index = wrk_index;
   vls->session_index = sid;
   hash_set (vls->vcl_wrk_index_to_session_index, wrk_index, sid);
+  vls_sh_to_vlsh_table_add (vls_wrk, vcl_session_handle (session),
+                           vls->vls_index);
   return vls;
 
 err:
@@ -1275,6 +1313,24 @@ vls_close (vls_handle_t vlsh)
   return rv;
 }
 
+int
+vls_shutdown (vls_handle_t vlsh, int how)
+{
+  vcl_locked_session_t *vls;
+  int rv;
+
+  vls_mt_detect ();
+  if (!(vls = vls_get_w_dlock (vlsh)))
+    return VPPCOM_EBADFD;
+
+  vls_mt_guard (vls, VLS_MT_OP_SPOOL);
+  rv = vppcom_session_shutdown (vls_to_sh (vls), how);
+  vls_mt_unguard ();
+  vls_get_and_unlock (vlsh);
+
+  return rv;
+}
+
 vls_handle_t
 vls_epoll_create (void)
 {
@@ -1297,16 +1353,9 @@ vls_epoll_create (void)
 static void
 vls_epoll_ctl_mp_checks (vcl_locked_session_t * vls, int op)
 {
-  if (vcl_n_workers () <= 1)
-    {
-      vlsl->epoll_mp_check = 1;
-      return;
-    }
-
-  if (op == EPOLL_CTL_MOD)
+  if (vcl_n_workers () <= 1 || op == EPOLL_CTL_MOD)
     return;
 
-  vlsl->epoll_mp_check = 1;
   vls_mp_checks (vls, op == EPOLL_CTL_ADD);
 }
 
@@ -1333,11 +1382,8 @@ vls_epoll_ctl (vls_handle_t ep_vlsh, int op, vls_handle_t vlsh,
   vls = vls_get_and_lock (vlsh);
   sh = vls_to_sh (vls);
 
-  if (PREDICT_FALSE (!vlsl->epoll_mp_check))
-    vls_epoll_ctl_mp_checks (vls, op);
-
+  vls_epoll_ctl_mp_checks (vls, op);
   vls_mt_table_runlock ();
-
   rv = vppcom_epoll_ctl (ep_sh, op, sh, event);
 
   vls_mt_table_rlock ();
@@ -1522,6 +1568,11 @@ static void
 vls_incercept_sigchld ()
 {
   struct sigaction sa;
+  if (old_sa.sa_sigaction)
+    {
+      VDBG (0, "have intercepted sigchld");
+      return;
+    }
   clib_memset (&sa, 0, sizeof (sa));
   sa.sa_sigaction = vls_intercept_sigchld_handler;
   sa.sa_flags = SA_SIGINFO;
@@ -1575,7 +1626,6 @@ vls_app_fork_child_handler (void)
   vlsl->vls_mt_n_threads = 0;
   vlsl->vls_wrk_index = vcl_get_worker_index ();
   vlsl->select_mp_check = 0;
-  vlsl->epoll_mp_check = 0;
   vls_mt_locks_init ();
 
   VDBG (0, "forked child main worker initialized");
@@ -1643,12 +1693,14 @@ vls_session_cleanup_rpc_handler (void *args)
 {
   vls_sess_cleanup_msg_t *msg = (vls_sess_cleanup_msg_t *) args;
   vcl_worker_t *wrk = vcl_worker_get_current ();
+  vls_worker_t *vls_wrk = vls_worker_get_current ();
   vcl_session_handle_t sh = vcl_session_handle_from_index (msg->session_index);
 
   VDBG (1, "process session cleanup of worker (session): %u (%u) from %u ()",
        wrk->wrk_index, msg->session_index, msg->origin_vcl_wrk);
 
   vppcom_session_close (sh);
+  vls_sh_to_vlsh_table_del (vls_wrk, sh);
 }
 
 static void