Skip to content

Commit

Permalink
coroutine: move pooling to common code
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bonzini authored and kevmw committed Feb 22, 2013
1 parent 4dc9f9d commit 4023978
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 86 deletions.
43 changes: 1 addition & 42 deletions coroutine-sigaltstack.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
43 changes: 1 addition & 42 deletions coroutine-ucontext.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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... */
Expand All @@ -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
Expand Down
45 changes: 43 additions & 2 deletions qemu-coroutine.c
Expand Up @@ -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;
Expand All @@ -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();
Expand Down

0 comments on commit 4023978

Please sign in to comment.