Skip to content

Commit

Permalink
monitor: add an implemention of qapi event emit method
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Wenchao Xia authored and Luiz Capitulino committed Jun 23, 2014
1 parent a589569 commit 43a14cf
Showing 1 changed file with 127 additions and 1 deletion.
128 changes: 127 additions & 1 deletion monitor.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 43a14cf

Please sign in to comment.