[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 05/16] coroutine-lock: make qemu_co_enter_next thread
From: |
Fam Zheng |
Subject: |
[Qemu-devel] [PULL 05/16] coroutine-lock: make qemu_co_enter_next thread-safe |
Date: |
Thu, 8 Feb 2018 10:19:42 +0800 |
From: Paolo Bonzini <address@hidden>
qemu_co_queue_next does not need to release and re-acquire the mutex,
because the queued coroutine does not run immediately. However, this
does not hold for qemu_co_enter_next. Now that qemu_co_queue_wait
can synchronize (via QemuLockable) with code that is not running in
coroutine context, it's important that code using qemu_co_enter_next
can easily use a standardized locking idiom.
First of all, qemu_co_enter_next must use aio_co_wake to restart the
coroutine. Second, the function gains a second argument, a QemuLockable*,
and the comments of qemu_co_queue_next and qemu_co_queue_restart_all
are adjusted to clarify the difference.
Signed-off-by: Paolo Bonzini <address@hidden>
Message-Id: <address@hidden>
Reviewed-by: Stefan Hajnoczi <address@hidden>
Reviewed-by: Fam Zheng <address@hidden>
Signed-off-by: Fam Zheng <address@hidden>
---
fsdev/qemu-fsdev-throttle.c | 4 ++--
include/qemu/coroutine.h | 19 +++++++++++++------
util/qemu-coroutine-lock.c | 10 ++++++++--
3 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/fsdev/qemu-fsdev-throttle.c b/fsdev/qemu-fsdev-throttle.c
index 49eebb5412..1dc07fbc12 100644
--- a/fsdev/qemu-fsdev-throttle.c
+++ b/fsdev/qemu-fsdev-throttle.c
@@ -20,13 +20,13 @@
static void fsdev_throttle_read_timer_cb(void *opaque)
{
FsThrottle *fst = opaque;
- qemu_co_enter_next(&fst->throttled_reqs[false]);
+ qemu_co_enter_next(&fst->throttled_reqs[false], NULL);
}
static void fsdev_throttle_write_timer_cb(void *opaque)
{
FsThrottle *fst = opaque;
- qemu_co_enter_next(&fst->throttled_reqs[true]);
+ qemu_co_enter_next(&fst->throttled_reqs[true], NULL);
}
void fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index 1e5f0957e6..6f8a487041 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -188,21 +188,28 @@ void qemu_co_queue_init(CoQueue *queue);
void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock);
/**
- * Restarts the next coroutine in the CoQueue and removes it from the queue.
- *
- * Returns true if a coroutine was restarted, false if the queue is empty.
+ * Removes the next coroutine from the CoQueue, and wake it up.
+ * Returns true if a coroutine was removed, false if the queue is empty.
*/
bool coroutine_fn qemu_co_queue_next(CoQueue *queue);
/**
- * Restarts all coroutines in the CoQueue and leaves the queue empty.
+ * Empties the CoQueue; all coroutines are woken up.
*/
void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue);
/**
- * Enter the next coroutine in the queue
+ * Removes the next coroutine from the CoQueue, and wake it up. Unlike
+ * qemu_co_queue_next, this function releases the lock during aio_co_wake
+ * because it is meant to be used outside coroutine context; in that case, the
+ * coroutine is entered immediately, before qemu_co_enter_next returns.
+ *
+ * If used in coroutine context, qemu_co_enter_next is equivalent to
+ * qemu_co_queue_next.
*/
-bool qemu_co_enter_next(CoQueue *queue);
+#define qemu_co_enter_next(queue, lock) \
+ qemu_co_enter_next_impl(queue, QEMU_MAKE_LOCKABLE(lock))
+bool qemu_co_enter_next_impl(CoQueue *queue, QemuLockable *lock);
/**
* Checks if the CoQueue is empty.
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index 2a66fc1467..78fb79acf8 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -132,7 +132,7 @@ void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue)
qemu_co_queue_do_restart(queue, false);
}
-bool qemu_co_enter_next(CoQueue *queue)
+bool qemu_co_enter_next_impl(CoQueue *queue, QemuLockable *lock)
{
Coroutine *next;
@@ -142,7 +142,13 @@ bool qemu_co_enter_next(CoQueue *queue)
}
QSIMPLEQ_REMOVE_HEAD(&queue->entries, co_queue_next);
- qemu_coroutine_enter(next);
+ if (lock) {
+ qemu_lockable_unlock(lock);
+ }
+ aio_co_wake(next);
+ if (lock) {
+ qemu_lockable_lock(lock);
+ }
return true;
}
--
2.14.3
- [Qemu-devel] [PULL 00/16] Docker and block patches, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 01/16] docker: change Fedora base image to fedora:27, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 02/16] test-coroutine: add simple CoMutex test, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 04/16] coroutine-lock: convert CoQueue to use QemuLockable, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 03/16] lockable: add QemuLockable, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 05/16] coroutine-lock: make qemu_co_enter_next thread-safe,
Fam Zheng <=
- [Qemu-devel] [PULL 06/16] curl: convert to CoQueue, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 07/16] stubs: Add stubs for ram block API, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 08/16] util: Introduce vfio helpers, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 10/16] block: Introduce buf register API, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 12/16] qemu-img: Map bench buffer, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 11/16] block/nvme: Implement .bdrv_(un)register_buf, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 09/16] block: Add VFIO based NVMe driver, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 14/16] docs: Add section for NVMe VFIO driver, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 15/16] qapi: Add NVMe driver options to the schema, Fam Zheng, 2018/02/07
- [Qemu-devel] [PULL 13/16] block: Move NVMe constants to a separate header, Fam Zheng, 2018/02/07