aboutsummaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/oslib-posix.c2
-rw-r--r--util/qemu-coroutine-lock.c19
-rw-r--r--util/qemu-coroutine.c5
3 files changed, 23 insertions, 3 deletions
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 048d40d9de..5e8b4b39ed 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -402,7 +402,7 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
/* touch pages simultaneously */
if (touch_all_pages(area, hpagesize, numpages, smp_cpus)) {
error_setg(errp, "os_mem_prealloc: Insufficient free host memory "
- "pages available to allocate guest RAM\n");
+ "pages available to allocate guest RAM");
}
ret = sigaction(SIGBUS, &oldact, NULL);
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index 6328eed26b..b44b5d55eb 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -77,10 +77,25 @@ void coroutine_fn qemu_co_queue_wait(CoQueue *queue, CoMutex *mutex)
void qemu_co_queue_run_restart(Coroutine *co)
{
Coroutine *next;
+ QSIMPLEQ_HEAD(, Coroutine) tmp_queue_wakeup =
+ QSIMPLEQ_HEAD_INITIALIZER(tmp_queue_wakeup);
trace_qemu_co_queue_run_restart(co);
- while ((next = QSIMPLEQ_FIRST(&co->co_queue_wakeup))) {
- QSIMPLEQ_REMOVE_HEAD(&co->co_queue_wakeup, co_queue_next);
+
+ /* Because "co" has yielded, any coroutine that we wakeup can resume it.
+ * If this happens and "co" terminates, co->co_queue_wakeup becomes
+ * invalid memory. Therefore, use a temporary queue and do not touch
+ * the "co" coroutine as soon as you enter another one.
+ *
+ * In its turn resumed "co" can pupulate "co_queue_wakeup" queue with
+ * new coroutines to be woken up. The caller, who has resumed "co",
+ * will be responsible for traversing the same queue, which may cause
+ * a different wakeup order but not any missing wakeups.
+ */
+ QSIMPLEQ_CONCAT(&tmp_queue_wakeup, &co->co_queue_wakeup);
+
+ while ((next = QSIMPLEQ_FIRST(&tmp_queue_wakeup))) {
+ QSIMPLEQ_REMOVE_HEAD(&tmp_queue_wakeup, co_queue_next);
qemu_coroutine_enter(next);
}
}
diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c
index 486af9a622..d6095c1d5a 100644
--- a/util/qemu-coroutine.c
+++ b/util/qemu-coroutine.c
@@ -126,6 +126,11 @@ void qemu_aio_coroutine_enter(AioContext *ctx, Coroutine *co)
qemu_co_queue_run_restart(co);
+ /* Beware, if ret == COROUTINE_YIELD and qemu_co_queue_run_restart()
+ * has started any other coroutine, "co" might have been reentered
+ * and even freed by now! So be careful and do not touch it.
+ */
+
switch (ret) {
case COROUTINE_YIELD:
return;