mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
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>
This commit is contained in:
committed by
Markus Armbruster
parent
ae286229f4
commit
b723eeb815
@@ -48,6 +48,10 @@ OBJECT_DEFINE_TYPE(MonitorHMP, monitor_hmp, MONITOR_HMP, MONITOR);
|
|||||||
|
|
||||||
static void monitor_hmp_finalize(Object *obj)
|
static void monitor_hmp_finalize(Object *obj)
|
||||||
{
|
{
|
||||||
|
MonitorHMP *mon = MONITOR_HMP(obj);
|
||||||
|
if (mon->rs) {
|
||||||
|
readline_free(mon->rs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool monitor_hmp_get_readline(Object *obj, Error **errp)
|
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,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor_data_init(&mon->parent_obj, false, false);
|
|
||||||
|
|
||||||
if (mon->use_readline) {
|
if (mon->use_readline) {
|
||||||
mon->rs = readline_init(monitor_readline_printf,
|
mon->rs = readline_init(monitor_readline_printf,
|
||||||
monitor_readline_flush,
|
monitor_readline_flush,
|
||||||
|
|||||||
@@ -193,8 +193,7 @@ extern QemuMutex monitor_lock;
|
|||||||
extern MonitorList mon_list;
|
extern MonitorList mon_list;
|
||||||
|
|
||||||
void monitor_complete(Monitor *mon, Error **errp);
|
void monitor_complete(Monitor *mon, Error **errp);
|
||||||
void monitor_data_init(Monitor *mon, bool is_qmp, bool use_io_thread);
|
void monitor_iothread_init(Monitor *mon);
|
||||||
void monitor_data_destroy(Monitor *mon);
|
|
||||||
int monitor_can_read(void *opaque);
|
int monitor_can_read(void *opaque);
|
||||||
void monitor_list_append(Monitor *mon);
|
void monitor_list_append(Monitor *mon);
|
||||||
void monitor_fdsets_cleanup(void);
|
void monitor_fdsets_cleanup(void);
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ static void monitor_finalize(Object *obj)
|
|||||||
Monitor *mon = MONITOR(obj);
|
Monitor *mon = MONITOR(obj);
|
||||||
|
|
||||||
g_free(mon->chardev_id);
|
g_free(mon->chardev_id);
|
||||||
|
g_free(mon->mon_cpu_path);
|
||||||
|
qemu_chr_fe_deinit(&mon->chr, false);
|
||||||
|
g_string_free(mon->outbuf, true);
|
||||||
|
qemu_mutex_destroy(&mon->mon_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *monitor_get_chardev_id(Object *obj, Error **errp)
|
static char *monitor_get_chardev_id(Object *obj, Error **errp)
|
||||||
@@ -108,6 +112,11 @@ static void monitor_class_init(ObjectClass *cls, const void *data)
|
|||||||
|
|
||||||
static void monitor_init(Object *obj)
|
static void monitor_init(Object *obj)
|
||||||
{
|
{
|
||||||
|
Monitor *mon = MONITOR(obj);
|
||||||
|
|
||||||
|
qemu_mutex_init(&mon->mon_lock);
|
||||||
|
mon->is_qmp = !!object_dynamic_cast(obj, TYPE_MONITOR_QMP);
|
||||||
|
mon->outbuf = g_string_new(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor *monitor_cur(void)
|
Monitor *monitor_cur(void)
|
||||||
@@ -639,38 +648,16 @@ void monitor_list_append(Monitor *mon)
|
|||||||
qemu_mutex_unlock(&monitor_lock);
|
qemu_mutex_unlock(&monitor_lock);
|
||||||
|
|
||||||
if (mon) {
|
if (mon) {
|
||||||
monitor_data_destroy(mon);
|
|
||||||
object_unparent(OBJECT(mon));
|
object_unparent(OBJECT(mon));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monitor_iothread_init(void)
|
void monitor_iothread_init(Monitor *mon)
|
||||||
{
|
{
|
||||||
mon_iothread = iothread_create("mon_iothread", &error_abort);
|
if (!mon_iothread) {
|
||||||
}
|
mon_iothread = iothread_create("mon_iothread", &error_abort);
|
||||||
|
|
||||||
void monitor_data_init(Monitor *mon, bool is_qmp, bool use_io_thread)
|
|
||||||
{
|
|
||||||
if (use_io_thread && !mon_iothread) {
|
|
||||||
monitor_iothread_init();
|
|
||||||
}
|
}
|
||||||
qemu_mutex_init(&mon->mon_lock);
|
mon->use_io_thread = true;
|
||||||
mon->is_qmp = is_qmp;
|
|
||||||
mon->outbuf = g_string_new(NULL);
|
|
||||||
mon->use_io_thread = use_io_thread;
|
|
||||||
}
|
|
||||||
|
|
||||||
void monitor_data_destroy(Monitor *mon)
|
|
||||||
{
|
|
||||||
g_free(mon->mon_cpu_path);
|
|
||||||
qemu_chr_fe_deinit(&mon->chr, false);
|
|
||||||
if (monitor_is_qmp(mon)) {
|
|
||||||
monitor_data_destroy_qmp(container_of(mon, MonitorQMP, parent_obj));
|
|
||||||
} else {
|
|
||||||
readline_free(container_of(mon, MonitorHMP, parent_obj)->rs);
|
|
||||||
}
|
|
||||||
g_string_free(mon->outbuf, true);
|
|
||||||
qemu_mutex_destroy(&mon->mon_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void monitor_cleanup(void)
|
void monitor_cleanup(void)
|
||||||
@@ -688,7 +675,7 @@ void monitor_cleanup(void)
|
|||||||
* Letting the iothread continue while shutting down the dispatcher
|
* Letting the iothread continue while shutting down the dispatcher
|
||||||
* means that new requests may still be coming in. This is okay,
|
* means that new requests may still be coming in. This is okay,
|
||||||
* we'll just leave them in the queue without sending a response
|
* we'll just leave them in the queue without sending a response
|
||||||
* and monitor_data_destroy() will free them.
|
* and object finalization will free them.
|
||||||
*/
|
*/
|
||||||
WITH_QEMU_LOCK_GUARD(&monitor_lock) {
|
WITH_QEMU_LOCK_GUARD(&monitor_lock) {
|
||||||
qmp_dispatcher_co_shutdown = true;
|
qmp_dispatcher_co_shutdown = true;
|
||||||
@@ -702,8 +689,8 @@ void monitor_cleanup(void)
|
|||||||
/*
|
/*
|
||||||
* We need to explicitly stop the I/O thread (but not destroy it),
|
* We need to explicitly stop the I/O thread (but not destroy it),
|
||||||
* clean up the monitor resources, then destroy the I/O thread since
|
* clean up the monitor resources, then destroy the I/O thread since
|
||||||
* we need to unregister from chardev below in
|
* we need to unregister from chardev below in object
|
||||||
* monitor_data_destroy(), and chardev is not thread-safe yet
|
* finalization, and chardev is not thread-safe yet
|
||||||
*/
|
*/
|
||||||
if (mon_iothread) {
|
if (mon_iothread) {
|
||||||
iothread_stop(mon_iothread);
|
iothread_stop(mon_iothread);
|
||||||
@@ -718,7 +705,6 @@ void monitor_cleanup(void)
|
|||||||
/* Permit QAPI event emission from character frontend release */
|
/* Permit QAPI event emission from character frontend release */
|
||||||
qemu_mutex_unlock(&monitor_lock);
|
qemu_mutex_unlock(&monitor_lock);
|
||||||
monitor_flush(mon);
|
monitor_flush(mon);
|
||||||
monitor_data_destroy(mon);
|
|
||||||
qemu_mutex_lock(&monitor_lock);
|
qemu_mutex_lock(&monitor_lock);
|
||||||
object_unparent(OBJECT(mon));
|
object_unparent(OBJECT(mon));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,8 +168,6 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
|
|||||||
char *output = NULL;
|
char *output = NULL;
|
||||||
MonitorHMP *hmp = MONITOR_HMP(object_new(TYPE_MONITOR_HMP));
|
MonitorHMP *hmp = MONITOR_HMP(object_new(TYPE_MONITOR_HMP));
|
||||||
|
|
||||||
monitor_data_init(&hmp->parent_obj, false, false);
|
|
||||||
|
|
||||||
if (has_cpu_index) {
|
if (has_cpu_index) {
|
||||||
int ret = monitor_set_cpu(&hmp->parent_obj, cpu_index);
|
int ret = monitor_set_cpu(&hmp->parent_obj, cpu_index);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -186,7 +184,6 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
monitor_data_destroy(&hmp->parent_obj);
|
|
||||||
object_unref(hmp);
|
object_unref(hmp);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,8 +73,16 @@ QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
|
|||||||
|
|
||||||
OBJECT_DEFINE_TYPE(MonitorQMP, monitor_qmp, MONITOR_QMP, MONITOR);
|
OBJECT_DEFINE_TYPE(MonitorQMP, monitor_qmp, MONITOR_QMP, MONITOR);
|
||||||
|
|
||||||
|
static void monitor_qmp_cleanup_req_queue_locked(MonitorQMP *mon);
|
||||||
|
|
||||||
static void monitor_qmp_finalize(Object *obj)
|
static void monitor_qmp_finalize(Object *obj)
|
||||||
{
|
{
|
||||||
|
MonitorQMP *mon = MONITOR_QMP(obj);
|
||||||
|
|
||||||
|
json_message_parser_destroy(&mon->parser);
|
||||||
|
qemu_mutex_destroy(&mon->qmp_queue_lock);
|
||||||
|
monitor_qmp_cleanup_req_queue_locked(mon);
|
||||||
|
g_queue_free(mon->qmp_requests);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool monitor_qmp_get_pretty(Object *obj, Error **errp)
|
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)
|
|||||||
monitor_qmp_set_pretty);
|
monitor_qmp_set_pretty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_qmp_command(void *opaque, QObject *req, Error *err);
|
||||||
static void monitor_qmp_init(Object *obj)
|
static void monitor_qmp_init(Object *obj)
|
||||||
{
|
{
|
||||||
|
MonitorQMP *mon = MONITOR_QMP(obj);
|
||||||
|
|
||||||
|
qemu_mutex_init(&mon->qmp_queue_lock);
|
||||||
|
mon->qmp_requests = g_queue_new();
|
||||||
|
|
||||||
|
json_message_parser_init(&mon->parser, handle_qmp_command, mon, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool qmp_oob_enabled(MonitorQMP *mon)
|
static bool qmp_oob_enabled(MonitorQMP *mon)
|
||||||
@@ -522,14 +537,6 @@ static void monitor_qmp_event(void *opaque, QEMUChrEvent event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void monitor_data_destroy_qmp(MonitorQMP *mon)
|
|
||||||
{
|
|
||||||
json_message_parser_destroy(&mon->parser);
|
|
||||||
qemu_mutex_destroy(&mon->qmp_queue_lock);
|
|
||||||
monitor_qmp_cleanup_req_queue_locked(mon);
|
|
||||||
g_queue_free(mon->qmp_requests);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void monitor_qmp_setup_handlers_bh(void *opaque)
|
static void monitor_qmp_setup_handlers_bh(void *opaque)
|
||||||
{
|
{
|
||||||
MonitorQMP *mon = opaque;
|
MonitorQMP *mon = opaque;
|
||||||
@@ -572,14 +579,11 @@ void monitor_new_qmp(const char *id, const char *chardev_id,
|
|||||||
qemu_chr_fe_set_echo(&mon->parent_obj.chr, true);
|
qemu_chr_fe_set_echo(&mon->parent_obj.chr, true);
|
||||||
|
|
||||||
/* Note: we run QMP monitor in I/O thread when @chr supports that */
|
/* Note: we run QMP monitor in I/O thread when @chr supports that */
|
||||||
monitor_data_init(&mon->parent_obj, true,
|
if (qemu_chr_has_feature(mon->parent_obj.chr.chr,
|
||||||
qemu_chr_has_feature(mon->parent_obj.chr.chr,
|
QEMU_CHAR_FEATURE_GCONTEXT)) {
|
||||||
QEMU_CHAR_FEATURE_GCONTEXT));
|
monitor_iothread_init(&mon->parent_obj);
|
||||||
|
}
|
||||||
|
|
||||||
qemu_mutex_init(&mon->qmp_queue_lock);
|
|
||||||
mon->qmp_requests = g_queue_new();
|
|
||||||
|
|
||||||
json_message_parser_init(&mon->parser, handle_qmp_command, mon, NULL);
|
|
||||||
if (mon->parent_obj.use_io_thread) {
|
if (mon->parent_obj.use_io_thread) {
|
||||||
/*
|
/*
|
||||||
* Make sure the old iowatch is gone. It's possible when
|
* Make sure the old iowatch is gone. It's possible when
|
||||||
|
|||||||
Reference in New Issue
Block a user