@@ -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 */
@@ -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;
+}
Signed-off-by: Max Reitz <mreitz@redhat.com> --- include/block/coroutine.h | 6 ++++++ qemu-coroutine-sleep.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+)