[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