root / qemu-coroutine.h @ 60e1b2a6
History | View | Annotate | Download (5.6 kB)
1 |
/*
|
---|---|
2 |
* QEMU coroutine implementation
|
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 |
#ifndef QEMU_COROUTINE_H
|
16 |
#define QEMU_COROUTINE_H
|
17 |
|
18 |
#include <stdbool.h> |
19 |
#include "qemu-queue.h" |
20 |
#include "qemu-timer.h" |
21 |
|
22 |
/**
|
23 |
* Coroutines are a mechanism for stack switching and can be used for
|
24 |
* cooperative userspace threading. These functions provide a simple but
|
25 |
* useful flavor of coroutines that is suitable for writing sequential code,
|
26 |
* rather than callbacks, for operations that need to give up control while
|
27 |
* waiting for events to complete.
|
28 |
*
|
29 |
* These functions are re-entrant and may be used outside the global mutex.
|
30 |
*/
|
31 |
|
32 |
/**
|
33 |
* Mark a function that executes in coroutine context
|
34 |
*
|
35 |
* Functions that execute in coroutine context cannot be called directly from
|
36 |
* normal functions. In the future it would be nice to enable compiler or
|
37 |
* static checker support for catching such errors. This annotation might make
|
38 |
* it possible and in the meantime it serves as documentation.
|
39 |
*
|
40 |
* For example:
|
41 |
*
|
42 |
* static void coroutine_fn foo(void) {
|
43 |
* ....
|
44 |
* }
|
45 |
*/
|
46 |
#define coroutine_fn
|
47 |
|
48 |
typedef struct Coroutine Coroutine; |
49 |
|
50 |
/**
|
51 |
* Coroutine entry point
|
52 |
*
|
53 |
* When the coroutine is entered for the first time, opaque is passed in as an
|
54 |
* argument.
|
55 |
*
|
56 |
* When this function returns, the coroutine is destroyed automatically and
|
57 |
* execution continues in the caller who last entered the coroutine.
|
58 |
*/
|
59 |
typedef void coroutine_fn CoroutineEntry(void *opaque); |
60 |
|
61 |
/**
|
62 |
* Create a new coroutine
|
63 |
*
|
64 |
* Use qemu_coroutine_enter() to actually transfer control to the coroutine.
|
65 |
*/
|
66 |
Coroutine *qemu_coroutine_create(CoroutineEntry *entry); |
67 |
|
68 |
/**
|
69 |
* Transfer control to a coroutine
|
70 |
*
|
71 |
* The opaque argument is passed as the argument to the entry point when
|
72 |
* entering the coroutine for the first time. It is subsequently ignored.
|
73 |
*/
|
74 |
void qemu_coroutine_enter(Coroutine *coroutine, void *opaque); |
75 |
|
76 |
/**
|
77 |
* Transfer control back to a coroutine's caller
|
78 |
*
|
79 |
* This function does not return until the coroutine is re-entered using
|
80 |
* qemu_coroutine_enter().
|
81 |
*/
|
82 |
void coroutine_fn qemu_coroutine_yield(void); |
83 |
|
84 |
/**
|
85 |
* Get the currently executing coroutine
|
86 |
*/
|
87 |
Coroutine *coroutine_fn qemu_coroutine_self(void);
|
88 |
|
89 |
/**
|
90 |
* Return whether or not currently inside a coroutine
|
91 |
*
|
92 |
* This can be used to write functions that work both when in coroutine context
|
93 |
* and when not in coroutine context. Note that such functions cannot use the
|
94 |
* coroutine_fn annotation since they work outside coroutine context.
|
95 |
*/
|
96 |
bool qemu_in_coroutine(void); |
97 |
|
98 |
|
99 |
|
100 |
/**
|
101 |
* CoQueues are a mechanism to queue coroutines in order to continue executing
|
102 |
* them later. They provide the fundamental primitives on which coroutine locks
|
103 |
* are built.
|
104 |
*/
|
105 |
typedef struct CoQueue { |
106 |
QTAILQ_HEAD(, Coroutine) entries; |
107 |
} CoQueue; |
108 |
|
109 |
/**
|
110 |
* Initialise a CoQueue. This must be called before any other operation is used
|
111 |
* on the CoQueue.
|
112 |
*/
|
113 |
void qemu_co_queue_init(CoQueue *queue);
|
114 |
|
115 |
/**
|
116 |
* Adds the current coroutine to the CoQueue and transfers control to the
|
117 |
* caller of the coroutine.
|
118 |
*/
|
119 |
void coroutine_fn qemu_co_queue_wait(CoQueue *queue);
|
120 |
|
121 |
/**
|
122 |
* Adds the current coroutine to the head of the CoQueue and transfers control to the
|
123 |
* caller of the coroutine.
|
124 |
*/
|
125 |
void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue);
|
126 |
|
127 |
/**
|
128 |
* Restarts the next coroutine in the CoQueue and removes it from the queue.
|
129 |
*
|
130 |
* Returns true if a coroutine was restarted, false if the queue is empty.
|
131 |
*/
|
132 |
bool qemu_co_queue_next(CoQueue *queue);
|
133 |
|
134 |
/**
|
135 |
* Restarts all coroutines in the CoQueue and leaves the queue empty.
|
136 |
*/
|
137 |
void qemu_co_queue_restart_all(CoQueue *queue);
|
138 |
|
139 |
/**
|
140 |
* Checks if the CoQueue is empty.
|
141 |
*/
|
142 |
bool qemu_co_queue_empty(CoQueue *queue);
|
143 |
|
144 |
|
145 |
/**
|
146 |
* Provides a mutex that can be used to synchronise coroutines
|
147 |
*/
|
148 |
typedef struct CoMutex { |
149 |
bool locked;
|
150 |
CoQueue queue; |
151 |
} CoMutex; |
152 |
|
153 |
/**
|
154 |
* Initialises a CoMutex. This must be called before any other operation is used
|
155 |
* on the CoMutex.
|
156 |
*/
|
157 |
void qemu_co_mutex_init(CoMutex *mutex);
|
158 |
|
159 |
/**
|
160 |
* Locks the mutex. If the lock cannot be taken immediately, control is
|
161 |
* transferred to the caller of the current coroutine.
|
162 |
*/
|
163 |
void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex);
|
164 |
|
165 |
/**
|
166 |
* Unlocks the mutex and schedules the next coroutine that was waiting for this
|
167 |
* lock to be run.
|
168 |
*/
|
169 |
void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex);
|
170 |
|
171 |
typedef struct CoRwlock { |
172 |
bool writer;
|
173 |
int reader;
|
174 |
CoQueue queue; |
175 |
} CoRwlock; |
176 |
|
177 |
/**
|
178 |
* Initialises a CoRwlock. This must be called before any other operation
|
179 |
* is used on the CoRwlock
|
180 |
*/
|
181 |
void qemu_co_rwlock_init(CoRwlock *lock);
|
182 |
|
183 |
/**
|
184 |
* Read locks the CoRwlock. If the lock cannot be taken immediately because
|
185 |
* of a parallel writer, control is transferred to the caller of the current
|
186 |
* coroutine.
|
187 |
*/
|
188 |
void qemu_co_rwlock_rdlock(CoRwlock *lock);
|
189 |
|
190 |
/**
|
191 |
* Write Locks the mutex. If the lock cannot be taken immediately because
|
192 |
* of a parallel reader, control is transferred to the caller of the current
|
193 |
* coroutine.
|
194 |
*/
|
195 |
void qemu_co_rwlock_wrlock(CoRwlock *lock);
|
196 |
|
197 |
/**
|
198 |
* Unlocks the read/write lock and schedules the next coroutine that was
|
199 |
* waiting for this lock to be run.
|
200 |
*/
|
201 |
void qemu_co_rwlock_unlock(CoRwlock *lock);
|
202 |
|
203 |
/**
|
204 |
* Yield the coroutine for a given duration
|
205 |
*
|
206 |
* Note this function uses timers and hence only works when a main loop is in
|
207 |
* use. See main-loop.h and do not use from qemu-tool programs.
|
208 |
*/
|
209 |
void coroutine_fn co_sleep_ns(QEMUClock *clock, int64_t ns);
|
210 |
|
211 |
#endif /* QEMU_COROUTINE_H */ |