Introducing a virtual "requires_iothread" method allows the code to
automatically initialize the I/O thread during object completion.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Tested-by: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
monitor/monitor-internal.h | 14 +++++++++-----
monitor/monitor.c | 22 ++++++++++++----------
monitor/qmp.c | 20 +++++++++++---------
3 files changed, 32 insertions(+), 24 deletions(-)
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index 592f146331..efd21b8912 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -121,6 +121,12 @@ struct MonitorClass {
* the monitor to accept further client input
*/
void (*accept_input)(Monitor *mon);
+
+ /*
+ * If non-NULL and returns true, then an I/O thread
+ * is required for processing the monitor
+ */
+ bool (*requires_iothread)(const Monitor *mon);
};
struct Monitor {
@@ -129,7 +135,6 @@ struct Monitor {
CharFrontend chr;
int suspend_cnt; /* Needs to be accessed atomically */
bool is_qmp;
- bool use_io_thread;
char *mon_cpu_path;
QTAILQ_ENTRY(Monitor) entry;
@@ -159,9 +164,8 @@ struct MonitorHMP {
bool use_readline;
/*
* State used only in the thread "owning" the monitor.
- * If @use_io_thread, this is @mon_iothread. (This does not actually happen
- * in the current state of the code.)
- * Else, it's the main thread.
+ * This is currently always the main thread, since
+ * HMP does not allow use of the I/O thread at this time.
* These members can be safely accessed without locks.
*/
ReadLineState *rs;
@@ -210,7 +214,7 @@ extern QemuMutex monitor_lock;
extern MonitorList mon_list;
void monitor_complete(Monitor *mon, Error **errp);
-void monitor_iothread_init(Monitor *mon);
+bool monitor_requires_iothread(const Monitor *mon);
int monitor_can_read(void *opaque);
void monitor_list_append(Monitor *mon);
void monitor_fdsets_cleanup(void);
diff --git a/monitor/monitor.c b/monitor/monitor.c
index 6e63e7a5c7..1b2bdcf68f 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -162,6 +162,12 @@ bool monitor_cur_is_qmp(void)
return cur_mon && monitor_is_qmp(cur_mon);
}
+bool monitor_requires_iothread(const Monitor *mon)
+{
+ MonitorClass *cls = MONITOR_GET_CLASS(mon);
+ return cls->requires_iothread && cls->requires_iothread(mon);
+}
+
/**
* Is @mon is using readline?
* Note: not all HMP monitors use readline, e.g., gdbserver has a
@@ -563,7 +569,7 @@ int monitor_suspend(Monitor *mon)
qatomic_inc(&mon->suspend_cnt);
- if (mon->use_io_thread) {
+ if (monitor_requires_iothread(mon)) {
/*
* Kick I/O thread to make sure this takes effect. It'll be
* evaluated again in prepare() of the watch object.
@@ -596,7 +602,7 @@ void monitor_resume(Monitor *mon)
if (qatomic_dec_fetch(&mon->suspend_cnt) == 0) {
AioContext *ctx;
- if (mon->use_io_thread) {
+ if (monitor_requires_iothread(mon)) {
ctx = iothread_get_aio_context(mon_iothread);
} else {
ctx = qemu_get_aio_context();
@@ -634,14 +640,6 @@ void monitor_list_append(Monitor *mon)
}
}
-void monitor_iothread_init(Monitor *mon)
-{
- if (!mon_iothread) {
- mon_iothread = iothread_create("mon_iothread", &error_abort);
- }
- mon->use_io_thread = true;
-}
-
void monitor_cleanup(void)
{
/*
@@ -743,6 +741,10 @@ void monitor_complete(Monitor *mon, Error **errp)
return;
}
}
+
+ if (monitor_requires_iothread(mon) && !mon_iothread) {
+ mon_iothread = iothread_create("mon_iothread", &error_abort);
+ }
}
int monitor_new(MonitorOptions *opts, bool allow_hmp, Error **errp)
diff --git a/monitor/qmp.c b/monitor/qmp.c
index d732fff9a3..8bbe25d8de 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -100,6 +100,7 @@ static void monitor_qmp_set_pretty(Object *obj, bool val, Error **errp)
}
static void monitor_qmp_emit_event(Monitor *mon, QAPIEvent event, QDict *qdict);
+static bool monitor_qmp_requires_iothread(const Monitor *mon);
static void monitor_qmp_class_init(ObjectClass *cls, const void *data)
{
@@ -110,6 +111,7 @@ static void monitor_qmp_class_init(ObjectClass *cls, const void *data)
monitor_qmp_set_pretty);
moncls->emit_event = monitor_qmp_emit_event;
+ moncls->requires_iothread = monitor_qmp_requires_iothread;
}
static void handle_qmp_command(void *opaque, QObject *req, Error *err);
@@ -136,6 +138,11 @@ static void monitor_qmp_emit_event(Monitor *mon, QAPIEvent event, QDict *qdict)
qmp_send_response(qmp, qdict);
}
+static bool monitor_qmp_requires_iothread(const Monitor *mon)
+{
+ return qemu_chr_has_feature(mon->chr.chr,
+ QEMU_CHAR_FEATURE_GCONTEXT);
+}
static bool qmp_oob_enabled(MonitorQMP *mon)
{
@@ -146,7 +153,8 @@ static void monitor_qmp_caps_reset(MonitorQMP *mon)
{
memset(mon->capab_offered, 0, sizeof(mon->capab_offered));
memset(mon->capab, 0, sizeof(mon->capab));
- mon->capab_offered[QMP_CAPABILITY_OOB] = mon->parent_obj.use_io_thread;
+ mon->capab_offered[QMP_CAPABILITY_OOB] =
+ monitor_requires_iothread(MONITOR(mon));
}
static void qmp_request_free(QMPRequest *req)
@@ -562,7 +570,7 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
MonitorQMP *mon = opaque;
GMainContext *context;
- assert(mon->parent_obj.use_io_thread);
+ assert(monitor_requires_iothread(MONITOR(mon)));
context = iothread_get_g_main_context(mon_iothread);
assert(context);
qemu_chr_fe_set_handlers(&mon->parent_obj.chr, monitor_can_read,
@@ -598,13 +606,7 @@ void monitor_new_qmp(const char *id, const char *chardev_id,
qemu_chr_fe_set_echo(&mon->parent_obj.chr, true);
- /* Note: we run QMP monitor in I/O thread when @chr supports that */
- if (qemu_chr_has_feature(mon->parent_obj.chr.chr,
- QEMU_CHAR_FEATURE_GCONTEXT)) {
- monitor_iothread_init(&mon->parent_obj);
- }
-
- if (mon->parent_obj.use_io_thread) {
+ if (monitor_requires_iothread(MONITOR(mon))) {
/*
* Make sure the old iowatch is gone. It's possible when
* e.g. the chardev is in client mode, with wait=on.
--
2.55.0