coroutine: move pooling to common code
The coroutine pool code is duplicated between the ucontext and sigaltstack backends, and absent from the win32 backend. But the code can be shared easily by moving it to qemu-coroutine.c. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
4dc9f9d67d
commit
402397843e
@ -33,15 +33,6 @@
|
||||
#include "qemu-common.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;
|
||||
|
||||
typedef struct {
|
||||
Coroutine base;
|
||||
void *stack;
|
||||
@ -85,17 +76,6 @@ static void qemu_coroutine_thread_cleanup(void *opaque)
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
static void __attribute__((destructor)) coroutine_cleanup(void)
|
||||
{
|
||||
Coroutine *co;
|
||||
Coroutine *tmp;
|
||||
|
||||
QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
|
||||
g_free(DO_UPCAST(CoroutineUContext, base, co)->stack);
|
||||
g_free(co);
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) coroutine_init(void)
|
||||
{
|
||||
int ret;
|
||||
@ -164,7 +144,7 @@ static void coroutine_trampoline(int signal)
|
||||
coroutine_bootstrap(self, co);
|
||||
}
|
||||
|
||||
static Coroutine *coroutine_new(void)
|
||||
Coroutine *qemu_coroutine_new(void)
|
||||
{
|
||||
const size_t stack_size = 1 << 20;
|
||||
CoroutineUContext *co;
|
||||
@ -272,31 +252,10 @@ static Coroutine *coroutine_new(void)
|
||||
return &co->base;
|
||||
}
|
||||
|
||||
Coroutine *qemu_coroutine_new(void)
|
||||
{
|
||||
Coroutine *co;
|
||||
|
||||
co = QSLIST_FIRST(&pool);
|
||||
if (co) {
|
||||
QSLIST_REMOVE_HEAD(&pool, pool_next);
|
||||
pool_size--;
|
||||
} else {
|
||||
co = coroutine_new();
|
||||
}
|
||||
return co;
|
||||
}
|
||||
|
||||
void qemu_coroutine_delete(Coroutine *co_)
|
||||
{
|
||||
CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
|
||||
|
||||
if (pool_size < POOL_MAX_SIZE) {
|
||||
QSLIST_INSERT_HEAD(&pool, &co->base, pool_next);
|
||||
co->base.caller = NULL;
|
||||
pool_size++;
|
||||
return;
|
||||
}
|
||||
|
||||
g_free(co->stack);
|
||||
g_free(co);
|
||||
}
|
||||
|
@ -34,15 +34,6 @@
|
||||
#include <valgrind/valgrind.h>
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
typedef struct {
|
||||
Coroutine base;
|
||||
void *stack;
|
||||
@ -96,17 +87,6 @@ static void qemu_coroutine_thread_cleanup(void *opaque)
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
static void __attribute__((destructor)) coroutine_cleanup(void)
|
||||
{
|
||||
Coroutine *co;
|
||||
Coroutine *tmp;
|
||||
|
||||
QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
|
||||
g_free(DO_UPCAST(CoroutineUContext, base, co)->stack);
|
||||
g_free(co);
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) coroutine_init(void)
|
||||
{
|
||||
int ret;
|
||||
@ -140,7 +120,7 @@ static void coroutine_trampoline(int i0, int i1)
|
||||
}
|
||||
}
|
||||
|
||||
static Coroutine *coroutine_new(void)
|
||||
Coroutine *qemu_coroutine_new(void)
|
||||
{
|
||||
const size_t stack_size = 1 << 20;
|
||||
CoroutineUContext *co;
|
||||
@ -185,20 +165,6 @@ static Coroutine *coroutine_new(void)
|
||||
return &co->base;
|
||||
}
|
||||
|
||||
Coroutine *qemu_coroutine_new(void)
|
||||
{
|
||||
Coroutine *co;
|
||||
|
||||
co = QSLIST_FIRST(&pool);
|
||||
if (co) {
|
||||
QSLIST_REMOVE_HEAD(&pool, pool_next);
|
||||
pool_size--;
|
||||
} else {
|
||||
co = coroutine_new();
|
||||
}
|
||||
return co;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VALGRIND_H
|
||||
#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
|
||||
/* Work around an unused variable in the valgrind.h macro... */
|
||||
@ -217,13 +183,6 @@ void qemu_coroutine_delete(Coroutine *co_)
|
||||
{
|
||||
CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
|
||||
|
||||
if (pool_size < POOL_MAX_SIZE) {
|
||||
QSLIST_INSERT_HEAD(&pool, &co->base, pool_next);
|
||||
co->base.caller = NULL;
|
||||
pool_size++;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VALGRIND_H
|
||||
valgrind_stack_deregister(co);
|
||||
#endif
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user