X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Fthreads.c;h=499a626e4701be08ffcbff16f45824697262f290;hb=a606d92107d4bf0107c3f54e2c87d39311f82075;hp=cf82e1802d6328ac7fc0d7a82e9ba9198eeb236d;hpb=f553a2cbbb8cca84ebf033335ebd2cd26dc19d69;p=vpp.git diff --git a/src/vlib/threads.c b/src/vlib/threads.c index cf82e1802d6..499a626e470 100644 --- a/src/vlib/threads.c +++ b/src/vlib/threads.c @@ -166,33 +166,6 @@ sort_registrations_by_no_clone (void *a0, void *a1) - ((i32) ((*tr1)->no_data_structure_clone))); } -static uword * -clib_sysfs_list_to_bitmap (char *filename) -{ - FILE *fp; - uword *r = 0; - - fp = fopen (filename, "r"); - - if (fp != NULL) - { - u8 *buffer = 0; - vec_validate (buffer, 256 - 1); - if (fgets ((char *) buffer, 256, fp)) - { - unformat_input_t in; - unformat_init_string (&in, (char *) buffer, - strlen ((char *) buffer)); - if (unformat (&in, "%U", unformat_bitmap_list, &r) != 1) - clib_warning ("unformat_bitmap_list failed"); - unformat_free (&in); - } - vec_free (buffer); - fclose (fp); - } - return r; -} - /* Called early in the init sequence */ @@ -670,6 +643,7 @@ vlib_launch_thread_int (void *fp, vlib_worker_thread_t * w, unsigned cpu_id) static clib_error_t * start_workers (vlib_main_t * vm) { + vlib_global_main_t *vgm = vlib_get_global_main (); int i, j; vlib_worker_thread_t *w; vlib_main_t *vm_clone; @@ -680,6 +654,7 @@ start_workers (vlib_main_t * vm) u32 n_vlib_mains = tm->n_vlib_mains; u32 worker_thread_index; clib_mem_heap_t *main_heap = clib_mem_get_per_cpu_heap (); + vlib_stats_register_mem_heap (main_heap); vec_reset_length (vlib_worker_threads); @@ -694,19 +669,17 @@ start_workers (vlib_main_t * vm) vlib_set_thread_name ((char *) w->name); } - vm->elog_main.lock = + vgm->elog_main.lock = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES); - vm->elog_main.lock[0] = 0; + vgm->elog_main.lock[0] = 0; clib_callback_data_init (&vm->vlib_node_runtime_perf_callbacks, &vm->worker_thread_main_loop_callback_lock); - /* Replace hand-crafted length-1 vector with a real vector */ - vlib_mains = 0; - - vec_validate_aligned (vlib_mains, n_vlib_mains - 1, CLIB_CACHE_LINE_BYTES); - _vec_len (vlib_mains) = 0; - vec_add1_aligned (vlib_mains, vm, CLIB_CACHE_LINE_BYTES); + vec_validate_aligned (vgm->vlib_mains, n_vlib_mains - 1, + CLIB_CACHE_LINE_BYTES); + _vec_len (vgm->vlib_mains) = 0; + vec_add1_aligned (vgm->vlib_mains, vm, CLIB_CACHE_LINE_BYTES); if (n_vlib_mains > 1) { @@ -727,7 +700,7 @@ start_workers (vlib_main_t * vm) /* Without update or refork */ *vlib_worker_threads->node_reforks_required = 0; - vm->need_vlib_worker_thread_node_runtime_update = 0; + vgm->need_vlib_worker_thread_node_runtime_update = 0; /* init timing */ vm->barrier_epoch = 0; @@ -780,14 +753,13 @@ start_workers (vlib_main_t * vm) vm_clone = clib_mem_alloc_aligned (sizeof (*vm_clone), CLIB_CACHE_LINE_BYTES); - clib_memcpy (vm_clone, vlib_mains[0], sizeof (*vm_clone)); + clib_memcpy (vm_clone, vlib_get_first_main (), + sizeof (*vm_clone)); vm_clone->thread_index = worker_thread_index; vm_clone->heap_base = w->thread_mheap; vm_clone->heap_aligned_base = (void *) (((uword) w->thread_mheap) & ~(VLIB_FRAME_ALIGN - 1)); - 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; @@ -799,7 +771,7 @@ start_workers (vlib_main_t * vm) (&vm_clone->vlib_node_runtime_perf_callbacks, &vm_clone->worker_thread_main_loop_callback_lock); - nm = &vlib_mains[0]->node_main; + nm = &vlib_get_first_main ()->node_main; nm_clone = &vm_clone->node_main; /* fork next frames array, preserving node runtime indices */ nm_clone->next_frames = vec_dup_aligned (nm->next_frames, @@ -899,18 +871,20 @@ start_workers (vlib_main_t * vm) /* Packet trace buffers are guaranteed to be empty, nothing to do here */ clib_mem_set_heap (oldheap); - vec_add1_aligned (vlib_mains, vm_clone, CLIB_CACHE_LINE_BYTES); + vec_add1_aligned (vgm->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); + vm_clone->error_main.counters = + vec_dup_aligned (vlib_get_first_main ()->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); + vm_clone->error_main.counters_last_clear = vec_dup_aligned ( + vlib_get_first_main ()->error_main.counters_last_clear, + CLIB_CACHE_LINE_BYTES); worker_thread_index++; } @@ -1128,6 +1102,7 @@ vlib_worker_thread_node_refork (void) /* keep previous node state */ new_n_clone->state = old_n_clone->state; + new_n_clone->flags = old_n_clone->flags; } vec_add1 (nm_clone->nodes, new_n_clone); new_n_clone++; @@ -1159,6 +1134,7 @@ vlib_worker_thread_node_refork (void) { rt = vlib_node_get_runtime (vm_clone, old_rt[j].node_index); rt->state = old_rt[j].state; + rt->flags = old_rt[j].flags; clib_memcpy_fast (rt->runtime_data, old_rt[j].runtime_data, VLIB_NODE_RUNTIME_DATA_SIZE); } @@ -1189,6 +1165,7 @@ vlib_worker_thread_node_refork (void) { rt = vlib_node_get_runtime (vm_clone, old_rt[j].node_index); rt->state = old_rt[j].state; + rt->flags = old_rt[j].flags; clib_memcpy_fast (rt->runtime_data, old_rt[j].runtime_data, VLIB_NODE_RUNTIME_DATA_SIZE); } @@ -1216,6 +1193,7 @@ vlib_worker_thread_node_refork (void) { rt = vlib_node_get_runtime (vm_clone, old_rt[j].node_index); rt->state = old_rt[j].state; + rt->flags = old_rt[j].flags; clib_memcpy_fast (rt->runtime_data, old_rt[j].runtime_data, VLIB_NODE_RUNTIME_DATA_SIZE); } @@ -1377,35 +1355,6 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input) VLIB_EARLY_CONFIG_FUNCTION (cpu_config, "cpu"); -void vnet_main_fixup (vlib_fork_fixup_t which) __attribute__ ((weak)); -void -vnet_main_fixup (vlib_fork_fixup_t which) -{ -} - -void -vlib_worker_thread_fork_fixup (vlib_fork_fixup_t which) -{ - vlib_main_t *vm = vlib_get_main (); - - if (vlib_mains == 0) - return; - - ASSERT (vlib_get_thread_index () == 0); - vlib_worker_thread_barrier_sync (vm); - - switch (which) - { - case VLIB_WORKER_THREAD_FORK_FIXUP_NEW_SW_IF_INDEX: - vnet_main_fixup (VLIB_WORKER_THREAD_FORK_FIXUP_NEW_SW_IF_INDEX); - break; - - default: - ASSERT (0); - } - vlib_worker_thread_barrier_release (vm); -} - /* * Enforce minimum open time to minimize packet loss due to Rx overflow, * based on a test based heuristic that barrier should be open for at least @@ -1557,6 +1506,7 @@ vlib_worker_thread_barrier_sync_int (vlib_main_t * vm, const char *func_name) void vlib_worker_thread_barrier_release (vlib_main_t * vm) { + vlib_global_main_t *vgm = vlib_get_global_main (); f64 deadline; f64 now; f64 minimum_open; @@ -1581,7 +1531,7 @@ 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) + if (vgm->need_vlib_worker_thread_node_runtime_update) { /* * Lock stat segment here, so we's safe when @@ -1592,7 +1542,7 @@ vlib_worker_thread_barrier_release (vlib_main_t * vm) /* Do stats elements on main thread */ worker_thread_node_runtime_update_internal (); - vm->need_vlib_worker_thread_node_runtime_update = 0; + vgm->need_vlib_worker_thread_node_runtime_update = 0; /* Do per thread rebuilds in parallel */ refork_needed = 1; @@ -1669,6 +1619,7 @@ vlib_worker_thread_barrier_release (vlib_main_t * vm) void vlib_worker_wait_one_loop (void) { + vlib_global_main_t *vgm = vlib_get_global_main (); ASSERT (vlib_get_thread_index () == 0); if (vlib_get_n_threads () < 2) @@ -1683,14 +1634,14 @@ vlib_worker_wait_one_loop (void) vec_validate (counts, vlib_get_n_threads () - 1); /* record the current loop counts */ - vec_foreach_index (ii, vlib_mains) - counts[ii] = vlib_mains[ii]->main_loop_count; + vec_foreach_index (ii, vgm->vlib_mains) + counts[ii] = vgm->vlib_mains[ii]->main_loop_count; /* spin until each changes, apart from the main thread, or we'd be * a while */ for (ii = 1; ii < vec_len (counts); ii++) { - while (counts[ii] == vlib_mains[ii]->main_loop_count) + while (counts[ii] == vgm->vlib_mains[ii]->main_loop_count) CLIB_PAUSE (); } @@ -1698,148 +1649,10 @@ vlib_worker_wait_one_loop (void) return; } -/* - * Check the frame queue to see if any frames are available. - * If so, pull the packets off the frames and put them to - * the handoff node. - */ -int -vlib_frame_queue_dequeue (vlib_main_t * vm, vlib_frame_queue_main_t * fqm) -{ - u32 thread_id = vm->thread_index; - vlib_frame_queue_t *fq = fqm->vlib_frame_queues[thread_id]; - vlib_frame_queue_elt_t *elt; - u32 *from, *to; - vlib_frame_t *f; - int msg_type; - int processed = 0; - u32 n_left_to_node; - u32 vectors = 0; - - ASSERT (fq); - ASSERT (vm == vlib_mains[thread_id]); - - if (PREDICT_FALSE (fqm->node_index == ~0)) - return 0; - /* - * Gather trace data for frame queues - */ - if (PREDICT_FALSE (fq->trace)) - { - frame_queue_trace_t *fqt; - frame_queue_nelt_counter_t *fqh; - u32 elix; - - fqt = &fqm->frame_queue_traces[thread_id]; - - fqt->nelts = fq->nelts; - fqt->head = fq->head; - fqt->head_hint = fq->head_hint; - fqt->tail = fq->tail; - fqt->threshold = fq->vector_threshold; - fqt->n_in_use = fqt->tail - fqt->head; - if (fqt->n_in_use >= fqt->nelts) - { - // if beyond max then use max - fqt->n_in_use = fqt->nelts - 1; - } - - /* Record the number of elements in use in the histogram */ - fqh = &fqm->frame_queue_histogram[thread_id]; - fqh->count[fqt->n_in_use]++; - - /* Record a snapshot of the elements in use */ - for (elix = 0; elix < fqt->nelts; elix++) - { - elt = fq->elts + ((fq->head + 1 + elix) & (fq->nelts - 1)); - if (1 || elt->valid) - { - fqt->n_vectors[elix] = elt->n_vectors; - } - } - fqt->written = 1; - } - - while (1) - { - vlib_buffer_t *b; - if (fq->head == fq->tail) - { - fq->head_hint = fq->head; - return processed; - } - - elt = fq->elts + ((fq->head + 1) & (fq->nelts - 1)); - - if (!elt->valid) - { - fq->head_hint = fq->head; - return processed; - } - - from = elt->buffer_index; - msg_type = elt->msg_type; - - ASSERT (msg_type == VLIB_FRAME_QUEUE_ELT_DISPATCH_FRAME); - ASSERT (elt->n_vectors <= VLIB_FRAME_SIZE); - - 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; - - while (n_left_to_node >= 4) - { - to[0] = from[0]; - to[1] = from[1]; - to[2] = from[2]; - to[3] = from[3]; - to += 4; - from += 4; - n_left_to_node -= 4; - } - - while (n_left_to_node > 0) - { - to[0] = from[0]; - to++; - from++; - n_left_to_node--; - } - - vectors += elt->n_vectors; - f->n_vectors = elt->n_vectors; - vlib_put_frame_to_node (vm, fqm->node_index, f); - - elt->valid = 0; - elt->n_vectors = 0; - elt->msg_type = 0xfefefefe; - CLIB_MEMORY_BARRIER (); - fq->head++; - processed++; - - /* - * Limit the number of packets pushed into the graph - */ - if (vectors >= fq->vector_threshold) - { - fq->head_hint = fq->head; - return processed; - } - } - ASSERT (0); - return processed; -} - void vlib_worker_thread_fn (void *arg) { + vlib_global_main_t *vgm = vlib_get_global_main (); vlib_worker_thread_t *w = (vlib_worker_thread_t *) arg; vlib_thread_main_t *tm = vlib_get_thread_main (); vlib_main_t *vm = vlib_get_main (); @@ -1853,8 +1666,11 @@ 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 */ ); + vm->worker_init_functions_called = hash_create (0, 0); + + e = vlib_call_init_exit_functions_no_sort ( + vm, &vgm->worker_init_function_registrations, 1 /* call_once */, + 0 /* is_global */); if (e) clib_error_report (e);