Patchwork [8/9] main-loop: drive main event loop via QContext

login
register
mail settings
Submitter Michael Roth
Date May 3, 2013, 4:03 p.m.
Message ID <1367597032-28934-9-git-send-email-mdroth@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/241345/
State New
Headers show

Comments

Michael Roth - May 3, 2013, 4:03 p.m.
This series attaches the global AioContext's GSource to the QContext
we've layered on top of the main GMainContext. This, paired with the
similar treatment given to IOHandlers earlier, allows us to drive the
main loop without using fill/poll functions to add/dispatch events that
are external to our main (Glib)QContext.

This patch breaks Slirp, which needs to be re-worked so that it can be
driven via QContext. Patches are on the list to port that to GSource,
so we assume for the purposes of this RFC that that's a solved problem.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 async.c             |   16 +++++++++++
 include/block/aio.h |    6 +++++
 main-loop.c         |   75 ++++++++++++++++++---------------------------------
 3 files changed, 48 insertions(+), 49 deletions(-)

Patch

diff --git a/async.c b/async.c
index 90fe906..a36e2e1 100644
--- a/async.c
+++ b/async.c
@@ -22,10 +22,13 @@ 
  * THE SOFTWARE.
  */
 
+#include <glib.h>
 #include "qemu-common.h"
 #include "block/aio.h"
 #include "block/thread-pool.h"
 #include "qemu/main-loop.h"
+#include "qcontext/qcontext.h"
+#include "qcontext/glib-qcontext.h"
 
 /***********************************************************/
 /* bottom halves (can be seen as timers which expire ASAP) */
@@ -219,6 +222,19 @@  AioContext *aio_context_new(void)
     return ctx;
 }
 
+void aio_context_attach(AioContext *ctx, QContext *qctx)
+{
+    GSource *aio_gsource = aio_get_g_source(ctx);
+    GMainContext *qctx_main_context =
+        glib_qcontext_get_context(GLIB_QCONTEXT(qctx));
+
+    /* TODO: implement AioContext as a QSource instead of a GSource
+     * so we can attach to any QContext implementation instead of
+     * acting directly on the underlying GMainContext
+     */
+    g_source_attach(aio_gsource, qctx_main_context);
+}
+
 void aio_context_ref(AioContext *ctx)
 {
     g_source_ref(&ctx->source);
diff --git a/include/block/aio.h b/include/block/aio.h
index 1836793..400df54 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -17,6 +17,7 @@ 
 #include "qemu-common.h"
 #include "qemu/queue.h"
 #include "qemu/event_notifier.h"
+#include "qcontext/qcontext.h"
 
 typedef struct BlockDriverAIOCB BlockDriverAIOCB;
 typedef void BlockDriverCompletionFunc(void *opaque, int ret);
@@ -244,4 +245,9 @@  void qemu_aio_set_fd_handler(int fd,
                              void *opaque);
 #endif
 
+/* Attach an AioContext to a QContext so that it can be driven by a
+ * QContext-based event loop
+ */
+void aio_context_attach(AioContext *ctx, QContext *qctx);
+
 #endif
diff --git a/main-loop.c b/main-loop.c
index ae284a6..708581d 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -136,7 +136,6 @@  static GArray *gpollfds;
 int qemu_init_main_loop(void)
 {
     int ret;
-    GSource *src;
     Error *err = NULL;
 
     init_clocks();
@@ -159,62 +158,37 @@  int qemu_init_main_loop(void)
         return ret;
     }
 
+    /* TODO: we can drop gpollfds completely once we integrate
+     * Ping Fan's slirp->glib patches. Until then slirp won't
+     * work since we're no longer driving it via fill/poll
+     * functions
+     */
     gpollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD));
     qemu_aio_context = aio_context_new();
-    src = aio_get_g_source(qemu_aio_context);
-    g_source_attach(src, NULL);
-    g_source_unref(src);
+    aio_context_attach(qemu_aio_context, qemu_qcontext);
     return 0;
 }
 
-static int max_priority;
-
 #ifndef _WIN32
-static int glib_pollfds_idx;
-static int glib_n_poll_fds;
-
-static void glib_pollfds_fill(uint32_t *cur_timeout)
-{
-    GMainContext *context = g_main_context_default();
-    int timeout = 0;
-    int n;
-
-    g_main_context_prepare(context, &max_priority);
-
-    glib_pollfds_idx = gpollfds->len;
-    n = glib_n_poll_fds;
-    do {
-        GPollFD *pfds;
-        glib_n_poll_fds = n;
-        g_array_set_size(gpollfds, glib_pollfds_idx + glib_n_poll_fds);
-        pfds = &g_array_index(gpollfds, GPollFD, glib_pollfds_idx);
-        n = g_main_context_query(context, max_priority, &timeout, pfds,
-                                 glib_n_poll_fds);
-    } while (n != glib_n_poll_fds);
-
-    if (timeout >= 0 && timeout < *cur_timeout) {
-        *cur_timeout = timeout;
-    }
-}
-
-static void glib_pollfds_poll(void)
-{
-    GMainContext *context = g_main_context_default();
-    GPollFD *pfds = &g_array_index(gpollfds, GPollFD, glib_pollfds_idx);
-
-    if (g_main_context_check(context, max_priority, pfds, glib_n_poll_fds)) {
-        g_main_context_dispatch(context);
-    }
-}
 
 #define MAX_MAIN_LOOP_SPIN (1000)
 
 static int os_host_main_loop_wait(uint32_t timeout)
 {
-    int ret;
+    QContext *qctx = qemu_get_qcontext();
+    gboolean ret;
+    int calculated_timeout = 0;
+    int events_dispatched = 0;
     static int spin_counter;
 
-    glib_pollfds_fill(&timeout);
+    ret = qcontext_prepare(qctx, &calculated_timeout);
+    if (ret) {
+        qcontext_dispatch(qctx);
+        events_dispatched = 1;
+    }
+    if (calculated_timeout >= 0 && calculated_timeout < timeout) {
+        timeout = calculated_timeout;
+    }
 
     /* If the I/O thread is very busy or we are incorrectly busy waiting in
      * the I/O thread, this can lead to starvation of the BQL such that the
@@ -241,15 +215,16 @@  static int os_host_main_loop_wait(uint32_t timeout)
     } else {
         spin_counter++;
     }
-
-    ret = g_poll((GPollFD *)gpollfds->data, gpollfds->len, timeout);
-
+    ret = qcontext_poll(qctx, timeout);
     if (timeout > 0) {
         qemu_mutex_lock_iothread();
     }
+    if (ret && qcontext_check(qctx)) {
+        qcontext_dispatch(qctx);
+        events_dispatched = 1;
+    }
 
-    glib_pollfds_poll();
-    return ret;
+    return events_dispatched;
 }
 #else
 /***********************************************************/
@@ -391,6 +366,8 @@  static void pollfds_poll(GArray *pollfds, int nfds, fd_set *rfds,
     }
 }
 
+static int max_priority;
+
 static int os_host_main_loop_wait(uint32_t timeout)
 {
     GMainContext *context = g_main_context_default();