This helper function behaves similarly to co_sleep_ns(), but the sleeping coroutine will be resumed when using qemu_aio_wait().
Signed-off-by: MORITA Kazutaka <morita.kazut...@lab.ntt.co.jp> --- include/block/coroutine.h | 8 ++++++++ qemu-coroutine-sleep.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/block/coroutine.h b/include/block/coroutine.h index 377805a..23ea6e9 100644 --- a/include/block/coroutine.h +++ b/include/block/coroutine.h @@ -210,6 +210,14 @@ void qemu_co_rwlock_unlock(CoRwlock *lock); void coroutine_fn co_sleep_ns(QEMUClock *clock, int64_t ns); /** + * Yield the coroutine for a given duration + * + * Behaves similarly to co_sleep_ns(), but the sleeping coroutine will be + * resumed when using qemu_aio_wait(). + */ +void coroutine_fn co_aio_sleep_ns(int64_t ns); + +/** * Yield until a file descriptor becomes readable * * Note that this function clobbers the handlers for the file descriptor. diff --git a/qemu-coroutine-sleep.c b/qemu-coroutine-sleep.c index 169ce5c..3955347 100644 --- a/qemu-coroutine-sleep.c +++ b/qemu-coroutine-sleep.c @@ -13,6 +13,7 @@ #include "block/coroutine.h" #include "qemu/timer.h" +#include "qemu/thread.h" typedef struct CoSleepCB { QEMUTimer *ts; @@ -37,3 +38,49 @@ void coroutine_fn co_sleep_ns(QEMUClock *clock, int64_t ns) qemu_del_timer(sleep_cb.ts); qemu_free_timer(sleep_cb.ts); } + +typedef struct CoAioSleepCB { + QEMUBH *bh; + int64_t ns; + Coroutine *co; +} CoAioSleepCB; + +static void co_aio_sleep_cb(void *opaque) +{ + CoAioSleepCB *aio_sleep_cb = opaque; + + qemu_coroutine_enter(aio_sleep_cb->co, NULL); +} + +static void *sleep_thread(void *opaque) +{ + CoAioSleepCB *aio_sleep_cb = opaque; + struct timespec req = { + .tv_sec = aio_sleep_cb->ns / 1000000000, + .tv_nsec = aio_sleep_cb->ns % 1000000000, + }; + struct timespec rem; + + while (nanosleep(&req, &rem) < 0 && errno == EINTR) { + req = rem; + } + + qemu_bh_schedule(aio_sleep_cb->bh); + + return NULL; +} + +void coroutine_fn co_aio_sleep_ns(int64_t ns) +{ + CoAioSleepCB aio_sleep_cb = { + .ns = ns, + .co = qemu_coroutine_self(), + }; + QemuThread thread; + + aio_sleep_cb.bh = qemu_bh_new(co_aio_sleep_cb, &aio_sleep_cb); + qemu_thread_create(&thread, sleep_thread, &aio_sleep_cb, + QEMU_THREAD_DETACHED); + qemu_coroutine_yield(); + qemu_bh_delete(aio_sleep_cb.bh); +} -- 1.8.1.3.566.gaa39828