diff mbox

[14/25] coroutine: Add co_yield_timeout()

Message ID 1424887718-10800-15-git-send-email-mreitz@redhat.com
State New
Headers show

Commit Message

Max Reitz Feb. 25, 2015, 6:08 p.m. UTC
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 include/block/coroutine.h |  6 ++++++
 qemu-coroutine-sleep.c    | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)
diff mbox

Patch

diff --git a/include/block/coroutine.h b/include/block/coroutine.h
index 20c027a..a05aefb 100644
--- a/include/block/coroutine.h
+++ b/include/block/coroutine.h
@@ -216,4 +216,10 @@  void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
  */
 void coroutine_fn yield_until_fd_readable(int fd);
 
+/**
+ * Yield with a timeout given in nanoseconds. Returns true if the timeout
+ * expired.
+ */
+bool coroutine_fn co_yield_timeout(QEMUClockType type, int64_t ns);
+
 #endif /* QEMU_COROUTINE_H */
diff --git a/qemu-coroutine-sleep.c b/qemu-coroutine-sleep.c
index 9abb7fd..9b33bf0 100644
--- a/qemu-coroutine-sleep.c
+++ b/qemu-coroutine-sleep.c
@@ -14,6 +14,7 @@ 
 #include "block/coroutine.h"
 #include "qemu/timer.h"
 #include "block/aio.h"
+#include "qemu/main-loop.h"
 
 typedef struct CoSleepCB {
     QEMUTimer *ts;
@@ -39,3 +40,36 @@  void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
     timer_del(sleep_cb.ts);
     timer_free(sleep_cb.ts);
 }
+
+typedef struct CoTimeoutCB {
+    Coroutine *co;
+    bool expired;
+} CoTimeoutCB;
+
+static void co_timeout_cb(void *opaque)
+{
+    CoTimeoutCB *timeout_cb = opaque;
+
+    timeout_cb->expired = true;
+    qemu_coroutine_enter(timeout_cb->co, NULL);
+}
+
+bool coroutine_fn co_yield_timeout(QEMUClockType type, int64_t ns)
+{
+    QEMUTimer timer;
+    CoTimeoutCB timeout_cb = {
+        .co = qemu_coroutine_self()
+    };
+
+    if (!ns) {
+        return true;
+    }
+
+    aio_timer_init(qemu_get_aio_context(), &timer, type, SCALE_NS,
+                   &co_timeout_cb, &timeout_cb);
+    timer_mod(&timer, qemu_clock_get_ns(type) + ns);
+    qemu_coroutine_yield();
+    timer_del(&timer);
+
+    return timeout_cb.expired;
+}