d[0] = data;
}
+/**
+ * Signal event to process from any thread.
+ *
+ * When in doubt, use this.
+ */
+always_inline void
+vlib_process_signal_event_mt (vlib_main_t * vm,
+ uword node_index, uword type_opaque, uword data)
+{
+ if (vlib_get_thread_index () != 0)
+ {
+ vlib_process_signal_event_mt_args_t args = {
+ .node_index = node_index,
+ .type_opaque = type_opaque,
+ .data = data,
+ };
+ vlib_rpc_call_main_thread (vlib_process_signal_event_mt_helper,
+ (u8 *) & args, sizeof (args));
+ }
+ else
+ vlib_process_signal_event (vm, node_index, type_opaque, data);
+}
+
always_inline void
vlib_process_signal_one_time_event (vlib_main_t * vm,
uword node_index,
return (fqm - tm->frame_queue_mains);
}
-
int
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)
{
frame_queue_nelt_counter_t *frame_queue_histogram;
} vlib_frame_queue_main_t;
+typedef struct
+{
+ uword node_index;
+ uword type_opaque;
+ uword data;
+} vlib_process_signal_event_mt_args_t;
+
/* Called early, in thread 0's context */
clib_error_t *vlib_thread_init (vlib_main_t * vm);
}
u8 *vlib_thread_stack_init (uword thread_index);
-
int vlib_thread_cb_register (struct vlib_main_t *vm,
vlib_thread_callbacks_t * cb);
+extern void *rpc_call_main_thread_cb_fn;
+
+void
+vlib_process_signal_event_mt_helper (vlib_process_signal_event_mt_args_t *
+ args);
+void vlib_rpc_call_main_thread (void *function, u8 * args, u32 size);
#endif /* included_vlib_threads_h */
#define foreach_plugin_trace_msg \
_(TRACE_PLUGIN_MSG_IDS,trace_plugin_msg_ids)
+/*
+ * Set the rpc callback at our earliest possible convenience.
+ * This avoids ordering issues between thread_init() -> start_workers and
+ * an init function which we could define here. If we ever intend to use
+ * vlib all by itself, we can't create a link-time dependency on
+ * an init function here and a typical "call foo_init first"
+ * guitar lick.
+ */
+
+extern void *rpc_call_main_thread_cb_fn;
+
static clib_error_t *
rpc_api_hookup (vlib_main_t * vm)
{
/* No reason to halt the parade to create a trace record... */
am->is_mp_safe[VL_API_TRACE_PLUGIN_MSG_IDS] = 1;
-
+ rpc_call_main_thread_cb_fn = vl_api_rpc_call_main_thread;
return 0;
}
clib_memcpy (vnet_buffer
(vlib_get_buffer
(vm, bi0_copy))->unused, &nowts, sizeof (nowts));
- vlib_process_signal_event (vm, pr->cli_process_id, event_type, bi0_copy);
+ vlib_process_signal_event_mt (vm, pr->cli_process_id, event_type, bi0_copy);
return 1;
}
i = 1 + ping_repeat;
break;
}
- vec_free(event_data);
+ vec_free (event_data);
}
}
vlib_cli_output (vm, "\n");