[sheepdog] [PATCH 08/11] coroutine: add co_aio_sleep_ns() to allow sleep in block drivers
MORITA Kazutaka
morita.kazutaka at lab.ntt.co.jp
Tue Jul 23 10:30:18 CEST 2013
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.kazutaka at 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
More information about the sheepdog
mailing list