summaryrefslogtreecommitdiff
path: root/qemu-coroutine.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2013-05-17 15:51:25 +0200
committerStefan Hajnoczi <stefanha@redhat.com>2013-05-24 16:17:56 +0200
commitb84c4586234b26ccc875595713f6f4491e5b3385 (patch)
treeecc4340be4db4dacf16d081eb110f07bd94c20fd /qemu-coroutine.c
parentbd91ecbf5b43b52321c4d938e16a612b9c68bf06 (diff)
downloadqemu-b84c4586234b26ccc875595713f6f4491e5b3385.tar.gz
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.c20
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)