* [Qemu-devel] [PATCH v10 1/7] monitor: rename out_lock to mon_lock
2018-06-08 3:55 [Qemu-devel] [PATCH v10 0/7] monitor: let Monitor be thread safe Peter Xu
@ 2018-06-08 3:55 ` Peter Xu
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 2/7] monitor: protect mon->fds with mon_lock Peter Xu
` (5 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Peter Xu @ 2018-06-08 3:55 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
Stefan Hajnoczi, Dr . David Alan Gilbert, peterx
The out_lock is protecting a few Monitor fields. In the future the
monitor code will start to run in multiple threads. We are going to
turn it into a bigger lock to protect not only the out buffer but also
most of the rest.
Since at it, rearrange the Monitor struct a bit.
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
monitor.c | 53 +++++++++++++++++++++++++++++------------------------
1 file changed, 29 insertions(+), 24 deletions(-)
diff --git a/monitor.c b/monitor.c
index 6d0cec552e..5bc9b2dcd0 100644
--- a/monitor.c
+++ b/monitor.c
@@ -206,15 +206,6 @@ struct Monitor {
int suspend_cnt; /* Needs to be accessed atomically */
bool skip_flush;
bool use_io_thr;
-
- /* We can't access guest memory when holding the lock */
- QemuMutex out_lock;
- QString *outbuf;
- guint out_watch;
-
- /* Read under either BQL or out_lock, written with BQL+out_lock. */
- int mux_out;
-
ReadLineState *rs;
MonitorQMP qmp;
gchar *mon_cpu_path;
@@ -223,6 +214,20 @@ struct Monitor {
mon_cmd_t *cmd_table;
QLIST_HEAD(,mon_fd_t) fds;
QTAILQ_ENTRY(Monitor) entry;
+
+ /*
+ * The per-monitor lock. We can't access guest memory when holding
+ * the lock.
+ */
+ QemuMutex mon_lock;
+
+ /*
+ * Fields that are protected by the per-monitor lock.
+ */
+ QString *outbuf;
+ guint out_watch;
+ /* Read under either BQL or mon_lock, written with BQL+mon_lock. */
+ int mux_out;
};
/* Let's add monitor global variables to this struct. */
@@ -365,14 +370,14 @@ static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
{
Monitor *mon = opaque;
- qemu_mutex_lock(&mon->out_lock);
+ qemu_mutex_lock(&mon->mon_lock);
mon->out_watch = 0;
monitor_flush_locked(mon);
- qemu_mutex_unlock(&mon->out_lock);
+ qemu_mutex_unlock(&mon->mon_lock);
return FALSE;
}
-/* Called with mon->out_lock held. */
+/* Called with mon->mon_lock held. */
static void monitor_flush_locked(Monitor *mon)
{
int rc;
@@ -410,9 +415,9 @@ static void monitor_flush_locked(Monitor *mon)
void monitor_flush(Monitor *mon)
{
- qemu_mutex_lock(&mon->out_lock);
+ qemu_mutex_lock(&mon->mon_lock);
monitor_flush_locked(mon);
- qemu_mutex_unlock(&mon->out_lock);
+ qemu_mutex_unlock(&mon->mon_lock);
}
/* flush at every end of line */
@@ -420,7 +425,7 @@ static void monitor_puts(Monitor *mon, const char *str)
{
char c;
- qemu_mutex_lock(&mon->out_lock);
+ qemu_mutex_lock(&mon->mon_lock);
for(;;) {
c = *str++;
if (c == '\0')
@@ -433,7 +438,7 @@ static void monitor_puts(Monitor *mon, const char *str)
monitor_flush_locked(mon);
}
}
- qemu_mutex_unlock(&mon->out_lock);
+ qemu_mutex_unlock(&mon->mon_lock);
}
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
@@ -724,7 +729,7 @@ static void monitor_data_init(Monitor *mon, bool skip_flush,
bool use_io_thr)
{
memset(mon, 0, sizeof(Monitor));
- qemu_mutex_init(&mon->out_lock);
+ qemu_mutex_init(&mon->mon_lock);
qemu_mutex_init(&mon->qmp.qmp_queue_lock);
mon->outbuf = qstring_new();
/* Use *mon_cmds by default. */
@@ -744,7 +749,7 @@ static void monitor_data_destroy(Monitor *mon)
}
readline_free(mon->rs);
qobject_unref(mon->outbuf);
- qemu_mutex_destroy(&mon->out_lock);
+ qemu_mutex_destroy(&mon->mon_lock);
qemu_mutex_destroy(&mon->qmp.qmp_queue_lock);
monitor_qmp_cleanup_req_queue_locked(mon);
monitor_qmp_cleanup_resp_queue_locked(mon);
@@ -776,13 +781,13 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
handle_hmp_command(&hmp, command_line);
cur_mon = old_mon;
- qemu_mutex_lock(&hmp.out_lock);
+ qemu_mutex_lock(&hmp.mon_lock);
if (qstring_get_length(hmp.outbuf) > 0) {
output = g_strdup(qstring_get_str(hmp.outbuf));
} else {
output = g_strdup("");
}
- qemu_mutex_unlock(&hmp.out_lock);
+ qemu_mutex_unlock(&hmp.mon_lock);
out:
monitor_data_destroy(&hmp);
@@ -4381,9 +4386,9 @@ static void monitor_event(void *opaque, int event)
switch (event) {
case CHR_EVENT_MUX_IN:
- qemu_mutex_lock(&mon->out_lock);
+ qemu_mutex_lock(&mon->mon_lock);
mon->mux_out = 0;
- qemu_mutex_unlock(&mon->out_lock);
+ qemu_mutex_unlock(&mon->mon_lock);
if (mon->reset_seen) {
readline_restart(mon->rs);
monitor_resume(mon);
@@ -4403,9 +4408,9 @@ static void monitor_event(void *opaque, int event)
} else {
atomic_inc(&mon->suspend_cnt);
}
- qemu_mutex_lock(&mon->out_lock);
+ qemu_mutex_lock(&mon->mon_lock);
mon->mux_out = 1;
- qemu_mutex_unlock(&mon->out_lock);
+ qemu_mutex_unlock(&mon->mon_lock);
break;
case CHR_EVENT_OPENED:
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v10 2/7] monitor: protect mon->fds with mon_lock
2018-06-08 3:55 [Qemu-devel] [PATCH v10 0/7] monitor: let Monitor be thread safe Peter Xu
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 1/7] monitor: rename out_lock to mon_lock Peter Xu
@ 2018-06-08 3:55 ` Peter Xu
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 3/7] monitor: more comments on lock-free elements Peter Xu
` (4 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Peter Xu @ 2018-06-08 3:55 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
Stefan Hajnoczi, Dr . David Alan Gilbert, peterx
mon->fds were protected by BQL. Now protect it by mon_lock so that it
can even be used in monitor iothread.
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
monitor.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/monitor.c b/monitor.c
index 5bc9b2dcd0..0fba3ccc20 100644
--- a/monitor.c
+++ b/monitor.c
@@ -212,7 +212,6 @@ struct Monitor {
BlockCompletionFunc *password_completion_cb;
void *password_opaque;
mon_cmd_t *cmd_table;
- QLIST_HEAD(,mon_fd_t) fds;
QTAILQ_ENTRY(Monitor) entry;
/*
@@ -224,6 +223,7 @@ struct Monitor {
/*
* Fields that are protected by the per-monitor lock.
*/
+ QLIST_HEAD(, mon_fd_t) fds;
QString *outbuf;
guint out_watch;
/* Read under either BQL or mon_lock, written with BQL+mon_lock. */
@@ -2187,7 +2187,7 @@ static void hmp_acl_remove(Monitor *mon, const QDict *qdict)
void qmp_getfd(const char *fdname, Error **errp)
{
mon_fd_t *monfd;
- int fd;
+ int fd, tmp_fd;
fd = qemu_chr_fe_get_msgfd(&cur_mon->chr);
if (fd == -1) {
@@ -2202,13 +2202,17 @@ void qmp_getfd(const char *fdname, Error **errp)
return;
}
+ qemu_mutex_lock(&cur_mon->mon_lock);
QLIST_FOREACH(monfd, &cur_mon->fds, next) {
if (strcmp(monfd->name, fdname) != 0) {
continue;
}
- close(monfd->fd);
+ tmp_fd = monfd->fd;
monfd->fd = fd;
+ qemu_mutex_unlock(&cur_mon->mon_lock);
+ /* Make sure close() is out of critical section */
+ close(tmp_fd);
return;
}
@@ -2217,24 +2221,31 @@ void qmp_getfd(const char *fdname, Error **errp)
monfd->fd = fd;
QLIST_INSERT_HEAD(&cur_mon->fds, monfd, next);
+ qemu_mutex_unlock(&cur_mon->mon_lock);
}
void qmp_closefd(const char *fdname, Error **errp)
{
mon_fd_t *monfd;
+ int tmp_fd;
+ qemu_mutex_lock(&cur_mon->mon_lock);
QLIST_FOREACH(monfd, &cur_mon->fds, next) {
if (strcmp(monfd->name, fdname) != 0) {
continue;
}
QLIST_REMOVE(monfd, next);
- close(monfd->fd);
+ tmp_fd = monfd->fd;
g_free(monfd->name);
g_free(monfd);
+ qemu_mutex_unlock(&cur_mon->mon_lock);
+ /* Make sure close() is out of critical section */
+ close(tmp_fd);
return;
}
+ qemu_mutex_unlock(&cur_mon->mon_lock);
error_setg(errp, QERR_FD_NOT_FOUND, fdname);
}
@@ -2242,6 +2253,7 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
{
mon_fd_t *monfd;
+ qemu_mutex_lock(&mon->mon_lock);
QLIST_FOREACH(monfd, &mon->fds, next) {
int fd;
@@ -2255,10 +2267,12 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
QLIST_REMOVE(monfd, next);
g_free(monfd->name);
g_free(monfd);
+ qemu_mutex_unlock(&mon->mon_lock);
return fd;
}
+ qemu_mutex_unlock(&mon->mon_lock);
error_setg(errp, "File descriptor named '%s' has not been found", fdname);
return -1;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v10 3/7] monitor: more comments on lock-free elements
2018-06-08 3:55 [Qemu-devel] [PATCH v10 0/7] monitor: let Monitor be thread safe Peter Xu
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 1/7] monitor: rename out_lock to mon_lock Peter Xu
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 2/7] monitor: protect mon->fds with mon_lock Peter Xu
@ 2018-06-08 3:55 ` Peter Xu
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 4/7] monitor: fix comment for monitor_lock Peter Xu
` (3 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Peter Xu @ 2018-06-08 3:55 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
Stefan Hajnoczi, Dr . David Alan Gilbert, peterx
Add some explicit comments for both Readline and cpu_set/cpu_get helpers
that they do not need the mon_lock protection.
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
monitor.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/monitor.c b/monitor.c
index 0fba3ccc20..5c60bf08cc 100644
--- a/monitor.c
+++ b/monitor.c
@@ -206,7 +206,15 @@ struct Monitor {
int suspend_cnt; /* Needs to be accessed atomically */
bool skip_flush;
bool use_io_thr;
+
+ /*
+ * State used only in the thread "owning" the monitor.
+ * If @use_io_thr, this is mon_global.mon_iothread.
+ * Else, it's the main thread.
+ * These members can be safely accessed without locks.
+ */
ReadLineState *rs;
+
MonitorQMP qmp;
gchar *mon_cpu_path;
BlockCompletionFunc *password_completion_cb;
@@ -1311,7 +1319,7 @@ void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable,
cur_mon->qmp.commands = &qmp_commands;
}
-/* set the current CPU defined by the user */
+/* Set the current CPU defined by the user. Callers must hold BQL. */
int monitor_set_cpu(int cpu_index)
{
CPUState *cpu;
@@ -1325,6 +1333,7 @@ int monitor_set_cpu(int cpu_index)
return 0;
}
+/* Callers must hold BQL. */
static CPUState *mon_get_cpu_sync(bool synchronize)
{
CPUState *cpu;
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v10 4/7] monitor: fix comment for monitor_lock
2018-06-08 3:55 [Qemu-devel] [PATCH v10 0/7] monitor: let Monitor be thread safe Peter Xu
` (2 preceding siblings ...)
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 3/7] monitor: more comments on lock-free elements Peter Xu
@ 2018-06-08 3:55 ` Peter Xu
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type Peter Xu
` (2 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Peter Xu @ 2018-06-08 3:55 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
Stefan Hajnoczi, Dr . David Alan Gilbert, peterx
Fix typo in d622cb5879c. Meanwhile move these variables close to each
other. monitor_qapi_event_state can be declared static, add that.
Reported-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
monitor.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/monitor.c b/monitor.c
index 5c60bf08cc..fa9c35631f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -266,10 +266,11 @@ typedef struct QMPRequest QMPRequest;
/* QMP checker flags */
#define QMP_ACCEPT_UNKNOWNS 1
-/* Protects mon_list, monitor_event_state. */
+/* Protects mon_list, monitor_qapi_event_state. */
static QemuMutex monitor_lock;
-
+static GHashTable *monitor_qapi_event_state;
static QTAILQ_HEAD(mon_list, Monitor) mon_list;
+
static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
static int mon_refcount;
@@ -571,8 +572,6 @@ static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
[QAPI_EVENT_VSERPORT_CHANGE] = { 1000 * SCALE_MS },
};
-GHashTable *monitor_qapi_event_state;
-
/*
* Emits the event to every monitor instance, @event is only used for trace
* Called with monitor_lock held.
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type
2018-06-08 3:55 [Qemu-devel] [PATCH v10 0/7] monitor: let Monitor be thread safe Peter Xu
` (3 preceding siblings ...)
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 4/7] monitor: fix comment for monitor_lock Peter Xu
@ 2018-06-08 3:55 ` Peter Xu
2018-06-08 5:38 ` Markus Armbruster
2018-06-08 13:31 ` Stefan Hajnoczi
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 6/7] monitor: move init global earlier Peter Xu
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 7/7] monitor: add lock to protect mon_fdsets Peter Xu
6 siblings, 2 replies; 13+ messages in thread
From: Peter Xu @ 2018-06-08 3:55 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
Stefan Hajnoczi, Dr . David Alan Gilbert, peterx
Instead, use a dynamic function to detect which clock we'll use. The
problem is that the old code will let monitor initialization depend on
configure_accelerator() (that's where qtest_enabled() start to take
effect). After this change, we don't have such a dependency any more.
We just need to make sure configure_accelerator() is called when we
start to use it. Now it's only used in monitor_qapi_event_queue() and
monitor_qapi_event_handler(), so we're good.
Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
monitor.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/monitor.c b/monitor.c
index fa9c35631f..2bda0dfa12 100644
--- a/monitor.c
+++ b/monitor.c
@@ -281,8 +281,6 @@ QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
Monitor *cur_mon;
-static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME;
-
static void monitor_command_cb(void *opaque, const char *cmdline,
void *readline_opaque);
@@ -309,6 +307,19 @@ static inline bool monitor_is_hmp_non_interactive(const Monitor *mon)
return !monitor_is_qmp(mon) && !monitor_uses_readline(mon);
}
+/*
+ * This should never be called before configure_accelerator() since
+ * only until then could we know whether qtest was enabled or not.
+ */
+static inline QEMUClockType monitor_get_clock(void)
+{
+ /*
+ * This allows us to perform tests on the monitor queues to verify
+ * that the rate limits are enforced.
+ */
+ return qtest_enabled() ? QEMU_CLOCK_VIRTUAL : QEMU_CLOCK_REALTIME;
+}
+
/**
* Is the current monitor, if any, a QMP monitor?
*/
@@ -632,7 +643,7 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
* monitor_qapi_event_handler() in evconf->rate ns. Any
* events arriving before then will be delayed until then.
*/
- int64_t now = qemu_clock_get_ns(event_clock_type);
+ int64_t now = qemu_clock_get_ns(monitor_get_clock());
monitor_qapi_event_emit(event, qdict);
@@ -640,7 +651,7 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
evstate->event = event;
evstate->data = qobject_ref(data);
evstate->qdict = NULL;
- evstate->timer = timer_new_ns(event_clock_type,
+ evstate->timer = timer_new_ns(monitor_get_clock(),
monitor_qapi_event_handler,
evstate);
g_hash_table_add(monitor_qapi_event_state, evstate);
@@ -665,7 +676,7 @@ static void monitor_qapi_event_handler(void *opaque)
qemu_mutex_lock(&monitor_lock);
if (evstate->qdict) {
- int64_t now = qemu_clock_get_ns(event_clock_type);
+ int64_t now = qemu_clock_get_ns(monitor_get_clock());
monitor_qapi_event_emit(evstate->event, evstate->qdict);
qobject_unref(evstate->qdict);
@@ -721,10 +732,6 @@ static gboolean qapi_event_throttle_equal(const void *a, const void *b)
static void monitor_qapi_event_init(void)
{
- if (qtest_enabled()) {
- event_clock_type = QEMU_CLOCK_VIRTUAL;
- }
-
monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash,
qapi_event_throttle_equal);
qmp_event_set_func_emit(monitor_qapi_event_queue);
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type Peter Xu
@ 2018-06-08 5:38 ` Markus Armbruster
2018-06-08 6:24 ` Peter Xu
2018-06-08 13:31 ` Stefan Hajnoczi
1 sibling, 1 reply; 13+ messages in thread
From: Markus Armbruster @ 2018-06-08 5:38 UTC (permalink / raw)
To: Peter Xu
Cc: qemu-devel, Dr . David Alan Gilbert, Stefan Hajnoczi,
Marc-André Lureau
Peter Xu <peterx@redhat.com> writes:
> Instead, use a dynamic function to detect which clock we'll use. The
> problem is that the old code will let monitor initialization depend on
> configure_accelerator() (that's where qtest_enabled() start to take
> effect). After this change, we don't have such a dependency any more.
> We just need to make sure configure_accelerator() is called when we
> start to use it. Now it's only used in monitor_qapi_event_queue() and
> monitor_qapi_event_handler(), so we're good.
>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
> monitor.c | 25 ++++++++++++++++---------
> 1 file changed, 16 insertions(+), 9 deletions(-)
>
> diff --git a/monitor.c b/monitor.c
> index fa9c35631f..2bda0dfa12 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -281,8 +281,6 @@ QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
>
> Monitor *cur_mon;
>
> -static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME;
> -
> static void monitor_command_cb(void *opaque, const char *cmdline,
> void *readline_opaque);
>
> @@ -309,6 +307,19 @@ static inline bool monitor_is_hmp_non_interactive(const Monitor *mon)
> return !monitor_is_qmp(mon) && !monitor_uses_readline(mon);
> }
>
> +/*
> + * This should never be called before configure_accelerator() since
> + * only until then could we know whether qtest was enabled or not.
Uh, we know it after then, not until then. What about
/*
* Return the clock to use for recording an event's time.
* Beware: result is invalid before configure_accelerator().
> + */
> +static inline QEMUClockType monitor_get_clock(void)
Suggest to rename to monitor_get_event_clock(), or just
get_event_clock().
Happy to apply touch-ups on commit.
> +{
> + /*
> + * This allows us to perform tests on the monitor queues to verify
> + * that the rate limits are enforced.
> + */
> + return qtest_enabled() ? QEMU_CLOCK_VIRTUAL : QEMU_CLOCK_REALTIME;
> +}
> +
> /**
> * Is the current monitor, if any, a QMP monitor?
> */
> @@ -632,7 +643,7 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
> * monitor_qapi_event_handler() in evconf->rate ns. Any
> * events arriving before then will be delayed until then.
> */
> - int64_t now = qemu_clock_get_ns(event_clock_type);
> + int64_t now = qemu_clock_get_ns(monitor_get_clock());
>
> monitor_qapi_event_emit(event, qdict);
>
> @@ -640,7 +651,7 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
> evstate->event = event;
> evstate->data = qobject_ref(data);
> evstate->qdict = NULL;
> - evstate->timer = timer_new_ns(event_clock_type,
> + evstate->timer = timer_new_ns(monitor_get_clock(),
> monitor_qapi_event_handler,
> evstate);
> g_hash_table_add(monitor_qapi_event_state, evstate);
> @@ -665,7 +676,7 @@ static void monitor_qapi_event_handler(void *opaque)
> qemu_mutex_lock(&monitor_lock);
>
> if (evstate->qdict) {
> - int64_t now = qemu_clock_get_ns(event_clock_type);
> + int64_t now = qemu_clock_get_ns(monitor_get_clock());
>
> monitor_qapi_event_emit(evstate->event, evstate->qdict);
> qobject_unref(evstate->qdict);
> @@ -721,10 +732,6 @@ static gboolean qapi_event_throttle_equal(const void *a, const void *b)
>
> static void monitor_qapi_event_init(void)
> {
> - if (qtest_enabled()) {
> - event_clock_type = QEMU_CLOCK_VIRTUAL;
> - }
> -
> monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash,
> qapi_event_throttle_equal);
> qmp_event_set_func_emit(monitor_qapi_event_queue);
With at least a suitable fix for the comment:
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type
2018-06-08 5:38 ` Markus Armbruster
@ 2018-06-08 6:24 ` Peter Xu
2018-06-08 7:09 ` Markus Armbruster
0 siblings, 1 reply; 13+ messages in thread
From: Peter Xu @ 2018-06-08 6:24 UTC (permalink / raw)
To: Markus Armbruster
Cc: qemu-devel, Dr . David Alan Gilbert, Stefan Hajnoczi,
Marc-André Lureau
On Fri, Jun 08, 2018 at 07:38:11AM +0200, Markus Armbruster wrote:
[...]
> > +/*
> > + * This should never be called before configure_accelerator() since
> > + * only until then could we know whether qtest was enabled or not.
>
> Uh, we know it after then, not until then. What about
>
> /*
> * Return the clock to use for recording an event's time.
> * Beware: result is invalid before configure_accelerator().
Oh, another Chinglish from me. :(
>
> > + */
> > +static inline QEMUClockType monitor_get_clock(void)
>
> Suggest to rename to monitor_get_event_clock(), or just
> get_event_clock().
>
> Happy to apply touch-ups on commit.
That'll be appreciated. Both changes work for me.
[...]
> With at least a suitable fix for the comment:
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
Thanks!
--
Peter Xu
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type
2018-06-08 6:24 ` Peter Xu
@ 2018-06-08 7:09 ` Markus Armbruster
2018-06-11 2:42 ` Peter Xu
0 siblings, 1 reply; 13+ messages in thread
From: Markus Armbruster @ 2018-06-08 7:09 UTC (permalink / raw)
To: Peter Xu
Cc: Markus Armbruster, Marc-André Lureau, qemu-devel,
Stefan Hajnoczi, Dr . David Alan Gilbert
Peter Xu <peterx@redhat.com> writes:
> On Fri, Jun 08, 2018 at 07:38:11AM +0200, Markus Armbruster wrote:
>
> [...]
>
>> > +/*
>> > + * This should never be called before configure_accelerator() since
>> > + * only until then could we know whether qtest was enabled or not.
>>
>> Uh, we know it after then, not until then. What about
>>
>> /*
>> * Return the clock to use for recording an event's time.
>> * Beware: result is invalid before configure_accelerator().
>
> Oh, another Chinglish from me. :(
Useful code, occasional Chinglish, the humility to go with it, and a
sense of humor --- you're doing fine.
[...]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type
2018-06-08 7:09 ` Markus Armbruster
@ 2018-06-11 2:42 ` Peter Xu
0 siblings, 0 replies; 13+ messages in thread
From: Peter Xu @ 2018-06-11 2:42 UTC (permalink / raw)
To: Markus Armbruster
Cc: Marc-André Lureau, qemu-devel, Stefan Hajnoczi,
Dr . David Alan Gilbert
On Fri, Jun 08, 2018 at 09:09:57AM +0200, Markus Armbruster wrote:
> Peter Xu <peterx@redhat.com> writes:
>
> > On Fri, Jun 08, 2018 at 07:38:11AM +0200, Markus Armbruster wrote:
> >
> > [...]
> >
> >> > +/*
> >> > + * This should never be called before configure_accelerator() since
> >> > + * only until then could we know whether qtest was enabled or not.
> >>
> >> Uh, we know it after then, not until then. What about
> >>
> >> /*
> >> * Return the clock to use for recording an event's time.
> >> * Beware: result is invalid before configure_accelerator().
> >
> > Oh, another Chinglish from me. :(
>
> Useful code, occasional Chinglish, the humility to go with it, and a
> sense of humor --- you're doing fine.
Very high evaluation. Thank you. :)
--
Peter Xu
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type Peter Xu
2018-06-08 5:38 ` Markus Armbruster
@ 2018-06-08 13:31 ` Stefan Hajnoczi
1 sibling, 0 replies; 13+ messages in thread
From: Stefan Hajnoczi @ 2018-06-08 13:31 UTC (permalink / raw)
To: Peter Xu
Cc: qemu-devel, Eric Blake, Marc-André Lureau, Markus Armbruster,
Dr . David Alan Gilbert
[-- Attachment #1: Type: text/plain, Size: 837 bytes --]
On Fri, Jun 08, 2018 at 11:55:09AM +0800, Peter Xu wrote:
> Instead, use a dynamic function to detect which clock we'll use. The
> problem is that the old code will let monitor initialization depend on
> configure_accelerator() (that's where qtest_enabled() start to take
> effect). After this change, we don't have such a dependency any more.
> We just need to make sure configure_accelerator() is called when we
> start to use it. Now it's only used in monitor_qapi_event_queue() and
> monitor_qapi_event_handler(), so we're good.
>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
> monitor.c | 25 ++++++++++++++++---------
> 1 file changed, 16 insertions(+), 9 deletions(-)
With Markus' suggestion:
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v10 6/7] monitor: move init global earlier
2018-06-08 3:55 [Qemu-devel] [PATCH v10 0/7] monitor: let Monitor be thread safe Peter Xu
` (4 preceding siblings ...)
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 5/7] monitor: remove event_clock_type Peter Xu
@ 2018-06-08 3:55 ` Peter Xu
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 7/7] monitor: add lock to protect mon_fdsets Peter Xu
6 siblings, 0 replies; 13+ messages in thread
From: Peter Xu @ 2018-06-08 3:55 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
Stefan Hajnoczi, Dr . David Alan Gilbert, peterx
Before this patch, monitor fd helpers might be called even earlier than
monitor_init_globals(). This can be problematic.
After previous work, now monitor_init_globals() does not depend on
accelerator initialization any more. Call it earlier (before CLI
parsing; that's where the monitor APIs might be called) to make sure it
is called before any of the monitor APIs.
Suggested-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
vl.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/vl.c b/vl.c
index 06031715ac..5ddea3d235 100644
--- a/vl.c
+++ b/vl.c
@@ -2978,6 +2978,7 @@ int main(int argc, char **argv, char **envp)
runstate_init();
postcopy_infrastructure_init();
+ monitor_init_globals();
if (qcrypto_init(&err) < 0) {
error_reportf_err(err, "cannot initialize crypto: ");
@@ -4412,12 +4413,6 @@ int main(int argc, char **argv, char **envp)
default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS);
default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS);
- /*
- * Note: qtest_enabled() (which is used in monitor_qapi_event_init())
- * depends on configure_accelerator() above.
- */
- monitor_init_globals();
-
if (qemu_opts_foreach(qemu_find_opts("mon"),
mon_init_func, NULL, NULL)) {
exit(1);
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v10 7/7] monitor: add lock to protect mon_fdsets
2018-06-08 3:55 [Qemu-devel] [PATCH v10 0/7] monitor: let Monitor be thread safe Peter Xu
` (5 preceding siblings ...)
2018-06-08 3:55 ` [Qemu-devel] [PATCH v10 6/7] monitor: move init global earlier Peter Xu
@ 2018-06-08 3:55 ` Peter Xu
6 siblings, 0 replies; 13+ messages in thread
From: Peter Xu @ 2018-06-08 3:55 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
Stefan Hajnoczi, Dr . David Alan Gilbert, peterx
Introduce a new global big lock for mon_fdsets. Take it where needed.
The monitor_fdset_get_fd() handling is a bit tricky: now we need to call
qemu_mutex_unlock() which might pollute errno, so we need to make sure
the correct errno be passed up to the callers. To make things simpler,
we let monitor_fdset_get_fd() return the -errno directly when error
happens, then in qemu_open() we move it back into errno.
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
monitor.c | 52 +++++++++++++++++++++++++++++++++++++++++----------
stubs/fdset.c | 2 +-
util/osdep.c | 3 ++-
3 files changed, 45 insertions(+), 12 deletions(-)
diff --git a/monitor.c b/monitor.c
index 2bda0dfa12..ede4aed8b6 100644
--- a/monitor.c
+++ b/monitor.c
@@ -271,7 +271,10 @@ static QemuMutex monitor_lock;
static GHashTable *monitor_qapi_event_state;
static QTAILQ_HEAD(mon_list, Monitor) mon_list;
+/* Protects mon_fdsets */
+static QemuMutex mon_fdsets_lock;
static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
+
static int mon_refcount;
static mon_cmd_t mon_cmds[];
@@ -2319,9 +2322,11 @@ static void monitor_fdsets_cleanup(void)
MonFdset *mon_fdset;
MonFdset *mon_fdset_next;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH_SAFE(mon_fdset, &mon_fdsets, next, mon_fdset_next) {
monitor_fdset_cleanup(mon_fdset);
}
+ qemu_mutex_unlock(&mon_fdsets_lock);
}
AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque,
@@ -2356,6 +2361,7 @@ void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t fd, Error **errp)
MonFdsetFd *mon_fdset_fd;
char fd_str[60];
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
if (mon_fdset->id != fdset_id) {
continue;
@@ -2375,10 +2381,12 @@ void qmp_remove_fd(int64_t fdset_id, bool has_fd, int64_t fd, Error **errp)
goto error;
}
monitor_fdset_cleanup(mon_fdset);
+ qemu_mutex_unlock(&mon_fdsets_lock);
return;
}
error:
+ qemu_mutex_unlock(&mon_fdsets_lock);
if (has_fd) {
snprintf(fd_str, sizeof(fd_str), "fdset-id:%" PRId64 ", fd:%" PRId64,
fdset_id, fd);
@@ -2394,6 +2402,7 @@ FdsetInfoList *qmp_query_fdsets(Error **errp)
MonFdsetFd *mon_fdset_fd;
FdsetInfoList *fdset_list = NULL;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
FdsetInfoList *fdset_info = g_malloc0(sizeof(*fdset_info));
FdsetFdInfoList *fdsetfd_list = NULL;
@@ -2423,6 +2432,7 @@ FdsetInfoList *qmp_query_fdsets(Error **errp)
fdset_info->next = fdset_list;
fdset_list = fdset_info;
}
+ qemu_mutex_unlock(&mon_fdsets_lock);
return fdset_list;
}
@@ -2435,6 +2445,7 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
MonFdsetFd *mon_fdset_fd;
AddfdInfo *fdinfo;
+ qemu_mutex_lock(&mon_fdsets_lock);
if (has_fdset_id) {
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
/* Break if match found or match impossible due to ordering by ID */
@@ -2455,6 +2466,7 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
if (fdset_id < 0) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id",
"a non-negative value");
+ qemu_mutex_unlock(&mon_fdsets_lock);
return NULL;
}
/* Use specified fdset ID */
@@ -2505,16 +2517,21 @@ AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
fdinfo->fdset_id = mon_fdset->id;
fdinfo->fd = mon_fdset_fd->fd;
+ qemu_mutex_unlock(&mon_fdsets_lock);
return fdinfo;
}
int monitor_fdset_get_fd(int64_t fdset_id, int flags)
{
-#ifndef _WIN32
+#ifdef _WIN32
+ return -ENOENT;
+#else
MonFdset *mon_fdset;
MonFdsetFd *mon_fdset_fd;
int mon_fd_flags;
+ int ret;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
if (mon_fdset->id != fdset_id) {
continue;
@@ -2522,20 +2539,24 @@ int monitor_fdset_get_fd(int64_t fdset_id, int flags)
QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
mon_fd_flags = fcntl(mon_fdset_fd->fd, F_GETFL);
if (mon_fd_flags == -1) {
- return -1;
+ ret = -errno;
+ goto out;
}
if ((flags & O_ACCMODE) == (mon_fd_flags & O_ACCMODE)) {
- return mon_fdset_fd->fd;
+ ret = mon_fdset_fd->fd;
+ goto out;
}
}
- errno = EACCES;
- return -1;
+ ret = -EACCES;
+ goto out;
}
-#endif
+ ret = -ENOENT;
- errno = ENOENT;
- return -1;
+out:
+ qemu_mutex_unlock(&mon_fdsets_lock);
+ return ret;
+#endif
}
int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
@@ -2543,20 +2564,25 @@ int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
MonFdset *mon_fdset;
MonFdsetFd *mon_fdset_fd_dup;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
if (mon_fdset->id != fdset_id) {
continue;
}
QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
if (mon_fdset_fd_dup->fd == dup_fd) {
- return -1;
+ goto err;
}
}
mon_fdset_fd_dup = g_malloc0(sizeof(*mon_fdset_fd_dup));
mon_fdset_fd_dup->fd = dup_fd;
QLIST_INSERT_HEAD(&mon_fdset->dup_fds, mon_fdset_fd_dup, next);
+ qemu_mutex_unlock(&mon_fdsets_lock);
return 0;
}
+
+err:
+ qemu_mutex_unlock(&mon_fdsets_lock);
return -1;
}
@@ -2565,6 +2591,7 @@ static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
MonFdset *mon_fdset;
MonFdsetFd *mon_fdset_fd_dup;
+ qemu_mutex_lock(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
QLIST_FOREACH(mon_fdset_fd_dup, &mon_fdset->dup_fds, next) {
if (mon_fdset_fd_dup->fd == dup_fd) {
@@ -2573,13 +2600,17 @@ static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
if (QLIST_EMPTY(&mon_fdset->dup_fds)) {
monitor_fdset_cleanup(mon_fdset);
}
- return -1;
+ goto err;
} else {
+ qemu_mutex_unlock(&mon_fdsets_lock);
return mon_fdset->id;
}
}
}
}
+
+err:
+ qemu_mutex_unlock(&mon_fdsets_lock);
return -1;
}
@@ -4519,6 +4550,7 @@ void monitor_init_globals(void)
monitor_qapi_event_init();
sortcmdlist();
qemu_mutex_init(&monitor_lock);
+ qemu_mutex_init(&mon_fdsets_lock);
monitor_iothread_init();
}
diff --git a/stubs/fdset.c b/stubs/fdset.c
index 6020cf28c8..4f3edf2ea4 100644
--- a/stubs/fdset.c
+++ b/stubs/fdset.c
@@ -14,7 +14,7 @@ int monitor_fdset_dup_fd_find(int dup_fd)
int monitor_fdset_get_fd(int64_t fdset_id, int flags)
{
- return -1;
+ return -ENOENT;
}
void monitor_fdset_dup_fd_remove(int dupfd)
diff --git a/util/osdep.c b/util/osdep.c
index a73de0e1ba..ea51d500b6 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -302,7 +302,8 @@ int qemu_open(const char *name, int flags, ...)
}
fd = monitor_fdset_get_fd(fdset_id, flags);
- if (fd == -1) {
+ if (fd < 0) {
+ errno = -fd;
return -1;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread