All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe
@ 2018-05-24  4:39 Peter Xu
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 1/4] monitor: rename out_lock to mon_lock Peter Xu
                   ` (4 more replies)
  0 siblings, 5 replies; 23+ messages in thread
From: Peter Xu @ 2018-05-24  4:39 UTC (permalink / raw)
  To: qemu-devel
  Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
	Stefan Hajnoczi, Dr . David Alan Gilbert, peterx

v7:
- let monitor_fdset_get_fd() return -errno, touch up qemu_open() to
  translate that into errno.  [Markus]
- touch up comment for Monitor.rs
- rebase, and torture the code a bit with qtest.

v6:
- add/drop some r-bs
- address all the comments from Markus
- rebase, and run some simple qtests to make sure nothing breaks

v5:
- collect r-bs and rebase
- move two close()s outside critical section [Dave]
- move comment to end of line [Stefan]

v4:
- fix a s/cur_mon/mon/ typo

v3:
- add comment for fields that are protected by monitor lock [Stefan]
- drop most of patch 2, only keep the protections for mon->fds [Stefan]
- add one trivial patch to add some more comments for either readline
  and cpu_get/cpu_set [Stefan]
- add protection for monitor_fdset_get_fd() [Stefan]

v2:
- cc correct people... sorry.

Stefan reported this problem that in the future we might start to have
more threads operating on the same Monitor object.  This seris try to
add fundamental support for it.

Please review.  Thanks,

Peter Xu (4):
  monitor: rename out_lock to mon_lock
  monitor: protect mon->fds with mon_lock
  monitor: more comments on lock-free fleids/funcs
  monitor: add lock to protect mon_fdsets

 monitor.c    | 155 +++++++++++++++++++++++++++++++++++++--------------
 util/osdep.c |   3 +-
 2 files changed, 115 insertions(+), 43 deletions(-)

-- 
2.17.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v7 1/4] monitor: rename out_lock to mon_lock
  2018-05-24  4:39 [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe Peter Xu
@ 2018-05-24  4:39 ` Peter Xu
  2018-05-24  8:29   ` Markus Armbruster
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 2/4] monitor: protect mon->fds with mon_lock Peter Xu
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2018-05-24  4:39 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
all the rest.

Since at it, rearrange the Monitor struct a bit.

Reviewed-by: Stefan Hajnoczi <stefanha@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 46814af533..14c681dc8a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -207,15 +207,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;
@@ -224,6 +215,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. */
@@ -366,14 +371,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;
@@ -411,9 +416,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 */
@@ -421,7 +426,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')
@@ -434,7 +439,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)
@@ -725,7 +730,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. */
@@ -745,7 +750,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);
@@ -777,13 +782,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);
@@ -4377,9 +4382,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);
@@ -4399,9 +4404,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.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v7 2/4] monitor: protect mon->fds with mon_lock
  2018-05-24  4:39 [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe Peter Xu
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 1/4] monitor: rename out_lock to mon_lock Peter Xu
@ 2018-05-24  4:39 ` Peter Xu
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs Peter Xu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2018-05-24  4:39 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 14c681dc8a..d6c3c08932 100644
--- a/monitor.c
+++ b/monitor.c
@@ -213,7 +213,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;
 
     /*
@@ -225,6 +224,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.  */
@@ -2189,7 +2189,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) {
@@ -2204,13 +2204,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;
     }
 
@@ -2219,24 +2223,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);
 }
 
@@ -2244,6 +2255,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;
 
@@ -2257,10 +2269,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.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs
  2018-05-24  4:39 [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe Peter Xu
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 1/4] monitor: rename out_lock to mon_lock Peter Xu
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 2/4] monitor: protect mon->fds with mon_lock Peter Xu
@ 2018-05-24  4:39 ` Peter Xu
  2018-05-24  8:08   ` Stefan Hajnoczi
  2018-05-24  8:41   ` Markus Armbruster
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets Peter Xu
  2018-05-24  4:46 ` [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe no-reply
  4 siblings, 2 replies; 23+ messages in thread
From: Peter Xu @ 2018-05-24  4:39 UTC (permalink / raw)
  To: qemu-devel
  Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
	Stefan Hajnoczi, Dr . David Alan Gilbert, peterx

Add some explicit comment for both Readline and cpu_set/cpu_get helpers
that they do not need the mon_lock protection.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 monitor.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/monitor.c b/monitor.c
index d6c3c08932..f01589f945 100644
--- a/monitor.c
+++ b/monitor.c
@@ -207,7 +207,16 @@ 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;
+    // other members that aren't shared
+
     MonitorQMP qmp;
     gchar *mon_cpu_path;
     BlockCompletionFunc *password_completion_cb;
@@ -1313,7 +1322,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;
@@ -1327,6 +1336,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.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets
  2018-05-24  4:39 [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe Peter Xu
                   ` (2 preceding siblings ...)
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs Peter Xu
@ 2018-05-24  4:39 ` Peter Xu
  2018-05-24  9:03   ` Markus Armbruster
  2018-05-24  9:28   ` Stefan Hajnoczi
  2018-05-24  4:46 ` [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe no-reply
  4 siblings, 2 replies; 23+ messages in thread
From: Peter Xu @ 2018-05-24  4:39 UTC (permalink / raw)
  To: qemu-devel
  Cc: Eric Blake, Marc-André Lureau, Markus Armbruster,
	Stefan Hajnoczi, Dr . David Alan Gilbert, peterx

Similar to previous patch, but 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 translate it back into errno.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 monitor.c    | 70 +++++++++++++++++++++++++++++++++++++++++-----------
 util/osdep.c |  3 ++-
 2 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/monitor.c b/monitor.c
index f01589f945..6266ff65c4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -271,6 +271,9 @@ typedef struct QMPRequest QMPRequest;
 /* Protects mon_list, monitor_event_state.  */
 static QemuMutex monitor_lock;
 
+/* Protects mon_fdsets */
+static QemuMutex mon_fdsets_lock;
+
 static QTAILQ_HEAD(mon_list, Monitor) mon_list;
 static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
 static int mon_refcount;
@@ -287,6 +290,16 @@ static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME;
 static void monitor_command_cb(void *opaque, const char *cmdline,
                                void *readline_opaque);
 
+/*
+ * This lock can be used very early, even during param parsing.
+ * Meanwhile it can also be used even at the end of main.  Let's keep
+ * it initialized for the whole lifecycle of QEMU.
+ */
+static void __attribute__((constructor)) mon_fdsets_lock_init(void)
+{
+    qemu_mutex_init(&mon_fdsets_lock);
+}
+
 /**
  * Is @mon a QMP monitor?
  */
@@ -2316,9 +2329,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,
@@ -2353,6 +2368,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;
@@ -2372,10 +2388,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);
@@ -2391,6 +2409,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;
@@ -2420,6 +2439,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;
 }
@@ -2432,6 +2452,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 */
@@ -2452,6 +2473,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 */
@@ -2502,16 +2524,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 = -ENOENT;
 
+    qemu_mutex_lock(&mon_fdsets_lock);
     QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
         if (mon_fdset->id != fdset_id) {
             continue;
@@ -2519,49 +2546,60 @@ 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;
+        break;
     }
+out:
+    qemu_mutex_unlock(&mon_fdsets_lock);
+    return ret;
 #endif
-
-    errno = ENOENT;
-    return -1;
 }
 
 int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
 {
     MonFdset *mon_fdset;
     MonFdsetFd *mon_fdset_fd_dup;
+    int ret = -1;
 
+    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;
+                ret = -1;
+                goto out;
             }
         }
         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);
-        return 0;
+        ret = 0;
+        break;
     }
-    return -1;
+
+out:
+    qemu_mutex_unlock(&mon_fdsets_lock);
+    return ret;
 }
 
 static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
 {
     MonFdset *mon_fdset;
     MonFdsetFd *mon_fdset_fd_dup;
+    int ret = -1;
 
+    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) {
@@ -2570,14 +2608,18 @@ 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;
+                    ret = -1;
+                    goto out;
                 } else {
-                    return mon_fdset->id;
+                    ret = mon_fdset->id;
+                    goto out;
                 }
             }
         }
     }
-    return -1;
+out:
+    qemu_mutex_unlock(&mon_fdsets_lock);
+    return ret;
 }
 
 int monitor_fdset_dup_fd_find(int dup_fd)
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.0

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe
  2018-05-24  4:39 [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe Peter Xu
                   ` (3 preceding siblings ...)
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets Peter Xu
@ 2018-05-24  4:46 ` no-reply
  4 siblings, 0 replies; 23+ messages in thread
From: no-reply @ 2018-05-24  4:46 UTC (permalink / raw)
  To: peterx; +Cc: famz, qemu-devel, armbru, dgilbert, stefanha, marcandre.lureau

Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20180524043952.11245-1-peterx@redhat.com
Subject: [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 t [tag update]            patchew/20180522035629.30428-1-peterx@redhat.com -> patchew/20180522035629.30428-1-peterx@redhat.com
 * [new tag]               patchew/20180524043952.11245-1-peterx@redhat.com -> patchew/20180524043952.11245-1-peterx@redhat.com
Switched to a new branch 'test'
dadcba2375 monitor: add lock to protect mon_fdsets
eda66671b9 monitor: more comments on lock-free fleids/funcs
b7d356e160 monitor: protect mon->fds with mon_lock
35eadfaff2 monitor: rename out_lock to mon_lock

=== OUTPUT BEGIN ===
Checking PATCH 1/4: monitor: rename out_lock to mon_lock...
Checking PATCH 2/4: monitor: protect mon->fds with mon_lock...
Checking PATCH 3/4: monitor: more comments on lock-free fleids/funcs...
ERROR: do not use C99 // comments
#28: FILE: monitor.c:218:
+    // other members that aren't shared

total: 1 errors, 0 warnings, 31 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 4/4: monitor: add lock to protect mon_fdsets...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs Peter Xu
@ 2018-05-24  8:08   ` Stefan Hajnoczi
  2018-05-24  8:49     ` Peter Xu
  2018-05-24  8:41   ` Markus Armbruster
  1 sibling, 1 reply; 23+ messages in thread
From: Stefan Hajnoczi @ 2018-05-24  8:08 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: 575 bytes --]

On Thu, May 24, 2018 at 12:39:51PM +0800, Peter Xu wrote:
> Add some explicit comment for both Readline and cpu_set/cpu_get helpers
> that they do not need the mon_lock protection.
> 
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  monitor.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)

Aside from the checkpatch.pl error that needs to be fixed (I like to use
a git hook to check automatically, see
http://blog.vmsplice.net/2011/03/how-to-automatically-run-checkpatchpl.html):

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 1/4] monitor: rename out_lock to mon_lock
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 1/4] monitor: rename out_lock to mon_lock Peter Xu
@ 2018-05-24  8:29   ` Markus Armbruster
  2018-05-24  8:45     ` Peter Xu
  0 siblings, 1 reply; 23+ messages in thread
From: Markus Armbruster @ 2018-05-24  8:29 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, Dr . David Alan Gilbert, Stefan Hajnoczi,
	Marc-André Lureau

Peter Xu <peterx@redhat.com> writes:

> 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
> all the rest.

Hmm, not sure about "all the rest": PATCH 3 marks a member as not
needing protection.  Shall I change this to "most of the rest" when I
apply?

>
> Since at it, rearrange the Monitor struct a bit.
>
> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
> Signed-off-by: Peter Xu <peterx@redhat.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs Peter Xu
  2018-05-24  8:08   ` Stefan Hajnoczi
@ 2018-05-24  8:41   ` Markus Armbruster
  2018-05-24  8:48     ` Peter Xu
  1 sibling, 1 reply; 23+ messages in thread
From: Markus Armbruster @ 2018-05-24  8:41 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, Dr . David Alan Gilbert, Stefan Hajnoczi,
	Marc-André Lureau

Regarding the subject: what are "fleids"?

Peter Xu <peterx@redhat.com> writes:

> Add some explicit comment for both Readline and cpu_set/cpu_get helpers
> that they do not need the mon_lock protection.
>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  monitor.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/monitor.c b/monitor.c
> index d6c3c08932..f01589f945 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -207,7 +207,16 @@ 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;
> +    // other members that aren't shared

Whoops, misunderstanding!  I meant this line as a placeholder, to
further illustrate my intent.  It should not be committed.  If we need a
comment here, it should use /* traditional comment syntax */.

> +
>      MonitorQMP qmp;
>      gchar *mon_cpu_path;
>      BlockCompletionFunc *password_completion_cb;
> @@ -1313,7 +1322,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;
> @@ -1327,6 +1336,7 @@ int monitor_set_cpu(int cpu_index)
>      return 0;
>  }
>  
> +/* Callers must hold BQL. */
>  static CPUState *mon_get_cpu_sync(bool synchronize)
>  {
>      CPUState *cpu;

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 1/4] monitor: rename out_lock to mon_lock
  2018-05-24  8:29   ` Markus Armbruster
@ 2018-05-24  8:45     ` Peter Xu
  2018-05-24 11:14       ` Markus Armbruster
  0 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2018-05-24  8:45 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Dr . David Alan Gilbert, Stefan Hajnoczi,
	Marc-André Lureau

On Thu, May 24, 2018 at 10:29:20AM +0200, Markus Armbruster wrote:
> Peter Xu <peterx@redhat.com> writes:
> 
> > 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
> > all the rest.
> 
> Hmm, not sure about "all the rest": PATCH 3 marks a member as not
> needing protection.  Shall I change this to "most of the rest" when I
> apply?

Of course. :) Please feel free to touch up the commit message where
necessary (this rule applies to all my patches).  I fully trust your
wordings.

Thanks!

-- 
Peter Xu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs
  2018-05-24  8:41   ` Markus Armbruster
@ 2018-05-24  8:48     ` Peter Xu
  2018-05-24 11:16       ` Markus Armbruster
  0 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2018-05-24  8:48 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Dr . David Alan Gilbert, Stefan Hajnoczi,
	Marc-André Lureau

On Thu, May 24, 2018 at 10:41:09AM +0200, Markus Armbruster wrote:
> Regarding the subject: what are "fleids"?

Ouch. :( I meant the word "fields".

> 
> Peter Xu <peterx@redhat.com> writes:
> 
> > Add some explicit comment for both Readline and cpu_set/cpu_get helpers
> > that they do not need the mon_lock protection.
> >
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> >  monitor.c | 12 +++++++++++-
> >  1 file changed, 11 insertions(+), 1 deletion(-)
> >
> > diff --git a/monitor.c b/monitor.c
> > index d6c3c08932..f01589f945 100644
> > --- a/monitor.c
> > +++ b/monitor.c
> > @@ -207,7 +207,16 @@ 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;
> > +    // other members that aren't shared
> 
> Whoops, misunderstanding!  I meant this line as a placeholder, to
> further illustrate my intent.  It should not be committed.  If we need a
> comment here, it should use /* traditional comment syntax */.

My fault.

Please let me know if you want me to repost...  Thanks,

-- 
Peter Xu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs
  2018-05-24  8:08   ` Stefan Hajnoczi
@ 2018-05-24  8:49     ` Peter Xu
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2018-05-24  8:49 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, Eric Blake, Marc-André Lureau,
	Markus Armbruster, Dr . David Alan Gilbert

On Thu, May 24, 2018 at 09:08:04AM +0100, Stefan Hajnoczi wrote:
> On Thu, May 24, 2018 at 12:39:51PM +0800, Peter Xu wrote:
> > Add some explicit comment for both Readline and cpu_set/cpu_get helpers
> > that they do not need the mon_lock protection.
> > 
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> >  monitor.c | 12 +++++++++++-
> >  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> Aside from the checkpatch.pl error that needs to be fixed (I like to use
> a git hook to check automatically, see
> http://blog.vmsplice.net/2011/03/how-to-automatically-run-checkpatchpl.html):
> 
> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

Thanks Stefan.  I start to use it now!

-- 
Peter Xu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets Peter Xu
@ 2018-05-24  9:03   ` Markus Armbruster
  2018-05-28  7:06     ` Peter Xu
  2018-05-24  9:28   ` Stefan Hajnoczi
  1 sibling, 1 reply; 23+ messages in thread
From: Markus Armbruster @ 2018-05-24  9:03 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, Dr . David Alan Gilbert, Stefan Hajnoczi,
	Marc-André Lureau

Peter Xu <peterx@redhat.com> writes:

> Similar to previous patch, but introduce a new global big lock for
> mon_fdsets.  Take it where needed.

The previous patch is "monitor: more comments on lock-free
fleids/funcs".  Sure you mean that one?
>
> 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 translate it back into errno.

Suggest s/translate/move/.
>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  monitor.c    | 70 +++++++++++++++++++++++++++++++++++++++++-----------
>  util/osdep.c |  3 ++-
>  2 files changed, 58 insertions(+), 15 deletions(-)
>
> diff --git a/monitor.c b/monitor.c
> index f01589f945..6266ff65c4 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -271,6 +271,9 @@ typedef struct QMPRequest QMPRequest;
>  /* Protects mon_list, monitor_event_state.  */

Not this patch's problem: there is no monitor_event_state.  Screwed up
in commit d622cb5879c.  I guess it's monitor_qapi_event_state.

>  static QemuMutex monitor_lock;
>  
> +/* Protects mon_fdsets */
> +static QemuMutex mon_fdsets_lock;
> +
>  static QTAILQ_HEAD(mon_list, Monitor) mon_list;
>  static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
>  static int mon_refcount;

Suggest to move mon_fdsets next to the lock protecting it.

> @@ -287,6 +290,16 @@ static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME;
>  static void monitor_command_cb(void *opaque, const char *cmdline,
>                                 void *readline_opaque);
>  
> +/*
> + * This lock can be used very early, even during param parsing.

Do you mean CLI parsing?

> + * Meanwhile it can also be used even at the end of main.  Let's keep
> + * it initialized for the whole lifecycle of QEMU.
> + */

Awkward question, since our main() is such a tangled mess, but here goes
anyway...  The existing place to initialize monitor.c's globals is
monitor_init_globals().  But that one runs too late, I guess:
parse_add_fd() runs earlier, and calls monitor_fdset_add_fd().  Unclean
even without this lock; no module should be used before its
initialization function runs.  Sure we can't run monitor_init_globals()
sufficiently early?

> +static void __attribute__((constructor)) mon_fdsets_lock_init(void)
> +{
> +    qemu_mutex_init(&mon_fdsets_lock);
> +}
> +
>  /**
>   * Is @mon a QMP monitor?
>   */
> @@ -2316,9 +2329,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,
> @@ -2353,6 +2368,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;
> @@ -2372,10 +2388,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);
> @@ -2391,6 +2409,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;
> @@ -2420,6 +2439,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;
>  }
> @@ -2432,6 +2452,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 */
> @@ -2452,6 +2473,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 */
> @@ -2502,16 +2524,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;

ENOENT feels odd, but I guess makes some sense since there is no way to
add entries.

> +#else
>      MonFdset *mon_fdset;
>      MonFdsetFd *mon_fdset_fd;
>      int mon_fd_flags;
> +    int ret = -ENOENT;
>  
> +    qemu_mutex_lock(&mon_fdsets_lock);
>      QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
>          if (mon_fdset->id != fdset_id) {
>              continue;
> @@ -2519,49 +2546,60 @@ 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;
> +        break;
>      }

I still think

           ret = -EACCES;
           goto out;
       }
       ret = -ENOENT;

   out:

would be clearer.

> +out:
> +    qemu_mutex_unlock(&mon_fdsets_lock);
> +    return ret;
>  #endif
> -
> -    errno = ENOENT;
> -    return -1;
>  }
>  
>  int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
>  {
>      MonFdset *mon_fdset;
>      MonFdsetFd *mon_fdset_fd_dup;
> +    int ret = -1;
>  
> +    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;
> +                ret = -1;

Dead assignment.  Alternatively,

> +                goto out;
>              }
>          }
>          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);
> -        return 0;
> +        ret = 0;
> +        break;
>      }

... add

       ret = -1;

here, and drop the initializer.  Your choice.

> -    return -1;
> +
> +out:
> +    qemu_mutex_unlock(&mon_fdsets_lock);
> +    return ret;
>  }
>  
>  static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
>  {
>      MonFdset *mon_fdset;
>      MonFdsetFd *mon_fdset_fd_dup;
> +    int ret = -1;
>  
> +    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) {
> @@ -2570,14 +2608,18 @@ 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;
> +                    ret = -1;
> +                    goto out;
>                  } else {
> -                    return mon_fdset->id;
> +                    ret = mon_fdset->id;
> +                    goto out;
>                  }
>              }
>          }
>      }
> -    return -1;
> +out:
> +    qemu_mutex_unlock(&mon_fdsets_lock);
> +    return ret;
>  }

Likewise.

>  
>  int monitor_fdset_dup_fd_find(int dup_fd)
> 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;
>          }

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets
  2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets Peter Xu
  2018-05-24  9:03   ` Markus Armbruster
@ 2018-05-24  9:28   ` Stefan Hajnoczi
  2018-05-25  3:30     ` Peter Xu
  1 sibling, 1 reply; 23+ messages in thread
From: Stefan Hajnoczi @ 2018-05-24  9:28 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: 257 bytes --]

On Thu, May 24, 2018 at 12:39:52PM +0800, Peter Xu wrote:
>  int monitor_fdset_get_fd(int64_t fdset_id, int flags)
>  {
> -#ifndef _WIN32
> +#ifdef _WIN32
> +    return -ENOENT;

stubs/fdset.c:monitor_fdset_get_fd() should return -ENOENT instead of -1
now.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 1/4] monitor: rename out_lock to mon_lock
  2018-05-24  8:45     ` Peter Xu
@ 2018-05-24 11:14       ` Markus Armbruster
  0 siblings, 0 replies; 23+ messages in thread
From: Markus Armbruster @ 2018-05-24 11:14 UTC (permalink / raw)
  To: Peter Xu
  Cc: Marc-André Lureau, qemu-devel, Stefan Hajnoczi,
	Dr . David Alan Gilbert

Peter Xu <peterx@redhat.com> writes:

> On Thu, May 24, 2018 at 10:29:20AM +0200, Markus Armbruster wrote:
>> Peter Xu <peterx@redhat.com> writes:
>> 
>> > 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
>> > all the rest.
>> 
>> Hmm, not sure about "all the rest": PATCH 3 marks a member as not
>> needing protection.  Shall I change this to "most of the rest" when I
>> apply?
>
> Of course. :) Please feel free to touch up the commit message where
> necessary (this rule applies to all my patches).  I fully trust your
> wordings.

Well, I don't, so I'll keep asking :)

> Thanks!

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs
  2018-05-24  8:48     ` Peter Xu
@ 2018-05-24 11:16       ` Markus Armbruster
  2018-05-28  6:28         ` Peter Xu
  0 siblings, 1 reply; 23+ messages in thread
From: Markus Armbruster @ 2018-05-24 11:16 UTC (permalink / raw)
  To: Peter Xu
  Cc: Marc-André Lureau, qemu-devel, Stefan Hajnoczi,
	Dr . David Alan Gilbert

Peter Xu <peterx@redhat.com> writes:

> On Thu, May 24, 2018 at 10:41:09AM +0200, Markus Armbruster wrote:
>> Regarding the subject: what are "fleids"?
>
> Ouch. :( I meant the word "fields".

Can touch that up in my tree.

>> Peter Xu <peterx@redhat.com> writes:
>> 
>> > Add some explicit comment for both Readline and cpu_set/cpu_get helpers
>> > that they do not need the mon_lock protection.
>> >
>> > Signed-off-by: Peter Xu <peterx@redhat.com>
>> > ---
>> >  monitor.c | 12 +++++++++++-
>> >  1 file changed, 11 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/monitor.c b/monitor.c
>> > index d6c3c08932..f01589f945 100644
>> > --- a/monitor.c
>> > +++ b/monitor.c
>> > @@ -207,7 +207,16 @@ 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;
>> > +    // other members that aren't shared
>> 
>> Whoops, misunderstanding!  I meant this line as a placeholder, to
>> further illustrate my intent.  It should not be committed.  If we need a
>> comment here, it should use /* traditional comment syntax */.
>
> My fault.
>
> Please let me know if you want me to repost...  Thanks,

Can touch that up, too.  No respin needed unless something more complex
comes up.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets
  2018-05-24  9:28   ` Stefan Hajnoczi
@ 2018-05-25  3:30     ` Peter Xu
  2018-05-25  9:01       ` Stefan Hajnoczi
  0 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2018-05-25  3:30 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, Eric Blake, Marc-André Lureau,
	Markus Armbruster, Dr . David Alan Gilbert

On Thu, May 24, 2018 at 10:28:37AM +0100, Stefan Hajnoczi wrote:
> On Thu, May 24, 2018 at 12:39:52PM +0800, Peter Xu wrote:
> >  int monitor_fdset_get_fd(int64_t fdset_id, int flags)
> >  {
> > -#ifndef _WIN32
> > +#ifdef _WIN32
> > +    return -ENOENT;
> 
> stubs/fdset.c:monitor_fdset_get_fd() should return -ENOENT instead of -1
> now.

Yes that's intended.  That's actually a suggestion from Markus since
changing the return code will simplify the code.  I mentioned it in
the commit message too:

"""
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 translate it back into errno.
"""

Thanks,

-- 
Peter Xu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets
  2018-05-25  3:30     ` Peter Xu
@ 2018-05-25  9:01       ` Stefan Hajnoczi
  2018-05-28  6:29         ` Peter Xu
  0 siblings, 1 reply; 23+ messages in thread
From: Stefan Hajnoczi @ 2018-05-25  9:01 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: 851 bytes --]

On Fri, May 25, 2018 at 11:30:22AM +0800, Peter Xu wrote:
> On Thu, May 24, 2018 at 10:28:37AM +0100, Stefan Hajnoczi wrote:
> > On Thu, May 24, 2018 at 12:39:52PM +0800, Peter Xu wrote:
> > >  int monitor_fdset_get_fd(int64_t fdset_id, int flags)
> > >  {
> > > -#ifndef _WIN32
> > > +#ifdef _WIN32
> > > +    return -ENOENT;
> > 
> > stubs/fdset.c:monitor_fdset_get_fd() should return -ENOENT instead of -1
> > now.
> 
> Yes that's intended.  That's actually a suggestion from Markus since
> changing the return code will simplify the code.

No, I understand that part.  I'm pointing out that
stubs/fdset.c:monitor_fdset_get_fd() still returns -1 because it was not
updated by this patch.

Since this patch changes the return value to -errno, the stub function
should be updated to return a sensible -errno value too.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs
  2018-05-24 11:16       ` Markus Armbruster
@ 2018-05-28  6:28         ` Peter Xu
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2018-05-28  6:28 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Marc-André Lureau, qemu-devel, Stefan Hajnoczi,
	Dr . David Alan Gilbert

On Thu, May 24, 2018 at 01:16:11PM +0200, Markus Armbruster wrote:
> Peter Xu <peterx@redhat.com> writes:
> 
> > On Thu, May 24, 2018 at 10:41:09AM +0200, Markus Armbruster wrote:
> >> Regarding the subject: what are "fleids"?
> >
> > Ouch. :( I meant the word "fields".
> 
> Can touch that up in my tree.

[...]

> >> > +    /*
> >> > +     * 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;
> >> > +    // other members that aren't shared
> >> 
> >> Whoops, misunderstanding!  I meant this line as a placeholder, to
> >> further illustrate my intent.  It should not be committed.  If we need a
> >> comment here, it should use /* traditional comment syntax */.
> >
> > My fault.
> >
> > Please let me know if you want me to repost...  Thanks,
> 
> Can touch that up, too.  No respin needed unless something more complex
> comes up.

I'll modify these two parts in my next post.

Regards,

-- 
Peter Xu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets
  2018-05-25  9:01       ` Stefan Hajnoczi
@ 2018-05-28  6:29         ` Peter Xu
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2018-05-28  6:29 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: qemu-devel, Eric Blake, Marc-André Lureau,
	Markus Armbruster, Dr . David Alan Gilbert

On Fri, May 25, 2018 at 10:01:57AM +0100, Stefan Hajnoczi wrote:
> On Fri, May 25, 2018 at 11:30:22AM +0800, Peter Xu wrote:
> > On Thu, May 24, 2018 at 10:28:37AM +0100, Stefan Hajnoczi wrote:
> > > On Thu, May 24, 2018 at 12:39:52PM +0800, Peter Xu wrote:
> > > >  int monitor_fdset_get_fd(int64_t fdset_id, int flags)
> > > >  {
> > > > -#ifndef _WIN32
> > > > +#ifdef _WIN32
> > > > +    return -ENOENT;
> > > 
> > > stubs/fdset.c:monitor_fdset_get_fd() should return -ENOENT instead of -1
> > > now.
> > 
> > Yes that's intended.  That's actually a suggestion from Markus since
> > changing the return code will simplify the code.
> 
> No, I understand that part.  I'm pointing out that
> stubs/fdset.c:monitor_fdset_get_fd() still returns -1 because it was not
> updated by this patch.
> 
> Since this patch changes the return value to -errno, the stub function
> should be updated to return a sensible -errno value too.

Sorry I overlooked.  You are right, I'll touch that up.

Regards,

-- 
Peter Xu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets
  2018-05-24  9:03   ` Markus Armbruster
@ 2018-05-28  7:06     ` Peter Xu
  2018-05-28 15:19       ` Markus Armbruster
  0 siblings, 1 reply; 23+ messages in thread
From: Peter Xu @ 2018-05-28  7:06 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Dr . David Alan Gilbert, Stefan Hajnoczi,
	Marc-André Lureau

On Thu, May 24, 2018 at 11:03:55AM +0200, Markus Armbruster wrote:
> Peter Xu <peterx@redhat.com> writes:
> 
> > Similar to previous patch, but introduce a new global big lock for
> > mon_fdsets.  Take it where needed.
> 
> The previous patch is "monitor: more comments on lock-free
> fleids/funcs".  Sure you mean that one?

No... I'll remove that sentence directly:

  "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 translate it back into errno.
> 
> Suggest s/translate/move/.

Okay.

> >
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> >  monitor.c    | 70 +++++++++++++++++++++++++++++++++++++++++-----------
> >  util/osdep.c |  3 ++-
> >  2 files changed, 58 insertions(+), 15 deletions(-)
> >
> > diff --git a/monitor.c b/monitor.c
> > index f01589f945..6266ff65c4 100644
> > --- a/monitor.c
> > +++ b/monitor.c
> > @@ -271,6 +271,9 @@ typedef struct QMPRequest QMPRequest;
> >  /* Protects mon_list, monitor_event_state.  */
> 
> Not this patch's problem: there is no monitor_event_state.  Screwed up
> in commit d622cb5879c.  I guess it's monitor_qapi_event_state.

I'll append another patch to do that, and move these fields together.

> 
> >  static QemuMutex monitor_lock;
> >  
> > +/* Protects mon_fdsets */
> > +static QemuMutex mon_fdsets_lock;
> > +
> >  static QTAILQ_HEAD(mon_list, Monitor) mon_list;
> >  static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
> >  static int mon_refcount;
> 
> Suggest to move mon_fdsets next to the lock protecting it.

Will do.

> 
> > @@ -287,6 +290,16 @@ static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME;
> >  static void monitor_command_cb(void *opaque, const char *cmdline,
> >                                 void *readline_opaque);
> >  
> > +/*
> > + * This lock can be used very early, even during param parsing.
> 
> Do you mean CLI parsing?

Yes, will s/param/CLI/.

> 
> > + * Meanwhile it can also be used even at the end of main.  Let's keep
> > + * it initialized for the whole lifecycle of QEMU.
> > + */
> 
> Awkward question, since our main() is such a tangled mess, but here goes
> anyway...  The existing place to initialize monitor.c's globals is
> monitor_init_globals().  But that one runs too late, I guess:
> parse_add_fd() runs earlier, and calls monitor_fdset_add_fd().  Unclean
> even without this lock; no module should be used before its
> initialization function runs.  Sure we can't run monitor_init_globals()
> sufficiently early?

Please see the comment for monitor_init_globals():

    /*
     * Note: qtest_enabled() (which is used in monitor_qapi_event_init())
     * depends on configure_accelerator() above.
     */
    monitor_init_globals();

So I guess it won't work to directly move it earlier.  The init
dependency of QEMU is really complicated.  I'll be fine now that we
mark totally independent init functions (like this one, which is a
mutex init only) as constructor, then we can save some time on
ordering issue.

> 
> > +static void __attribute__((constructor)) mon_fdsets_lock_init(void)
> > +{
> > +    qemu_mutex_init(&mon_fdsets_lock);
> > +}
> > +
> >  /**
> >   * Is @mon a QMP monitor?
> >   */
> > @@ -2316,9 +2329,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,
> > @@ -2353,6 +2368,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;
> > @@ -2372,10 +2388,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);
> > @@ -2391,6 +2409,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;
> > @@ -2420,6 +2439,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;
> >  }
> > @@ -2432,6 +2452,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 */
> > @@ -2452,6 +2473,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 */
> > @@ -2502,16 +2524,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;
> 
> ENOENT feels odd, but I guess makes some sense since there is no way to
> add entries.
> 
> > +#else
> >      MonFdset *mon_fdset;
> >      MonFdsetFd *mon_fdset_fd;
> >      int mon_fd_flags;
> > +    int ret = -ENOENT;
> >  
> > +    qemu_mutex_lock(&mon_fdsets_lock);
> >      QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
> >          if (mon_fdset->id != fdset_id) {
> >              continue;
> > @@ -2519,49 +2546,60 @@ 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;
> > +        break;
> >      }
> 
> I still think
> 
>            ret = -EACCES;
>            goto out;
>        }
>        ret = -ENOENT;
> 
>    out:
> 
> would be clearer.

I'll take your advice.

> 
> > +out:
> > +    qemu_mutex_unlock(&mon_fdsets_lock);
> > +    return ret;
> >  #endif
> > -
> > -    errno = ENOENT;
> > -    return -1;
> >  }
> >  
> >  int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
> >  {
> >      MonFdset *mon_fdset;
> >      MonFdsetFd *mon_fdset_fd_dup;
> > +    int ret = -1;
> >  
> > +    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;
> > +                ret = -1;
> 
> Dead assignment.  Alternatively,
> 
> > +                goto out;
> >              }
> >          }
> >          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);
> > -        return 0;
> > +        ret = 0;
> > +        break;
> >      }
> 
> ... add
> 
>        ret = -1;
> 
> here, and drop the initializer.  Your choice.

The variable "ret" brought some trouble, so I decided to remove it
directly. :)

@@ -2538,20 +2569,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;
 }

> 
> > -    return -1;
> > +
> > +out:
> > +    qemu_mutex_unlock(&mon_fdsets_lock);
> > +    return ret;
> >  }
> >  
> >  static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
> >  {
> >      MonFdset *mon_fdset;
> >      MonFdsetFd *mon_fdset_fd_dup;
> > +    int ret = -1;
> >  
> > +    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) {
> > @@ -2570,14 +2608,18 @@ 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;
> > +                    ret = -1;
> > +                    goto out;
> >                  } else {
> > -                    return mon_fdset->id;
> > +                    ret = mon_fdset->id;
> > +                    goto out;
> >                  }
> >              }
> >          }
> >      }
> > -    return -1;
> > +out:
> > +    qemu_mutex_unlock(&mon_fdsets_lock);
> > +    return ret;
> >  }
> 
> Likewise.

I'll do similar thing to drop "ret":

@@ -2560,6 +2596,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) {
@@ -2568,13 +2605,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;
 }

Thanks,

-- 
Peter Xu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets
  2018-05-28  7:06     ` Peter Xu
@ 2018-05-28 15:19       ` Markus Armbruster
  2018-05-29  5:51         ` Peter Xu
  0 siblings, 1 reply; 23+ messages in thread
From: Markus Armbruster @ 2018-05-28 15:19 UTC (permalink / raw)
  To: Peter Xu
  Cc: Marc-André Lureau, qemu-devel, Stefan Hajnoczi,
	Dr . David Alan Gilbert

Peter Xu <peterx@redhat.com> writes:

> On Thu, May 24, 2018 at 11:03:55AM +0200, Markus Armbruster wrote:
>> Peter Xu <peterx@redhat.com> writes:
>> 
>> > Similar to previous patch, but introduce a new global big lock for
>> > mon_fdsets.  Take it where needed.
>> 
>> The previous patch is "monitor: more comments on lock-free
>> fleids/funcs".  Sure you mean that one?
>
> No... I'll remove that sentence directly:
>
>   "Introduce a new global big lock for mon_fdsets.  Take it where needed."

Works for me.

>> > 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 translate it back into errno.
>> 
>> Suggest s/translate/move/.
>
> Okay.
>
>> >
>> > Signed-off-by: Peter Xu <peterx@redhat.com>
>> > ---
>> >  monitor.c    | 70 +++++++++++++++++++++++++++++++++++++++++-----------
>> >  util/osdep.c |  3 ++-
>> >  2 files changed, 58 insertions(+), 15 deletions(-)
>> >
>> > diff --git a/monitor.c b/monitor.c
>> > index f01589f945..6266ff65c4 100644
>> > --- a/monitor.c
>> > +++ b/monitor.c
>> > @@ -271,6 +271,9 @@ typedef struct QMPRequest QMPRequest;
>> >  /* Protects mon_list, monitor_event_state.  */
>> 
>> Not this patch's problem: there is no monitor_event_state.  Screwed up
>> in commit d622cb5879c.  I guess it's monitor_qapi_event_state.
>
> I'll append another patch to do that, and move these fields together.
>
>> 
>> >  static QemuMutex monitor_lock;
>> >  
>> > +/* Protects mon_fdsets */
>> > +static QemuMutex mon_fdsets_lock;
>> > +
>> >  static QTAILQ_HEAD(mon_list, Monitor) mon_list;
>> >  static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
>> >  static int mon_refcount;
>> 
>> Suggest to move mon_fdsets next to the lock protecting it.
>
> Will do.
>
>> 
>> > @@ -287,6 +290,16 @@ static QEMUClockType event_clock_type = QEMU_CLOCK_REALTIME;
>> >  static void monitor_command_cb(void *opaque, const char *cmdline,
>> >                                 void *readline_opaque);
>> >  
>> > +/*
>> > + * This lock can be used very early, even during param parsing.
>> 
>> Do you mean CLI parsing?
>
> Yes, will s/param/CLI/.
>
>> 
>> > + * Meanwhile it can also be used even at the end of main.  Let's keep
>> > + * it initialized for the whole lifecycle of QEMU.
>> > + */
>> 
>> Awkward question, since our main() is such a tangled mess, but here goes
>> anyway...  The existing place to initialize monitor.c's globals is
>> monitor_init_globals().  But that one runs too late, I guess:
>> parse_add_fd() runs earlier, and calls monitor_fdset_add_fd().  Unclean
>> even without this lock; no module should be used before its
>> initialization function runs.  Sure we can't run monitor_init_globals()
>> sufficiently early?
>
> Please see the comment for monitor_init_globals():
>
>     /*
>      * Note: qtest_enabled() (which is used in monitor_qapi_event_init())
>      * depends on configure_accelerator() above.
>      */
>     monitor_init_globals();
>
> So I guess it won't work to directly move it earlier.  The init
> dependency of QEMU is really complicated.  I'll be fine now that we
> mark totally independent init functions (like this one, which is a
> mutex init only) as constructor, then we can save some time on
> ordering issue.

Let me rephrase.  There's a preexisting issue: main() calls monitor.c
functions before calling its initialization function
monitor_init_globals().  This needs to be cleaned up.  Would you be
willing to do it?

Possible solutions:

* Perhaps we can move monitor_init_globals() up and/or the code calling
  into monitor.c early down sufficiently.

* Calculate event_clock_type on each use instead of ahead of time.  It's
  qtest_enabled ? QEMU_CLOCK_VIRTUAL : QEMU_CLOCK_REALTIME, and neither
  of its users needs to be fast.  Then move monitor_init_globals before
  the code calling into monitor.c.

I'm not opposed to use of constructors for self-contained initialization
(no calls to other modules).  But I don't like initialization spread
over multiple functions.

>> > +static void __attribute__((constructor)) mon_fdsets_lock_init(void)
>> > +{
>> > +    qemu_mutex_init(&mon_fdsets_lock);
>> > +}
>> > +
>> >  /**
>> >   * Is @mon a QMP monitor?
>> >   */
>> > @@ -2316,9 +2329,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,
>> > @@ -2353,6 +2368,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;
>> > @@ -2372,10 +2388,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);
>> > @@ -2391,6 +2409,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;
>> > @@ -2420,6 +2439,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;
>> >  }
>> > @@ -2432,6 +2452,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 */
>> > @@ -2452,6 +2473,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 */
>> > @@ -2502,16 +2524,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;
>> 
>> ENOENT feels odd, but I guess makes some sense since there is no way to
>> add entries.
>> 
>> > +#else
>> >      MonFdset *mon_fdset;
>> >      MonFdsetFd *mon_fdset_fd;
>> >      int mon_fd_flags;
>> > +    int ret = -ENOENT;
>> >  
>> > +    qemu_mutex_lock(&mon_fdsets_lock);
>> >      QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
>> >          if (mon_fdset->id != fdset_id) {
>> >              continue;
>> > @@ -2519,49 +2546,60 @@ 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;
>> > +        break;
>> >      }
>> 
>> I still think
>> 
>>            ret = -EACCES;
>>            goto out;
>>        }
>>        ret = -ENOENT;
>> 
>>    out:
>> 
>> would be clearer.
>
> I'll take your advice.
>
>> 
>> > +out:
>> > +    qemu_mutex_unlock(&mon_fdsets_lock);
>> > +    return ret;
>> >  #endif
>> > -
>> > -    errno = ENOENT;
>> > -    return -1;
>> >  }
>> >  
>> >  int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd)
>> >  {
>> >      MonFdset *mon_fdset;
>> >      MonFdsetFd *mon_fdset_fd_dup;
>> > +    int ret = -1;
>> >  
>> > +    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;
>> > +                ret = -1;
>> 
>> Dead assignment.  Alternatively,
>> 
>> > +                goto out;
>> >              }
>> >          }
>> >          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);
>> > -        return 0;
>> > +        ret = 0;
>> > +        break;
>> >      }
>> 
>> ... add
>> 
>>        ret = -1;
>> 
>> here, and drop the initializer.  Your choice.
>
> The variable "ret" brought some trouble, so I decided to remove it
> directly. :)
>
> @@ -2538,20 +2569,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;
>  }

Works for me.

>> 
>> > -    return -1;
>> > +
>> > +out:
>> > +    qemu_mutex_unlock(&mon_fdsets_lock);
>> > +    return ret;
>> >  }
>> >  
>> >  static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
>> >  {
>> >      MonFdset *mon_fdset;
>> >      MonFdsetFd *mon_fdset_fd_dup;
>> > +    int ret = -1;
>> >  
>> > +    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) {
>> > @@ -2570,14 +2608,18 @@ 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;
>> > +                    ret = -1;
>> > +                    goto out;
>> >                  } else {
>> > -                    return mon_fdset->id;
>> > +                    ret = mon_fdset->id;
>> > +                    goto out;
>> >                  }
>> >              }
>> >          }
>> >      }
>> > -    return -1;
>> > +out:
>> > +    qemu_mutex_unlock(&mon_fdsets_lock);
>> > +    return ret;
>> >  }
>> 
>> Likewise.
>
> I'll do similar thing to drop "ret":
>
> @@ -2560,6 +2596,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) {
> @@ -2568,13 +2605,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;
>  }

Also works for me.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets
  2018-05-28 15:19       ` Markus Armbruster
@ 2018-05-29  5:51         ` Peter Xu
  0 siblings, 0 replies; 23+ messages in thread
From: Peter Xu @ 2018-05-29  5:51 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Marc-André Lureau, qemu-devel, Stefan Hajnoczi,
	Dr . David Alan Gilbert

On Mon, May 28, 2018 at 05:19:08PM +0200, Markus Armbruster wrote:

[...]

> >> 
> >> > + * Meanwhile it can also be used even at the end of main.  Let's keep
> >> > + * it initialized for the whole lifecycle of QEMU.
> >> > + */
> >> 
> >> Awkward question, since our main() is such a tangled mess, but here goes
> >> anyway...  The existing place to initialize monitor.c's globals is
> >> monitor_init_globals().  But that one runs too late, I guess:
> >> parse_add_fd() runs earlier, and calls monitor_fdset_add_fd().  Unclean
> >> even without this lock; no module should be used before its
> >> initialization function runs.  Sure we can't run monitor_init_globals()
> >> sufficiently early?
> >
> > Please see the comment for monitor_init_globals():
> >
> >     /*
> >      * Note: qtest_enabled() (which is used in monitor_qapi_event_init())
> >      * depends on configure_accelerator() above.
> >      */
> >     monitor_init_globals();
> >
> > So I guess it won't work to directly move it earlier.  The init
> > dependency of QEMU is really complicated.  I'll be fine now that we
> > mark totally independent init functions (like this one, which is a
> > mutex init only) as constructor, then we can save some time on
> > ordering issue.
> 
> Let me rephrase.  There's a preexisting issue: main() calls monitor.c
> functions before calling its initialization function
> monitor_init_globals().  This needs to be cleaned up.  Would you be
> willing to do it?
> 
> Possible solutions:
> 
> * Perhaps we can move monitor_init_globals() up and/or the code calling
>   into monitor.c early down sufficiently.
> 
> * Calculate event_clock_type on each use instead of ahead of time.  It's
>   qtest_enabled ? QEMU_CLOCK_VIRTUAL : QEMU_CLOCK_REALTIME, and neither
>   of its users needs to be fast.  Then move monitor_init_globals before
>   the code calling into monitor.c.

Indeed.  Obviously you thought a step further. :)

> 
> I'm not opposed to use of constructors for self-contained initialization
> (no calls to other modules).  But I don't like initialization spread
> over multiple functions.

Since this work will actually decide where I should init this new
fdset lock, so I'll try to do that altogether within the series.

Thanks for your suggestions!  It makes sense.

-- 
Peter Xu

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2018-05-29  5:51 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-24  4:39 [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe Peter Xu
2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 1/4] monitor: rename out_lock to mon_lock Peter Xu
2018-05-24  8:29   ` Markus Armbruster
2018-05-24  8:45     ` Peter Xu
2018-05-24 11:14       ` Markus Armbruster
2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 2/4] monitor: protect mon->fds with mon_lock Peter Xu
2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 3/4] monitor: more comments on lock-free fleids/funcs Peter Xu
2018-05-24  8:08   ` Stefan Hajnoczi
2018-05-24  8:49     ` Peter Xu
2018-05-24  8:41   ` Markus Armbruster
2018-05-24  8:48     ` Peter Xu
2018-05-24 11:16       ` Markus Armbruster
2018-05-28  6:28         ` Peter Xu
2018-05-24  4:39 ` [Qemu-devel] [PATCH v7 4/4] monitor: add lock to protect mon_fdsets Peter Xu
2018-05-24  9:03   ` Markus Armbruster
2018-05-28  7:06     ` Peter Xu
2018-05-28 15:19       ` Markus Armbruster
2018-05-29  5:51         ` Peter Xu
2018-05-24  9:28   ` Stefan Hajnoczi
2018-05-25  3:30     ` Peter Xu
2018-05-25  9:01       ` Stefan Hajnoczi
2018-05-28  6:29         ` Peter Xu
2018-05-24  4:46 ` [Qemu-devel] [PATCH v7 0/4] monitor: let Monitor be thread safe no-reply

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.