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