2011-01-17 19:08:14 +03:00
|
|
|
/*
|
|
|
|
* QEMU coroutines
|
|
|
|
*
|
|
|
|
* Copyright IBM, Corp. 2011
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
|
|
|
|
* Kevin Wolf <kwolf@redhat.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU LGPL, version 2 or later.
|
|
|
|
* See the COPYING.LIB file in the top-level directory.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-01-29 20:49:55 +03:00
|
|
|
#include "qemu/osdep.h"
|
2011-01-17 19:08:14 +03:00
|
|
|
#include "trace.h"
|
2013-05-17 17:51:25 +04:00
|
|
|
#include "qemu/thread.h"
|
coroutine: rewrite pool to avoid mutex
This patch removes the mutex by using fancy lock-free manipulation of
the pool. Lock-free stacks and queues are not hard, but they can suffer
from the ABA problem so they are better avoided unless you have some
deferred reclamation scheme like RCU. Otherwise you have to stick
with adding to a list, and emptying it completely. This is what this
patch does, by coupling a lock-free global list of available coroutines
with per-CPU lists that are actually used on coroutine creation.
Whenever the destruction pool is big enough, the next thread that runs
out of coroutines will steal the whole destruction pool. This is positive
in two ways:
1) the allocation does not have to do any atomic operation in the fast
path, it's entirely using thread-local storage. Once every POOL_BATCH_SIZE
allocations it will do a single atomic_xchg. Release does an atomic_cmpxchg
loop, that hopefully doesn't cause any starvation, and an atomic_inc.
A later patch will also remove atomic operations from the release path,
and try to avoid the atomic_xchg altogether---succeeding in doing so if
all devices either use ioeventfd or are not submitting requests actively.
2) in theory this should be completely adaptive. The number of coroutines
around should be a little more than POOL_BATCH_SIZE * number of allocating
threads; so this also empties qemu_coroutine_adjust_pool_size. (The previous
pool size was POOL_BATCH_SIZE * number of block backends, so it was a bit
more generous. But if you actually have many high-iodepth disks, it's better
to put them in different iothreads, which will also use separate thread
pools and aio=native file descriptors).
This speeds up perf/cost (in tests/test-coroutine) by a factor of ~1.33.
No matter if we end with some kind of coroutine bypass scheme or not,
it cannot hurt to optimize hot code.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 1417518350-6167-6-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-12-02 14:05:48 +03:00
|
|
|
#include "qemu/atomic.h"
|
2015-09-01 16:48:02 +03:00
|
|
|
#include "qemu/coroutine_int.h"
|
2022-03-07 18:38:52 +03:00
|
|
|
#include "qemu/coroutine-tls.h"
|
2024-03-18 21:34:29 +03:00
|
|
|
#include "qemu/cutils.h"
|
2017-02-13 16:52:19 +03:00
|
|
|
#include "block/aio.h"
|
2011-01-17 19:08:14 +03:00
|
|
|
|
2013-02-19 14:59:09 +04:00
|
|
|
enum {
|
2024-03-18 21:34:29 +03:00
|
|
|
COROUTINE_POOL_BATCH_MAX_SIZE = 128,
|
2013-02-19 14:59:09 +04:00
|
|
|
};
|
|
|
|
|
2024-03-18 21:34:29 +03:00
|
|
|
/*
|
|
|
|
* Coroutine creation and deletion is expensive so a pool of unused coroutines
|
|
|
|
* is kept as a cache. When the pool has coroutines available, they are
|
|
|
|
* recycled instead of creating new ones from scratch. Coroutines are added to
|
|
|
|
* the pool upon termination.
|
|
|
|
*
|
|
|
|
* The pool is global but each thread maintains a small local pool to avoid
|
|
|
|
* global pool contention. Threads fetch and return batches of coroutines from
|
|
|
|
* the global pool to maintain their local pool. The local pool holds up to two
|
|
|
|
* batches whereas the maximum size of the global pool is controlled by the
|
|
|
|
* qemu_coroutine_inc_pool_size() API.
|
|
|
|
*
|
|
|
|
* .-----------------------------------.
|
|
|
|
* | Batch 1 | Batch 2 | Batch 3 | ... | global_pool
|
|
|
|
* `-----------------------------------'
|
|
|
|
*
|
|
|
|
* .-------------------.
|
|
|
|
* | Batch 1 | Batch 2 | per-thread local_pool (maximum 2 batches)
|
|
|
|
* `-------------------'
|
|
|
|
*/
|
|
|
|
typedef struct CoroutinePoolBatch {
|
|
|
|
/* Batches are kept in a list */
|
|
|
|
QSLIST_ENTRY(CoroutinePoolBatch) next;
|
|
|
|
|
|
|
|
/* This batch holds up to @COROUTINE_POOL_BATCH_MAX_SIZE coroutines */
|
|
|
|
QSLIST_HEAD(, Coroutine) list;
|
|
|
|
unsigned int size;
|
|
|
|
} CoroutinePoolBatch;
|
|
|
|
|
|
|
|
typedef QSLIST_HEAD(, CoroutinePoolBatch) CoroutinePool;
|
|
|
|
|
|
|
|
/* Host operating system limit on number of pooled coroutines */
|
|
|
|
static unsigned int global_pool_hard_max_size;
|
|
|
|
|
|
|
|
static QemuMutex global_pool_lock; /* protects the following variables */
|
|
|
|
static CoroutinePool global_pool = QSLIST_HEAD_INITIALIZER(global_pool);
|
|
|
|
static unsigned int global_pool_size;
|
|
|
|
static unsigned int global_pool_max_size = COROUTINE_POOL_BATCH_MAX_SIZE;
|
|
|
|
|
|
|
|
QEMU_DEFINE_STATIC_CO_TLS(CoroutinePool, local_pool);
|
|
|
|
QEMU_DEFINE_STATIC_CO_TLS(Notifier, local_pool_cleanup_notifier);
|
2022-03-07 18:38:52 +03:00
|
|
|
|
2024-03-18 21:34:29 +03:00
|
|
|
static CoroutinePoolBatch *coroutine_pool_batch_new(void)
|
|
|
|
{
|
|
|
|
CoroutinePoolBatch *batch = g_new(CoroutinePoolBatch, 1);
|
|
|
|
|
|
|
|
QSLIST_INIT(&batch->list);
|
|
|
|
batch->size = 0;
|
|
|
|
return batch;
|
|
|
|
}
|
coroutine: rewrite pool to avoid mutex
This patch removes the mutex by using fancy lock-free manipulation of
the pool. Lock-free stacks and queues are not hard, but they can suffer
from the ABA problem so they are better avoided unless you have some
deferred reclamation scheme like RCU. Otherwise you have to stick
with adding to a list, and emptying it completely. This is what this
patch does, by coupling a lock-free global list of available coroutines
with per-CPU lists that are actually used on coroutine creation.
Whenever the destruction pool is big enough, the next thread that runs
out of coroutines will steal the whole destruction pool. This is positive
in two ways:
1) the allocation does not have to do any atomic operation in the fast
path, it's entirely using thread-local storage. Once every POOL_BATCH_SIZE
allocations it will do a single atomic_xchg. Release does an atomic_cmpxchg
loop, that hopefully doesn't cause any starvation, and an atomic_inc.
A later patch will also remove atomic operations from the release path,
and try to avoid the atomic_xchg altogether---succeeding in doing so if
all devices either use ioeventfd or are not submitting requests actively.
2) in theory this should be completely adaptive. The number of coroutines
around should be a little more than POOL_BATCH_SIZE * number of allocating
threads; so this also empties qemu_coroutine_adjust_pool_size. (The previous
pool size was POOL_BATCH_SIZE * number of block backends, so it was a bit
more generous. But if you actually have many high-iodepth disks, it's better
to put them in different iothreads, which will also use separate thread
pools and aio=native file descriptors).
This speeds up perf/cost (in tests/test-coroutine) by a factor of ~1.33.
No matter if we end with some kind of coroutine bypass scheme or not,
it cannot hurt to optimize hot code.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 1417518350-6167-6-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-12-02 14:05:48 +03:00
|
|
|
|
2024-03-18 21:34:29 +03:00
|
|
|
static void coroutine_pool_batch_delete(CoroutinePoolBatch *batch)
|
coroutine: rewrite pool to avoid mutex
This patch removes the mutex by using fancy lock-free manipulation of
the pool. Lock-free stacks and queues are not hard, but they can suffer
from the ABA problem so they are better avoided unless you have some
deferred reclamation scheme like RCU. Otherwise you have to stick
with adding to a list, and emptying it completely. This is what this
patch does, by coupling a lock-free global list of available coroutines
with per-CPU lists that are actually used on coroutine creation.
Whenever the destruction pool is big enough, the next thread that runs
out of coroutines will steal the whole destruction pool. This is positive
in two ways:
1) the allocation does not have to do any atomic operation in the fast
path, it's entirely using thread-local storage. Once every POOL_BATCH_SIZE
allocations it will do a single atomic_xchg. Release does an atomic_cmpxchg
loop, that hopefully doesn't cause any starvation, and an atomic_inc.
A later patch will also remove atomic operations from the release path,
and try to avoid the atomic_xchg altogether---succeeding in doing so if
all devices either use ioeventfd or are not submitting requests actively.
2) in theory this should be completely adaptive. The number of coroutines
around should be a little more than POOL_BATCH_SIZE * number of allocating
threads; so this also empties qemu_coroutine_adjust_pool_size. (The previous
pool size was POOL_BATCH_SIZE * number of block backends, so it was a bit
more generous. But if you actually have many high-iodepth disks, it's better
to put them in different iothreads, which will also use separate thread
pools and aio=native file descriptors).
This speeds up perf/cost (in tests/test-coroutine) by a factor of ~1.33.
No matter if we end with some kind of coroutine bypass scheme or not,
it cannot hurt to optimize hot code.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 1417518350-6167-6-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-12-02 14:05:48 +03:00
|
|
|
{
|
|
|
|
Coroutine *co;
|
|
|
|
Coroutine *tmp;
|
|
|
|
|
2024-03-18 21:34:29 +03:00
|
|
|
QSLIST_FOREACH_SAFE(co, &batch->list, pool_next, tmp) {
|
|
|
|
QSLIST_REMOVE_HEAD(&batch->list, pool_next);
|
coroutine: rewrite pool to avoid mutex
This patch removes the mutex by using fancy lock-free manipulation of
the pool. Lock-free stacks and queues are not hard, but they can suffer
from the ABA problem so they are better avoided unless you have some
deferred reclamation scheme like RCU. Otherwise you have to stick
with adding to a list, and emptying it completely. This is what this
patch does, by coupling a lock-free global list of available coroutines
with per-CPU lists that are actually used on coroutine creation.
Whenever the destruction pool is big enough, the next thread that runs
out of coroutines will steal the whole destruction pool. This is positive
in two ways:
1) the allocation does not have to do any atomic operation in the fast
path, it's entirely using thread-local storage. Once every POOL_BATCH_SIZE
allocations it will do a single atomic_xchg. Release does an atomic_cmpxchg
loop, that hopefully doesn't cause any starvation, and an atomic_inc.
A later patch will also remove atomic operations from the release path,
and try to avoid the atomic_xchg altogether---succeeding in doing so if
all devices either use ioeventfd or are not submitting requests actively.
2) in theory this should be completely adaptive. The number of coroutines
around should be a little more than POOL_BATCH_SIZE * number of allocating
threads; so this also empties qemu_coroutine_adjust_pool_size. (The previous
pool size was POOL_BATCH_SIZE * number of block backends, so it was a bit
more generous. But if you actually have many high-iodepth disks, it's better
to put them in different iothreads, which will also use separate thread
pools and aio=native file descriptors).
This speeds up perf/cost (in tests/test-coroutine) by a factor of ~1.33.
No matter if we end with some kind of coroutine bypass scheme or not,
it cannot hurt to optimize hot code.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 1417518350-6167-6-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-12-02 14:05:48 +03:00
|
|
|
qemu_coroutine_delete(co);
|
|
|
|
}
|
2024-03-18 21:34:29 +03:00
|
|
|
g_free(batch);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void local_pool_cleanup(Notifier *n, void *value)
|
|
|
|
{
|
|
|
|
CoroutinePool *local_pool = get_ptr_local_pool();
|
|
|
|
CoroutinePoolBatch *batch;
|
|
|
|
CoroutinePoolBatch *tmp;
|
|
|
|
|
|
|
|
QSLIST_FOREACH_SAFE(batch, local_pool, next, tmp) {
|
|
|
|
QSLIST_REMOVE_HEAD(local_pool, next);
|
|
|
|
coroutine_pool_batch_delete(batch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ensure the atexit notifier is registered */
|
|
|
|
static void local_pool_cleanup_init_once(void)
|
|
|
|
{
|
|
|
|
Notifier *notifier = get_ptr_local_pool_cleanup_notifier();
|
|
|
|
if (!notifier->notify) {
|
|
|
|
notifier->notify = local_pool_cleanup;
|
|
|
|
qemu_thread_atexit_add(notifier);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Helper to get the next unused coroutine from the local pool */
|
|
|
|
static Coroutine *coroutine_pool_get_local(void)
|
|
|
|
{
|
|
|
|
CoroutinePool *local_pool = get_ptr_local_pool();
|
|
|
|
CoroutinePoolBatch *batch = QSLIST_FIRST(local_pool);
|
|
|
|
Coroutine *co;
|
|
|
|
|
|
|
|
if (unlikely(!batch)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
co = QSLIST_FIRST(&batch->list);
|
|
|
|
QSLIST_REMOVE_HEAD(&batch->list, pool_next);
|
|
|
|
batch->size--;
|
|
|
|
|
|
|
|
if (batch->size == 0) {
|
|
|
|
QSLIST_REMOVE_HEAD(local_pool, next);
|
|
|
|
coroutine_pool_batch_delete(batch);
|
|
|
|
}
|
|
|
|
return co;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the next batch from the global pool */
|
|
|
|
static void coroutine_pool_refill_local(void)
|
|
|
|
{
|
|
|
|
CoroutinePool *local_pool = get_ptr_local_pool();
|
|
|
|
CoroutinePoolBatch *batch;
|
|
|
|
|
|
|
|
WITH_QEMU_LOCK_GUARD(&global_pool_lock) {
|
|
|
|
batch = QSLIST_FIRST(&global_pool);
|
|
|
|
|
|
|
|
if (batch) {
|
|
|
|
QSLIST_REMOVE_HEAD(&global_pool, next);
|
|
|
|
global_pool_size -= batch->size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (batch) {
|
|
|
|
QSLIST_INSERT_HEAD(local_pool, batch, next);
|
|
|
|
local_pool_cleanup_init_once();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add a batch of coroutines to the global pool */
|
|
|
|
static void coroutine_pool_put_global(CoroutinePoolBatch *batch)
|
|
|
|
{
|
|
|
|
WITH_QEMU_LOCK_GUARD(&global_pool_lock) {
|
|
|
|
unsigned int max = MIN(global_pool_max_size,
|
|
|
|
global_pool_hard_max_size);
|
|
|
|
|
|
|
|
if (global_pool_size < max) {
|
|
|
|
QSLIST_INSERT_HEAD(&global_pool, batch, next);
|
|
|
|
|
|
|
|
/* Overshooting the max pool size is allowed */
|
|
|
|
global_pool_size += batch->size;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The global pool was full, so throw away this batch */
|
|
|
|
coroutine_pool_batch_delete(batch);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the next unused coroutine from the pool or return NULL */
|
|
|
|
static Coroutine *coroutine_pool_get(void)
|
|
|
|
{
|
|
|
|
Coroutine *co;
|
|
|
|
|
|
|
|
co = coroutine_pool_get_local();
|
|
|
|
if (!co) {
|
|
|
|
coroutine_pool_refill_local();
|
|
|
|
co = coroutine_pool_get_local();
|
|
|
|
}
|
|
|
|
return co;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void coroutine_pool_put(Coroutine *co)
|
|
|
|
{
|
|
|
|
CoroutinePool *local_pool = get_ptr_local_pool();
|
|
|
|
CoroutinePoolBatch *batch = QSLIST_FIRST(local_pool);
|
|
|
|
|
|
|
|
if (unlikely(!batch)) {
|
|
|
|
batch = coroutine_pool_batch_new();
|
|
|
|
QSLIST_INSERT_HEAD(local_pool, batch, next);
|
|
|
|
local_pool_cleanup_init_once();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unlikely(batch->size >= COROUTINE_POOL_BATCH_MAX_SIZE)) {
|
|
|
|
CoroutinePoolBatch *next = QSLIST_NEXT(batch, next);
|
|
|
|
|
|
|
|
/* Is the local pool full? */
|
|
|
|
if (next) {
|
|
|
|
QSLIST_REMOVE_HEAD(local_pool, next);
|
|
|
|
coroutine_pool_put_global(batch);
|
|
|
|
}
|
|
|
|
|
|
|
|
batch = coroutine_pool_batch_new();
|
|
|
|
QSLIST_INSERT_HEAD(local_pool, batch, next);
|
|
|
|
}
|
|
|
|
|
|
|
|
QSLIST_INSERT_HEAD(&batch->list, co, pool_next);
|
|
|
|
batch->size++;
|
coroutine: rewrite pool to avoid mutex
This patch removes the mutex by using fancy lock-free manipulation of
the pool. Lock-free stacks and queues are not hard, but they can suffer
from the ABA problem so they are better avoided unless you have some
deferred reclamation scheme like RCU. Otherwise you have to stick
with adding to a list, and emptying it completely. This is what this
patch does, by coupling a lock-free global list of available coroutines
with per-CPU lists that are actually used on coroutine creation.
Whenever the destruction pool is big enough, the next thread that runs
out of coroutines will steal the whole destruction pool. This is positive
in two ways:
1) the allocation does not have to do any atomic operation in the fast
path, it's entirely using thread-local storage. Once every POOL_BATCH_SIZE
allocations it will do a single atomic_xchg. Release does an atomic_cmpxchg
loop, that hopefully doesn't cause any starvation, and an atomic_inc.
A later patch will also remove atomic operations from the release path,
and try to avoid the atomic_xchg altogether---succeeding in doing so if
all devices either use ioeventfd or are not submitting requests actively.
2) in theory this should be completely adaptive. The number of coroutines
around should be a little more than POOL_BATCH_SIZE * number of allocating
threads; so this also empties qemu_coroutine_adjust_pool_size. (The previous
pool size was POOL_BATCH_SIZE * number of block backends, so it was a bit
more generous. But if you actually have many high-iodepth disks, it's better
to put them in different iothreads, which will also use separate thread
pools and aio=native file descriptors).
This speeds up perf/cost (in tests/test-coroutine) by a factor of ~1.33.
No matter if we end with some kind of coroutine bypass scheme or not,
it cannot hurt to optimize hot code.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 1417518350-6167-6-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-12-02 14:05:48 +03:00
|
|
|
}
|
2013-02-19 14:59:09 +04:00
|
|
|
|
coroutine: move entry argument to qemu_coroutine_create
In practice the entry argument is always known at creation time, and
it is confusing that sometimes qemu_coroutine_enter is used with a
non-NULL argument to re-enter a coroutine (this happens in
block/sheepdog.c and tests/test-coroutine.c). So pass the opaque value
at creation time, for consistency with e.g. aio_bh_new.
Mostly done with the following semantic patch:
@ entry1 @
expression entry, arg, co;
@@
- co = qemu_coroutine_create(entry);
+ co = qemu_coroutine_create(entry, arg);
...
- qemu_coroutine_enter(co, arg);
+ qemu_coroutine_enter(co);
@ entry2 @
expression entry, arg;
identifier co;
@@
- Coroutine *co = qemu_coroutine_create(entry);
+ Coroutine *co = qemu_coroutine_create(entry, arg);
...
- qemu_coroutine_enter(co, arg);
+ qemu_coroutine_enter(co);
@ entry3 @
expression entry, arg;
@@
- qemu_coroutine_enter(qemu_coroutine_create(entry), arg);
+ qemu_coroutine_enter(qemu_coroutine_create(entry, arg));
@ reentry @
expression co;
@@
- qemu_coroutine_enter(co, NULL);
+ qemu_coroutine_enter(co);
except for the aforementioned few places where the semantic patch
stumbled (as expected) and for test_co_queue, which would otherwise
produce an uninitialized variable warning.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2016-07-04 20:10:01 +03:00
|
|
|
Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque)
|
2011-01-17 19:08:14 +03:00
|
|
|
{
|
2013-09-11 18:42:35 +04:00
|
|
|
Coroutine *co = NULL;
|
2013-02-19 14:59:09 +04:00
|
|
|
|
2023-10-05 15:31:27 +03:00
|
|
|
if (IS_ENABLED(CONFIG_COROUTINE_POOL)) {
|
2024-03-18 21:34:29 +03:00
|
|
|
co = coroutine_pool_get();
|
2013-05-17 17:51:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!co) {
|
2013-02-19 14:59:09 +04:00
|
|
|
co = qemu_coroutine_new();
|
|
|
|
}
|
|
|
|
|
2011-01-17 19:08:14 +03:00
|
|
|
co->entry = entry;
|
coroutine: move entry argument to qemu_coroutine_create
In practice the entry argument is always known at creation time, and
it is confusing that sometimes qemu_coroutine_enter is used with a
non-NULL argument to re-enter a coroutine (this happens in
block/sheepdog.c and tests/test-coroutine.c). So pass the opaque value
at creation time, for consistency with e.g. aio_bh_new.
Mostly done with the following semantic patch:
@ entry1 @
expression entry, arg, co;
@@
- co = qemu_coroutine_create(entry);
+ co = qemu_coroutine_create(entry, arg);
...
- qemu_coroutine_enter(co, arg);
+ qemu_coroutine_enter(co);
@ entry2 @
expression entry, arg;
identifier co;
@@
- Coroutine *co = qemu_coroutine_create(entry);
+ Coroutine *co = qemu_coroutine_create(entry, arg);
...
- qemu_coroutine_enter(co, arg);
+ qemu_coroutine_enter(co);
@ entry3 @
expression entry, arg;
@@
- qemu_coroutine_enter(qemu_coroutine_create(entry), arg);
+ qemu_coroutine_enter(qemu_coroutine_create(entry, arg));
@ reentry @
expression co;
@@
- qemu_coroutine_enter(co, NULL);
+ qemu_coroutine_enter(co);
except for the aforementioned few places where the semantic patch
stumbled (as expected) and for test_co_queue, which would otherwise
produce an uninitialized variable warning.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2016-07-04 20:10:01 +03:00
|
|
|
co->entry_arg = opaque;
|
2016-07-04 20:09:59 +03:00
|
|
|
QSIMPLEQ_INIT(&co->co_queue_wakeup);
|
2011-01-17 19:08:14 +03:00
|
|
|
return co;
|
|
|
|
}
|
|
|
|
|
2013-02-19 14:59:09 +04:00
|
|
|
static void coroutine_delete(Coroutine *co)
|
|
|
|
{
|
coroutine: rewrite pool to avoid mutex
This patch removes the mutex by using fancy lock-free manipulation of
the pool. Lock-free stacks and queues are not hard, but they can suffer
from the ABA problem so they are better avoided unless you have some
deferred reclamation scheme like RCU. Otherwise you have to stick
with adding to a list, and emptying it completely. This is what this
patch does, by coupling a lock-free global list of available coroutines
with per-CPU lists that are actually used on coroutine creation.
Whenever the destruction pool is big enough, the next thread that runs
out of coroutines will steal the whole destruction pool. This is positive
in two ways:
1) the allocation does not have to do any atomic operation in the fast
path, it's entirely using thread-local storage. Once every POOL_BATCH_SIZE
allocations it will do a single atomic_xchg. Release does an atomic_cmpxchg
loop, that hopefully doesn't cause any starvation, and an atomic_inc.
A later patch will also remove atomic operations from the release path,
and try to avoid the atomic_xchg altogether---succeeding in doing so if
all devices either use ioeventfd or are not submitting requests actively.
2) in theory this should be completely adaptive. The number of coroutines
around should be a little more than POOL_BATCH_SIZE * number of allocating
threads; so this also empties qemu_coroutine_adjust_pool_size. (The previous
pool size was POOL_BATCH_SIZE * number of block backends, so it was a bit
more generous. But if you actually have many high-iodepth disks, it's better
to put them in different iothreads, which will also use separate thread
pools and aio=native file descriptors).
This speeds up perf/cost (in tests/test-coroutine) by a factor of ~1.33.
No matter if we end with some kind of coroutine bypass scheme or not,
it cannot hurt to optimize hot code.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 1417518350-6167-6-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-12-02 14:05:48 +03:00
|
|
|
co->caller = NULL;
|
|
|
|
|
2023-10-05 15:31:27 +03:00
|
|
|
if (IS_ENABLED(CONFIG_COROUTINE_POOL)) {
|
2024-03-18 21:34:29 +03:00
|
|
|
coroutine_pool_put(co);
|
|
|
|
} else {
|
|
|
|
qemu_coroutine_delete(co);
|
2013-02-19 14:59:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-10 15:06:12 +03:00
|
|
|
void qemu_aio_coroutine_enter(AioContext *ctx, Coroutine *co)
|
2011-01-17 19:08:14 +03:00
|
|
|
{
|
2018-03-22 18:28:33 +03:00
|
|
|
QSIMPLEQ_HEAD(, Coroutine) pending = QSIMPLEQ_HEAD_INITIALIZER(pending);
|
|
|
|
Coroutine *from = qemu_coroutine_self();
|
2017-11-18 06:27:09 +03:00
|
|
|
|
2018-03-22 18:28:33 +03:00
|
|
|
QSIMPLEQ_INSERT_TAIL(&pending, co, co_queue_next);
|
2011-01-17 19:08:14 +03:00
|
|
|
|
2018-03-22 18:28:33 +03:00
|
|
|
/* Run co and any queued coroutines */
|
|
|
|
while (!QSIMPLEQ_EMPTY(&pending)) {
|
|
|
|
Coroutine *to = QSIMPLEQ_FIRST(&pending);
|
|
|
|
CoroutineAction ret;
|
2017-11-18 06:27:09 +03:00
|
|
|
|
2023-03-03 13:00:43 +03:00
|
|
|
/*
|
|
|
|
* Read to before to->scheduled; pairs with qatomic_cmpxchg in
|
|
|
|
* qemu_co_sleep(), aio_co_schedule() etc.
|
|
|
|
*/
|
|
|
|
smp_read_barrier_depends();
|
|
|
|
|
|
|
|
const char *scheduled = qatomic_read(&to->scheduled);
|
2011-01-17 19:08:14 +03:00
|
|
|
|
2018-03-22 18:28:33 +03:00
|
|
|
QSIMPLEQ_REMOVE_HEAD(&pending, co_queue_next);
|
2017-02-13 16:52:19 +03:00
|
|
|
|
2018-03-22 18:28:33 +03:00
|
|
|
trace_qemu_aio_coroutine_enter(ctx, from, to, to->entry_arg);
|
2017-02-13 16:52:19 +03:00
|
|
|
|
2018-03-22 18:28:33 +03:00
|
|
|
/* if the Coroutine has already been scheduled, entering it again will
|
|
|
|
* cause us to enter it twice, potentially even after the coroutine has
|
|
|
|
* been deleted */
|
|
|
|
if (scheduled) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: Co-routine was already scheduled in '%s'\n",
|
|
|
|
__func__, scheduled);
|
|
|
|
abort();
|
|
|
|
}
|
2015-02-10 13:31:52 +03:00
|
|
|
|
2018-03-22 18:28:33 +03:00
|
|
|
if (to->caller) {
|
|
|
|
fprintf(stderr, "Co-routine re-entered recursively\n");
|
|
|
|
abort();
|
|
|
|
}
|
coroutine-lock: do not touch coroutine after another one has been entered
Submission of requests on linux aio is a bit tricky and can lead to
requests completions on submission path:
44713c9e8547 ("linux-aio: Handle io_submit() failure gracefully")
0ed93d84edab ("linux-aio: process completions from ioq_submit()")
That means that any coroutine which has been yielded in order to wait
for completion can be resumed from submission path and be eventually
terminated (freed).
The following use-after-free crash was observed when IO throttling
was enabled:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f5813dff700 (LWP 56417)]
virtqueue_unmap_sg (elem=0x7f5804009a30, len=1, vq=<optimized out>) at virtio.c:252
(gdb) bt
#0 virtqueue_unmap_sg (elem=0x7f5804009a30, len=1, vq=<optimized out>) at virtio.c:252
^^^^^^^^^^^^^^
remember the address
#1 virtqueue_fill (vq=0x5598b20d21b0, elem=0x7f5804009a30, len=1, idx=0) at virtio.c:282
#2 virtqueue_push (vq=0x5598b20d21b0, elem=elem@entry=0x7f5804009a30, len=<optimized out>) at virtio.c:308
#3 virtio_blk_req_complete (req=req@entry=0x7f5804009a30, status=status@entry=0 '\000') at virtio-blk.c:61
#4 virtio_blk_rw_complete (opaque=<optimized out>, ret=0) at virtio-blk.c:126
#5 blk_aio_complete (acb=0x7f58040068d0) at block-backend.c:923
#6 coroutine_trampoline (i0=<optimized out>, i1=<optimized out>) at coroutine-ucontext.c:78
(gdb) p * elem
$8 = {index = 77, out_num = 2, in_num = 1,
in_addr = 0x7f5804009ad8, out_addr = 0x7f5804009ae0,
in_sg = 0x0, out_sg = 0x7f5804009a50}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'in_sg' and 'out_sg' are invalid.
e.g. it is impossible that 'in_sg' is zero,
instead its value must be equal to:
(gdb) p/x 0x7f5804009ad8 + sizeof(elem->in_addr[0]) + 2 * sizeof(elem->out_addr[0])
$26 = 0x7f5804009af0
Seems 'elem' was corrupted. Meanwhile another thread raised an abort:
Thread 12 (Thread 0x7f57f2ffd700 (LWP 56426)):
#0 raise () from /lib/x86_64-linux-gnu/libc.so.6
#1 abort () from /lib/x86_64-linux-gnu/libc.so.6
#2 qemu_coroutine_enter (co=0x7f5804009af0) at qemu-coroutine.c:113
#3 qemu_co_queue_run_restart (co=0x7f5804009a30) at qemu-coroutine-lock.c:60
#4 qemu_coroutine_enter (co=0x7f5804009a30) at qemu-coroutine.c:119
^^^^^^^^^^^^^^^^^^
WTF?? this is equal to elem from crashed thread
#5 qemu_co_queue_run_restart (co=0x7f57e7f16ae0) at qemu-coroutine-lock.c:60
#6 qemu_coroutine_enter (co=0x7f57e7f16ae0) at qemu-coroutine.c:119
#7 qemu_co_queue_run_restart (co=0x7f5807e112a0) at qemu-coroutine-lock.c:60
#8 qemu_coroutine_enter (co=0x7f5807e112a0) at qemu-coroutine.c:119
#9 qemu_co_queue_run_restart (co=0x7f5807f17820) at qemu-coroutine-lock.c:60
#10 qemu_coroutine_enter (co=0x7f5807f17820) at qemu-coroutine.c:119
#11 qemu_co_queue_run_restart (co=0x7f57e7f18e10) at qemu-coroutine-lock.c:60
#12 qemu_coroutine_enter (co=0x7f57e7f18e10) at qemu-coroutine.c:119
#13 qemu_co_enter_next (queue=queue@entry=0x5598b1e742d0) at qemu-coroutine-lock.c:106
#14 timer_cb (blk=0x5598b1e74280, is_write=<optimized out>) at throttle-groups.c:419
Crash can be explained by access of 'co' object from the loop inside
qemu_co_queue_run_restart():
while ((next = QSIMPLEQ_FIRST(&co->co_queue_wakeup))) {
QSIMPLEQ_REMOVE_HEAD(&co->co_queue_wakeup, co_queue_next);
^^^^^^^^^^^^^^^^^^^^
on each iteration 'co' is accessed,
but 'co' can be already freed
qemu_coroutine_enter(next);
}
When 'next' coroutine is resumed (entered) it can in its turn resume
'co', and eventually free it. That's why we see 'co' (which was freed)
has the same address as 'elem' from the first backtrace.
The fix is obvious: use temporary queue and do not touch coroutine after
first qemu_coroutine_enter() is invoked.
The issue is quite rare and happens every ~12 hours on very high IO
and CPU load (building linux kernel with -j512 inside guest) when IO
throttling is enabled. With the fix applied guest is running ~35 hours
and is still alive so far.
Signed-off-by: Roman Pen <roman.penyaev@profitbricks.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20170601160847.23720-1-roman.penyaev@profitbricks.com
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Fam Zheng <famz@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-devel@nongnu.org
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-06-01 19:08:47 +03:00
|
|
|
|
2018-03-22 18:28:33 +03:00
|
|
|
to->caller = from;
|
|
|
|
to->ctx = ctx;
|
|
|
|
|
|
|
|
/* Store to->ctx before anything that stores to. Matches
|
|
|
|
* barrier in aio_co_wake and qemu_co_mutex_wake.
|
|
|
|
*/
|
|
|
|
smp_wmb();
|
|
|
|
|
|
|
|
ret = qemu_coroutine_switch(from, to, COROUTINE_ENTER);
|
|
|
|
|
|
|
|
/* Queued coroutines are run depth-first; previously pending coroutines
|
|
|
|
* run after those queued more recently.
|
|
|
|
*/
|
|
|
|
QSIMPLEQ_PREPEND(&pending, &to->co_queue_wakeup);
|
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
case COROUTINE_YIELD:
|
|
|
|
break;
|
|
|
|
case COROUTINE_TERMINATE:
|
|
|
|
assert(!to->locks_held);
|
|
|
|
trace_qemu_coroutine_terminate(to);
|
|
|
|
coroutine_delete(to);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
2015-02-10 13:31:52 +03:00
|
|
|
}
|
2011-01-17 19:08:14 +03:00
|
|
|
}
|
|
|
|
|
2017-04-10 15:06:12 +03:00
|
|
|
void qemu_coroutine_enter(Coroutine *co)
|
|
|
|
{
|
|
|
|
qemu_aio_coroutine_enter(qemu_get_current_aio_context(), co);
|
|
|
|
}
|
|
|
|
|
2016-11-07 18:34:35 +03:00
|
|
|
void qemu_coroutine_enter_if_inactive(Coroutine *co)
|
|
|
|
{
|
|
|
|
if (!qemu_coroutine_entered(co)) {
|
|
|
|
qemu_coroutine_enter(co);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-17 19:08:14 +03:00
|
|
|
void coroutine_fn qemu_coroutine_yield(void)
|
|
|
|
{
|
|
|
|
Coroutine *self = qemu_coroutine_self();
|
|
|
|
Coroutine *to = self->caller;
|
|
|
|
|
|
|
|
trace_qemu_coroutine_yield(self, to);
|
|
|
|
|
|
|
|
if (!to) {
|
|
|
|
fprintf(stderr, "Co-routine is yielding to no one\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
self->caller = NULL;
|
2015-02-10 13:17:53 +03:00
|
|
|
qemu_coroutine_switch(self, to, COROUTINE_YIELD);
|
2011-01-17 19:08:14 +03:00
|
|
|
}
|
2016-09-27 18:18:34 +03:00
|
|
|
|
|
|
|
bool qemu_coroutine_entered(Coroutine *co)
|
|
|
|
{
|
|
|
|
return co->caller;
|
|
|
|
}
|
2018-08-17 19:54:18 +03:00
|
|
|
|
2022-09-22 11:49:03 +03:00
|
|
|
AioContext *qemu_coroutine_get_aio_context(Coroutine *co)
|
2018-08-17 19:54:18 +03:00
|
|
|
{
|
|
|
|
return co->ctx;
|
|
|
|
}
|
2022-02-14 14:53:02 +03:00
|
|
|
|
2022-05-10 18:10:19 +03:00
|
|
|
void qemu_coroutine_inc_pool_size(unsigned int additional_pool_size)
|
2022-02-14 14:53:02 +03:00
|
|
|
{
|
2024-03-18 21:34:29 +03:00
|
|
|
QEMU_LOCK_GUARD(&global_pool_lock);
|
|
|
|
global_pool_max_size += additional_pool_size;
|
2022-02-14 14:53:02 +03:00
|
|
|
}
|
|
|
|
|
2022-05-10 18:10:19 +03:00
|
|
|
void qemu_coroutine_dec_pool_size(unsigned int removing_pool_size)
|
2022-02-14 14:53:02 +03:00
|
|
|
{
|
2024-03-18 21:34:29 +03:00
|
|
|
QEMU_LOCK_GUARD(&global_pool_lock);
|
|
|
|
global_pool_max_size -= removing_pool_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int get_global_pool_hard_max_size(void)
|
|
|
|
{
|
|
|
|
#ifdef __linux__
|
|
|
|
g_autofree char *contents = NULL;
|
|
|
|
int max_map_count;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Linux processes can have up to max_map_count virtual memory areas
|
|
|
|
* (VMAs). mmap(2), mprotect(2), etc fail with ENOMEM beyond this limit. We
|
|
|
|
* must limit the coroutine pool to a safe size to avoid running out of
|
|
|
|
* VMAs.
|
|
|
|
*/
|
|
|
|
if (g_file_get_contents("/proc/sys/vm/max_map_count", &contents, NULL,
|
|
|
|
NULL) &&
|
|
|
|
qemu_strtoi(contents, NULL, 10, &max_map_count) == 0) {
|
|
|
|
/*
|
2024-03-20 21:12:32 +03:00
|
|
|
* This is an upper bound that avoids exceeding max_map_count. Leave a
|
|
|
|
* fixed amount for non-coroutine users like library dependencies,
|
|
|
|
* vhost-user, etc. Each coroutine takes up 2 VMAs so halve the
|
|
|
|
* remaining amount.
|
2024-03-18 21:34:29 +03:00
|
|
|
*/
|
2024-03-20 21:12:32 +03:00
|
|
|
if (max_map_count > 5000) {
|
|
|
|
return (max_map_count - 5000) / 2;
|
|
|
|
} else {
|
|
|
|
/* Disable the global pool but threads still have local pools */
|
|
|
|
return 0;
|
|
|
|
}
|
2024-03-18 21:34:29 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return UINT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __attribute__((constructor)) qemu_coroutine_init(void)
|
|
|
|
{
|
|
|
|
qemu_mutex_init(&global_pool_lock);
|
|
|
|
global_pool_hard_max_size = get_global_pool_hard_max_size();
|
2022-02-14 14:53:02 +03:00
|
|
|
}
|