+always_inline void
+session_pool_remove_peeker (u32 thread_index)
+{
+ session_worker_t *wrk = &session_main.wrk[thread_index];
+ if (thread_index == vlib_get_thread_index ())
+ return;
+ clib_rwlock_reader_unlock (&wrk->peekers_rw_locks);
+}
+
+/**
+ * Get session from handle and 'lock' pool resize if not in same thread
+ *
+ * Caller should drop the peek 'lock' as soon as possible.
+ */
+always_inline session_t *
+session_get_from_handle_safe (u64 handle)
+{
+ u32 thread_index = session_thread_from_handle (handle);
+ session_worker_t *wrk = &session_main.wrk[thread_index];
+
+ if (thread_index == vlib_get_thread_index ())
+ {
+ return pool_elt_at_index (wrk->sessions,
+ session_index_from_handle (handle));
+ }
+ else
+ {
+ session_pool_add_peeker (thread_index);
+ /* Don't use pool_elt_at index. See @ref session_pool_add_peeker */
+ return wrk->sessions + session_index_from_handle (handle);
+ }
+}
+
+always_inline u32
+session_get_index (session_t * s)
+{
+ return (s - session_main.wrk[s->thread_index].sessions);
+}
+
+always_inline session_t *
+session_clone_safe (u32 session_index, u32 thread_index)
+{
+ session_t *old_s, *new_s;
+ u32 current_thread_index = vlib_get_thread_index ();
+
+ /* If during the memcpy pool is reallocated AND the memory allocator
+ * decides to give the old chunk of memory to somebody in a hurry to
+ * scribble something on it, we have a problem. So add this thread as
+ * a session pool peeker.
+ */
+ session_pool_add_peeker (thread_index);
+ new_s = session_alloc (current_thread_index);
+ old_s = session_main.wrk[thread_index].sessions + session_index;
+ clib_memcpy_fast (new_s, old_s, sizeof (*new_s));
+ session_pool_remove_peeker (thread_index);
+ new_s->thread_index = current_thread_index;
+ new_s->session_index = session_get_index (new_s);
+ return new_s;
+}
+
+int session_open (u32 app_index, session_endpoint_t * tep, u32 opaque);
+int session_listen (session_t * s, session_endpoint_cfg_t * sep);
+int session_stop_listen (session_t * s);
+void session_close (session_t * s);
+void session_transport_close (session_t * s);
+void session_transport_cleanup (session_t * s);
+int session_send_io_evt_to_thread (svm_fifo_t * f,
+ session_evt_type_t evt_type);
+int session_enqueue_notify (session_t * s);
+int session_dequeue_notify (session_t * s);
+int session_send_io_evt_to_thread_custom (void *data, u32 thread_index,
+ session_evt_type_t evt_type);
+void session_send_rpc_evt_to_thread (u32 thread_index, void *fp,
+ void *rpc_args);
+void session_send_rpc_evt_to_thread_force (u32 thread_index, void *fp,
+ void *rpc_args);
+void session_add_self_custom_tx_evt (transport_connection_t * tc,
+ u8 has_prio);
+transport_connection_t *session_get_transport (session_t * s);
+void session_get_endpoint (session_t * s, transport_endpoint_t * tep,
+ u8 is_lcl);
+
+u8 *format_session (u8 * s, va_list * args);
+uword unformat_session (unformat_input_t * input, va_list * args);
+uword unformat_transport_connection (unformat_input_t * input,
+ va_list * args);