Kevin Wolf <kw...@redhat.com> writes: > Often, QMP command handlers are not only called to handle QMP commands, > but also from a corresponding HMP command handler. In order to give them > a consistent environment, optionally run HMP command handlers in a > coroutine, too. > > The implementation is a lot simpler than in QMP because for HMP, we > still block the VM while the coroutine is running. > > Signed-off-by: Kevin Wolf <kw...@redhat.com> > --- > monitor/monitor-internal.h | 1 + > monitor/hmp.c | 38 ++++++++++++++++++++++++++++++++------ > 2 files changed, 33 insertions(+), 6 deletions(-) > > diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h > index b55d6df07f..ad2e64be13 100644 > --- a/monitor/monitor-internal.h > +++ b/monitor/monitor-internal.h > @@ -74,6 +74,7 @@ typedef struct HMPCommand { > const char *help; > const char *flags; /* p=preconfig */ > void (*cmd)(Monitor *mon, const QDict *qdict); > + bool coroutine; > /* > * @sub_table is a list of 2nd level of commands. If it does not exist, > * cmd should be used. If it exists, sub_table[?].cmd should be > diff --git a/monitor/hmp.c b/monitor/hmp.c > index 3e73a4c3ce..ab0e3e279f 100644 > --- a/monitor/hmp.c > +++ b/monitor/hmp.c > @@ -1056,12 +1056,25 @@ fail: > return NULL; > } > > +typedef struct HandleHmpCommandCo { > + Monitor *mon; > + const HMPCommand *cmd; > + QDict *qdict; > + bool done; > +} HandleHmpCommandCo; > + > +static void handle_hmp_command_co(void *opaque) > +{ > + HandleHmpCommandCo *data = opaque; > + data->cmd->cmd(data->mon, data->qdict); > + data->done = true; > +} > + > void handle_hmp_command(MonitorHMP *mon, const char *cmdline) > { > QDict *qdict; > const HMPCommand *cmd; > const char *cmd_start = cmdline; > - Monitor *old_mon; > > trace_handle_hmp_command(mon, cmdline); > > @@ -1080,11 +1093,24 @@ void handle_hmp_command(MonitorHMP *mon, const char > *cmdline) > return; > } > > - /* old_mon is non-NULL when called from qmp_human_monitor_command() */ > - old_mon = monitor_cur(); > - monitor_set_cur(qemu_coroutine_self(), &mon->common); > - cmd->cmd(&mon->common, qdict); > - monitor_set_cur(qemu_coroutine_self(), old_mon); > + if (!cmd->coroutine) { > + /* old_mon is non-NULL when called from qmp_human_monitor_command() > */ > + Monitor *old_mon = monitor_cur(); > + monitor_set_cur(qemu_coroutine_self(), &mon->common); > + cmd->cmd(&mon->common, qdict); > + monitor_set_cur(qemu_coroutine_self(), old_mon); > + } else { > + HandleHmpCommandCo data = { > + .mon = &mon->common, > + .cmd = cmd, > + .qdict = qdict, > + .done = false, > + }; > + Coroutine *co = qemu_coroutine_create(handle_hmp_command_co, &data); > + monitor_set_cur(co, &mon->common);
Where is the matching monitor_set_cur(co, NULL)? > + aio_co_enter(qemu_get_aio_context(), co); > + AIO_WAIT_WHILE(qemu_get_aio_context(), !data.done); > + } > > qobject_unref(qdict); > }