[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2.1 07/36] monitor: add an implemention of qapi even
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH 2.1 07/36] monitor: add an implemention of qapi event emit method |
Date: |
Wed, 18 Jun 2014 08:43:31 +0200 |
From: Wenchao Xia <address@hidden>
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 <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
monitor.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 127 insertions(+), 1 deletion(-)
diff --git a/monitor.c b/monitor.c
index 2901187..2e36fed 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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;
@@ -491,6 +501,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
@@ -588,7 +713,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)
{
@@ -5350,6 +5475,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;
}
--
1.9.3
- [Qemu-devel] [PATCH 2.1 02/36] qapi: Add includes from qapi/ as dependencies, (continued)
- [Qemu-devel] [PATCH 2.1 02/36] qapi: Add includes from qapi/ as dependencies, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 04/36] qapi script: add event support, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 01/36] os-posix: include sys/time.h, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 05/36] test: add test cases for qapi event, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 08/36] qapi: add new schema file qapi-event.json, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 03/36] qapi: add event helper functions, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 06/36] qapi: adjust existing defines, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 07/36] monitor: add an implemention of qapi event emit method,
Paolo Bonzini <=
- [Qemu-devel] [PATCH 2.1 09/36] qapi event: convert SHUTDOWN, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 10/36] qapi event: convert POWERDOWN, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 11/36] qapi event: convert RESET, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 12/36] qapi event: convert STOP, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 14/36] qapi event: convert SUSPEND, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 15/36] qapi event: convert SUSPEND_DISK, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 16/36] qapi event: convert WAKEUP, Paolo Bonzini, 2014/06/18
- [Qemu-devel] [PATCH 2.1 13/36] qapi event: convert RESUME, Paolo Bonzini, 2014/06/18