X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Fthreads.c;h=2f141f10d057d36bb6c7176542d4c9ab0c36f977;hb=ce32770251e4494803f2ab01d7b07801618b7bf0;hp=7454d5a18f3776032e97c0776a78b90644b6e24b;hpb=5517bd34535e4ffffb838a835bb95ddcb77e2bba;p=vpp.git diff --git a/src/vlib/threads.c b/src/vlib/threads.c index 7454d5a18f3..2f141f10d05 100644 --- a/src/vlib/threads.c +++ b/src/vlib/threads.c @@ -17,17 +17,14 @@ #include #include #include +#include #include #include #include -#include #include -DECLARE_CJ_GLOBAL_LOG; - - u32 vl (void *p) { @@ -283,6 +280,8 @@ vlib_thread_init (vlib_main_t * vm) w->thread_id = pthread_self (); tm->n_vlib_mains = 1; + vlib_get_thread_core_numa (w, w->cpu_id); + if (tm->sched_policy != ~0) { struct sched_param sched_param; @@ -334,12 +333,24 @@ vlib_thread_init (vlib_main_t * vm) { for (j = 0; j < tr->count; j++) { + /* Do not use CPU 0 by default - leave it to the host and IRQs */ + uword avail_c0 = clib_bitmap_get (avail_cpu, 0); + avail_cpu = clib_bitmap_set (avail_cpu, 0, 0); + uword c = clib_bitmap_first_set (avail_cpu); + /* Use CPU 0 as a last resort */ + if (c == ~0 && avail_c0) + { + c = 0; + avail_c0 = 0; + } + if (c == ~0) return clib_error_return (0, "no available cpus to be used for" " the '%s' thread", tr->name); + avail_cpu = clib_bitmap_set (avail_cpu, 0, avail_c0); avail_cpu = clib_bitmap_set (avail_cpu, c, 0); tr->coremask = clib_bitmap_set (tr->coremask, c, 1); } @@ -577,24 +588,38 @@ vlib_worker_thread_bootstrap_fn (void *arg) return rv; } -static void -vlib_get_thread_core_socket (vlib_worker_thread_t * w, unsigned cpu_id) +void +vlib_get_thread_core_numa (vlib_worker_thread_t * w, unsigned cpu_id) { const char *sys_cpu_path = "/sys/devices/system/cpu/cpu"; + const char *sys_node_path = "/sys/devices/system/node/node"; + clib_bitmap_t *nbmp = 0, *cbmp = 0; + u32 node; u8 *p = 0; - int core_id = -1, socket_id = -1; + int core_id = -1, numa_id = -1; p = format (p, "%s%u/topology/core_id%c", sys_cpu_path, cpu_id, 0); clib_sysfs_read ((char *) p, "%d", &core_id); vec_reset_length (p); - p = - format (p, "%s%u/topology/physical_package_id%c", sys_cpu_path, cpu_id, - 0); - clib_sysfs_read ((char *) p, "%d", &socket_id); + + /* *INDENT-OFF* */ + clib_sysfs_read ("/sys/devices/system/node/online", "%U", + unformat_bitmap_list, &nbmp); + clib_bitmap_foreach (node, nbmp, ({ + p = format (p, "%s%u/cpulist%c", sys_node_path, node, 0); + clib_sysfs_read ((char *) p, "%U", unformat_bitmap_list, &cbmp); + if (clib_bitmap_get (cbmp, cpu_id)) + numa_id = node; + vec_reset_length (cbmp); + vec_reset_length (p); + })); + /* *INDENT-ON* */ + vec_free (nbmp); + vec_free (cbmp); vec_free (p); w->core_id = core_id; - w->socket_id = socket_id; + w->numa_id = numa_id; } static clib_error_t * @@ -602,9 +627,28 @@ vlib_launch_thread_int (void *fp, vlib_worker_thread_t * w, unsigned cpu_id) { vlib_thread_main_t *tm = &vlib_thread_main; void *(*fp_arg) (void *) = fp; + void *numa_heap; w->cpu_id = cpu_id; - vlib_get_thread_core_socket (w, cpu_id); + vlib_get_thread_core_numa (w, cpu_id); + + /* Set up NUMA-bound heap if indicated */ + if (clib_per_numa_mheaps[w->numa_id] == 0) + { + /* If the user requested a NUMA heap, create it... */ + if (tm->numa_heap_size) + { + numa_heap = clib_mem_init_thread_safe_numa + (0 /* DIY */ , tm->numa_heap_size, w->numa_id); + clib_per_numa_mheaps[w->numa_id] = numa_heap; + } + else + { + /* Or, use the main heap */ + clib_per_numa_mheaps[w->numa_id] = w->thread_mheap; + } + } + if (tm->cb.vlib_launch_thread_cb && !w->registration->use_pthreads) return tm->cb.vlib_launch_thread_cb (fp, (void *) w, cpu_id); else @@ -707,15 +751,8 @@ start_workers (vlib_main_t * vm) vec_add2 (vlib_worker_threads, w, 1); /* Currently unused, may not really work */ if (tr->mheap_size) - { -#if USE_DLMALLOC == 0 - w->thread_mheap = - mheap_alloc (0 /* use VM */ , tr->mheap_size); -#else - w->thread_mheap = create_mspace (tr->mheap_size, - 0 /* unlocked */ ); -#endif - } + w->thread_mheap = create_mspace (tr->mheap_size, + 0 /* unlocked */ ); else w->thread_mheap = main_heap; @@ -879,13 +916,8 @@ start_workers (vlib_main_t * vm) vec_add2 (vlib_worker_threads, w, 1); if (tr->mheap_size) { -#if USE_DLMALLOC == 0 - w->thread_mheap = - mheap_alloc (0 /* use VM */ , tr->mheap_size); -#else w->thread_mheap = create_mspace (tr->mheap_size, 0 /* locked */ ); -#endif } else w->thread_mheap = main_heap; @@ -1242,6 +1274,9 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input) ; else if (unformat (input, "skip-cores %u", &tm->skip_cores)) ; + else if (unformat (input, "numa-heap-size %U", + unformat_memory_size, &tm->numa_heap_size)) + ; else if (unformat (input, "coremask-%s %U", &name, unformat_bitmap_mask, &bitmap) || unformat (input, "corelist-%s %U", &name, @@ -1257,6 +1292,10 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input) return clib_error_return (0, "corelist cannot be set for '%s' threads", name); + if (tr->count) + return clib_error_return + (0, "core placement of '%s' threads is already configured", + name); tr->coremask = bitmap; tr->count = clib_bitmap_count_set_bits (tr->coremask); @@ -1275,9 +1314,14 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input) return clib_error_return (0, "no such thread type 3 '%s'", name); tr = (vlib_thread_registration_t *) p[0]; + if (tr->fixed_count) return clib_error_return - (0, "number of %s threads not configurable", tr->name); + (0, "number of '%s' threads not configurable", name); + if (tr->count) + return clib_error_return + (0, "number of '%s' threads is already configured", name); + tr->count = count; } else @@ -1429,7 +1473,7 @@ vlib_worker_thread_barrier_sync_int (vlib_main_t * vm, const char *func_name) for (i = 1; i < vec_len (vlib_mains); i++) max_vector_rate = clib_max (max_vector_rate, - vlib_last_vectors_per_main_loop_as_f64 (vlib_mains[i])); + (f64) vlib_last_vectors_per_main_loop (vlib_mains[i])); vlib_worker_threads[0].barrier_sync_count++; @@ -1766,17 +1810,19 @@ vlib_frame_queue_main_init (u32 node_index, u32 frame_queue_nelts) vlib_frame_queue_main_t *fqm; vlib_frame_queue_t *fq; int i; + u32 num_threads; if (frame_queue_nelts == 0) frame_queue_nelts = FRAME_QUEUE_MAX_NELTS; - ASSERT (frame_queue_nelts >= 8); + num_threads = 1 /* main thread */ + tm->n_threads; + ASSERT (frame_queue_nelts >= 8 + num_threads); vec_add2 (tm->frame_queue_mains, fqm, 1); fqm->node_index = node_index; fqm->frame_queue_nelts = frame_queue_nelts; - fqm->queue_hi_thresh = frame_queue_nelts - 2; + fqm->queue_hi_thresh = frame_queue_nelts - num_threads; vec_validate (fqm->vlib_frame_queues, tm->n_vlib_mains - 1); vec_validate (fqm->per_thread_data, tm->n_vlib_mains - 1); @@ -1848,11 +1894,17 @@ show_clock_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { int i; - f64 now; + int verbose = 0; + clib_timebase_t _tb, *tb = &_tb; - now = vlib_time_now (vm); + (void) unformat (input, "verbose %=", &verbose, 1); + + clib_timebase_init (tb, 0 /* GMT */ , CLIB_TIMEBASE_DAYLIGHT_NONE, + &vm->clib_time); - vlib_cli_output (vm, "Time now %.9f", now); + vlib_cli_output (vm, "%U, %U GMT", format_clib_time, &vm->clib_time, + verbose, format_clib_timebase_time, + clib_timebase_now (tb)); if (vec_len (vlib_mains) == 1) return 0; @@ -1864,6 +1916,10 @@ show_clock_command_fn (vlib_main_t * vm, { if (vlib_mains[i] == 0) continue; + + vlib_cli_output (vm, "%d: %U", i, format_clib_time, + &vlib_mains[i]->clib_time, verbose); + vlib_cli_output (vm, "Thread %d offset %.9f error %.9f", i, vlib_mains[i]->time_offset, vm->time_last_barrier_release -