Set main thread affinity before main heap is allocated
[vpp.git] / src / vlib / threads.c
index 2d9ce84..4e4f13e 100644 (file)
@@ -289,7 +289,7 @@ sort_registrations_by_no_clone (void *a0, void *a1)
 }
 
 static uword *
-vlib_sysfs_list_to_bitmap (char *filename)
+clib_sysfs_list_to_bitmap (char *filename)
 {
   FILE *fp;
   uword *r = 0;
@@ -331,12 +331,18 @@ vlib_thread_init (vlib_main_t * vm)
 
   /* get bitmaps of active cpu cores and sockets */
   tm->cpu_core_bitmap =
-    vlib_sysfs_list_to_bitmap ("/sys/devices/system/cpu/online");
+    clib_sysfs_list_to_bitmap ("/sys/devices/system/cpu/online");
   tm->cpu_socket_bitmap =
-    vlib_sysfs_list_to_bitmap ("/sys/devices/system/node/online");
+    clib_sysfs_list_to_bitmap ("/sys/devices/system/node/online");
 
   avail_cpu = clib_bitmap_dup (tm->cpu_core_bitmap);
 
+  /* by default we skip core 0, unless it is the only one available */
+  if (tm->skip_cores == ~0 && clib_bitmap_count_set_bits (avail_cpu) == 1)
+    tm->skip_cores = 0;
+  else
+    tm->skip_cores = 1;
+
   /* skip cores */
   for (i = 0; i < tm->skip_cores; i++)
     {
@@ -372,13 +378,6 @@ vlib_thread_init (vlib_main_t * vm)
     {
       tm->cb.vlib_thread_set_lcore_cb (0, tm->main_lcore);
     }
-  else
-    {
-      cpu_set_t cpuset;
-      CPU_ZERO (&cpuset);
-      CPU_SET (tm->main_lcore, &cpuset);
-      pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t), &cpuset);
-    }
 
   /* as many threads as stacks... */
   vec_validate_aligned (vlib_worker_threads, vec_len (vlib_thread_stacks) - 1,
@@ -783,7 +782,6 @@ start_workers (vlib_main_t * vm)
       for (i = 0; i < vec_len (tm->registrations); i++)
        {
          vlib_node_main_t *nm, *nm_clone;
-         vlib_buffer_main_t *bm_clone;
          vlib_buffer_free_list_t *fl_clone, *fl_orig;
          vlib_buffer_free_list_t *orig_freelist_pool;
          int k;
@@ -822,21 +820,25 @@ start_workers (vlib_main_t * vm)
              /* Fork vlib_global_main et al. Look for bugs here */
              oldheap = clib_mem_set_heap (w->thread_mheap);
 
-             vm_clone = clib_mem_alloc (sizeof (*vm_clone));
+             vm_clone = clib_mem_alloc_aligned (sizeof (*vm_clone),
+                                                CLIB_CACHE_LINE_BYTES);
              clib_memcpy (vm_clone, vlib_mains[0], sizeof (*vm_clone));
 
              vm_clone->thread_index = worker_thread_index;
              vm_clone->heap_base = w->thread_mheap;
-             vm_clone->mbuf_alloc_list = 0;
              vm_clone->init_functions_called =
                hash_create (0, /* value bytes */ 0);
+             vm_clone->pending_rpc_requests = 0;
+             vec_validate (vm_clone->pending_rpc_requests, 0);
+             _vec_len (vm_clone->pending_rpc_requests) = 0;
              memset (&vm_clone->random_buffer, 0,
                      sizeof (vm_clone->random_buffer));
 
              nm = &vlib_mains[0]->node_main;
              nm_clone = &vm_clone->node_main;
              /* fork next frames array, preserving node runtime indices */
-             nm_clone->next_frames = vec_dup (nm->next_frames);
+             nm_clone->next_frames = vec_dup_aligned (nm->next_frames,
+                                                      CLIB_CACHE_LINE_BYTES);
              for (j = 0; j < vec_len (nm_clone->next_frames); j++)
                {
                  vlib_next_frame_t *nf = &nm_clone->next_frames[j];
@@ -873,7 +875,8 @@ start_workers (vlib_main_t * vm)
                  n++;
                }
              nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL] =
-               vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]);
+               vec_dup_aligned (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL],
+                                CLIB_CACHE_LINE_BYTES);
              vec_foreach (rt,
                           nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL])
              {
@@ -887,7 +890,8 @@ start_workers (vlib_main_t * vm)
              }
 
              nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT] =
-               vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT]);
+               vec_dup_aligned (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT],
+                                CLIB_CACHE_LINE_BYTES);
              vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT])
              {
                vlib_node_t *n = vlib_get_node (vm, rt->node_index);
@@ -899,7 +903,8 @@ start_workers (vlib_main_t * vm)
                                         n->runtime_data_bytes));
              }
 
-             nm_clone->processes = vec_dup (nm->processes);
+             nm_clone->processes = vec_dup_aligned (nm->processes,
+                                                    CLIB_CACHE_LINE_BYTES);
 
              /* zap the (per worker) frame freelists, etc */
              nm_clone->frame_sizes = 0;
@@ -910,25 +915,23 @@ start_workers (vlib_main_t * vm)
              clib_mem_set_heap (oldheap);
              vec_add1_aligned (vlib_mains, vm_clone, CLIB_CACHE_LINE_BYTES);
 
-             vm_clone->error_main.counters =
-               vec_dup (vlib_mains[0]->error_main.counters);
-             vm_clone->error_main.counters_last_clear =
-               vec_dup (vlib_mains[0]->error_main.counters_last_clear);
+             vm_clone->error_main.counters = vec_dup_aligned
+               (vlib_mains[0]->error_main.counters, CLIB_CACHE_LINE_BYTES);
+             vm_clone->error_main.counters_last_clear = vec_dup_aligned
+               (vlib_mains[0]->error_main.counters_last_clear,
+                CLIB_CACHE_LINE_BYTES);
 
              /* Fork the vlib_buffer_main_t free lists, etc. */
-             bm_clone = vec_dup (vm_clone->buffer_main);
-             vm_clone->buffer_main = bm_clone;
-
-             orig_freelist_pool = bm_clone->buffer_free_list_pool;
-             bm_clone->buffer_free_list_pool = 0;
+             orig_freelist_pool = vm_clone->buffer_free_list_pool;
+             vm_clone->buffer_free_list_pool = 0;
 
             /* *INDENT-OFF* */
             pool_foreach (fl_orig, orig_freelist_pool,
                           ({
-                            pool_get_aligned (bm_clone->buffer_free_list_pool,
+                            pool_get_aligned (vm_clone->buffer_free_list_pool,
                                               fl_clone, CLIB_CACHE_LINE_BYTES);
                             ASSERT (fl_orig - orig_freelist_pool
-                                    == fl_clone - bm_clone->buffer_free_list_pool);
+                                    == fl_clone - vm_clone->buffer_free_list_pool);
 
                             fl_clone[0] = fl_orig[0];
                             fl_clone->buffers = 0;
@@ -1094,7 +1097,8 @@ vlib_worker_thread_node_refork (void)
 
   nm_clone = &vm_clone->node_main;
   vec_free (nm_clone->next_frames);
-  nm_clone->next_frames = vec_dup (nm->next_frames);
+  nm_clone->next_frames = vec_dup_aligned (nm->next_frames,
+                                          CLIB_CACHE_LINE_BYTES);
 
   for (j = 0; j < vec_len (nm_clone->next_frames); j++)
     {
@@ -1162,7 +1166,8 @@ vlib_worker_thread_node_refork (void)
   /* re-clone internal nodes */
   old_rt = nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL];
   nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL] =
-    vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]);
+    vec_dup_aligned (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL],
+                    CLIB_CACHE_LINE_BYTES);
 
   vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL])
   {
@@ -1188,7 +1193,8 @@ vlib_worker_thread_node_refork (void)
   /* re-clone input nodes */
   old_rt = nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT];
   nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT] =
-    vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT]);
+    vec_dup_aligned (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT],
+                    CLIB_CACHE_LINE_BYTES);
 
   vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT])
   {
@@ -1211,7 +1217,8 @@ vlib_worker_thread_node_refork (void)
 
   vec_free (old_rt);
 
-  nm_clone->processes = vec_dup (nm->processes);
+  nm_clone->processes = vec_dup_aligned (nm->processes,
+                                        CLIB_CACHE_LINE_BYTES);
 }
 
 void
@@ -1254,6 +1261,7 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input)
   tm->n_thread_stacks = 1;     /* account for main thread */
   tm->sched_policy = ~0;
   tm->sched_priority = ~0;
+  tm->skip_cores = ~0;
 
   tr = tm->next;
 
@@ -1484,6 +1492,18 @@ vlib_worker_thread_barrier_sync_int (vlib_main_t * vm)
 
 }
 
+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)
 {
@@ -1513,6 +1533,13 @@ vlib_worker_thread_barrier_release (vlib_main_t * vm)
   /* Update (all) node runtimes before releasing the barrier, if needed */
   if (vm->need_vlib_worker_thread_node_runtime_update)
     {
+      /*
+       * Lock stat segment here, so we's safe when
+       * rebuilding the stat segment node clones from the
+       * stat thread...
+       */
+      vlib_stat_segment_lock ();
+
       /* Do stats elements on main thread */
       worker_thread_node_runtime_update_internal ();
       vm->need_vlib_worker_thread_node_runtime_update = 0;
@@ -1554,6 +1581,7 @@ vlib_worker_thread_barrier_release (vlib_main_t * vm)
              os_panic ();
            }
        }
+      vlib_stat_segment_unlock ();
     }
 
   t_closed_total = now - vm->barrier_epoch;
@@ -1767,7 +1795,6 @@ vlib_frame_queue_main_init (u32 node_index, u32 frame_queue_nelts)
   return (fqm - tm->frame_queue_mains);
 }
 
-
 int
 vlib_thread_cb_register (struct vlib_main_t *vm, vlib_thread_callbacks_t * cb)
 {
@@ -1781,6 +1808,29 @@ vlib_thread_cb_register (struct vlib_main_t *vm, vlib_thread_callbacks_t * cb)
   return 0;
 }
 
+void
+vlib_process_signal_event_mt_helper (vlib_process_signal_event_mt_args_t *
+                                    args)
+{
+  ASSERT (vlib_get_thread_index () == 0);
+  vlib_process_signal_event (vlib_get_main (), args->node_index,
+                            args->type_opaque, args->data);
+}
+
+void *rpc_call_main_thread_cb_fn;
+
+void
+vlib_rpc_call_main_thread (void *callback, u8 * args, u32 arg_size)
+{
+  if (rpc_call_main_thread_cb_fn)
+    {
+      void (*fp) (void *, u8 *, u32) = rpc_call_main_thread_cb_fn;
+      (*fp) (callback, args, arg_size);
+    }
+  else
+    clib_warning ("BUG: rpc_call_main_thread_cb_fn NULL!");
+}
+
 clib_error_t *
 threads_init (vlib_main_t * vm)
 {