qemu-block
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]