diff options
author | Wenchao Xia <wenchaoqemu@gmail.com> | 2014-06-18 08:43:31 +0200 |
---|---|---|
committer | Luiz Capitulino <lcapitulino@redhat.com> | 2014-06-23 11:01:25 -0400 |
commit | 43a14cfc0f122f3a18fdfe9e16538a6798b95b59 (patch) | |
tree | 4579e7db0fa96d9723a70e250a9ba59cfe3e818e /monitor.c | |
parent | a589569f2f40a0454b52398035cfe7fbe44ab1e9 (diff) |
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: Wenchao Xia <wenchaoqemu@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 128 |
1 files changed, 127 insertions, 1 deletions
@@ -71,6 +71,8 @@ #include "hmp.h" #include "qemu/thread.h" #include "block/qapi.h" +#include "qapi/qmp-event.h" +#include "qapi-event.h" /* for pic/irq_info */ #if defined(TARGET_SPARC) @@ -187,6 +189,14 @@ typedef struct MonitorEventState { QObject *data; /* Event pending delayed dispatch */ } 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 { CharDriverState *chr; int mux_out; @@ -492,6 +502,121 @@ static const char *monitor_event_names[] = { QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != 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 @@ -589,7 +714,7 @@ static void monitor_protocol_event_handler(void *opaque) * more than 1 event will be emitted within @rate * milliseconds */ -static void +static void __attribute__((__unused__)) monitor_protocol_event_throttle(MonitorEvent event, int64_t rate) { @@ -5358,6 +5483,7 @@ void monitor_init(CharDriverState *chr, int flags) if (is_first_init) { monitor_protocol_event_init(); + monitor_qapi_event_init(); sortcmdlist(); is_first_init = 0; } |