Statistics
| Branch: | Revision:

root / qemu-coroutine.h @ 0b03bdfc

History | View | Annotate | Download (5.3 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 e9e6295b Zhi Yong Wu
 * Adds the current coroutine to the head of the CoQueue and transfers control to the
122 e9e6295b Zhi Yong Wu
 * caller of the coroutine.
123 e9e6295b Zhi Yong Wu
 */
124 e9e6295b Zhi Yong Wu
void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue);
125 e9e6295b Zhi Yong Wu
126 e9e6295b Zhi Yong Wu
/**
127 b96e9247 Kevin Wolf
 * Restarts the next coroutine in the CoQueue and removes it from the queue.
128 b96e9247 Kevin Wolf
 *
129 b96e9247 Kevin Wolf
 * Returns true if a coroutine was restarted, false if the queue is empty.
130 b96e9247 Kevin Wolf
 */
131 b96e9247 Kevin Wolf
bool qemu_co_queue_next(CoQueue *queue);
132 b96e9247 Kevin Wolf
133 b96e9247 Kevin Wolf
/**
134 e8ee5e4c Stefan Hajnoczi
 * Restarts all coroutines in the CoQueue and leaves the queue empty.
135 e8ee5e4c Stefan Hajnoczi
 */
136 e8ee5e4c Stefan Hajnoczi
void qemu_co_queue_restart_all(CoQueue *queue);
137 e8ee5e4c Stefan Hajnoczi
138 e8ee5e4c Stefan Hajnoczi
/**
139 b96e9247 Kevin Wolf
 * Checks if the CoQueue is empty.
140 b96e9247 Kevin Wolf
 */
141 b96e9247 Kevin Wolf
bool qemu_co_queue_empty(CoQueue *queue);
142 b96e9247 Kevin Wolf
143 b96e9247 Kevin Wolf
144 b96e9247 Kevin Wolf
/**
145 b96e9247 Kevin Wolf
 * Provides a mutex that can be used to synchronise coroutines
146 b96e9247 Kevin Wolf
 */
147 b96e9247 Kevin Wolf
typedef struct CoMutex {
148 b96e9247 Kevin Wolf
    bool locked;
149 b96e9247 Kevin Wolf
    CoQueue queue;
150 b96e9247 Kevin Wolf
} CoMutex;
151 b96e9247 Kevin Wolf
152 b96e9247 Kevin Wolf
/**
153 b96e9247 Kevin Wolf
 * Initialises a CoMutex. This must be called before any other operation is used
154 b96e9247 Kevin Wolf
 * on the CoMutex.
155 b96e9247 Kevin Wolf
 */
156 b96e9247 Kevin Wolf
void qemu_co_mutex_init(CoMutex *mutex);
157 b96e9247 Kevin Wolf
158 b96e9247 Kevin Wolf
/**
159 b96e9247 Kevin Wolf
 * Locks the mutex. If the lock cannot be taken immediately, control is
160 b96e9247 Kevin Wolf
 * transferred to the caller of the current coroutine.
161 b96e9247 Kevin Wolf
 */
162 b96e9247 Kevin Wolf
void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex);
163 b96e9247 Kevin Wolf
164 b96e9247 Kevin Wolf
/**
165 b96e9247 Kevin Wolf
 * Unlocks the mutex and schedules the next coroutine that was waiting for this
166 b96e9247 Kevin Wolf
 * lock to be run.
167 b96e9247 Kevin Wolf
 */
168 b96e9247 Kevin Wolf
void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex);
169 b96e9247 Kevin Wolf
170 12888904 Aneesh Kumar K.V
typedef struct CoRwlock {
171 12888904 Aneesh Kumar K.V
    bool writer;
172 12888904 Aneesh Kumar K.V
    int reader;
173 12888904 Aneesh Kumar K.V
    CoQueue queue;
174 12888904 Aneesh Kumar K.V
} CoRwlock;
175 12888904 Aneesh Kumar K.V
176 12888904 Aneesh Kumar K.V
/**
177 12888904 Aneesh Kumar K.V
 * Initialises a CoRwlock. This must be called before any other operation
178 12888904 Aneesh Kumar K.V
 * is used on the CoRwlock
179 12888904 Aneesh Kumar K.V
 */
180 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_init(CoRwlock *lock);
181 12888904 Aneesh Kumar K.V
182 12888904 Aneesh Kumar K.V
/**
183 12888904 Aneesh Kumar K.V
 * Read locks the CoRwlock. If the lock cannot be taken immediately because
184 12888904 Aneesh Kumar K.V
 * of a parallel writer, control is transferred to the caller of the current
185 12888904 Aneesh Kumar K.V
 * coroutine.
186 12888904 Aneesh Kumar K.V
 */
187 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_rdlock(CoRwlock *lock);
188 12888904 Aneesh Kumar K.V
189 12888904 Aneesh Kumar K.V
/**
190 12888904 Aneesh Kumar K.V
 * Write Locks the mutex. If the lock cannot be taken immediately because
191 12888904 Aneesh Kumar K.V
 * of a parallel reader, control is transferred to the caller of the current
192 12888904 Aneesh Kumar K.V
 * coroutine.
193 12888904 Aneesh Kumar K.V
 */
194 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_wrlock(CoRwlock *lock);
195 12888904 Aneesh Kumar K.V
196 12888904 Aneesh Kumar K.V
/**
197 12888904 Aneesh Kumar K.V
 * Unlocks the read/write lock and schedules the next coroutine that was
198 12888904 Aneesh Kumar K.V
 * waiting for this lock to be run.
199 12888904 Aneesh Kumar K.V
 */
200 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_unlock(CoRwlock *lock);
201 12888904 Aneesh Kumar K.V
202 00dccaf1 Kevin Wolf
#endif /* QEMU_COROUTINE_H */