qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/2] monitor: Add an input buffer for QMP reading


From: Yury Kotov
Subject: [PATCH 2/2] monitor: Add an input buffer for QMP reading
Date: Thu, 19 Dec 2019 19:07:56 +0300

The monitor_qmp_can_read (as a callback of qemu_chr_fe_set_handlers)
should return size of buffer which monitor_qmp_read can process.
Currently, monitor_can_read returns 1, because it guarantees that
only one QMP command can be handled at a time.
Thus, for each QMP command, len(QMD) iterations of the main loop
are required to handle a command.

This patch adds an input buffer to speed up reading and to keep
the guarantee of executing one command at a time.

Signed-off-by: Yury Kotov <address@hidden>
---
 monitor/monitor-internal.h | 11 +++++++++++
 monitor/monitor.c          | 27 +++++++++++++++++++++++++++
 monitor/qmp.c              | 17 +++++++++++++++--
 3 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index c0ba29abf1..22983b9dda 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -32,6 +32,8 @@
 #include "qemu/readline.h"
 #include "sysemu/iothread.h"
 
+#define MON_INPUT_BUFFER_SIZE   1024
+
 /*
  * Supported types:
  *
@@ -93,6 +95,11 @@ struct Monitor {
     gchar *mon_cpu_path;
     QTAILQ_ENTRY(Monitor) entry;
 
+    /* Must be accessed only by monitor's iothread */
+    char inbuf[MON_INPUT_BUFFER_SIZE];
+    int inbuf_pos;
+    int inbuf_len;
+
     /*
      * The per-monitor lock. We can't access guest memory when holding
      * the lock.
@@ -169,9 +176,13 @@ void monitor_data_destroy(Monitor *mon);
 void monitor_list_append(Monitor *mon);
 void monitor_fdsets_cleanup(void);
 
+void monitor_inbuf_write(Monitor *mon, const char *buf, int size);
+int monitor_inbuf_read(Monitor *mon, char *buf, int size);
+
 void qmp_send_response(MonitorQMP *mon, const QDict *rsp);
 void monitor_data_destroy_qmp(MonitorQMP *mon);
 void monitor_qmp_bh_dispatcher(void *data);
+void monitor_qmp_handle_inbuf(Monitor *mon);
 
 int get_monitor_def(int64_t *pval, const char *name);
 void help_cmd(Monitor *mon, const char *name);
diff --git a/monitor/monitor.c b/monitor/monitor.c
index d25cc8ea4a..9eb258ac2f 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -440,6 +440,29 @@ static gboolean qapi_event_throttle_equal(const void *a, 
const void *b)
     return TRUE;
 }
 
+void monitor_inbuf_write(Monitor *mon, const char *buf, int size)
+{
+    int pos = mon->inbuf_pos + mon->inbuf_len;
+
+    assert(size <= sizeof(mon->inbuf) - mon->inbuf_len);
+    while (size-- > 0) {
+        mon->inbuf[pos++ % sizeof(mon->inbuf)] = *buf++;
+        mon->inbuf_len++;
+    }
+}
+
+int monitor_inbuf_read(Monitor *mon, char *buf, int size)
+{
+    int read_bytes = 0;
+
+    while (read_bytes < size && mon->inbuf_len > 0) {
+        buf[read_bytes++] = mon->inbuf[mon->inbuf_pos++];
+        mon->inbuf_pos %= sizeof(mon->inbuf);
+        mon->inbuf_len--;
+    }
+    return read_bytes;
+}
+
 int monitor_suspend(Monitor *mon)
 {
     if (monitor_is_hmp_non_interactive(mon)) {
@@ -465,6 +488,10 @@ static void monitor_accept_input(void *opaque)
     Monitor *mon = opaque;
 
     qemu_chr_fe_accept_input(&mon->chr);
+
+    if (mon->is_qmp) {
+        monitor_qmp_handle_inbuf(mon);
+    }
 }
 
 void monitor_resume(Monitor *mon)
diff --git a/monitor/qmp.c b/monitor/qmp.c
index 37884c6c43..9d2634eeb3 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -315,14 +315,27 @@ static int monitor_qmp_can_read(void *opaque)
 {
     Monitor *mon = opaque;
 
-    return !atomic_mb_read(&mon->suspend_cnt);
+    return sizeof(mon->inbuf) - mon->inbuf_len;
+}
+
+void monitor_qmp_handle_inbuf(Monitor *mon)
+{
+    MonitorQMP *mon_qmp = container_of(mon, MonitorQMP, common);
+    char ch;
+
+    /* Handle only one byte at a time, because monitor may become suspened */
+    while (!atomic_mb_read(&mon->suspend_cnt) &&
+           monitor_inbuf_read(mon, &ch, 1)) {
+        json_message_parser_feed(&mon_qmp->parser, &ch, 1);
+    }
 }
 
 static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size)
 {
     MonitorQMP *mon = opaque;
 
-    json_message_parser_feed(&mon->parser, (const char *) buf, size);
+    monitor_inbuf_write(&mon->common, (const char *)buf, size);
+    monitor_qmp_handle_inbuf(&mon->common);
 }
 
 static QDict *qmp_greeting(MonitorQMP *mon)
-- 
2.24.1




reply via email to

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