root / async.c @ a540f158
History | View | Annotate | Download (5.3 kB)
1 | 4f999d05 | Kevin Wolf | /*
|
---|---|---|---|
2 | 4f999d05 | Kevin Wolf | * QEMU System Emulator
|
3 | 4f999d05 | Kevin Wolf | *
|
4 | 4f999d05 | Kevin Wolf | * Copyright (c) 2003-2008 Fabrice Bellard
|
5 | 4f999d05 | Kevin Wolf | *
|
6 | 4f999d05 | Kevin Wolf | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 4f999d05 | Kevin Wolf | * of this software and associated documentation files (the "Software"), to deal
|
8 | 4f999d05 | Kevin Wolf | * in the Software without restriction, including without limitation the rights
|
9 | 4f999d05 | Kevin Wolf | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 4f999d05 | Kevin Wolf | * copies of the Software, and to permit persons to whom the Software is
|
11 | 4f999d05 | Kevin Wolf | * furnished to do so, subject to the following conditions:
|
12 | 4f999d05 | Kevin Wolf | *
|
13 | 4f999d05 | Kevin Wolf | * The above copyright notice and this permission notice shall be included in
|
14 | 4f999d05 | Kevin Wolf | * all copies or substantial portions of the Software.
|
15 | 4f999d05 | Kevin Wolf | *
|
16 | 4f999d05 | Kevin Wolf | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 4f999d05 | Kevin Wolf | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 4f999d05 | Kevin Wolf | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 4f999d05 | Kevin Wolf | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 4f999d05 | Kevin Wolf | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 4f999d05 | Kevin Wolf | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 4f999d05 | Kevin Wolf | * THE SOFTWARE.
|
23 | 4f999d05 | Kevin Wolf | */
|
24 | 4f999d05 | Kevin Wolf | |
25 | 4f999d05 | Kevin Wolf | #include "qemu-common.h" |
26 | 737e150e | Paolo Bonzini | #include "block/aio.h" |
27 | 9b34277d | Stefan Hajnoczi | #include "block/thread-pool.h" |
28 | 1de7afc9 | Paolo Bonzini | #include "qemu/main-loop.h" |
29 | 9a1e9481 | Kevin Wolf | |
30 | 4f999d05 | Kevin Wolf | /***********************************************************/
|
31 | 4f999d05 | Kevin Wolf | /* bottom halves (can be seen as timers which expire ASAP) */
|
32 | 4f999d05 | Kevin Wolf | |
33 | 4f999d05 | Kevin Wolf | struct QEMUBH {
|
34 | 2f4dc3c1 | Paolo Bonzini | AioContext *ctx; |
35 | 4f999d05 | Kevin Wolf | QEMUBHFunc *cb; |
36 | 4f999d05 | Kevin Wolf | void *opaque;
|
37 | 4f999d05 | Kevin Wolf | QEMUBH *next; |
38 | 9b47b17e | Stefan Weil | bool scheduled;
|
39 | 9b47b17e | Stefan Weil | bool idle;
|
40 | 9b47b17e | Stefan Weil | bool deleted;
|
41 | 4f999d05 | Kevin Wolf | }; |
42 | 4f999d05 | Kevin Wolf | |
43 | f627aab1 | Paolo Bonzini | QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
|
44 | 4f999d05 | Kevin Wolf | { |
45 | 4f999d05 | Kevin Wolf | QEMUBH *bh; |
46 | 7267c094 | Anthony Liguori | bh = g_malloc0(sizeof(QEMUBH));
|
47 | 2f4dc3c1 | Paolo Bonzini | bh->ctx = ctx; |
48 | 4f999d05 | Kevin Wolf | bh->cb = cb; |
49 | 4f999d05 | Kevin Wolf | bh->opaque = opaque; |
50 | f627aab1 | Paolo Bonzini | bh->next = ctx->first_bh; |
51 | f627aab1 | Paolo Bonzini | ctx->first_bh = bh; |
52 | 4f999d05 | Kevin Wolf | return bh;
|
53 | 4f999d05 | Kevin Wolf | } |
54 | 4f999d05 | Kevin Wolf | |
55 | f627aab1 | Paolo Bonzini | int aio_bh_poll(AioContext *ctx)
|
56 | 4f999d05 | Kevin Wolf | { |
57 | 7887f620 | Kevin Wolf | QEMUBH *bh, **bhp, *next; |
58 | 4f999d05 | Kevin Wolf | int ret;
|
59 | 648fb0ea | Kevin Wolf | |
60 | f627aab1 | Paolo Bonzini | ctx->walking_bh++; |
61 | 4f999d05 | Kevin Wolf | |
62 | 4f999d05 | Kevin Wolf | ret = 0;
|
63 | f627aab1 | Paolo Bonzini | for (bh = ctx->first_bh; bh; bh = next) {
|
64 | 7887f620 | Kevin Wolf | next = bh->next; |
65 | 4f999d05 | Kevin Wolf | if (!bh->deleted && bh->scheduled) {
|
66 | 4f999d05 | Kevin Wolf | bh->scheduled = 0;
|
67 | 4f999d05 | Kevin Wolf | if (!bh->idle)
|
68 | 4f999d05 | Kevin Wolf | ret = 1;
|
69 | 4f999d05 | Kevin Wolf | bh->idle = 0;
|
70 | 4f999d05 | Kevin Wolf | bh->cb(bh->opaque); |
71 | 4f999d05 | Kevin Wolf | } |
72 | 4f999d05 | Kevin Wolf | } |
73 | 4f999d05 | Kevin Wolf | |
74 | f627aab1 | Paolo Bonzini | ctx->walking_bh--; |
75 | 648fb0ea | Kevin Wolf | |
76 | 4f999d05 | Kevin Wolf | /* remove deleted bhs */
|
77 | f627aab1 | Paolo Bonzini | if (!ctx->walking_bh) {
|
78 | f627aab1 | Paolo Bonzini | bhp = &ctx->first_bh; |
79 | 648fb0ea | Kevin Wolf | while (*bhp) {
|
80 | 648fb0ea | Kevin Wolf | bh = *bhp; |
81 | 648fb0ea | Kevin Wolf | if (bh->deleted) {
|
82 | 648fb0ea | Kevin Wolf | *bhp = bh->next; |
83 | 648fb0ea | Kevin Wolf | g_free(bh); |
84 | 648fb0ea | Kevin Wolf | } else {
|
85 | 648fb0ea | Kevin Wolf | bhp = &bh->next; |
86 | 648fb0ea | Kevin Wolf | } |
87 | 648fb0ea | Kevin Wolf | } |
88 | 4f999d05 | Kevin Wolf | } |
89 | 4f999d05 | Kevin Wolf | |
90 | 4f999d05 | Kevin Wolf | return ret;
|
91 | 4f999d05 | Kevin Wolf | } |
92 | 4f999d05 | Kevin Wolf | |
93 | 4f999d05 | Kevin Wolf | void qemu_bh_schedule_idle(QEMUBH *bh)
|
94 | 4f999d05 | Kevin Wolf | { |
95 | 4f999d05 | Kevin Wolf | if (bh->scheduled)
|
96 | 4f999d05 | Kevin Wolf | return;
|
97 | 4f999d05 | Kevin Wolf | bh->scheduled = 1;
|
98 | 4f999d05 | Kevin Wolf | bh->idle = 1;
|
99 | 4f999d05 | Kevin Wolf | } |
100 | 4f999d05 | Kevin Wolf | |
101 | 4f999d05 | Kevin Wolf | void qemu_bh_schedule(QEMUBH *bh)
|
102 | 4f999d05 | Kevin Wolf | { |
103 | 4f999d05 | Kevin Wolf | if (bh->scheduled)
|
104 | 4f999d05 | Kevin Wolf | return;
|
105 | 4f999d05 | Kevin Wolf | bh->scheduled = 1;
|
106 | 4f999d05 | Kevin Wolf | bh->idle = 0;
|
107 | 2f4dc3c1 | Paolo Bonzini | aio_notify(bh->ctx); |
108 | 4f999d05 | Kevin Wolf | } |
109 | 4f999d05 | Kevin Wolf | |
110 | 4f999d05 | Kevin Wolf | void qemu_bh_cancel(QEMUBH *bh)
|
111 | 4f999d05 | Kevin Wolf | { |
112 | 4f999d05 | Kevin Wolf | bh->scheduled = 0;
|
113 | 4f999d05 | Kevin Wolf | } |
114 | 4f999d05 | Kevin Wolf | |
115 | 4f999d05 | Kevin Wolf | void qemu_bh_delete(QEMUBH *bh)
|
116 | 4f999d05 | Kevin Wolf | { |
117 | 4f999d05 | Kevin Wolf | bh->scheduled = 0;
|
118 | 4f999d05 | Kevin Wolf | bh->deleted = 1;
|
119 | 4f999d05 | Kevin Wolf | } |
120 | 4f999d05 | Kevin Wolf | |
121 | 22bfa75e | Paolo Bonzini | static gboolean
|
122 | 22bfa75e | Paolo Bonzini | aio_ctx_prepare(GSource *source, gint *timeout) |
123 | 4f999d05 | Kevin Wolf | { |
124 | 22bfa75e | Paolo Bonzini | AioContext *ctx = (AioContext *) source; |
125 | 4f999d05 | Kevin Wolf | QEMUBH *bh; |
126 | 4f999d05 | Kevin Wolf | |
127 | f627aab1 | Paolo Bonzini | for (bh = ctx->first_bh; bh; bh = bh->next) {
|
128 | 4f999d05 | Kevin Wolf | if (!bh->deleted && bh->scheduled) {
|
129 | 4f999d05 | Kevin Wolf | if (bh->idle) {
|
130 | 4f999d05 | Kevin Wolf | /* idle bottom halves will be polled at least
|
131 | 4f999d05 | Kevin Wolf | * every 10ms */
|
132 | 22bfa75e | Paolo Bonzini | *timeout = 10;
|
133 | 4f999d05 | Kevin Wolf | } else {
|
134 | 4f999d05 | Kevin Wolf | /* non-idle bottom halves will be executed
|
135 | 4f999d05 | Kevin Wolf | * immediately */
|
136 | 4f999d05 | Kevin Wolf | *timeout = 0;
|
137 | f5022a13 | Paolo Bonzini | return true; |
138 | 4f999d05 | Kevin Wolf | } |
139 | 4f999d05 | Kevin Wolf | } |
140 | 4f999d05 | Kevin Wolf | } |
141 | e3713e00 | Paolo Bonzini | |
142 | f5022a13 | Paolo Bonzini | return false; |
143 | e3713e00 | Paolo Bonzini | } |
144 | e3713e00 | Paolo Bonzini | |
145 | e3713e00 | Paolo Bonzini | static gboolean
|
146 | e3713e00 | Paolo Bonzini | aio_ctx_check(GSource *source) |
147 | e3713e00 | Paolo Bonzini | { |
148 | e3713e00 | Paolo Bonzini | AioContext *ctx = (AioContext *) source; |
149 | e3713e00 | Paolo Bonzini | QEMUBH *bh; |
150 | e3713e00 | Paolo Bonzini | |
151 | e3713e00 | Paolo Bonzini | for (bh = ctx->first_bh; bh; bh = bh->next) {
|
152 | e3713e00 | Paolo Bonzini | if (!bh->deleted && bh->scheduled) {
|
153 | e3713e00 | Paolo Bonzini | return true; |
154 | e3713e00 | Paolo Bonzini | } |
155 | e3713e00 | Paolo Bonzini | } |
156 | e3713e00 | Paolo Bonzini | return aio_pending(ctx);
|
157 | e3713e00 | Paolo Bonzini | } |
158 | e3713e00 | Paolo Bonzini | |
159 | e3713e00 | Paolo Bonzini | static gboolean
|
160 | e3713e00 | Paolo Bonzini | aio_ctx_dispatch(GSource *source, |
161 | e3713e00 | Paolo Bonzini | GSourceFunc callback, |
162 | e3713e00 | Paolo Bonzini | gpointer user_data) |
163 | e3713e00 | Paolo Bonzini | { |
164 | e3713e00 | Paolo Bonzini | AioContext *ctx = (AioContext *) source; |
165 | e3713e00 | Paolo Bonzini | |
166 | e3713e00 | Paolo Bonzini | assert(callback == NULL);
|
167 | e3713e00 | Paolo Bonzini | aio_poll(ctx, false);
|
168 | e3713e00 | Paolo Bonzini | return true; |
169 | e3713e00 | Paolo Bonzini | } |
170 | e3713e00 | Paolo Bonzini | |
171 | 2f4dc3c1 | Paolo Bonzini | static void |
172 | 2f4dc3c1 | Paolo Bonzini | aio_ctx_finalize(GSource *source) |
173 | 2f4dc3c1 | Paolo Bonzini | { |
174 | 2f4dc3c1 | Paolo Bonzini | AioContext *ctx = (AioContext *) source; |
175 | 2f4dc3c1 | Paolo Bonzini | |
176 | 9b34277d | Stefan Hajnoczi | thread_pool_free(ctx->thread_pool); |
177 | 2f4dc3c1 | Paolo Bonzini | aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL); |
178 | 2f4dc3c1 | Paolo Bonzini | event_notifier_cleanup(&ctx->notifier); |
179 | 6b5f8762 | Stefan Hajnoczi | g_array_free(ctx->pollfds, TRUE); |
180 | 2f4dc3c1 | Paolo Bonzini | } |
181 | 2f4dc3c1 | Paolo Bonzini | |
182 | e3713e00 | Paolo Bonzini | static GSourceFuncs aio_source_funcs = {
|
183 | e3713e00 | Paolo Bonzini | aio_ctx_prepare, |
184 | e3713e00 | Paolo Bonzini | aio_ctx_check, |
185 | e3713e00 | Paolo Bonzini | aio_ctx_dispatch, |
186 | 2f4dc3c1 | Paolo Bonzini | aio_ctx_finalize |
187 | e3713e00 | Paolo Bonzini | }; |
188 | e3713e00 | Paolo Bonzini | |
189 | e3713e00 | Paolo Bonzini | GSource *aio_get_g_source(AioContext *ctx) |
190 | e3713e00 | Paolo Bonzini | { |
191 | e3713e00 | Paolo Bonzini | g_source_ref(&ctx->source); |
192 | e3713e00 | Paolo Bonzini | return &ctx->source;
|
193 | e3713e00 | Paolo Bonzini | } |
194 | a915f4bc | Paolo Bonzini | |
195 | 9b34277d | Stefan Hajnoczi | ThreadPool *aio_get_thread_pool(AioContext *ctx) |
196 | 9b34277d | Stefan Hajnoczi | { |
197 | 9b34277d | Stefan Hajnoczi | if (!ctx->thread_pool) {
|
198 | 9b34277d | Stefan Hajnoczi | ctx->thread_pool = thread_pool_new(ctx); |
199 | 9b34277d | Stefan Hajnoczi | } |
200 | 9b34277d | Stefan Hajnoczi | return ctx->thread_pool;
|
201 | 9b34277d | Stefan Hajnoczi | } |
202 | 9b34277d | Stefan Hajnoczi | |
203 | 2f4dc3c1 | Paolo Bonzini | void aio_notify(AioContext *ctx)
|
204 | 2f4dc3c1 | Paolo Bonzini | { |
205 | 2f4dc3c1 | Paolo Bonzini | event_notifier_set(&ctx->notifier); |
206 | 2f4dc3c1 | Paolo Bonzini | } |
207 | 2f4dc3c1 | Paolo Bonzini | |
208 | f627aab1 | Paolo Bonzini | AioContext *aio_context_new(void)
|
209 | f627aab1 | Paolo Bonzini | { |
210 | 2f4dc3c1 | Paolo Bonzini | AioContext *ctx; |
211 | 2f4dc3c1 | Paolo Bonzini | ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
|
212 | 6b5f8762 | Stefan Hajnoczi | ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD));
|
213 | 9b34277d | Stefan Hajnoczi | ctx->thread_pool = NULL;
|
214 | 2f4dc3c1 | Paolo Bonzini | event_notifier_init(&ctx->notifier, false);
|
215 | 2f4dc3c1 | Paolo Bonzini | aio_set_event_notifier(ctx, &ctx->notifier, |
216 | 2f4dc3c1 | Paolo Bonzini | (EventNotifierHandler *) |
217 | 2f4dc3c1 | Paolo Bonzini | event_notifier_test_and_clear, NULL);
|
218 | 2f4dc3c1 | Paolo Bonzini | |
219 | 2f4dc3c1 | Paolo Bonzini | return ctx;
|
220 | e3713e00 | Paolo Bonzini | } |
221 | e3713e00 | Paolo Bonzini | |
222 | e3713e00 | Paolo Bonzini | void aio_context_ref(AioContext *ctx)
|
223 | e3713e00 | Paolo Bonzini | { |
224 | e3713e00 | Paolo Bonzini | g_source_ref(&ctx->source); |
225 | e3713e00 | Paolo Bonzini | } |
226 | e3713e00 | Paolo Bonzini | |
227 | e3713e00 | Paolo Bonzini | void aio_context_unref(AioContext *ctx)
|
228 | e3713e00 | Paolo Bonzini | { |
229 | e3713e00 | Paolo Bonzini | g_source_unref(&ctx->source); |
230 | f627aab1 | Paolo Bonzini | } |