aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2025-03-17 15:51:59 +0100
committerAndrew Yourtchenko <ayourtch@gmail.com>2025-03-26 13:24:19 +0000
commit8a5add5c00479d337e4d3428d7c98de4d843c0d3 (patch)
treee9c9b4e0abd0f0a08ed2019a1842f7c4302f5ba0
parent27c80923d0cc941c3d6954e2339b0ec75bcf18f9 (diff)
vlib: add new node type - SCHED nodes
SCHED nodes are new type of nodes, similar to input nodes but they are scheduled to be run from timing wheel. SCHED nodes work both on main and worker threads. Typically SCHED nodes can be scheduled to be run in two ways: - vlib_node_set_interrupt_pending() - from any thread, run ASAP - vlib_node_schedule() - from own thread, afer sepcific interval Type: feature Change-Id: Id29a66532328d9b3c454e65d09495e8fb479cedf Signed-off-by: Damjan Marion <damarion@cisco.com>
-rw-r--r--src/vlib/main.c315
-rw-r--r--src/vlib/main.h5
-rw-r--r--src/vlib/node.c13
-rw-r--r--src/vlib/node.h98
-rw-r--r--src/vlib/node_cli.c3
-rw-r--r--src/vlib/node_funcs.h77
-rw-r--r--src/vlib/threads.c222
-rw-r--r--src/vlib/time.h3
-rw-r--r--src/vlib/unix/input.c20
9 files changed, 378 insertions, 378 deletions
diff --git a/src/vlib/main.c b/src/vlib/main.c
index 731e788d30d..c4b1de41069 100644
--- a/src/vlib/main.c
+++ b/src/vlib/main.c
@@ -871,16 +871,16 @@ add_trajectory_trace (vlib_buffer_t * b, u32 node_index)
}
static_always_inline u64
-dispatch_node (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_node_type_t type,
- vlib_node_state_t dispatch_state,
- vlib_frame_t * frame, u64 last_time_stamp)
+dispatch_node (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_node_type_t type, vlib_frame_t *frame,
+ vlib_node_dispatch_reason_t dispatch_reason,
+ u64 last_time_stamp)
{
uword n, v;
u64 t;
vlib_node_main_t *nm = &vm->node_main;
vlib_next_frame_t *nf;
+ vlib_node_type_atts_t attr = node_type_attrs[type];
if (CLIB_DEBUG > 0)
{
@@ -888,15 +888,14 @@ dispatch_node (vlib_main_t * vm,
ASSERT (n->type == type);
}
- /* Only non-internal nodes may be disabled. */
- if (type != VLIB_NODE_TYPE_INTERNAL && node->state != dispatch_state)
+ if (attr.can_be_disabled == 0 && node->state == VLIB_NODE_STATE_DISABLED)
{
- ASSERT (type != VLIB_NODE_TYPE_INTERNAL);
+ ASSERT (0); /* disabled node should not be dispatched */
return last_time_stamp;
}
- if ((type == VLIB_NODE_TYPE_PRE_INPUT || type == VLIB_NODE_TYPE_INPUT)
- && dispatch_state != VLIB_NODE_STATE_INTERRUPT)
+ if (attr.decrement_main_loop_per_calls_if_polling &&
+ node->state == VLIB_NODE_STATE_POLLING)
{
u32 c = node->input_main_loops_per_call;
/* Only call node when count reaches zero. */
@@ -938,18 +937,13 @@ dispatch_node (vlib_main_t * vm,
vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
add_trajectory_trace (b, node->node_index);
}
- if (PREDICT_TRUE (vm->dispatch_wrapper_fn == 0))
- n = node->function (vm, node, frame);
- else
- n = vm->dispatch_wrapper_fn (vm, node, frame);
}
+
+ node->dispatch_reason = dispatch_reason;
+ if (PREDICT_TRUE (vm->dispatch_wrapper_fn == 0))
+ n = node->function (vm, node, frame);
else
- {
- if (PREDICT_TRUE (vm->dispatch_wrapper_fn == 0))
- n = node->function (vm, node, frame);
- else
- n = vm->dispatch_wrapper_fn (vm, node, frame);
- }
+ n = vm->dispatch_wrapper_fn (vm, node, frame);
t = clib_cpu_time_now ();
@@ -968,7 +962,8 @@ dispatch_node (vlib_main_t * vm,
/* When in adaptive mode and vector rate crosses threshold switch to
polling mode and vice versa. */
- if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_ADAPTIVE_MODE))
+ if (PREDICT_FALSE (attr.supports_adaptive_mode &&
+ node->flags & VLIB_NODE_FLAG_ADAPTIVE_MODE))
{
ELOG_TYPE_DECLARE (e) =
{
@@ -985,8 +980,8 @@ dispatch_node (vlib_main_t * vm,
u32 node_name, vector_length, is_polling;
} *ed;
- if ((dispatch_state == VLIB_NODE_STATE_INTERRUPT
- && v >= nm->polling_threshold_vector_length) &&
+ if ((node->state == VLIB_NODE_STATE_INTERRUPT &&
+ v >= nm->polling_threshold_vector_length) &&
!(node->flags &
VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE))
{
@@ -1012,8 +1007,8 @@ dispatch_node (vlib_main_t * vm,
ed->is_polling = 1;
}
}
- else if (dispatch_state == VLIB_NODE_STATE_POLLING
- && v <= nm->interrupt_threshold_vector_length)
+ else if (node->state == VLIB_NODE_STATE_POLLING &&
+ v <= nm->interrupt_threshold_vector_length)
{
vlib_node_t *n = vlib_get_node (vm, node->node_index);
if (node->flags &
@@ -1103,10 +1098,9 @@ dispatch_pending_node (vlib_main_t * vm, uword pending_frame_index,
n->flags |= (nf->flags & VLIB_FRAME_TRACE) ? VLIB_NODE_FLAG_TRACE : 0;
nf->flags &= ~VLIB_FRAME_TRACE;
- last_time_stamp = dispatch_node (vm, n,
- VLIB_NODE_TYPE_INTERNAL,
- VLIB_NODE_STATE_POLLING,
- f, last_time_stamp);
+ last_time_stamp =
+ dispatch_node (vm, n, VLIB_NODE_TYPE_INTERNAL, f,
+ VLIB_NODE_DISPATCH_REASON_PENDING_FRAME, last_time_stamp);
/* Internal node vector-rate accounting, for summary stats */
vm->internal_node_vectors += f->n_vectors;
vm->internal_node_calls++;
@@ -1260,6 +1254,20 @@ vlib_process_resume (vlib_main_t * vm, vlib_process_t * p)
return r;
}
+static void
+process_timer_start (vlib_main_t *vm, vlib_process_t *p, u32 runtime_index)
+{
+ TWT (tw_timer_wheel) *tw = (TWT (tw_timer_wheel) *) vm->timing_wheel;
+ vlib_tw_event_t e = { .type = VLIB_TW_EVENT_T_PROCESS_NODE,
+ .index = runtime_index };
+
+ if (p->resume_clock_interval == 0)
+ return;
+
+ p->stop_timer_handle = TW (tw_timer_start) (tw, e.as_u32, 0 /* timer_id */,
+ p->resume_clock_interval);
+}
+
static u64
dispatch_process (vlib_main_t * vm,
vlib_process_t * p, vlib_frame_t * f, u64 last_time_stamp)
@@ -1309,15 +1317,7 @@ dispatch_process (vlib_main_t * vm,
p->n_suspends += 1;
p->suspended_process_frame_index = pf - nm->suspended_process_frames;
- if (p->resume_clock_interval)
- {
- TWT (tw_timer_wheel) *tw = (TWT (tw_timer_wheel) *) nm->timing_wheel;
- p->stop_timer_handle =
- TW (tw_timer_start) (tw,
- vlib_timing_wheel_data_set_suspended_process (
- node->runtime_index) /* [sic] pool idex */,
- 0 /* timer_id */, p->resume_clock_interval);
- }
+ process_timer_start (vm, p, node->runtime_index);
}
else
p->state = VLIB_PROCESS_STATE_NOT_STARTED;
@@ -1419,15 +1419,7 @@ dispatch_suspended_process (vlib_main_t *vm, vlib_process_restore_t *r,
/* Suspend it again. */
n_vectors = 0;
p->n_suspends += 1;
- if (p->resume_clock_interval)
- {
- p->stop_timer_handle =
- TW (tw_timer_start) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
- vlib_timing_wheel_data_set_suspended_process
- (node->runtime_index) /* [sic] pool idex */ ,
- 0 /* timer_id */ ,
- p->resume_clock_interval);
- }
+ process_timer_start (vm, p, node->runtime_index);
}
else
{
@@ -1452,6 +1444,61 @@ dispatch_suspended_process (vlib_main_t *vm, vlib_process_restore_t *r,
return t;
}
+static void
+process_expired_timer_cb (u32 *expired_timer_handles)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ vlib_node_main_t *nm = &vm->node_main;
+ u32 *handle;
+
+ vec_foreach (handle, expired_timer_handles)
+ {
+ vlib_tw_event_t e = { .as_u32 = *handle };
+ vlib_process_restore_t restore = {};
+
+ if (e.type == VLIB_TW_EVENT_T_TIMED_EVENT)
+ {
+ restore.reason = VLIB_PROCESS_RESTORE_REASON_TIMED_EVENT;
+ restore.timed_event_data_pool_index = e.index;
+ vec_add1 (nm->process_restore_current, restore);
+ }
+ else if (e.type == VLIB_TW_EVENT_T_PROCESS_NODE)
+ {
+ vlib_process_t *p = vec_elt (nm->processes, e.index);
+ p->stop_timer_handle = ~0;
+ restore.reason = VLIB_PROCESS_RESTORE_REASON_CLOCK;
+ restore.runtime_index = e.index;
+ vec_add1 (nm->process_restore_current, restore);
+ }
+ else if (e.type == VLIB_TW_EVENT_T_SCHED_NODE)
+ {
+ vec_add1 (nm->sched_node_pending, e.index);
+ }
+ else
+ ASSERT (0);
+ }
+}
+
+static void
+vlib_tw_init (vlib_main_t *vm)
+{
+ TWT (tw_timer_wheel) *tw = (TWT (tw_timer_wheel) *) vm->timing_wheel;
+ tw = clib_mem_alloc_aligned (sizeof (TWT (tw_timer_wheel)),
+ CLIB_CACHE_LINE_BYTES);
+ /* Create the process timing wheel */
+ TW (tw_timer_wheel_init)
+ (tw, process_expired_timer_cb /* callback */, 1 / VLIB_TW_TICKS_PER_SECOND,
+ ~0 /* max expirations per call */);
+ vm->timing_wheel = tw;
+}
+
+static void
+vlib_tw_expire_timers (vlib_main_t *vm)
+{
+ TWT (tw_timer_wheel) *tw = (TWT (tw_timer_wheel) *) vm->timing_wheel;
+ TW (tw_timer_expire_timers) (tw, vlib_time_now (vm));
+}
+
static_always_inline void
vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
{
@@ -1548,58 +1595,59 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
clib_call_callbacks (vm->worker_thread_main_loop_callbacks, vm,
cpu_time_now);
- /* Process pre-input nodes. */
cpu_time_now = clib_cpu_time_now ();
- vec_foreach (n, nm->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT])
- cpu_time_now = dispatch_node (vm, n,
- VLIB_NODE_TYPE_PRE_INPUT,
- VLIB_NODE_STATE_POLLING,
- /* frame */ 0,
- cpu_time_now);
-
- if (clib_interrupt_is_any_pending (nm->pre_input_node_interrupts))
- {
- int int_num = -1;
- while ((int_num = clib_interrupt_get_next_and_clear (
- nm->pre_input_node_interrupts, int_num)) != -1)
+ for (vlib_node_type_t nt = 0; nt < VLIB_N_NODE_TYPE; nt++)
+ {
+ if (node_type_attrs[nt].can_be_polled)
+ vec_foreach (n, nm->nodes_by_type[nt])
+ if (n->state == VLIB_NODE_STATE_POLLING)
+ cpu_time_now = dispatch_node (
+ vm, n, nt,
+ /* frame */ 0, VLIB_NODE_DISPATCH_REASON_POLL, cpu_time_now);
+
+ if (node_type_attrs[nt].may_receive_interrupts &&
+ nm->node_interrupts[nt] &&
+ clib_interrupt_is_any_pending (nm->node_interrupts[nt]))
{
- vlib_node_runtime_t *n;
- n = vec_elt_at_index (
- nm->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT], int_num);
- cpu_time_now = dispatch_node (vm, n, VLIB_NODE_TYPE_PRE_INPUT,
- VLIB_NODE_STATE_INTERRUPT,
- /* frame */ 0, cpu_time_now);
+ int int_num = -1;
+
+ while ((int_num = clib_interrupt_get_next_and_clear (
+ nm->node_interrupts[nt], int_num)) != -1)
+ {
+ vlib_node_runtime_t *n;
+ n = vec_elt_at_index (nm->nodes_by_type[nt], int_num);
+ cpu_time_now = dispatch_node (
+ vm, n, nt,
+ /* frame */ 0, VLIB_NODE_DISPATCH_REASON_INTERRUPT,
+ cpu_time_now);
+ }
}
}
- /* Next process input nodes. */
- vec_foreach (n, nm->nodes_by_type[VLIB_NODE_TYPE_INPUT])
- cpu_time_now = dispatch_node (vm, n,
- VLIB_NODE_TYPE_INPUT,
- VLIB_NODE_STATE_POLLING,
- /* frame */ 0,
- cpu_time_now);
-
- if (PREDICT_TRUE (is_main && vm->queue_signal_pending == 0))
- vm->queue_signal_callback (vm);
-
- if (clib_interrupt_is_any_pending (nm->input_node_interrupts))
+ /* Process sched nodes. */
+ if (vec_len (nm->sched_node_pending))
{
- int int_num = -1;
-
- while ((int_num = clib_interrupt_get_next_and_clear (
- nm->input_node_interrupts, int_num)) != -1)
+ vec_foreach_index (i, nm->sched_node_pending)
{
- vlib_node_runtime_t *n;
- n = vec_elt_at_index (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT],
- int_num);
- cpu_time_now = dispatch_node (vm, n, VLIB_NODE_TYPE_INPUT,
- VLIB_NODE_STATE_INTERRUPT,
- /* frame */ 0, cpu_time_now);
+ vlib_node_t *n = vlib_get_node (vm, nm->sched_node_pending[i]);
+ if (n->type == VLIB_NODE_TYPE_SCHED)
+ {
+ vlib_node_runtime_t *nr =
+ vlib_node_get_runtime (vm, n->index);
+ nr->stop_timer_handle_plus_1 = 0;
+ cpu_time_now = dispatch_node (
+ vm, nr, VLIB_NODE_TYPE_SCHED,
+ /* frame */ 0, VLIB_NODE_DISPATCH_REASON_SCHED,
+ cpu_time_now);
+ }
}
+ vec_reset_length (nm->sched_node_pending);
}
+ if (PREDICT_TRUE (is_main && vm->queue_signal_pending == 0))
+ vm->queue_signal_callback (vm);
+
/* Input nodes may have added work to the pending vector.
Process pending vector until there is nothing left.
All pending vectors will be processed from input -> output. */
@@ -1632,8 +1680,7 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
if (PREDICT_FALSE (vm->elog_trace_graph_dispatch))
ed = ELOG_DATA (&vlib_global_main.elog_main, es);
- TW (tw_timer_expire_timers)
- ((TWT (tw_timer_wheel) *) nm->timing_wheel, vlib_time_now (vm));
+ vlib_tw_expire_timers (vm);
ASSERT (nm->process_restore_current != 0);
@@ -1664,7 +1711,7 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
p->stop_timer_handle = ~0;
void *data;
data = vlib_process_signal_event_helper (
- nm, n, p, te->event_type_index, te->n_data_elts,
+ vm, nm, n, p, te->event_type_index, te->n_data_elts,
te->n_data_elt_bytes);
if (te->n_data_bytes < sizeof (te->inline_event_data))
clib_memcpy_fast (data, te->inline_event_data,
@@ -1691,6 +1738,9 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
nm->process_restore_next);
}
}
+ else
+ vlib_tw_expire_timers (vm);
+
vlib_increment_main_loop_counter (vm);
/* Record time stamp in case there are no enabled nodes and above
calls do not update time stamp. */
@@ -1725,18 +1775,6 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
}
}
-static void
-vlib_main_loop (vlib_main_t * vm)
-{
- vlib_main_or_worker_loop (vm, /* is_main */ 1);
-}
-
-void
-vlib_worker_loop (vlib_main_t * vm)
-{
- vlib_main_or_worker_loop (vm, /* is_main */ 0);
-}
-
vlib_global_main_t vlib_global_main;
void
@@ -1862,34 +1900,6 @@ vl_api_get_elog_trace_api_messages (void)
return 0;
}
-static void
-process_expired_timer_cb (u32 *expired_timer_handles)
-{
- vlib_main_t *vm = vlib_get_main ();
- vlib_node_main_t *nm = &vm->node_main;
- u32 *handle;
-
- vec_foreach (handle, expired_timer_handles)
- {
- u32 index = vlib_timing_wheel_data_get_index (*handle);
- vlib_process_restore_t restore = {};
-
- if (vlib_timing_wheel_data_is_timed_event (*handle))
- {
- restore.reason = VLIB_PROCESS_RESTORE_REASON_TIMED_EVENT;
- restore.timed_event_data_pool_index = index;
- }
- else
- {
- vlib_process_t *p = vec_elt (nm->processes, index);
- p->stop_timer_handle = ~0;
- restore.reason = VLIB_PROCESS_RESTORE_REASON_CLOCK;
- restore.runtime_index = index;
- }
- vec_add1 (nm->process_restore_current, restore);
- }
-}
-
/* Main function. */
int
vlib_main (vlib_main_t * volatile vm, unformat_input_t * input)
@@ -1988,20 +1998,13 @@ vlib_main (vlib_main_t * volatile vm, unformat_input_t * input)
if ((error = vlib_call_all_init_functions (vm)))
goto done;
- nm->timing_wheel = clib_mem_alloc_aligned (sizeof (TWT (tw_timer_wheel)),
- CLIB_CACHE_LINE_BYTES);
+ vlib_tw_init (vm);
vec_validate (nm->process_restore_current, 10);
vec_validate (nm->process_restore_next, 10);
vec_set_len (nm->process_restore_current, 0);
vec_set_len (nm->process_restore_next, 0);
- /* Create the process timing wheel */
- TW (tw_timer_wheel_init)
- ((TWT (tw_timer_wheel) *) nm->timing_wheel,
- process_expired_timer_cb /* callback */, 10e-6 /* timer period 10us */,
- ~0 /* max expirations per call */);
-
vec_validate (vm->pending_rpc_requests, 0);
vec_set_len (vm->pending_rpc_requests, 0);
vec_validate (vm->processing_rpc_requests, 0);
@@ -2052,7 +2055,7 @@ vlib_main (vlib_main_t * volatile vm, unformat_input_t * input)
goto done;
}
- vlib_main_loop (vm);
+ vlib_main_or_worker_loop (vm, /* is_main */ 1);
done:
/* Stop worker threads, barrier will not be released */
@@ -2072,6 +2075,38 @@ done:
return vm->main_loop_exit_status;
}
+static 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_main_t *vm = vlib_get_main ();
+ clib_error_t *e;
+
+ ASSERT (vm->thread_index == vlib_get_thread_index ());
+
+ vlib_worker_thread_init (w);
+ clib_time_init (&vm->clib_time);
+ clib_mem_set_heap (w->thread_mheap);
+ vlib_tw_init (vm);
+
+ 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);
+
+ vlib_main_or_worker_loop (vm, /* is_main */ 0);
+}
+
+VLIB_REGISTER_THREAD (worker_thread_reg, static) = {
+ .name = "workers",
+ .short_name = "wk",
+ .function = vlib_worker_thread_fn,
+};
+
vlib_main_t *
vlib_get_main_not_inline (void)
{
diff --git a/src/vlib/main.h b/src/vlib/main.h
index 94b8c4fa954..907346beda2 100644
--- a/src/vlib/main.h
+++ b/src/vlib/main.h
@@ -258,6 +258,9 @@ typedef struct vlib_main_t
u32 buffer_alloc_success_seed;
f64 buffer_alloc_success_rate;
+ /* Timing wheel for scheduling time-based node dispatch. */
+ void *timing_wheel;
+
#ifdef CLIB_SANITIZE_ADDR
/* address sanitizer stack save */
void *asan_stack_save;
@@ -319,8 +322,6 @@ typedef struct vlib_global_main_t
/* Global main structure. */
extern vlib_global_main_t vlib_global_main;
-void vlib_worker_loop (vlib_main_t * vm);
-
always_inline f64
vlib_time_now (vlib_main_t * vm)
{
diff --git a/src/vlib/node.c b/src/vlib/node.c
index c0572f3cf83..edeb6dc70a7 100644
--- a/src/vlib/node.c
+++ b/src/vlib/node.c
@@ -518,7 +518,7 @@ vlib_register_node (vlib_main_t *vm, vlib_node_registration_t *r, char *fmt,
vlib_node_runtime_t *rt;
u32 i;
- if (n->type == VLIB_NODE_TYPE_PROCESS)
+ if (node_type_attrs[n->type].is_process)
{
vlib_process_t *p;
uword log2_n_stack_bytes;
@@ -559,15 +559,14 @@ vlib_register_node (vlib_main_t *vm, vlib_node_registration_t *r, char *fmt,
{
vec_add2_aligned (nm->nodes_by_type[n->type], rt, 1,
/* align */ CLIB_CACHE_LINE_BYTES);
- if (n->type == VLIB_NODE_TYPE_INPUT)
- clib_interrupt_resize (&nm->input_node_interrupts,
- vec_len (nm->nodes_by_type[n->type]));
- else if (n->type == VLIB_NODE_TYPE_PRE_INPUT)
- clib_interrupt_resize (&nm->pre_input_node_interrupts,
- vec_len (nm->nodes_by_type[n->type]));
+
n->runtime_index = rt - nm->nodes_by_type[n->type];
}
+ if (node_type_attrs[n->type].may_receive_interrupts)
+ clib_interrupt_resize (&nm->node_interrupts[n->type],
+ vec_len (nm->nodes_by_type[n->type]));
+
if (n->type == VLIB_NODE_TYPE_INPUT)
nm->input_node_counts_by_state[n->state] += 1;
diff --git a/src/vlib/node.h b/src/vlib/node.h
index bb6d8f818a8..22d5a4843d7 100644
--- a/src/vlib/node.h
+++ b/src/vlib/node.h
@@ -83,9 +83,46 @@ typedef enum
/* "Process" nodes which can be suspended and later resumed. */
VLIB_NODE_TYPE_PROCESS,
+ /* Nodes to by called by per-thread timing wheel. */
+ VLIB_NODE_TYPE_SCHED,
+
VLIB_N_NODE_TYPE,
} vlib_node_type_t;
+typedef struct
+{
+ u8 can_be_disabled : 1;
+ u8 may_receive_interrupts : 1;
+ u8 decrement_main_loop_per_calls_if_polling : 1;
+ u8 supports_adaptive_mode : 1;
+ u8 can_be_polled : 1;
+ u8 is_process : 1;
+} vlib_node_type_atts_t;
+
+static const vlib_node_type_atts_t node_type_attrs[VLIB_N_NODE_TYPE] ={
+ [VLIB_NODE_TYPE_PRE_INPUT] = {
+ .can_be_disabled = 1,
+ .may_receive_interrupts = 1,
+ .decrement_main_loop_per_calls_if_polling = 1,
+ .can_be_polled = 1,
+ },
+ [VLIB_NODE_TYPE_INPUT] = {
+ .can_be_disabled = 1,
+ .may_receive_interrupts = 1,
+ .decrement_main_loop_per_calls_if_polling = 1,
+ .supports_adaptive_mode = 1,
+ .can_be_polled = 1,
+ },
+ [VLIB_NODE_TYPE_PROCESS] = {
+ .can_be_disabled = 1,
+ .is_process = 1,
+ },
+ [VLIB_NODE_TYPE_SCHED] = {
+ .can_be_disabled = 1,
+ .may_receive_interrupts = 1,
+ },
+};
+
typedef struct _vlib_node_fn_registration
{
vlib_node_function_t *function;
@@ -245,7 +282,16 @@ typedef enum
foreach_vlib_node_state
#undef _
VLIB_N_NODE_STATE,
-} vlib_node_state_t;
+} __clib_packed vlib_node_state_t;
+
+typedef enum
+{
+ VLIB_NODE_DISPATCH_REASON_UNKNOWN = 0,
+ VLIB_NODE_DISPATCH_REASON_PENDING_FRAME,
+ VLIB_NODE_DISPATCH_REASON_POLL,
+ VLIB_NODE_DISPATCH_REASON_INTERRUPT,
+ VLIB_NODE_DISPATCH_REASON_SCHED,
+} __clib_packed vlib_node_dispatch_reason_t;
typedef struct vlib_node_t
{
@@ -498,7 +544,10 @@ typedef struct vlib_node_runtime_t
u16 flags; /**< Copy of main node flags. */
- u16 state; /**< Input node state. */
+ vlib_node_state_t state; /**< Input node state. */
+
+ vlib_node_dispatch_reason_t
+ dispatch_reason; /**< Reason for running this node. */
u16 n_next_nodes;
@@ -507,6 +556,9 @@ typedef struct vlib_node_runtime_t
last time this node ran. Set to
zero before first run of this
node. */
+ u32 stop_timer_handle_plus_1; /**< Timing wheel stop handle for
+ SCHED node incremented by 1,
+ 0 = no timer running. */
CLIB_ALIGN_MARK (runtime_data_pad, 8);
@@ -679,29 +731,22 @@ typedef struct
}
vlib_signal_timed_event_data_t;
-always_inline uword
-vlib_timing_wheel_data_is_timed_event (u32 d)
-{
- return d & 1;
-}
-
-always_inline u32
-vlib_timing_wheel_data_set_suspended_process (u32 i)
-{
- return 0 + 2 * i;
-}
-
-always_inline u32
-vlib_timing_wheel_data_set_timed_event (u32 i)
+typedef enum
{
- return 1 + 2 * i;
-}
+ VLIB_TW_EVENT_T_PROCESS_NODE = 1,
+ VLIB_TW_EVENT_T_TIMED_EVENT = 2,
+ VLIB_TW_EVENT_T_SCHED_NODE = 3,
+} vlib_tw_event_type_t;
-always_inline uword
-vlib_timing_wheel_data_get_index (u32 d)
+typedef union
{
- return d / 2;
-}
+ struct
+ {
+ u32 type : 2; /* vlib_tw_event_type_t */
+ u32 index : 30;
+ };
+ u32 as_u32;
+} vlib_tw_event_t;
typedef struct
{
@@ -727,8 +772,7 @@ typedef struct
vlib_node_runtime_t *nodes_by_type[VLIB_N_NODE_TYPE];
/* Node runtime indices for input nodes with pending interrupts. */
- void *input_node_interrupts;
- void *pre_input_node_interrupts;
+ void *node_interrupts[VLIB_N_NODE_TYPE];
/* Input nodes are switched from/to interrupt to/from polling mode
when average vector length goes above/below polling/interrupt
@@ -742,14 +786,14 @@ typedef struct
/* Vector of internal node's frames waiting to be called. */
vlib_pending_frame_t *pending_frames;
- /* Timing wheel for scheduling time-based node dispatch. */
- void *timing_wheel;
-
vlib_signal_timed_event_data_t *signal_timed_event_data_pool;
/* Vector of process nodes waiting for restore */
vlib_process_restore_t *process_restore_current;
+ /* Vector of sched nodes waiting to be calleed */
+ u32 *sched_node_pending;
+
/* Vector of process nodes waiting for restore in next greaph scheduler run
*/
vlib_process_restore_t *process_restore_next;
diff --git a/src/vlib/node_cli.c b/src/vlib/node_cli.c
index 16e904e8433..375b17bd7ae 100644
--- a/src/vlib/node_cli.c
+++ b/src/vlib/node_cli.c
@@ -734,6 +734,9 @@ show_node (vlib_main_t * vm, unformat_input_t * input,
case VLIB_NODE_TYPE_PROCESS:
type_str = "process";
break;
+ case VLIB_NODE_TYPE_SCHED:
+ type_str = "sched";
+ break;
default:
type_str = "unknown";
}
diff --git a/src/vlib/node_funcs.h b/src/vlib/node_funcs.h
index ffa17ba7bb1..91fedaa4c9c 100644
--- a/src/vlib/node_funcs.h
+++ b/src/vlib/node_funcs.h
@@ -50,6 +50,8 @@
#include <vppinfra/tw_timer_1t_3w_1024sl_ov.h>
#include <vppinfra/interrupt.h>
+#define VLIB_TW_TICKS_PER_SECOND 1e5 /* 10 us */
+
#ifdef CLIB_SANITIZE_ADDR
#include <sanitizer/asan_interface.h>
#endif
@@ -249,17 +251,9 @@ vlib_node_set_interrupt_pending (vlib_main_t *vm, u32 node_index)
{
vlib_node_main_t *nm = &vm->node_main;
vlib_node_t *n = vec_elt (nm->nodes, node_index);
- void *interrupts = 0;
+ void *interrupts = nm->node_interrupts[n->type];
- if (n->type == VLIB_NODE_TYPE_INPUT)
- interrupts = nm->input_node_interrupts;
- else if (n->type == VLIB_NODE_TYPE_PRE_INPUT)
- interrupts = nm->pre_input_node_interrupts;
- else
- {
- ASSERT (0);
- return;
- }
+ ASSERT (interrupts);
if (vm != vlib_get_main ())
clib_interrupt_set_atomic (interrupts, n->runtime_index);
@@ -267,6 +261,25 @@ vlib_node_set_interrupt_pending (vlib_main_t *vm, u32 node_index)
clib_interrupt_set (interrupts, n->runtime_index);
}
+always_inline void
+vlib_node_schedule (vlib_main_t *vm, u32 node_index, f64 dt)
+{
+ TWT (tw_timer_wheel) *tw = (TWT (tw_timer_wheel) *) vm->timing_wheel;
+ u64 ticks;
+
+ vlib_node_runtime_t *rt = vlib_node_get_runtime (vm, node_index);
+ vlib_tw_event_t e = {
+ .type = VLIB_TW_EVENT_T_SCHED_NODE,
+ .index = node_index,
+ };
+
+ dt = flt_round_nearest (dt * VLIB_TW_TICKS_PER_SECOND);
+ ticks = clib_max ((u64) dt, 1);
+
+ rt->stop_timer_handle_plus_1 =
+ 1 + TW (tw_timer_start) (tw, e.as_u32, 0 /* timer_id */, ticks);
+}
+
always_inline vlib_process_t *
vlib_get_process_from_node (vlib_main_t * vm, vlib_node_t * node)
{
@@ -570,14 +583,14 @@ vlib_get_current_process_node_index (vlib_main_t * vm)
return process->node_runtime.node_index;
}
-/** Returns TRUE if a process suspend time is less than 10us
+/** Returns TRUE if a process suspend time is less than vlib timer wheel tick
@param dt - remaining poll time in seconds
- @returns 1 if dt < 10e-6, 0 otherwise
+ @returns 1 if dt < 1/VLIB_TW_TICKS_PER_SECOND, 0 otherwise
*/
always_inline uword
vlib_process_suspend_time_is_zero (f64 dt)
{
- return dt < 10e-6;
+ return dt < (1 / VLIB_TW_TICKS_PER_SECOND);
}
/** Suspend a vlib cooperative multi-tasking thread for a period of time
@@ -601,7 +614,7 @@ vlib_process_suspend (vlib_main_t * vm, f64 dt)
if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
{
/* expiration time in 10us ticks */
- p->resume_clock_interval = dt * 1e5;
+ p->resume_clock_interval = dt * VLIB_TW_TICKS_PER_SECOND;
vlib_process_start_switch_stack (vm, 0);
clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
}
@@ -912,7 +925,7 @@ vlib_process_wait_for_event_or_clock (vlib_main_t * vm, f64 dt)
r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND);
if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
{
- p->resume_clock_interval = dt * 1e5;
+ p->resume_clock_interval = dt * VLIB_TW_TICKS_PER_SECOND;
vlib_process_start_switch_stack (vm, 0);
clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
}
@@ -963,12 +976,11 @@ vlib_process_delete_one_time_event (vlib_main_t * vm, uword node_index,
}
always_inline void *
-vlib_process_signal_event_helper (vlib_node_main_t * nm,
- vlib_node_t * n,
- vlib_process_t * p,
- uword t,
+vlib_process_signal_event_helper (vlib_main_t *vm, vlib_node_main_t *nm,
+ vlib_node_t *n, vlib_process_t *p, uword t,
uword n_data_elts, uword n_data_elt_bytes)
{
+ TWT (tw_timer_wheel) *tw = (TWT (tw_timer_wheel) *) vm->timing_wheel;
uword add_to_pending = 0, delete_from_wheel = 0;
u8 *data_to_be_written_by_caller;
vec_attr_t va = { .elt_sz = n_data_elt_bytes };
@@ -1016,8 +1028,7 @@ vlib_process_signal_event_helper (vlib_node_main_t * nm,
break;
}
- if (TW (tw_timer_handle_is_free) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
- p->stop_timer_handle))
+ if (TW (tw_timer_handle_is_free) (tw, p->stop_timer_handle))
delete_from_wheel = 0;
/* Never add current process to pending vector since current process is
@@ -1036,8 +1047,7 @@ vlib_process_signal_event_helper (vlib_node_main_t * nm,
if (delete_from_wheel)
{
- TW (tw_timer_stop)
- ((TWT (tw_timer_wheel) *) nm->timing_wheel, p->stop_timer_handle);
+ TW (tw_timer_stop) (tw, p->stop_timer_handle);
p->stop_timer_handle = ~0;
}
@@ -1069,7 +1079,7 @@ vlib_process_signal_event_data (vlib_main_t * vm,
else
t = h[0];
- return vlib_process_signal_event_helper (nm, n, p, t, n_data_elts,
+ return vlib_process_signal_event_helper (vm, nm, n, p, t, n_data_elts,
n_data_elt_bytes);
}
@@ -1080,6 +1090,7 @@ vlib_process_signal_event_at_time (vlib_main_t * vm,
uword type_opaque,
uword n_data_elts, uword n_data_elt_bytes)
{
+ TWT (tw_timer_wheel) *tw = (TWT (tw_timer_wheel) *) vm->timing_wheel;
vlib_node_main_t *nm = &vm->node_main;
vlib_node_t *n = vlib_get_node (vm, node_index);
vlib_process_t *p = vec_elt (nm->processes, n->runtime_index);
@@ -1097,7 +1108,7 @@ vlib_process_signal_event_at_time (vlib_main_t * vm,
t = h[0];
if (vlib_process_suspend_time_is_zero (dt))
- return vlib_process_signal_event_helper (nm, n, p, t, n_data_elts,
+ return vlib_process_signal_event_helper (vm, nm, n, p, t, n_data_elts,
n_data_elt_bytes);
else
{
@@ -1118,11 +1129,13 @@ vlib_process_signal_event_at_time (vlib_main_t * vm,
te->event_type_index = t;
p->stop_timer_handle =
- TW (tw_timer_start) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
- vlib_timing_wheel_data_set_timed_event
- (te - nm->signal_timed_event_data_pool),
- 0 /* timer_id */ ,
- (vlib_time_now (vm) + dt) * 1e5);
+ TW (tw_timer_start) (tw,
+ (vlib_tw_event_t){
+ .type = VLIB_TW_EVENT_T_TIMED_EVENT,
+ .index = te - nm->signal_timed_event_data_pool,
+ }
+ .as_u32,
+ 0 /* timer_id */, dt * VLIB_TW_TICKS_PER_SECOND);
/* Inline data big enough to hold event? */
if (te->n_data_bytes < sizeof (te->inline_event_data))
@@ -1146,8 +1159,8 @@ vlib_process_signal_one_time_event_data (vlib_main_t * vm,
vlib_node_main_t *nm = &vm->node_main;
vlib_node_t *n = vlib_get_node (vm, node_index);
vlib_process_t *p = vec_elt (nm->processes, n->runtime_index);
- return vlib_process_signal_event_helper (nm, n, p, type_index, n_data_elts,
- n_data_elt_bytes);
+ return vlib_process_signal_event_helper (vm, nm, n, p, type_index,
+ n_data_elts, n_data_elt_bytes);
}
always_inline void
diff --git a/src/vlib/threads.c b/src/vlib/threads.c
index 9dce1b8c8bd..0a5779c2d2e 100644
--- a/src/vlib/threads.c
+++ b/src/vlib/threads.c
@@ -705,52 +705,29 @@ start_workers (vlib_main_t * vm)
vec_add1 (nm_clone->nodes, n);
n++;
}
- nm_clone->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])
- {
- vlib_node_t *n = vlib_get_node (vm, rt->node_index);
- /* copy initial runtime_data from node */
- if (n->runtime_data && n->runtime_data_bytes > 0)
- clib_memcpy (rt->runtime_data, n->runtime_data,
- clib_min (VLIB_NODE_RUNTIME_DATA_SIZE,
- n->runtime_data_bytes));
- }
-
- nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT] =
- vec_dup_aligned (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT],
- CLIB_CACHE_LINE_BYTES);
- clib_interrupt_init (
- &nm_clone->input_node_interrupts,
- vec_len (nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]));
- clib_interrupt_init (
- &nm_clone->pre_input_node_interrupts,
- vec_len (nm_clone->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT]));
- vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT])
- {
- vlib_node_t *n = vlib_get_node (vm, rt->node_index);
- /* copy initial runtime_data from node */
- if (n->runtime_data && n->runtime_data_bytes > 0)
- clib_memcpy (rt->runtime_data, n->runtime_data,
- clib_min (VLIB_NODE_RUNTIME_DATA_SIZE,
- n->runtime_data_bytes));
- }
-
- nm_clone->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT] =
- vec_dup_aligned (nm->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT],
- CLIB_CACHE_LINE_BYTES);
- vec_foreach (rt,
- nm_clone->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT])
- {
- vlib_node_t *n = vlib_get_node (vm, rt->node_index);
- /* copy initial runtime_data from node */
- if (n->runtime_data && n->runtime_data_bytes > 0)
- clib_memcpy (rt->runtime_data, n->runtime_data,
- clib_min (VLIB_NODE_RUNTIME_DATA_SIZE,
- n->runtime_data_bytes));
- }
+
+ foreach_int (nt, VLIB_NODE_TYPE_INTERNAL,
+ VLIB_NODE_TYPE_PRE_INPUT, VLIB_NODE_TYPE_INPUT,
+ VLIB_NODE_TYPE_SCHED)
+ {
+ u32 n_nodes = vec_len (nm_clone->nodes_by_type[nt]);
+ nm_clone->nodes_by_type[nt] = vec_dup_aligned (
+ nm->nodes_by_type[nt], CLIB_CACHE_LINE_BYTES);
+
+ if (node_type_attrs[nt].may_receive_interrupts)
+ clib_interrupt_init (&nm_clone->node_interrupts[nt],
+ n_nodes);
+
+ vec_foreach (rt, nm_clone->nodes_by_type[nt])
+ {
+ vlib_node_t *n = vlib_get_node (vm, rt->node_index);
+ /* copy initial runtime_data from node */
+ if (n->runtime_data && n->runtime_data_bytes > 0)
+ clib_memcpy (rt->runtime_data, n->runtime_data,
+ clib_min (VLIB_NODE_RUNTIME_DATA_SIZE,
+ n->runtime_data_bytes));
+ }
+ }
nm_clone->processes = vec_dup_aligned (nm->processes,
CLIB_CACHE_LINE_BYTES);
@@ -1016,101 +993,53 @@ vlib_worker_thread_node_refork (void)
vec_free (old_nodes_clone);
+ /* re-clone nodes */
- /* 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_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])
- {
- vlib_node_t *n = vlib_get_node (vm, rt->node_index);
- /* copy runtime_data, will be overwritten later for existing rt */
- if (n->runtime_data && n->runtime_data_bytes > 0)
- clib_memcpy_fast (rt->runtime_data, n->runtime_data,
- clib_min (VLIB_NODE_RUNTIME_DATA_SIZE,
- n->runtime_data_bytes));
- }
-
- for (j = 0; j < vec_len (old_rt); j++)
+ foreach_int (nt, VLIB_NODE_TYPE_INTERNAL, VLIB_NODE_TYPE_PRE_INPUT,
+ VLIB_NODE_TYPE_INPUT, VLIB_NODE_TYPE_SCHED)
{
- 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);
- }
+ old_rt = nm_clone->nodes_by_type[nt];
+ u32 n_nodes = vec_len (nm->nodes_by_type[nt]);
- vec_free (old_rt);
-
- /* 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_aligned (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT],
- CLIB_CACHE_LINE_BYTES);
- clib_interrupt_resize (
- &nm_clone->input_node_interrupts,
- vec_len (nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]));
- clib_interrupt_resize (
- &nm_clone->pre_input_node_interrupts,
- vec_len (nm_clone->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT]));
-
- vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT])
- {
- vlib_node_t *n = vlib_get_node (vm, rt->node_index);
- /* copy runtime_data, will be overwritten later for existing rt */
- if (n->runtime_data && n->runtime_data_bytes > 0)
- clib_memcpy_fast (rt->runtime_data, n->runtime_data,
- clib_min (VLIB_NODE_RUNTIME_DATA_SIZE,
- n->runtime_data_bytes));
- }
+ nm_clone->nodes_by_type[nt] =
+ vec_dup_aligned (nm->nodes_by_type[nt], CLIB_CACHE_LINE_BYTES);
- for (j = 0; j < vec_len (old_rt); j++)
- {
- 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);
- }
+ if (nm_clone->node_interrupts[nt])
+ clib_interrupt_resize (&nm_clone->node_interrupts[nt], n_nodes);
- for (j = vec_len (old_rt);
- j < vec_len (nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]); j++)
- {
- rt = &nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT][j];
- nm_clone->input_node_counts_by_state[rt->state] += 1;
- }
-
- vec_free (old_rt);
+ vec_foreach (rt, nm_clone->nodes_by_type[nt])
+ {
+ vlib_node_t *n = vlib_get_node (vm, rt->node_index);
+ /* copy runtime_data, will be overwritten later for existing rt */
+ if (n->runtime_data && n->runtime_data_bytes > 0)
+ clib_memcpy_fast (
+ rt->runtime_data, n->runtime_data,
+ clib_min (VLIB_NODE_RUNTIME_DATA_SIZE, n->runtime_data_bytes));
+ }
- /* re-clone pre-input nodes */
- old_rt = nm_clone->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT];
- nm_clone->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT] =
- vec_dup_aligned (nm->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT],
- CLIB_CACHE_LINE_BYTES);
+ for (j = 0; j < vec_len (old_rt); j++)
+ {
+ 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);
+ }
- vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT])
- {
- vlib_node_t *n = vlib_get_node (vm, rt->node_index);
- /* copy runtime_data, will be overwritten later for existing rt */
- if (n->runtime_data && n->runtime_data_bytes > 0)
- clib_memcpy_fast (rt->runtime_data, n->runtime_data,
- clib_min (VLIB_NODE_RUNTIME_DATA_SIZE,
- n->runtime_data_bytes));
- }
+ if (nt == VLIB_NODE_TYPE_INPUT)
+ {
+ for (j = vec_len (old_rt);
+ j < vec_len (nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT]);
+ j++)
+ {
+ rt = &nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT][j];
+ nm_clone->input_node_counts_by_state[rt->state] += 1;
+ }
+ }
- for (j = 0; j < vec_len (old_rt); j++)
- {
- 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);
+ vec_free (old_rt);
}
- vec_free (old_rt);
-
vec_free (nm_clone->processes);
nm_clone->processes = vec_dup_aligned (nm->processes,
CLIB_CACHE_LINE_BYTES);
@@ -1630,37 +1559,6 @@ vlib_worker_flush_pending_rpc_requests (vlib_main_t *vm)
clib_spinlock_unlock_if_init (&vm_global->pending_rpc_lock);
}
-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_main_t *vm = vlib_get_main ();
- clib_error_t *e;
-
- ASSERT (vm->thread_index == vlib_get_thread_index ());
-
- vlib_worker_thread_init (w);
- clib_time_init (&vm->clib_time);
- clib_mem_set_heap (w->thread_mheap);
-
- 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);
-
- vlib_worker_loop (vm);
-}
-
-VLIB_REGISTER_THREAD (worker_thread_reg, static) = {
- .name = "workers",
- .short_name = "wk",
- .function = vlib_worker_thread_fn,
-};
-
extern clib_march_fn_registration
*vlib_frame_queue_dequeue_with_aux_fn_march_fn_registrations;
extern clib_march_fn_registration
diff --git a/src/vlib/time.h b/src/vlib/time.h
index 61873bb2ef3..a9dc5395661 100644
--- a/src/vlib/time.h
+++ b/src/vlib/time.h
@@ -12,8 +12,7 @@
static inline f64
vlib_time_get_next_timer (vlib_main_t *vm)
{
- vlib_node_main_t *nm = &vm->node_main;
- TWT (tw_timer_wheel) *wheel = nm->timing_wheel;
+ TWT (tw_timer_wheel) *wheel = vm->timing_wheel;
return TW (tw_timer_first_expires_in_ticks) (wheel) * wheel->timer_interval;
}
diff --git a/src/vlib/unix/input.c b/src/vlib/unix/input.c
index e96cd902466..302d1eb1194 100644
--- a/src/vlib/unix/input.c
+++ b/src/vlib/unix/input.c
@@ -130,6 +130,17 @@ linux_epoll_file_update (clib_file_t * f, clib_file_update_type_t update_type)
}
}
+static int
+is_int_pending (vlib_node_main_t *nm)
+{
+
+ for (int nt = 0; nt < VLIB_N_NODE_TYPE; nt++)
+ if (nm->node_interrupts[nt] &&
+ clib_interrupt_is_any_pending (nm->node_interrupts[nt]))
+ return 1;
+ return 0;
+}
+
static_always_inline uword
linux_epoll_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * frame, u32 thread_index)
@@ -174,8 +185,8 @@ linux_epoll_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
else if (is_main && vector_rate < 2 && vm->api_queue_nonempty == 0
&& nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] == 0)
{
- ticks_until_expiration = TW (tw_timer_first_expires_in_ticks)
- ((TWT (tw_timer_wheel) *) nm->timing_wheel);
+ ticks_until_expiration = TW (tw_timer_first_expires_in_ticks) (
+ (TWT (tw_timer_wheel) *) vm->timing_wheel);
/* Nothing on the fast wheel, sleep 10ms */
if (ticks_until_expiration == TW_SLOTS_PER_RING)
@@ -250,10 +261,7 @@ linux_epoll_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
while (nanosleep (&ts, &tsrem) < 0)
ts = tsrem;
if (*vlib_worker_threads->wait_at_barrier ||
- clib_interrupt_is_any_pending (
- nm->input_node_interrupts) ||
- clib_interrupt_is_any_pending (
- nm->pre_input_node_interrupts))
+ is_int_pending (nm))
goto done;
}
}