aboutsummaryrefslogtreecommitdiff
path: root/qemu-coroutine.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu-coroutine.c')
-rw-r--r--qemu-coroutine.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/qemu-coroutine.c b/qemu-coroutine.c
index 0f6e268574..25a14c605d 100644
--- a/qemu-coroutine.c
+++ b/qemu-coroutine.c
@@ -17,13 +17,54 @@
#include "block/coroutine.h"
#include "block/coroutine_int.h"
+enum {
+ /* Maximum free pool size prevents holding too many freed coroutines */
+ POOL_MAX_SIZE = 64,
+};
+
+/** Free list to speed up creation */
+static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool);
+static unsigned int pool_size;
+
Coroutine *qemu_coroutine_create(CoroutineEntry *entry)
{
- Coroutine *co = qemu_coroutine_new();
+ Coroutine *co;
+
+ co = QSLIST_FIRST(&pool);
+ if (co) {
+ QSLIST_REMOVE_HEAD(&pool, pool_next);
+ pool_size--;
+ } else {
+ co = qemu_coroutine_new();
+ }
+
co->entry = entry;
return co;
}
+static void coroutine_delete(Coroutine *co)
+{
+ if (pool_size < POOL_MAX_SIZE) {
+ QSLIST_INSERT_HEAD(&pool, co, pool_next);
+ co->caller = NULL;
+ pool_size++;
+ return;
+ }
+
+ qemu_coroutine_delete(co);
+}
+
+static void __attribute__((destructor)) coroutine_cleanup(void)
+{
+ Coroutine *co;
+ Coroutine *tmp;
+
+ QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
+ QSLIST_REMOVE_HEAD(&pool, pool_next);
+ qemu_coroutine_delete(co);
+ }
+}
+
static void coroutine_swap(Coroutine *from, Coroutine *to)
{
CoroutineAction ret;
@@ -35,7 +76,7 @@ static void coroutine_swap(Coroutine *from, Coroutine *to)
return;
case COROUTINE_TERMINATE:
trace_qemu_coroutine_terminate(to);
- qemu_coroutine_delete(to);
+ coroutine_delete(to);
return;
default:
abort();