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