Introducing a virtual "requires_iothread" method allows the code to automatically initialize the I/O thread during object completion. 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 4928e5201e..a700d747fa 100644 --- a/monitor/monitor.c +++ b/monitor/monitor.c @@ -159,6 +159,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 @@ -560,7 +566,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. @@ -593,7 +599,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(); @@ -631,14 +637,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) { /* @@ -733,6 +731,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 b21dfbe578..95b2c02497 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, @@ -597,13 +605,7 @@ void monitor_new_qmp(const char *chardev_id, bool pretty, Error **errp) 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.54.0