[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH V6 06/29] monitor: add an implemention as qapi event
From: |
Wenchao Xia |
Subject: |
[Qemu-devel] [PATCH V6 06/29] monitor: add an implemention as qapi event emit method |
Date: |
Thu, 5 Jun 2014 05:22:01 -0700 |
Now monitor has been hooked on the new event mechanism, so the patches
later 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 <address@hidden>
---
monitor.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
trace-events | 4 ++
2 files changed, 131 insertions(+), 1 deletions(-)
diff --git a/monitor.c b/monitor.c
index 593679a..e122381 100644
--- a/monitor.c
+++ b/monitor.c
@@ -69,6 +69,8 @@
#include "qmp-commands.h"
#include "hmp.h"
#include "qemu/thread.h"
+#include "qapi/qmp-event.h"
+#include "qapi-event.h"
/* for pic/irq_info */
#if defined(TARGET_SPARC)
@@ -185,6 +187,14 @@ typedef struct MonitorEventState {
QObject *data; /* Event pending delayed dispatch */
} MonitorEventState;
+typedef struct MonitorQAPIEventState {
+ QAPIEvent event; /* Event being tracked */
+ int64_t rate; /* Period over which to throttle. 0 to disable */
+ int64_t last; /* Time at which event was last emitted */
+ QEMUTimer *timer; /* Timer for handling delayed events */
+ QObject *data; /* Event pending delayed dispatch */
+} MonitorQAPIEventState;
+
struct Monitor {
CharDriverState *chr;
int mux_out;
@@ -489,6 +499,122 @@ 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_qapi_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(int event_kind, QDict *data, Error **errp)
+{
+ MonitorQAPIEventState *evstate;
+ assert(event_kind < QAPI_EVENT_MAX);
+ QAPIEvent event = (QAPIEvent)event_kind;
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+
+ evstate = &(monitor_qapi_event_state[event]);
+ trace_monitor_qapi_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_qapi_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 monitor_qapi_event_throttle(QAPIEvent event, int64_t rate)
+{
+ MonitorQAPIEventState *evstate;
+ assert(event < QAPI_EVENT_MAX);
+
+ evstate = &(monitor_qapi_event_state[event]);
+
+ trace_monitor_qapi_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
@@ -507,7 +633,6 @@ monitor_protocol_event_emit(MonitorEvent event,
}
}
-
/*
* Queue a new event for emission to Monitor instances,
* applying any rate limiting if required.
@@ -5169,6 +5294,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;
}
diff --git a/trace-events b/trace-events
index ffe6e62..f4b8dbb 100644
--- a/trace-events
+++ b/trace-events
@@ -932,6 +932,10 @@ monitor_protocol_event_handler(uint32_t event, void *data,
uint64_t last, uint64
monitor_protocol_event_emit(uint32_t event, void *data) "event=%d data=%p"
monitor_protocol_event_queue(uint32_t event, void *data, uint64_t rate,
uint64_t last, uint64_t now) "event=%d data=%p rate=%" PRId64 " last=%" PRId64
" now=%" PRId64
monitor_protocol_event_throttle(uint32_t event, uint64_t rate) "event=%d
rate=%" PRId64
+monitor_qapi_event_emit(uint32_t event, void *data) "event=%d data=%p"
+monitor_qapi_event_queue(uint32_t event, void *data, uint64_t rate, uint64_t
last, uint64_t now) "event=%d data=%p rate=%" PRId64 " last=%" PRId64 " now=%"
PRId64
+monitor_qapi_event_handler(uint32_t event, void *data, uint64_t last, uint64_t
now) "event=%d data=%p last=%" PRId64 " now=%" PRId64
+monitor_qapi_event_throttle(uint32_t event, uint64_t rate) "event=%d rate=%"
PRId64
# hw/net/opencores_eth.c
open_eth_mii_write(unsigned idx, uint16_t v) "MII[%02x] <- %04x"
--
1.7.1
- [Qemu-devel] [PATCH V6 00/29] add direct support of event in qapi schema, Wenchao Xia, 2014/06/05
- [Qemu-devel] [PATCH V6 01/29] os-posix: include sys/time.h, Wenchao Xia, 2014/06/05
- [Qemu-devel] [PATCH V6 02/29] qapi: add event helper functions, Wenchao Xia, 2014/06/05
- [Qemu-devel] [PATCH V6 03/29] qapi script: add event support, Wenchao Xia, 2014/06/05
- [Qemu-devel] [PATCH V6 04/29] test: add test cases for qapi event, Wenchao Xia, 2014/06/05
- [Qemu-devel] [PATCH V6 05/29] qapi: adjust existing defines, Wenchao Xia, 2014/06/05
- [Qemu-devel] [PATCH V6 06/29] monitor: add an implemention as qapi event emit method,
Wenchao Xia <=
- [Qemu-devel] [PATCH V6 07/29] qapi: add new schema file qapi-event.json, Wenchao Xia, 2014/06/05
- [Qemu-devel] [PATCH V6 08/29] qapi event: convert SHUTDOWN, Wenchao Xia, 2014/06/05
- [Qemu-devel] [PATCH V6 09/29] qapi event: convert POWERDOWN, Wenchao Xia, 2014/06/05