#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)
* imapacts observed timings.
*/
-u32
-elog_global_id_for_msg_name (const char *msg_name)
-{
- uword *p, r;
- static uword *h;
- u8 *name_copy;
-
- if (!h)
- h = hash_create_string (0, sizeof (uword));
-
- p = hash_get_mem (h, msg_name);
- if (p)
- return p[0];
- r = elog_string (&vlib_global_main.elog_main, "%s", msg_name);
-
- name_copy = format (0, "%s%c", msg_name, 0);
-
- hash_set_mem (h, name_copy, r);
-
- return r;
-}
-
static inline void
barrier_trace_sync (f64 t_entry, f64 t_open, f64 t_closed)
{
ed = ELOG_DATA (&vlib_global_main.elog_main, e);
ed->count = (int) vlib_worker_threads[0].barrier_sync_count;
- ed->caller = elog_global_id_for_msg_name
- (vlib_worker_threads[0].barrier_caller);
+ ed->caller = elog_string (&vlib_global_main.elog_main,
+ (char *) vlib_worker_threads[0].barrier_caller);
ed->t_entry = (int) (1000000.0 * t_entry);
ed->t_open = (int) (1000000.0 * t_open);
ed->t_closed = (int) (1000000.0 * t_closed);
ed = ELOG_DATA (&vlib_global_main.elog_main, e);
ed->depth = (int) vlib_worker_threads[0].recursion_level - 1;
- ed->caller = elog_global_id_for_msg_name
- (vlib_worker_threads[0].barrier_caller);
+ ed->caller = elog_string (&vlib_global_main.elog_main,
+ (char *) vlib_worker_threads[0].barrier_caller);
}
static inline void
#ifdef VLIB_SUPPORTS_ARBITRARY_SCALAR_SIZES
nm_clone->frame_size_hash = hash_create (0, sizeof (uword));
#endif
+ nm_clone->node_by_error = nm->node_by_error;
/* 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);
+ /* 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);
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;
clib_mem_alloc_no_fail (vec_len (nm->nodes) * sizeof (*new_n_clone));
for (j = 0; j < vec_len (nm->nodes); j++)
{
- vlib_node_t *old_n_clone;
- vlib_node_t *new_n;
-
- new_n = nm->nodes[j];
- old_n_clone = old_nodes_clone[j];
+ vlib_node_t *new_n = nm->nodes[j];
clib_memcpy_fast (new_n_clone, new_n, sizeof (*new_n));
/* none of the copied nodes have enqueue rights given out */
}
else
{
+ vlib_node_t *old_n_clone = old_nodes_clone[j];
/* Copy stats if the old data is valid */
clib_memcpy_fast (&new_n_clone->stats_total,
&old_n_clone->stats_total,
nm_clone->processes = vec_dup_aligned (nm->processes,
CLIB_CACHE_LINE_BYTES);
+ nm_clone->node_by_error = nm->node_by_error;
}
void
#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)
{
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++;
}
-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)
{
while (1)
{
+ vlib_buffer_t *b;
if (fq->head == fq->tail)
{
fq->head_hint = fq->head;
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;
clib_time_init (&vm->clib_time);
clib_mem_set_heap (w->thread_mheap);
- /* 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
+ 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 ();
+
vlib_worker_loop (vm);
}
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);