@samitouri / QOSamiQemu / commits / b723eeb815

monitor: move monitor_data_(init|destroy) into QOM init/finalize

Start to take advantage of QOM, by using object init and finalize methods to replace monitor_data_init and monitor_data_destroy. A standalone helper is provided to enable the I/O thread for QMP where appropriate for the chardev backend. 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> Message-ID: <20260706135824.2623960-12-berrange@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Daniel P. Berrangé committed Jul 6, 2026 at 14:57 UTC b723eeb815477a3736e21456345c3fd6d7586fd2
5 files changed +40 -52
monitor/hmp.c
+4 -2
@@ -48,6 +48,10 @@ OBJECT_DEFINE_TYPE(MonitorHMP, monitor_hmp, MONITOR_HMP, MONITOR);
48
49 static void monitor_hmp_finalize(Object *obj)
50 {
51 + MonitorHMP *mon = MONITOR_HMP(obj);
52 + if (mon->rs) {
53 + readline_free(mon->rs);
54 + }
55 }
56
57 static bool monitor_hmp_get_readline(Object *obj, Error **errp)
@@ -1590,8 +1594,6 @@ void monitor_new_hmp(const char *id, const char *chardev_id,
1594 return;
1595 }
1596
1593 - monitor_data_init(&mon->parent_obj, false, false);
1594 -
1597 if (mon->use_readline) {
1598 mon->rs = readline_init(monitor_readline_printf,
1599 monitor_readline_flush,
monitor/monitor-internal.h
+1 -2
@@ -193,8 +193,7 @@ extern QemuMutex monitor_lock;
193 extern MonitorList mon_list;
194
195 void monitor_complete(Monitor *mon, Error **errp);
196 -void monitor_data_init(Monitor *mon, bool is_qmp, bool use_io_thread);
197 -void monitor_data_destroy(Monitor *mon);
196 +void monitor_iothread_init(Monitor *mon);
197 int monitor_can_read(void *opaque);
198 void monitor_list_append(Monitor *mon);
199 void monitor_fdsets_cleanup(void);
monitor/monitor.c
+16 -30
@@ -82,6 +82,10 @@ static void monitor_finalize(Object *obj)
82 Monitor *mon = MONITOR(obj);
83
84 g_free(mon->chardev_id);
85 + g_free(mon->mon_cpu_path);
86 + qemu_chr_fe_deinit(&mon->chr, false);
87 + g_string_free(mon->outbuf, true);
88 + qemu_mutex_destroy(&mon->mon_lock);
89 }
90
91 static char *monitor_get_chardev_id(Object *obj, Error **errp)
@@ -108,6 +112,11 @@ static void monitor_class_init(ObjectClass *cls, const void *data)
112
113 static void monitor_init(Object *obj)
114 {
115 + Monitor *mon = MONITOR(obj);
116 +
117 + qemu_mutex_init(&mon->mon_lock);
118 + mon->is_qmp = !!object_dynamic_cast(obj, TYPE_MONITOR_QMP);
119 + mon->outbuf = g_string_new(NULL);
120 }
121
122 Monitor *monitor_cur(void)
@@ -639,38 +648,16 @@ void monitor_list_append(Monitor *mon)
648 qemu_mutex_unlock(&monitor_lock);
649
650 if (mon) {
642 - monitor_data_destroy(mon);
651 object_unparent(OBJECT(mon));
652 }
653 }
654
647 -static void monitor_iothread_init(void)
648 -{
649 - mon_iothread = iothread_create("mon_iothread", &error_abort);
650 -}
651 -
652 -void monitor_data_init(Monitor *mon, bool is_qmp, bool use_io_thread)
655 +void monitor_iothread_init(Monitor *mon)
656 {
654 - if (use_io_thread && !mon_iothread) {
655 - monitor_iothread_init();
657 + if (!mon_iothread) {
658 + mon_iothread = iothread_create("mon_iothread", &error_abort);
659 }
657 - qemu_mutex_init(&mon->mon_lock);
658 - mon->is_qmp = is_qmp;
659 - mon->outbuf = g_string_new(NULL);
660 - mon->use_io_thread = use_io_thread;
661 -}
662 -
663 -void monitor_data_destroy(Monitor *mon)
664 -{
665 - g_free(mon->mon_cpu_path);
666 - qemu_chr_fe_deinit(&mon->chr, false);
667 - if (monitor_is_qmp(mon)) {
668 - monitor_data_destroy_qmp(container_of(mon, MonitorQMP, parent_obj));
669 - } else {
670 - readline_free(container_of(mon, MonitorHMP, parent_obj)->rs);
671 - }
672 - g_string_free(mon->outbuf, true);
673 - qemu_mutex_destroy(&mon->mon_lock);
660 + mon->use_io_thread = true;
661 }
662
663 void monitor_cleanup(void)
@@ -688,7 +675,7 @@ void monitor_cleanup(void)
675 * Letting the iothread continue while shutting down the dispatcher
676 * means that new requests may still be coming in. This is okay,
677 * we'll just leave them in the queue without sending a response
691 - * and monitor_data_destroy() will free them.
678 + * and object finalization will free them.
679 */
680 WITH_QEMU_LOCK_GUARD(&monitor_lock) {
681 qmp_dispatcher_co_shutdown = true;
@@ -702,8 +689,8 @@ void monitor_cleanup(void)
689 /*
690 * We need to explicitly stop the I/O thread (but not destroy it),
691 * clean up the monitor resources, then destroy the I/O thread since
705 - * we need to unregister from chardev below in
706 - * monitor_data_destroy(), and chardev is not thread-safe yet
692 + * we need to unregister from chardev below in object
693 + * finalization, and chardev is not thread-safe yet
694 */
695 if (mon_iothread) {
696 iothread_stop(mon_iothread);
@@ -718,7 +705,6 @@ void monitor_cleanup(void)
705 /* Permit QAPI event emission from character frontend release */
706 qemu_mutex_unlock(&monitor_lock);
707 monitor_flush(mon);
721 - monitor_data_destroy(mon);
708 qemu_mutex_lock(&monitor_lock);
709 object_unparent(OBJECT(mon));
710 }
monitor/qmp-cmds.c
-3
@@ -168,8 +168,6 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
168 char *output = NULL;
169 MonitorHMP *hmp = MONITOR_HMP(object_new(TYPE_MONITOR_HMP));
170
171 - monitor_data_init(&hmp->parent_obj, false, false);
172 -
171 if (has_cpu_index) {
172 int ret = monitor_set_cpu(&hmp->parent_obj, cpu_index);
173 if (ret < 0) {
@@ -186,7 +184,6 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
184 }
185
186 out:
189 - monitor_data_destroy(&hmp->parent_obj);
187 object_unref(hmp);
188 return output;
189 }
monitor/qmp.c
+19 -15
@@ -73,8 +73,16 @@ QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
73
74 OBJECT_DEFINE_TYPE(MonitorQMP, monitor_qmp, MONITOR_QMP, MONITOR);
75
76 +static void monitor_qmp_cleanup_req_queue_locked(MonitorQMP *mon);
77 +
78 static void monitor_qmp_finalize(Object *obj)
79 {
80 + MonitorQMP *mon = MONITOR_QMP(obj);
81 +
82 + json_message_parser_destroy(&mon->parser);
83 + qemu_mutex_destroy(&mon->qmp_queue_lock);
84 + monitor_qmp_cleanup_req_queue_locked(mon);
85 + g_queue_free(mon->qmp_requests);
86 }
87
88 static bool monitor_qmp_get_pretty(Object *obj, Error **errp)
@@ -98,8 +106,15 @@ static void monitor_qmp_class_init(ObjectClass *cls, const void *data)
106 monitor_qmp_set_pretty);
107 }
108
109 +static void handle_qmp_command(void *opaque, QObject *req, Error *err);
110 static void monitor_qmp_init(Object *obj)
111 {
112 + MonitorQMP *mon = MONITOR_QMP(obj);
113 +
114 + qemu_mutex_init(&mon->qmp_queue_lock);
115 + mon->qmp_requests = g_queue_new();
116 +
117 + json_message_parser_init(&mon->parser, handle_qmp_command, mon, NULL);
118 }
119
120 static bool qmp_oob_enabled(MonitorQMP *mon)
@@ -522,14 +537,6 @@ static void monitor_qmp_event(void *opaque, QEMUChrEvent event)
537 }
538 }
539
525 -void monitor_data_destroy_qmp(MonitorQMP *mon)
526 -{
527 - json_message_parser_destroy(&mon->parser);
528 - qemu_mutex_destroy(&mon->qmp_queue_lock);
529 - monitor_qmp_cleanup_req_queue_locked(mon);
530 - g_queue_free(mon->qmp_requests);
531 -}
532 -
540 static void monitor_qmp_setup_handlers_bh(void *opaque)
541 {
542 MonitorQMP *mon = opaque;
@@ -572,14 +579,11 @@ void monitor_new_qmp(const char *id, const char *chardev_id,
579 qemu_chr_fe_set_echo(&mon->parent_obj.chr, true);
580
581 /* Note: we run QMP monitor in I/O thread when @chr supports that */
575 - monitor_data_init(&mon->parent_obj, true,
576 - qemu_chr_has_feature(mon->parent_obj.chr.chr,
577 - QEMU_CHAR_FEATURE_GCONTEXT));
578 -
579 - qemu_mutex_init(&mon->qmp_queue_lock);
580 - mon->qmp_requests = g_queue_new();
582 + if (qemu_chr_has_feature(mon->parent_obj.chr.chr,
583 + QEMU_CHAR_FEATURE_GCONTEXT)) {
584 + monitor_iothread_init(&mon->parent_obj);
585 + }
586
582 - json_message_parser_init(&mon->parser, handle_qmp_command, mon, NULL);
587 if (mon->parent_obj.use_io_thread) {
588 /*
589 * Make sure the old iowatch is gone. It's possible when