[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH v2 2/8] coroutine-lock: release lock when restarting all coro
From: |
Emanuele Giuseppe Esposito |
Subject: |
[RFC PATCH v2 2/8] coroutine-lock: release lock when restarting all coroutines |
Date: |
Tue, 26 Apr 2022 04:51:08 -0400 |
Current implementation of qemu_co_queue_do_restart
does not releases the lock before calling aio_co_wake.
Most of the time this is fine, but if the coroutine
acquires the lock again then we have a deadlock.
Instead of duplicating code, use qemu_co_enter_next_impl, since
it implements exactly the same functionality that we
want.
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
---
include/qemu/coroutine.h | 10 ++++++++++
util/qemu-coroutine-lock.c | 26 ++++++++++----------------
2 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index c828a95ee0..c49cdc21b4 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -220,6 +220,16 @@ bool qemu_co_queue_next(CoQueue *queue);
*/
void qemu_co_queue_restart_all(CoQueue *queue);
+/**
+ * Empties the CoQueue; all coroutines are woken up.
+ * OK to run from coroutine and non-coroutine context.
+ * Unlocks lock before waking up each coroutine takes it again
+ * when done.
+ */
+#define qemu_co_queue_restart_all_lockable(queue, lock) \
+ qemu_co_queue_restart_all_impl(queue, QEMU_MAKE_LOCKABLE(lock))
+void qemu_co_queue_restart_all_impl(CoQueue *queue, QemuLockable *lock);
+
/**
* 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
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index 2669403839..17bb0d0c95 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -67,32 +67,26 @@ void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue,
QemuLockable *lock)
}
}
-static bool qemu_co_queue_do_restart(CoQueue *queue, bool single)
+static void qemu_co_queue_do_restart(CoQueue *queue, QemuLockable *lock)
{
- Coroutine *next;
-
- if (QSIMPLEQ_EMPTY(&queue->entries)) {
- return false;
+ while (qemu_co_enter_next_impl(queue, lock)) {
+ /* nop */
}
-
- while ((next = QSIMPLEQ_FIRST(&queue->entries)) != NULL) {
- QSIMPLEQ_REMOVE_HEAD(&queue->entries, co_queue_next);
- aio_co_wake(next);
- if (single) {
- break;
- }
- }
- return true;
}
bool qemu_co_queue_next(CoQueue *queue)
{
- return qemu_co_queue_do_restart(queue, true);
+ return qemu_co_enter_next_impl(queue, NULL);
}
void qemu_co_queue_restart_all(CoQueue *queue)
{
- qemu_co_queue_do_restart(queue, false);
+ qemu_co_queue_do_restart(queue, NULL);
+}
+
+void qemu_co_queue_restart_all_impl(CoQueue *queue, QemuLockable *lock)
+{
+ qemu_co_queue_do_restart(queue, lock);
}
bool qemu_co_enter_next_impl(CoQueue *queue, QemuLockable *lock)
--
2.31.1
[RFC PATCH v2 7/8] graph-lock: implement WITH_GRAPH_RDLOCK_GUARD and GRAPH_RDLOCK_GUARD macros, Emanuele Giuseppe Esposito, 2022/04/26