diff options
| author | Anand Avati <avati@redhat.com> | 2013-03-06 01:11:59 -0800 | 
|---|---|---|
| committer | Anand Avati <avati@redhat.com> | 2013-09-03 11:25:33 -0700 | 
| commit | 0d60175bd684cf6a14f750579d82dbd1ba97fcbc (patch) | |
| tree | 1571f530548196006526442f3fc027cb623bb6fa /contrib/qemu/qemu-coroutine.c | |
| parent | 7dbfbfd3694e02b90e8f3ce509f5279da1523a02 (diff) | |
contrib/qemu: Import qemu block source code
This qemu block format source code and its minimal
dependency files will be used in the next patch to implement
a qemu-block format translator.
Change-Id: Ic87638972f7ea9b3df84d7a0539512a250c11c1c
BUG: 986775
Signed-off-by: Anand Avati <avati@redhat.com>
Reviewed-on: http://review.gluster.org/5366
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Diffstat (limited to 'contrib/qemu/qemu-coroutine.c')
| -rw-r--r-- | contrib/qemu/qemu-coroutine.c | 135 | 
1 files changed, 135 insertions, 0 deletions
diff --git a/contrib/qemu/qemu-coroutine.c b/contrib/qemu/qemu-coroutine.c new file mode 100644 index 000000000..423430d3a --- /dev/null +++ b/contrib/qemu/qemu-coroutine.c @@ -0,0 +1,135 @@ +/* + * QEMU coroutines + * + * Copyright IBM, Corp. 2011 + * + * Authors: + *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com> + *  Kevin Wolf         <kwolf@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "trace.h" +#include "qemu-common.h" +#include "qemu/thread.h" +#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 QemuMutex pool_lock; +static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool); +static unsigned int pool_size; + +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--; +    } +    qemu_mutex_unlock(&pool_lock); + +    if (!co) { +        co = qemu_coroutine_new(); +    } + +    co->entry = entry; +    QTAILQ_INIT(&co->co_queue_wakeup); +    return co; +} + +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__((constructor)) coroutine_pool_init(void) +{ +    qemu_mutex_init(&pool_lock); +} + +static void __attribute__((destructor)) coroutine_pool_cleanup(void) +{ +    Coroutine *co; +    Coroutine *tmp; + +    QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) { +        QSLIST_REMOVE_HEAD(&pool, pool_next); +        qemu_coroutine_delete(co); +    } + +    qemu_mutex_destroy(&pool_lock); +} + +static void coroutine_swap(Coroutine *from, Coroutine *to) +{ +    CoroutineAction ret; + +    ret = qemu_coroutine_switch(from, to, COROUTINE_YIELD); + +    qemu_co_queue_run_restart(to); + +    switch (ret) { +    case COROUTINE_YIELD: +        return; +    case COROUTINE_TERMINATE: +        trace_qemu_coroutine_terminate(to); +        coroutine_delete(to); +        return; +    default: +        abort(); +    } +} + +void qemu_coroutine_enter(Coroutine *co, void *opaque) +{ +    Coroutine *self = qemu_coroutine_self(); + +    trace_qemu_coroutine_enter(self, co, opaque); + +    if (co->caller) { +        fprintf(stderr, "Co-routine re-entered recursively\n"); +        abort(); +    } + +    co->caller = self; +    co->entry_arg = opaque; +    coroutine_swap(self, co); +} + +void coroutine_fn qemu_coroutine_yield(void) +{ +    Coroutine *self = qemu_coroutine_self(); +    Coroutine *to = self->caller; + +    trace_qemu_coroutine_yield(self, to); + +    if (!to) { +        fprintf(stderr, "Co-routine is yielding to no one\n"); +        abort(); +    } + +    self->caller = NULL; +    coroutine_swap(self, to); +}  | 
