]> git.proxmox.com Git - qemu.git/blame - qemu-coroutine.c
sparc64: use direct interrupt mapping for PCI devices
[qemu.git] / qemu-coroutine.c
CommitLineData
00dccaf1
KW
1/*
2 * QEMU coroutines
3 *
4 * Copyright IBM, Corp. 2011
5 *
6 * Authors:
7 * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
8 * Kevin Wolf <kwolf@redhat.com>
9 *
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.
12 *
13 */
14
15#include "trace.h"
16#include "qemu-common.h"
737e150e
PB
17#include "block/coroutine.h"
18#include "block/coroutine_int.h"
00dccaf1 19
40239784
PB
20enum {
21 /* Maximum free pool size prevents holding too many freed coroutines */
22 POOL_MAX_SIZE = 64,
23};
24
25/** Free list to speed up creation */
26static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool);
27static unsigned int pool_size;
28
00dccaf1
KW
29Coroutine *qemu_coroutine_create(CoroutineEntry *entry)
30{
40239784
PB
31 Coroutine *co;
32
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();
39 }
40
00dccaf1
KW
41 co->entry = entry;
42 return co;
43}
44
40239784
PB
45static void coroutine_delete(Coroutine *co)
46{
47 if (pool_size < POOL_MAX_SIZE) {
48 QSLIST_INSERT_HEAD(&pool, co, pool_next);
49 co->caller = NULL;
50 pool_size++;
51 return;
52 }
53
54 qemu_coroutine_delete(co);
55}
56
57static void __attribute__((destructor)) coroutine_cleanup(void)
58{
59 Coroutine *co;
60 Coroutine *tmp;
61
62 QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
63 QSLIST_REMOVE_HEAD(&pool, pool_next);
64 qemu_coroutine_delete(co);
65 }
66}
67
00dccaf1
KW
68static void coroutine_swap(Coroutine *from, Coroutine *to)
69{
70 CoroutineAction ret;
71
72 ret = qemu_coroutine_switch(from, to, COROUTINE_YIELD);
73
74 switch (ret) {
75 case COROUTINE_YIELD:
76 return;
77 case COROUTINE_TERMINATE:
78 trace_qemu_coroutine_terminate(to);
40239784 79 coroutine_delete(to);
00dccaf1
KW
80 return;
81 default:
82 abort();
83 }
84}
85
86void qemu_coroutine_enter(Coroutine *co, void *opaque)
87{
88 Coroutine *self = qemu_coroutine_self();
89
90 trace_qemu_coroutine_enter(self, co, opaque);
91
92 if (co->caller) {
93 fprintf(stderr, "Co-routine re-entered recursively\n");
94 abort();
95 }
96
97 co->caller = self;
98 co->entry_arg = opaque;
99 coroutine_swap(self, co);
100}
101
102void coroutine_fn qemu_coroutine_yield(void)
103{
104 Coroutine *self = qemu_coroutine_self();
105 Coroutine *to = self->caller;
106
107 trace_qemu_coroutine_yield(self, to);
108
109 if (!to) {
110 fprintf(stderr, "Co-routine is yielding to no one\n");
111 abort();
112 }
113
114 self->caller = NULL;
115 coroutine_swap(self, to);
116}