vlib: packet tracer support for pkt thread handoffs
[vpp.git] / src / vlib / threads.c
index cb1eb5f..9112538 100644 (file)
 #include <vlib/threads.h>
 #include <vlib/unix/cj.h>
 
+#include <vlib/stat_weak_inlines.h>
+
 DECLARE_CJ_GLOBAL_LOG;
 
-#define FRAME_QUEUE_NELTS 64
 
 u32
 vl (void *p)
@@ -872,8 +873,13 @@ start_workers (vlib_main_t * vm)
              clib_mem_set_heap (oldheap);
              vec_add1_aligned (vlib_mains, vm_clone, CLIB_CACHE_LINE_BYTES);
 
+             /* Switch to the stats segment ... */
+             void *oldheap = vlib_stats_push_heap (0);
              vm_clone->error_main.counters = vec_dup_aligned
                (vlib_mains[0]->error_main.counters, CLIB_CACHE_LINE_BYTES);
+             vlib_stats_pop_heap2 (vm_clone->error_main.counters,
+                                   worker_thread_index, oldheap, 1);
+
              vm_clone->error_main.counters_last_clear = vec_dup_aligned
                (vlib_mains[0]->error_main.counters_last_clear,
                 CLIB_CACHE_LINE_BYTES);
@@ -1036,9 +1042,15 @@ vlib_worker_thread_node_refork (void)
   clib_memcpy_fast (&vm_clone->error_main, &vm->error_main,
                    sizeof (vm->error_main));
   j = vec_len (vm->error_main.counters) - 1;
+
+  /* Switch to the stats segment ... */
+  void *oldheap = vlib_stats_push_heap (0);
   vec_validate_aligned (old_counters, j, CLIB_CACHE_LINE_BYTES);
-  vec_validate_aligned (old_counters_all_clear, j, CLIB_CACHE_LINE_BYTES);
   vm_clone->error_main.counters = old_counters;
+  vlib_stats_pop_heap2 (vm_clone->error_main.counters, vm_clone->thread_index,
+                       oldheap, 0);
+
+  vec_validate_aligned (old_counters_all_clear, j, CLIB_CACHE_LINE_BYTES);
   vm_clone->error_main.counters_last_clear = old_counters_all_clear;
 
   nm_clone = &vm_clone->node_main;
@@ -1376,6 +1388,31 @@ vlib_worker_thread_fork_fixup (vlib_fork_fixup_t which)
 #define BARRIER_MINIMUM_OPEN_FACTOR 3
 #endif
 
+void
+vlib_worker_thread_initial_barrier_sync_and_release (vlib_main_t * vm)
+{
+  f64 deadline;
+  f64 now = vlib_time_now (vm);
+  u32 count = vec_len (vlib_mains) - 1;
+
+  /* No worker threads? */
+  if (count == 0)
+    return;
+
+  deadline = now + BARRIER_SYNC_TIMEOUT;
+  *vlib_worker_threads->wait_at_barrier = 1;
+  while (*vlib_worker_threads->workers_at_barrier != count)
+    {
+      if ((now = vlib_time_now (vm)) > deadline)
+       {
+         fformat (stderr, "%s: worker thread deadlock\n", __FUNCTION__);
+         os_panic ();
+       }
+      CLIB_PAUSE ();
+    }
+  *vlib_worker_threads->wait_at_barrier = 0;
+}
+
 void
 vlib_worker_thread_barrier_sync_int (vlib_main_t * vm, const char *func_name)
 {
@@ -1466,18 +1503,6 @@ vlib_worker_thread_barrier_sync_int (vlib_main_t * vm, const char *func_name)
 
 }
 
-void vlib_stat_segment_lock (void) __attribute__ ((weak));
-void
-vlib_stat_segment_lock (void)
-{
-}
-
-void vlib_stat_segment_unlock (void) __attribute__ ((weak));
-void
-vlib_stat_segment_unlock (void)
-{
-}
-
 void
 vlib_worker_thread_barrier_release (vlib_main_t * vm)
 {
@@ -1648,6 +1673,7 @@ vlib_frame_queue_dequeue (vlib_main_t * vm, vlib_frame_queue_main_t * fqm)
 
   while (1)
     {
+      vlib_buffer_t *b;
       if (fq->head == fq->tail)
        {
          fq->head_hint = fq->head;
@@ -1670,6 +1696,11 @@ vlib_frame_queue_dequeue (vlib_main_t * vm, vlib_frame_queue_main_t * fqm)
 
       f = vlib_get_frame_to_node (vm, fqm->node_index);
 
+      /* If the first vector is traced, set the frame trace flag */
+      b = vlib_get_buffer (vm, from[0]);
+      if (b->flags & VLIB_BUFFER_IS_TRACED)
+       f->frame_flags |= VLIB_NODE_FLAG_TRACE;
+
       to = vlib_frame_vector_args (f);
 
       n_left_to_node = elt->n_vectors;
@@ -1731,15 +1762,15 @@ vlib_worker_thread_fn (void *arg)
   clib_time_init (&vm->clib_time);
   clib_mem_set_heap (w->thread_mheap);
 
+  e = vlib_call_init_exit_functions_no_sort
+    (vm, &vm->worker_init_function_registrations, 1 /* call_once */ );
+  if (e)
+    clib_error_report (e);
+
   /* Wait until the dpdk init sequence is complete */
   while (tm->extern_thread_mgmt && tm->worker_thread_release == 0)
     vlib_worker_thread_barrier_check ();
 
-  e = vlib_call_init_exit_functions
-    (vm, vm->worker_init_function_registrations, 1 /* call_once */ );
-  if (e)
-    clib_error_report (e);
-
   vlib_worker_loop (vm);
 }
 
@@ -1760,7 +1791,7 @@ vlib_frame_queue_main_init (u32 node_index, u32 frame_queue_nelts)
   int i;
 
   if (frame_queue_nelts == 0)
-    frame_queue_nelts = FRAME_QUEUE_NELTS;
+    frame_queue_nelts = FRAME_QUEUE_MAX_NELTS;
 
   ASSERT (frame_queue_nelts >= 8);