提交 43a14cfc 编写于 作者: W Wenchao Xia 提交者: Luiz Capitulino

monitor: add an implemention of qapi event emit method

The monitor is now hooked on the new event mechanism, so that later
patches can convert event callers one by one. Most code are copied from
old monitor_protocol_* functions with some modification.

Note that two build time warnings will be raised after this patch. One is
caused by no caller of monitor_qapi_event_throttle(), the other one is
caused by QAPI_EVENT_MAX = 0. They will be fixed automatically after
full event conversion later.
Signed-off-by: NWenchao Xia <wenchaoqemu@gmail.com>
Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
Reviewed-by: NEric Blake <eblake@redhat.com>
Signed-off-by: NLuiz Capitulino <lcapitulino@redhat.com>
上级 a589569f
...@@ -71,6 +71,8 @@ ...@@ -71,6 +71,8 @@
#include "hmp.h" #include "hmp.h"
#include "qemu/thread.h" #include "qemu/thread.h"
#include "block/qapi.h" #include "block/qapi.h"
#include "qapi/qmp-event.h"
#include "qapi-event.h"
/* for pic/irq_info */ /* for pic/irq_info */
#if defined(TARGET_SPARC) #if defined(TARGET_SPARC)
...@@ -187,6 +189,14 @@ typedef struct MonitorEventState { ...@@ -187,6 +189,14 @@ typedef struct MonitorEventState {
QObject *data; /* Event pending delayed dispatch */ QObject *data; /* Event pending delayed dispatch */
} MonitorEventState; } MonitorEventState;
typedef struct MonitorQAPIEventState {
QAPIEvent event; /* Event being tracked */
int64_t rate; /* Minimum time (in ns) between two events */
int64_t last; /* QEMU_CLOCK_REALTIME value at last emission */
QEMUTimer *timer; /* Timer for handling delayed events */
QObject *data; /* Event pending delayed dispatch */
} MonitorQAPIEventState;
struct Monitor { struct Monitor {
CharDriverState *chr; CharDriverState *chr;
int mux_out; int mux_out;
...@@ -492,6 +502,121 @@ static const char *monitor_event_names[] = { ...@@ -492,6 +502,121 @@ static const char *monitor_event_names[] = {
QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX) QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
static MonitorEventState monitor_event_state[QEVENT_MAX]; static MonitorEventState monitor_event_state[QEVENT_MAX];
static MonitorQAPIEventState monitor_qapi_event_state[QAPI_EVENT_MAX];
/*
* Emits the event to every monitor instance, @event is only used for trace
*/
static void monitor_qapi_event_emit(QAPIEvent event, QObject *data)
{
Monitor *mon;
trace_monitor_protocol_event_emit(event, data);
QLIST_FOREACH(mon, &mon_list, entry) {
if (monitor_ctrl_mode(mon) && qmp_cmd_mode(mon)) {
monitor_json_emitter(mon, data);
}
}
}
/*
* Queue a new event for emission to Monitor instances,
* applying any rate limiting if required.
*/
static void
monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp)
{
MonitorQAPIEventState *evstate;
assert(event < QAPI_EVENT_MAX);
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
evstate = &(monitor_qapi_event_state[event]);
trace_monitor_protocol_event_queue(event,
data,
evstate->rate,
evstate->last,
now);
/* Rate limit of 0 indicates no throttling */
if (!evstate->rate) {
monitor_qapi_event_emit(event, QOBJECT(data));
evstate->last = now;
} else {
int64_t delta = now - evstate->last;
if (evstate->data ||
delta < evstate->rate) {
/* If there's an existing event pending, replace
* it with the new event, otherwise schedule a
* timer for delayed emission
*/
if (evstate->data) {
qobject_decref(evstate->data);
} else {
int64_t then = evstate->last + evstate->rate;
timer_mod_ns(evstate->timer, then);
}
evstate->data = QOBJECT(data);
qobject_incref(evstate->data);
} else {
monitor_qapi_event_emit(event, QOBJECT(data));
evstate->last = now;
}
}
}
/*
* The callback invoked by QemuTimer when a delayed
* event is ready to be emitted
*/
static void monitor_qapi_event_handler(void *opaque)
{
MonitorQAPIEventState *evstate = opaque;
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
trace_monitor_protocol_event_handler(evstate->event,
evstate->data,
evstate->last,
now);
if (evstate->data) {
monitor_qapi_event_emit(evstate->event, evstate->data);
qobject_decref(evstate->data);
evstate->data = NULL;
}
evstate->last = now;
}
/*
* @event: the event ID to be limited
* @rate: the rate limit in milliseconds
*
* Sets a rate limit on a particular event, so no
* more than 1 event will be emitted within @rate
* milliseconds
*/
static void __attribute__((__unused__))
monitor_qapi_event_throttle(QAPIEvent event, int64_t rate)
{
MonitorQAPIEventState *evstate;
assert(event < QAPI_EVENT_MAX);
evstate = &(monitor_qapi_event_state[event]);
trace_monitor_protocol_event_throttle(event, rate);
evstate->event = event;
evstate->rate = rate * SCALE_MS;
evstate->last = 0;
evstate->data = NULL;
evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
SCALE_MS,
monitor_qapi_event_handler,
evstate);
}
static void monitor_qapi_event_init(void)
{
qmp_event_set_func_emit(monitor_qapi_event_queue);
}
/* /*
* Emits the event to every monitor instance * Emits the event to every monitor instance
...@@ -589,7 +714,7 @@ static void monitor_protocol_event_handler(void *opaque) ...@@ -589,7 +714,7 @@ static void monitor_protocol_event_handler(void *opaque)
* more than 1 event will be emitted within @rate * more than 1 event will be emitted within @rate
* milliseconds * milliseconds
*/ */
static void static void __attribute__((__unused__))
monitor_protocol_event_throttle(MonitorEvent event, monitor_protocol_event_throttle(MonitorEvent event,
int64_t rate) int64_t rate)
{ {
...@@ -5358,6 +5483,7 @@ void monitor_init(CharDriverState *chr, int flags) ...@@ -5358,6 +5483,7 @@ void monitor_init(CharDriverState *chr, int flags)
if (is_first_init) { if (is_first_init) {
monitor_protocol_event_init(); monitor_protocol_event_init();
monitor_qapi_event_init();
sortcmdlist(); sortcmdlist();
is_first_init = 0; is_first_init = 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册