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