diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2013-05-17 15:51:25 +0200 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2013-05-24 16:17:56 +0200 |
commit | b84c4586234b26ccc875595713f6f4491e5b3385 (patch) | |
tree | ecc4340be4db4dacf16d081eb110f07bd94c20fd /qemu-coroutine.c | |
parent | bd91ecbf5b43b52321c4d938e16a612b9c68bf06 (diff) |
coroutine: protect global pool with a mutex
The coroutine freelist is a global pool of unused coroutines. It avoids
the setup/teardown overhead associated with the coroutine lifecycle.
Since the pool is global, we need to synchronize access so that
coroutines can be used outside the BQL.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'qemu-coroutine.c')
-rw-r--r-- | qemu-coroutine.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/qemu-coroutine.c b/qemu-coroutine.c index 25a14c605d..60ac79e680 100644 --- a/qemu-coroutine.c +++ b/qemu-coroutine.c @@ -14,6 +14,7 @@ #include "trace.h" #include "qemu-common.h" +#include "qemu/thread.h" #include "block/coroutine.h" #include "block/coroutine_int.h" @@ -23,6 +24,7 @@ enum { }; /** Free list to speed up creation */ +static QemuMutex pool_lock; static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool); static unsigned int pool_size; @@ -30,11 +32,15 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry) { Coroutine *co; + qemu_mutex_lock(&pool_lock); co = QSLIST_FIRST(&pool); if (co) { QSLIST_REMOVE_HEAD(&pool, pool_next); pool_size--; - } else { + } + qemu_mutex_unlock(&pool_lock); + + if (!co) { co = qemu_coroutine_new(); } @@ -44,17 +50,25 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry) static void coroutine_delete(Coroutine *co) { + qemu_mutex_lock(&pool_lock); if (pool_size < POOL_MAX_SIZE) { QSLIST_INSERT_HEAD(&pool, co, pool_next); co->caller = NULL; pool_size++; + qemu_mutex_unlock(&pool_lock); return; } + qemu_mutex_unlock(&pool_lock); qemu_coroutine_delete(co); } -static void __attribute__((destructor)) coroutine_cleanup(void) +static void __attribute__((constructor)) coroutine_pool_init(void) +{ + qemu_mutex_init(&pool_lock); +} + +static void __attribute__((destructor)) coroutine_pool_cleanup(void) { Coroutine *co; Coroutine *tmp; @@ -63,6 +77,8 @@ static void __attribute__((destructor)) coroutine_cleanup(void) QSLIST_REMOVE_HEAD(&pool, pool_next); qemu_coroutine_delete(co); } + + qemu_mutex_destroy(&pool_lock); } static void coroutine_swap(Coroutine *from, Coroutine *to) |