ae23c9
From 59776df6fa3156a467e889ae00751da4bf6857eb Mon Sep 17 00:00:00 2001
ae23c9
From: Fam Zheng <famz@redhat.com>
ae23c9
Date: Tue, 9 Oct 2018 08:16:50 +0100
ae23c9
Subject: [PATCH 06/17] aio-posix: compute timeout before polling
ae23c9
ae23c9
RH-Author: Fam Zheng <famz@redhat.com>
ae23c9
Message-id: <20181009081651.15463-5-famz@redhat.com>
ae23c9
Patchwork-id: 82453
ae23c9
O-Subject: [RHEL8/rhel qemu-kvm PATCH 4/5] aio-posix: compute timeout before polling
ae23c9
Bugzilla: 1632622
ae23c9
RH-Acked-by: Thomas Huth <thuth@redhat.com>
ae23c9
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
ae23c9
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
ae23c9
ae23c9
From: Paolo Bonzini <pbonzini@redhat.com>
ae23c9
ae23c9
BZ: 1632622
ae23c9
ae23c9
This is a preparation for the next patch, and also a very small
ae23c9
optimization.  Compute the timeout only once, before invoking
ae23c9
try_poll_mode, and adjust it in run_poll_handlers.  The adjustment
ae23c9
is the polling time when polling fails, or zero (non-blocking) if
ae23c9
polling succeeds.
ae23c9
ae23c9
Fixes: 70232b5253a3c4e03ed1ac47ef9246a8ac66c6fa
ae23c9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
ae23c9
Message-Id: <20180912171040.1732-3-pbonzini@redhat.com>
ae23c9
Reviewed-by: Fam Zheng <famz@redhat.com>
ae23c9
Signed-off-by: Fam Zheng <famz@redhat.com>
ae23c9
(cherry picked from commit e30cffa04d52e35996569f1cfac111be19576bde)
ae23c9
Signed-off-by: Fam Zheng <famz@redhat.com>
ae23c9
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ae23c9
---
ae23c9
 util/aio-posix.c  | 59 ++++++++++++++++++++++++++++++++-----------------------
ae23c9
 util/trace-events |  4 ++--
ae23c9
 2 files changed, 36 insertions(+), 27 deletions(-)
ae23c9
ae23c9
diff --git a/util/aio-posix.c b/util/aio-posix.c
ae23c9
index 1d7cc53..1b17597 100644
ae23c9
--- a/util/aio-posix.c
ae23c9
+++ b/util/aio-posix.c
ae23c9
@@ -490,7 +490,7 @@ static void add_pollfd(AioHandler *node)
ae23c9
     npfd++;
ae23c9
 }
ae23c9
 
ae23c9
-static bool run_poll_handlers_once(AioContext *ctx)
ae23c9
+static bool run_poll_handlers_once(AioContext *ctx, int64_t *timeout)
ae23c9
 {
ae23c9
     bool progress = false;
ae23c9
     AioHandler *node;
ae23c9
@@ -500,6 +500,7 @@ static bool run_poll_handlers_once(AioContext *ctx)
ae23c9
             aio_node_check(ctx, node->is_external) &&
ae23c9
             node->io_poll(node->opaque) &&
ae23c9
             node->opaque != &ctx->notifier) {
ae23c9
+            *timeout = 0;
ae23c9
             progress = true;
ae23c9
         }
ae23c9
 
ae23c9
@@ -522,31 +523,38 @@ static bool run_poll_handlers_once(AioContext *ctx)
ae23c9
  *
ae23c9
  * Returns: true if progress was made, false otherwise
ae23c9
  */
ae23c9
-static bool run_poll_handlers(AioContext *ctx, int64_t max_ns)
ae23c9
+static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
ae23c9
 {
ae23c9
     bool progress;
ae23c9
-    int64_t end_time;
ae23c9
+    int64_t start_time, elapsed_time;
ae23c9
 
ae23c9
     assert(ctx->notify_me);
ae23c9
     assert(qemu_lockcnt_count(&ctx->list_lock) > 0);
ae23c9
 
ae23c9
-    trace_run_poll_handlers_begin(ctx, max_ns);
ae23c9
-
ae23c9
-    end_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + max_ns;
ae23c9
+    trace_run_poll_handlers_begin(ctx, max_ns, *timeout);
ae23c9
 
ae23c9
+    start_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
ae23c9
     do {
ae23c9
-        progress = run_poll_handlers_once(ctx);
ae23c9
-    } while (!progress && qemu_clock_get_ns(QEMU_CLOCK_REALTIME) < end_time
ae23c9
+        progress = run_poll_handlers_once(ctx, timeout);
ae23c9
+        elapsed_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start_time;
ae23c9
+    } while (!progress && elapsed_time < max_ns
ae23c9
              && !atomic_read(&ctx->poll_disable_cnt));
ae23c9
 
ae23c9
-    trace_run_poll_handlers_end(ctx, progress);
ae23c9
+    /* If time has passed with no successful polling, adjust *timeout to
ae23c9
+     * keep the same ending time.
ae23c9
+     */
ae23c9
+    if (*timeout != -1) {
ae23c9
+        *timeout -= MIN(*timeout, elapsed_time);
ae23c9
+    }
ae23c9
 
ae23c9
+    trace_run_poll_handlers_end(ctx, progress, *timeout);
ae23c9
     return progress;
ae23c9
 }
ae23c9
 
ae23c9
 /* try_poll_mode:
ae23c9
  * @ctx: the AioContext
ae23c9
- * @blocking: busy polling is only attempted when blocking is true
ae23c9
+ * @timeout: timeout for blocking wait, computed by the caller and updated if
ae23c9
+ *    polling succeeds.
ae23c9
  *
ae23c9
  * ctx->notify_me must be non-zero so this function can detect aio_notify().
ae23c9
  *
ae23c9
@@ -554,19 +562,16 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns)
ae23c9
  *
ae23c9
  * Returns: true if progress was made, false otherwise
ae23c9
  */
ae23c9
-static bool try_poll_mode(AioContext *ctx, bool blocking)
ae23c9
+static bool try_poll_mode(AioContext *ctx, int64_t *timeout)
ae23c9
 {
ae23c9
-    if (blocking && ctx->poll_max_ns && !atomic_read(&ctx->poll_disable_cnt)) {
ae23c9
-        /* See qemu_soonest_timeout() uint64_t hack */
ae23c9
-        int64_t max_ns = MIN((uint64_t)aio_compute_timeout(ctx),
ae23c9
-                             (uint64_t)ctx->poll_ns);
ae23c9
+    /* See qemu_soonest_timeout() uint64_t hack */
ae23c9
+    int64_t max_ns = MIN((uint64_t)*timeout, (uint64_t)ctx->poll_ns);
ae23c9
 
ae23c9
-        if (max_ns) {
ae23c9
-            poll_set_started(ctx, true);
ae23c9
+    if (max_ns && !atomic_read(&ctx->poll_disable_cnt)) {
ae23c9
+        poll_set_started(ctx, true);
ae23c9
 
ae23c9
-            if (run_poll_handlers(ctx, max_ns)) {
ae23c9
-                return true;
ae23c9
-            }
ae23c9
+        if (run_poll_handlers(ctx, max_ns, timeout)) {
ae23c9
+            return true;
ae23c9
         }
ae23c9
     }
ae23c9
 
ae23c9
@@ -575,7 +580,7 @@ static bool try_poll_mode(AioContext *ctx, bool blocking)
ae23c9
     /* Even if we don't run busy polling, try polling once in case it can make
ae23c9
      * progress and the caller will be able to avoid ppoll(2)/epoll_wait(2).
ae23c9
      */
ae23c9
-    return run_poll_handlers_once(ctx);
ae23c9
+    return run_poll_handlers_once(ctx, timeout);
ae23c9
 }
ae23c9
 
ae23c9
 bool aio_poll(AioContext *ctx, bool blocking)
ae23c9
@@ -605,8 +610,14 @@ bool aio_poll(AioContext *ctx, bool blocking)
ae23c9
         start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
ae23c9
     }
ae23c9
 
ae23c9
-    progress = try_poll_mode(ctx, blocking);
ae23c9
-    if (!progress) {
ae23c9
+    timeout = blocking ? aio_compute_timeout(ctx) : 0;
ae23c9
+    progress = try_poll_mode(ctx, &timeout);
ae23c9
+    assert(!(timeout && progress));
ae23c9
+
ae23c9
+    /* If polling is allowed, non-blocking aio_poll does not need the
ae23c9
+     * system call---a single round of run_poll_handlers_once suffices.
ae23c9
+     */
ae23c9
+    if (timeout || atomic_read(&ctx->poll_disable_cnt)) {
ae23c9
         assert(npfd == 0);
ae23c9
 
ae23c9
         /* fill pollfds */
ae23c9
@@ -620,8 +631,6 @@ bool aio_poll(AioContext *ctx, bool blocking)
ae23c9
             }
ae23c9
         }
ae23c9
 
ae23c9
-        timeout = blocking ? aio_compute_timeout(ctx) : 0;
ae23c9
-
ae23c9
         /* wait until next event */
ae23c9
         if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
ae23c9
             AioHandler epoll_handler;
ae23c9
diff --git a/util/trace-events b/util/trace-events
ae23c9
index 4822434..79569b7 100644
ae23c9
--- a/util/trace-events
ae23c9
+++ b/util/trace-events
ae23c9
@@ -1,8 +1,8 @@
ae23c9
 # See docs/devel/tracing.txt for syntax documentation.
ae23c9
 
ae23c9
 # util/aio-posix.c
ae23c9
-run_poll_handlers_begin(void *ctx, int64_t max_ns) "ctx %p max_ns %"PRId64
ae23c9
-run_poll_handlers_end(void *ctx, bool progress) "ctx %p progress %d"
ae23c9
+run_poll_handlers_begin(void *ctx, int64_t max_ns, int64_t timeout) "ctx %p max_ns %"PRId64 " timeout %"PRId64
ae23c9
+run_poll_handlers_end(void *ctx, bool progress, int64_t timeout) "ctx %p progress %d new timeout %"PRId64
ae23c9
 poll_shrink(void *ctx, int64_t old, int64_t new) "ctx %p old %"PRId64" new %"PRId64
ae23c9
 poll_grow(void *ctx, int64_t old, int64_t new) "ctx %p old %"PRId64" new %"PRId64
ae23c9
 
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9