mmu-hash*: Fold pte_check*() logic into caller
[qemu/agraf.git] / qemu-coroutine.c
blob25a14c605db5acea79ded776b33153d039725e43
1 /*
2 * QEMU coroutines
4 * Copyright IBM, Corp. 2011
6 * Authors:
7 * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
8 * Kevin Wolf <kwolf@redhat.com>
10 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
11 * See the COPYING.LIB file in the top-level directory.
15 #include "trace.h"
16 #include "qemu-common.h"
17 #include "block/coroutine.h"
18 #include "block/coroutine_int.h"
20 enum {
21 /* Maximum free pool size prevents holding too many freed coroutines */
22 POOL_MAX_SIZE = 64,
25 /** Free list to speed up creation */
26 static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool);
27 static unsigned int pool_size;
29 Coroutine *qemu_coroutine_create(CoroutineEntry *entry)
31 Coroutine *co;
33 co = QSLIST_FIRST(&pool);
34 if (co) {
35 QSLIST_REMOVE_HEAD(&pool, pool_next);
36 pool_size--;
37 } else {
38 co = qemu_coroutine_new();
41 co->entry = entry;
42 return co;
45 static void coroutine_delete(Coroutine *co)
47 if (pool_size < POOL_MAX_SIZE) {
48 QSLIST_INSERT_HEAD(&pool, co, pool_next);
49 co->caller = NULL;
50 pool_size++;
51 return;
54 qemu_coroutine_delete(co);
57 static void __attribute__((destructor)) coroutine_cleanup(void)
59 Coroutine *co;
60 Coroutine *tmp;
62 QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
63 QSLIST_REMOVE_HEAD(&pool, pool_next);
64 qemu_coroutine_delete(co);
68 static void coroutine_swap(Coroutine *from, Coroutine *to)
70 CoroutineAction ret;
72 ret = qemu_coroutine_switch(from, to, COROUTINE_YIELD);
74 switch (ret) {
75 case COROUTINE_YIELD:
76 return;
77 case COROUTINE_TERMINATE:
78 trace_qemu_coroutine_terminate(to);
79 coroutine_delete(to);
80 return;
81 default:
82 abort();
86 void qemu_coroutine_enter(Coroutine *co, void *opaque)
88 Coroutine *self = qemu_coroutine_self();
90 trace_qemu_coroutine_enter(self, co, opaque);
92 if (co->caller) {
93 fprintf(stderr, "Co-routine re-entered recursively\n");
94 abort();
97 co->caller = self;
98 co->entry_arg = opaque;
99 coroutine_swap(self, co);
102 void coroutine_fn qemu_coroutine_yield(void)
104 Coroutine *self = qemu_coroutine_self();
105 Coroutine *to = self->caller;
107 trace_qemu_coroutine_yield(self, to);
109 if (!to) {
110 fprintf(stderr, "Co-routine is yielding to no one\n");
111 abort();
114 self->caller = NULL;
115 coroutine_swap(self, to);