diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/oslib-posix.c | 2 | ||||
-rw-r--r-- | util/qemu-coroutine-lock.c | 19 | ||||
-rw-r--r-- | util/qemu-coroutine.c | 5 |
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; |