qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]