qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 2/2] monitor: delay monitor iothread creation


From: Wolfgang Bumiller
Subject: [Qemu-devel] [PATCH v2 2/2] monitor: delay monitor iothread creation
Date: Fri, 28 Sep 2018 09:58:32 +0200

Commit d32749deb615 moved the call to monitor_init_globals()
to before os_daemonize(), making it an unsuitable place to
spawn the monitor iothread as it won't be inherited over the
fork() in os_daemonize().

We now spawn the thread the first time we instantiate a
monitor which actually has use_io_thread == true. Therefore
mon_iothread initialization is protected by monitor_lock.

We still need to create the qmp_dispatcher_bh when not using
iothreads, so this now still happens via
monitor_init_globals().

Signed-off-by: Wolfgang Bumiller <address@hidden>
Fixes: d32749deb615 ("monitor: move init global earlier")
---
Changes to v1:
 - move mon_iothread declaration down to monitor_lock's declaration
   (updating monitor_lock's coverage comment)
 - in monitor_data_init() assert() that mon_iothread is not NULL or
   not used instead of initializing it there, as its usage pattern is
   so that it is a initialized once before being used, or never used
   at all.
 - in monitor_iothread_init(), protect mon_iothread initialization
   with monitor_lock
 - in monitor_init(): run monitor_ithread_init() in the `use_oob`
   branch.
   Note that I currently also test for mon_iothread being NULL there,
   which we could leave this out as spawning new monitors isn't
   something that happens a lot, but I like the idea of avoiding
   taking a lock when not required.
   Otherwise, I can send a v3 with this removed.

 monitor.c | 49 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/monitor.c b/monitor.c
index d47e4259fd..870584a548 100644
--- a/monitor.c
+++ b/monitor.c
@@ -239,9 +239,6 @@ struct Monitor {
     int mux_out;
 };
 
-/* Shared monitor I/O thread */
-IOThread *mon_iothread;
-
 /* Bottom half to dispatch the requests received from I/O thread */
 QEMUBH *qmp_dispatcher_bh;
 
@@ -262,10 +259,11 @@ typedef struct QMPRequest QMPRequest;
 /* QMP checker flags */
 #define QMP_ACCEPT_UNKNOWNS 1
 
-/* Protects mon_list, monitor_qapi_event_state.  */
+/* Protects mon_list, monitor_qapi_event_state and mon_iothread. */
 static QemuMutex monitor_lock;
 static GHashTable *monitor_qapi_event_state;
 static QTAILQ_HEAD(mon_list, Monitor) mon_list;
+IOThread *mon_iothread; /* Shared monitor I/O thread */
 
 /* Protects mon_fdsets */
 static QemuMutex mon_fdsets_lock;
@@ -710,6 +708,7 @@ static void handle_hmp_command(Monitor *mon, const char 
*cmdline);
 static void monitor_data_init(Monitor *mon, bool skip_flush,
                               bool use_io_thread)
 {
+    assert(!use_io_thread || mon_iothread);
     memset(mon, 0, sizeof(Monitor));
     qemu_mutex_init(&mon->mon_lock);
     qemu_mutex_init(&mon->qmp.qmp_queue_lock);
@@ -4453,16 +4452,11 @@ static AioContext *monitor_get_aio_context(void)
 
 static void monitor_iothread_init(void)
 {
-    mon_iothread = iothread_create("mon_iothread", &error_abort);
-
-    /*
-     * The dispatcher BH must run in the main loop thread, since we
-     * have commands assuming that context.  It would be nice to get
-     * rid of those assumptions.
-     */
-    qmp_dispatcher_bh = aio_bh_new(iohandler_get_aio_context(),
-                                   monitor_qmp_bh_dispatcher,
-                                   NULL);
+    qemu_mutex_lock(&monitor_lock);
+    if (!mon_iothread) {
+        mon_iothread = iothread_create("mon_iothread", &error_abort);
+    }
+    qemu_mutex_unlock(&monitor_lock);
 }
 
 void monitor_init_globals(void)
@@ -4472,7 +4466,15 @@ void monitor_init_globals(void)
     sortcmdlist();
     qemu_mutex_init(&monitor_lock);
     qemu_mutex_init(&mon_fdsets_lock);
-    monitor_iothread_init();
+
+    /*
+     * The dispatcher BH must run in the main loop thread, since we
+     * have commands assuming that context.  It would be nice to get
+     * rid of those assumptions.
+     */
+    qmp_dispatcher_bh = aio_bh_new(iohandler_get_aio_context(),
+                                   monitor_qmp_bh_dispatcher,
+                                   NULL);
 }
 
 /* These functions just adapt the readline interface in a typesafe way.  We
@@ -4535,6 +4537,9 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
     monitor_list_append(mon);
 }
 
+/*
+ * This expects to be run in the main thread.
+ */
 void monitor_init(Chardev *chr, int flags)
 {
     Monitor *mon = g_malloc(sizeof(*mon));
@@ -4551,6 +4556,9 @@ void monitor_init(Chardev *chr, int flags)
             error_report("Monitor out-of-band is only supported by QMP");
             exit(1);
         }
+        if (!mon_iothread) {
+            monitor_iothread_init();
+        }
     }
 
     monitor_data_init(mon, false, use_oob);
@@ -4607,7 +4615,9 @@ void monitor_cleanup(void)
      * we need to unregister from chardev below in
      * monitor_data_destroy(), and chardev is not thread-safe yet
      */
-    iothread_stop(mon_iothread);
+    if (mon_iothread) {
+        iothread_stop(mon_iothread);
+    }
 
     /* Flush output buffers and destroy monitors */
     qemu_mutex_lock(&monitor_lock);
@@ -4622,9 +4632,10 @@ void monitor_cleanup(void)
     /* QEMUBHs needs to be deleted before destroying the I/O thread */
     qemu_bh_delete(qmp_dispatcher_bh);
     qmp_dispatcher_bh = NULL;
-
-    iothread_destroy(mon_iothread);
-    mon_iothread = NULL;
+    if (mon_iothread) {
+        iothread_destroy(mon_iothread);
+        mon_iothread = NULL;
+    }
 }
 
 QemuOptsList qemu_mon_opts = {
-- 
2.11.0





reply via email to

[Prev in Thread] Current Thread [Next in Thread]