]> git.proxmox.com Git - mirror_qemu.git/blame - tests/test-aio.c
qtest: Adapt vhost-user-test to latest vhost-user changes
[mirror_qemu.git] / tests / test-aio.c
CommitLineData
b2ea25d7
PB
1/*
2 * AioContext tests
3 *
4 * Copyright Red Hat, Inc. 2012
5 *
6 * Authors:
7 * Paolo Bonzini <pbonzini@redhat.com>
8 *
9 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
10 * See the COPYING.LIB file in the top-level directory.
11 */
12
13#include <glib.h>
737e150e 14#include "block/aio.h"
dae21b98 15#include "qemu/timer.h"
a94a3fac 16#include "qemu/sockets.h"
b2ea25d7
PB
17
18AioContext *ctx;
19
24d1a6d9
SH
20typedef struct {
21 EventNotifier e;
22 int n;
23 int active;
24 bool auto_set;
25} EventNotifierTestData;
26
9fe3781f
SH
27/* Wait until there are no more BHs or AIO requests */
28static void wait_for_aio(void)
29{
30 while (aio_poll(ctx, true)) {
31 /* Do nothing */
32 }
33}
34
24d1a6d9
SH
35/* Wait until event notifier becomes inactive */
36static void wait_until_inactive(EventNotifierTestData *data)
37{
38 while (data->active > 0) {
39 aio_poll(ctx, true);
40 }
41}
42
b2ea25d7
PB
43/* Simple callbacks for testing. */
44
45typedef struct {
46 QEMUBH *bh;
47 int n;
48 int max;
49} BHTestData;
50
b53edf97
AB
51typedef struct {
52 QEMUTimer timer;
53 QEMUClockType clock_type;
54 int n;
55 int max;
56 int64_t ns;
57 AioContext *ctx;
58} TimerTestData;
59
b2ea25d7
PB
60static void bh_test_cb(void *opaque)
61{
62 BHTestData *data = opaque;
63 if (++data->n < data->max) {
64 qemu_bh_schedule(data->bh);
65 }
66}
67
08757094
SW
68#if !defined(_WIN32)
69
b53edf97
AB
70static void timer_test_cb(void *opaque)
71{
72 TimerTestData *data = opaque;
73 if (++data->n < data->max) {
74 timer_mod(&data->timer,
75 qemu_clock_get_ns(data->clock_type) + data->ns);
76 }
77}
78
79static void dummy_io_handler_read(void *opaque)
80{
81}
82
08757094
SW
83#endif /* !_WIN32 */
84
b2ea25d7
PB
85static void bh_delete_cb(void *opaque)
86{
87 BHTestData *data = opaque;
88 if (++data->n < data->max) {
89 qemu_bh_schedule(data->bh);
90 } else {
91 qemu_bh_delete(data->bh);
92 data->bh = NULL;
93 }
94}
95
b2ea25d7
PB
96static void event_ready_cb(EventNotifier *e)
97{
98 EventNotifierTestData *data = container_of(e, EventNotifierTestData, e);
99 g_assert(event_notifier_test_and_clear(e));
100 data->n++;
101 if (data->active > 0) {
102 data->active--;
103 }
104 if (data->auto_set && data->active) {
105 event_notifier_set(e);
106 }
107}
108
109/* Tests using aio_*. */
110
111static void test_notify(void)
112{
113 g_assert(!aio_poll(ctx, false));
114 aio_notify(ctx);
115 g_assert(!aio_poll(ctx, true));
116 g_assert(!aio_poll(ctx, false));
117}
118
98563fc3
SH
119typedef struct {
120 QemuMutex start_lock;
121 bool thread_acquired;
122} AcquireTestData;
123
124static void *test_acquire_thread(void *opaque)
125{
126 AcquireTestData *data = opaque;
127
128 /* Wait for other thread to let us start */
129 qemu_mutex_lock(&data->start_lock);
130 qemu_mutex_unlock(&data->start_lock);
131
132 aio_context_acquire(ctx);
133 aio_context_release(ctx);
134
135 data->thread_acquired = true; /* success, we got here */
136
137 return NULL;
138}
139
140static void dummy_notifier_read(EventNotifier *unused)
141{
142 g_assert(false); /* should never be invoked */
143}
144
145static void test_acquire(void)
146{
147 QemuThread thread;
148 EventNotifier notifier;
149 AcquireTestData data;
150
151 /* Dummy event notifier ensures aio_poll() will block */
152 event_notifier_init(&notifier, false);
153 aio_set_event_notifier(ctx, &notifier, dummy_notifier_read);
154 g_assert(!aio_poll(ctx, false)); /* consume aio_notify() */
155
156 qemu_mutex_init(&data.start_lock);
157 qemu_mutex_lock(&data.start_lock);
158 data.thread_acquired = false;
159
160 qemu_thread_create(&thread, "test_acquire_thread",
161 test_acquire_thread,
162 &data, QEMU_THREAD_JOINABLE);
163
164 /* Block in aio_poll(), let other thread kick us and acquire context */
165 aio_context_acquire(ctx);
166 qemu_mutex_unlock(&data.start_lock); /* let the thread run */
167 g_assert(!aio_poll(ctx, true));
168 aio_context_release(ctx);
169
170 qemu_thread_join(&thread);
171 aio_set_event_notifier(ctx, &notifier, NULL);
172 event_notifier_cleanup(&notifier);
173
174 g_assert(data.thread_acquired);
175}
176
b2ea25d7
PB
177static void test_bh_schedule(void)
178{
179 BHTestData data = { .n = 0 };
180 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
181
182 qemu_bh_schedule(data.bh);
183 g_assert_cmpint(data.n, ==, 0);
184
185 g_assert(aio_poll(ctx, true));
186 g_assert_cmpint(data.n, ==, 1);
187
188 g_assert(!aio_poll(ctx, false));
189 g_assert_cmpint(data.n, ==, 1);
190 qemu_bh_delete(data.bh);
191}
192
193static void test_bh_schedule10(void)
194{
195 BHTestData data = { .n = 0, .max = 10 };
196 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
197
198 qemu_bh_schedule(data.bh);
199 g_assert_cmpint(data.n, ==, 0);
200
201 g_assert(aio_poll(ctx, false));
202 g_assert_cmpint(data.n, ==, 1);
203
204 g_assert(aio_poll(ctx, true));
205 g_assert_cmpint(data.n, ==, 2);
206
9fe3781f 207 wait_for_aio();
b2ea25d7
PB
208 g_assert_cmpint(data.n, ==, 10);
209
210 g_assert(!aio_poll(ctx, false));
211 g_assert_cmpint(data.n, ==, 10);
212 qemu_bh_delete(data.bh);
213}
214
215static void test_bh_cancel(void)
216{
217 BHTestData data = { .n = 0 };
218 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
219
220 qemu_bh_schedule(data.bh);
221 g_assert_cmpint(data.n, ==, 0);
222
223 qemu_bh_cancel(data.bh);
224 g_assert_cmpint(data.n, ==, 0);
225
226 g_assert(!aio_poll(ctx, false));
227 g_assert_cmpint(data.n, ==, 0);
228 qemu_bh_delete(data.bh);
229}
230
231static void test_bh_delete(void)
232{
233 BHTestData data = { .n = 0 };
234 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
235
236 qemu_bh_schedule(data.bh);
237 g_assert_cmpint(data.n, ==, 0);
238
239 qemu_bh_delete(data.bh);
240 g_assert_cmpint(data.n, ==, 0);
241
242 g_assert(!aio_poll(ctx, false));
243 g_assert_cmpint(data.n, ==, 0);
244}
245
246static void test_bh_delete_from_cb(void)
247{
248 BHTestData data1 = { .n = 0, .max = 1 };
249
250 data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
251
252 qemu_bh_schedule(data1.bh);
253 g_assert_cmpint(data1.n, ==, 0);
254
9fe3781f 255 wait_for_aio();
b2ea25d7
PB
256 g_assert_cmpint(data1.n, ==, data1.max);
257 g_assert(data1.bh == NULL);
258
259 g_assert(!aio_poll(ctx, false));
b2ea25d7
PB
260}
261
262static void test_bh_delete_from_cb_many(void)
263{
264 BHTestData data1 = { .n = 0, .max = 1 };
265 BHTestData data2 = { .n = 0, .max = 3 };
266 BHTestData data3 = { .n = 0, .max = 2 };
267 BHTestData data4 = { .n = 0, .max = 4 };
268
269 data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
270 data2.bh = aio_bh_new(ctx, bh_delete_cb, &data2);
271 data3.bh = aio_bh_new(ctx, bh_delete_cb, &data3);
272 data4.bh = aio_bh_new(ctx, bh_delete_cb, &data4);
273
274 qemu_bh_schedule(data1.bh);
275 qemu_bh_schedule(data2.bh);
276 qemu_bh_schedule(data3.bh);
277 qemu_bh_schedule(data4.bh);
278 g_assert_cmpint(data1.n, ==, 0);
279 g_assert_cmpint(data2.n, ==, 0);
280 g_assert_cmpint(data3.n, ==, 0);
281 g_assert_cmpint(data4.n, ==, 0);
282
283 g_assert(aio_poll(ctx, false));
284 g_assert_cmpint(data1.n, ==, 1);
285 g_assert_cmpint(data2.n, ==, 1);
286 g_assert_cmpint(data3.n, ==, 1);
287 g_assert_cmpint(data4.n, ==, 1);
288 g_assert(data1.bh == NULL);
289
9fe3781f 290 wait_for_aio();
b2ea25d7
PB
291 g_assert_cmpint(data1.n, ==, data1.max);
292 g_assert_cmpint(data2.n, ==, data2.max);
293 g_assert_cmpint(data3.n, ==, data3.max);
294 g_assert_cmpint(data4.n, ==, data4.max);
295 g_assert(data1.bh == NULL);
296 g_assert(data2.bh == NULL);
297 g_assert(data3.bh == NULL);
298 g_assert(data4.bh == NULL);
299}
300
301static void test_bh_flush(void)
302{
303 BHTestData data = { .n = 0 };
304 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
305
306 qemu_bh_schedule(data.bh);
307 g_assert_cmpint(data.n, ==, 0);
308
9fe3781f 309 wait_for_aio();
b2ea25d7
PB
310 g_assert_cmpint(data.n, ==, 1);
311
312 g_assert(!aio_poll(ctx, false));
313 g_assert_cmpint(data.n, ==, 1);
314 qemu_bh_delete(data.bh);
315}
316
317static void test_set_event_notifier(void)
318{
319 EventNotifierTestData data = { .n = 0, .active = 0 };
320 event_notifier_init(&data.e, false);
f2e5dca4 321 aio_set_event_notifier(ctx, &data.e, event_ready_cb);
b2ea25d7
PB
322 g_assert(!aio_poll(ctx, false));
323 g_assert_cmpint(data.n, ==, 0);
324
f2e5dca4 325 aio_set_event_notifier(ctx, &data.e, NULL);
b2ea25d7
PB
326 g_assert(!aio_poll(ctx, false));
327 g_assert_cmpint(data.n, ==, 0);
328 event_notifier_cleanup(&data.e);
329}
330
331static void test_wait_event_notifier(void)
332{
333 EventNotifierTestData data = { .n = 0, .active = 1 };
334 event_notifier_init(&data.e, false);
f2e5dca4 335 aio_set_event_notifier(ctx, &data.e, event_ready_cb);
164a101f 336 g_assert(!aio_poll(ctx, false));
b2ea25d7
PB
337 g_assert_cmpint(data.n, ==, 0);
338 g_assert_cmpint(data.active, ==, 1);
339
340 event_notifier_set(&data.e);
341 g_assert(aio_poll(ctx, false));
342 g_assert_cmpint(data.n, ==, 1);
343 g_assert_cmpint(data.active, ==, 0);
344
345 g_assert(!aio_poll(ctx, false));
346 g_assert_cmpint(data.n, ==, 1);
347 g_assert_cmpint(data.active, ==, 0);
348
f2e5dca4 349 aio_set_event_notifier(ctx, &data.e, NULL);
b2ea25d7
PB
350 g_assert(!aio_poll(ctx, false));
351 g_assert_cmpint(data.n, ==, 1);
352
353 event_notifier_cleanup(&data.e);
354}
355
356static void test_flush_event_notifier(void)
357{
358 EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
359 event_notifier_init(&data.e, false);
f2e5dca4 360 aio_set_event_notifier(ctx, &data.e, event_ready_cb);
164a101f 361 g_assert(!aio_poll(ctx, false));
b2ea25d7
PB
362 g_assert_cmpint(data.n, ==, 0);
363 g_assert_cmpint(data.active, ==, 10);
364
365 event_notifier_set(&data.e);
366 g_assert(aio_poll(ctx, false));
367 g_assert_cmpint(data.n, ==, 1);
368 g_assert_cmpint(data.active, ==, 9);
369 g_assert(aio_poll(ctx, false));
370
24d1a6d9 371 wait_until_inactive(&data);
b2ea25d7
PB
372 g_assert_cmpint(data.n, ==, 10);
373 g_assert_cmpint(data.active, ==, 0);
374 g_assert(!aio_poll(ctx, false));
375
f2e5dca4 376 aio_set_event_notifier(ctx, &data.e, NULL);
b2ea25d7
PB
377 g_assert(!aio_poll(ctx, false));
378 event_notifier_cleanup(&data.e);
379}
380
381static void test_wait_event_notifier_noflush(void)
382{
383 EventNotifierTestData data = { .n = 0 };
384 EventNotifierTestData dummy = { .n = 0, .active = 1 };
385
386 event_notifier_init(&data.e, false);
f2e5dca4 387 aio_set_event_notifier(ctx, &data.e, event_ready_cb);
b2ea25d7
PB
388
389 g_assert(!aio_poll(ctx, false));
390 g_assert_cmpint(data.n, ==, 0);
391
392 /* Until there is an active descriptor, aio_poll may or may not call
393 * event_ready_cb. Still, it must not block. */
394 event_notifier_set(&data.e);
164a101f 395 g_assert(aio_poll(ctx, true));
b2ea25d7
PB
396 data.n = 0;
397
398 /* An active event notifier forces aio_poll to look at EventNotifiers. */
399 event_notifier_init(&dummy.e, false);
f2e5dca4 400 aio_set_event_notifier(ctx, &dummy.e, event_ready_cb);
b2ea25d7
PB
401
402 event_notifier_set(&data.e);
403 g_assert(aio_poll(ctx, false));
404 g_assert_cmpint(data.n, ==, 1);
164a101f 405 g_assert(!aio_poll(ctx, false));
b2ea25d7
PB
406 g_assert_cmpint(data.n, ==, 1);
407
408 event_notifier_set(&data.e);
409 g_assert(aio_poll(ctx, false));
410 g_assert_cmpint(data.n, ==, 2);
164a101f 411 g_assert(!aio_poll(ctx, false));
b2ea25d7
PB
412 g_assert_cmpint(data.n, ==, 2);
413
414 event_notifier_set(&dummy.e);
24d1a6d9 415 wait_until_inactive(&dummy);
b2ea25d7
PB
416 g_assert_cmpint(data.n, ==, 2);
417 g_assert_cmpint(dummy.n, ==, 1);
418 g_assert_cmpint(dummy.active, ==, 0);
419
f2e5dca4 420 aio_set_event_notifier(ctx, &dummy.e, NULL);
b2ea25d7
PB
421 event_notifier_cleanup(&dummy.e);
422
f2e5dca4 423 aio_set_event_notifier(ctx, &data.e, NULL);
b2ea25d7
PB
424 g_assert(!aio_poll(ctx, false));
425 g_assert_cmpint(data.n, ==, 2);
426
427 event_notifier_cleanup(&data.e);
428}
429
08757094
SW
430#if !defined(_WIN32)
431
b53edf97
AB
432static void test_timer_schedule(void)
433{
434 TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
435 .max = 2,
436 .clock_type = QEMU_CLOCK_VIRTUAL };
437 int pipefd[2];
438
439 /* aio_poll will not block to wait for timers to complete unless it has
440 * an fd to wait on. Fixing this breaks other tests. So create a dummy one.
441 */
a94a3fac
AB
442 g_assert(!qemu_pipe(pipefd));
443 qemu_set_nonblock(pipefd[0]);
444 qemu_set_nonblock(pipefd[1]);
445
b53edf97 446 aio_set_fd_handler(ctx, pipefd[0],
91c68f14 447 dummy_io_handler_read, NULL, NULL);
b53edf97
AB
448 aio_poll(ctx, false);
449
450 aio_timer_init(ctx, &data.timer, data.clock_type,
451 SCALE_NS, timer_test_cb, &data);
452 timer_mod(&data.timer,
453 qemu_clock_get_ns(data.clock_type) +
454 data.ns);
455
456 g_assert_cmpint(data.n, ==, 0);
457
458 /* timer_mod may well cause an event notifer to have gone off,
459 * so clear that
460 */
461 do {} while (aio_poll(ctx, false));
462
463 g_assert(!aio_poll(ctx, false));
464 g_assert_cmpint(data.n, ==, 0);
465
fcdda211 466 g_usleep(1 * G_USEC_PER_SEC);
b53edf97
AB
467 g_assert_cmpint(data.n, ==, 0);
468
469 g_assert(aio_poll(ctx, false));
470 g_assert_cmpint(data.n, ==, 1);
471
472 /* timer_mod called by our callback */
473 do {} while (aio_poll(ctx, false));
474
475 g_assert(!aio_poll(ctx, false));
476 g_assert_cmpint(data.n, ==, 1);
477
478 g_assert(aio_poll(ctx, true));
479 g_assert_cmpint(data.n, ==, 2);
480
481 /* As max is now 2, an event notifier should not have gone off */
482
483 g_assert(!aio_poll(ctx, false));
484 g_assert_cmpint(data.n, ==, 2);
485
486 aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL);
487 close(pipefd[0]);
488 close(pipefd[1]);
489
490 timer_del(&data.timer);
491}
492
08757094
SW
493#endif /* !_WIN32 */
494
b2ea25d7
PB
495/* Now the same tests, using the context as a GSource. They are
496 * very similar to the ones above, with g_main_context_iteration
497 * replacing aio_poll. However:
498 * - sometimes both the AioContext and the glib main loop wake
499 * themselves up. Hence, some "g_assert(!aio_poll(ctx, false));"
500 * are replaced by "while (g_main_context_iteration(NULL, false));".
9fe3781f 501 * - there is no exact replacement for a blocking wait.
b2ea25d7
PB
502 * "while (g_main_context_iteration(NULL, true)" seems to work,
503 * but it is not documented _why_ it works. For these tests a
504 * non-blocking loop like "while (g_main_context_iteration(NULL, false)"
505 * works well, and that's what I am using.
506 */
507
508static void test_source_notify(void)
509{
510 while (g_main_context_iteration(NULL, false));
511 aio_notify(ctx);
512 g_assert(g_main_context_iteration(NULL, true));
513 g_assert(!g_main_context_iteration(NULL, false));
514}
515
516static void test_source_flush(void)
517{
518 g_assert(!g_main_context_iteration(NULL, false));
519 aio_notify(ctx);
520 while (g_main_context_iteration(NULL, false));
521 g_assert(!g_main_context_iteration(NULL, false));
522}
523
524static void test_source_bh_schedule(void)
525{
526 BHTestData data = { .n = 0 };
527 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
528
529 qemu_bh_schedule(data.bh);
530 g_assert_cmpint(data.n, ==, 0);
531
532 g_assert(g_main_context_iteration(NULL, true));
533 g_assert_cmpint(data.n, ==, 1);
534
535 g_assert(!g_main_context_iteration(NULL, false));
536 g_assert_cmpint(data.n, ==, 1);
537 qemu_bh_delete(data.bh);
538}
539
540static void test_source_bh_schedule10(void)
541{
542 BHTestData data = { .n = 0, .max = 10 };
543 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
544
545 qemu_bh_schedule(data.bh);
546 g_assert_cmpint(data.n, ==, 0);
547
548 g_assert(g_main_context_iteration(NULL, false));
549 g_assert_cmpint(data.n, ==, 1);
550
551 g_assert(g_main_context_iteration(NULL, true));
552 g_assert_cmpint(data.n, ==, 2);
553
554 while (g_main_context_iteration(NULL, false));
555 g_assert_cmpint(data.n, ==, 10);
556
557 g_assert(!g_main_context_iteration(NULL, false));
558 g_assert_cmpint(data.n, ==, 10);
559 qemu_bh_delete(data.bh);
560}
561
562static void test_source_bh_cancel(void)
563{
564 BHTestData data = { .n = 0 };
565 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
566
567 qemu_bh_schedule(data.bh);
568 g_assert_cmpint(data.n, ==, 0);
569
570 qemu_bh_cancel(data.bh);
571 g_assert_cmpint(data.n, ==, 0);
572
573 while (g_main_context_iteration(NULL, false));
574 g_assert_cmpint(data.n, ==, 0);
575 qemu_bh_delete(data.bh);
576}
577
578static void test_source_bh_delete(void)
579{
580 BHTestData data = { .n = 0 };
581 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
582
583 qemu_bh_schedule(data.bh);
584 g_assert_cmpint(data.n, ==, 0);
585
586 qemu_bh_delete(data.bh);
587 g_assert_cmpint(data.n, ==, 0);
588
589 while (g_main_context_iteration(NULL, false));
590 g_assert_cmpint(data.n, ==, 0);
591}
592
593static void test_source_bh_delete_from_cb(void)
594{
595 BHTestData data1 = { .n = 0, .max = 1 };
596
597 data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
598
599 qemu_bh_schedule(data1.bh);
600 g_assert_cmpint(data1.n, ==, 0);
601
602 g_main_context_iteration(NULL, true);
603 g_assert_cmpint(data1.n, ==, data1.max);
604 g_assert(data1.bh == NULL);
605
606 g_assert(!g_main_context_iteration(NULL, false));
607}
608
609static void test_source_bh_delete_from_cb_many(void)
610{
611 BHTestData data1 = { .n = 0, .max = 1 };
612 BHTestData data2 = { .n = 0, .max = 3 };
613 BHTestData data3 = { .n = 0, .max = 2 };
614 BHTestData data4 = { .n = 0, .max = 4 };
615
616 data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
617 data2.bh = aio_bh_new(ctx, bh_delete_cb, &data2);
618 data3.bh = aio_bh_new(ctx, bh_delete_cb, &data3);
619 data4.bh = aio_bh_new(ctx, bh_delete_cb, &data4);
620
621 qemu_bh_schedule(data1.bh);
622 qemu_bh_schedule(data2.bh);
623 qemu_bh_schedule(data3.bh);
624 qemu_bh_schedule(data4.bh);
625 g_assert_cmpint(data1.n, ==, 0);
626 g_assert_cmpint(data2.n, ==, 0);
627 g_assert_cmpint(data3.n, ==, 0);
628 g_assert_cmpint(data4.n, ==, 0);
629
630 g_assert(g_main_context_iteration(NULL, false));
631 g_assert_cmpint(data1.n, ==, 1);
632 g_assert_cmpint(data2.n, ==, 1);
633 g_assert_cmpint(data3.n, ==, 1);
634 g_assert_cmpint(data4.n, ==, 1);
635 g_assert(data1.bh == NULL);
636
637 while (g_main_context_iteration(NULL, false));
638 g_assert_cmpint(data1.n, ==, data1.max);
639 g_assert_cmpint(data2.n, ==, data2.max);
640 g_assert_cmpint(data3.n, ==, data3.max);
641 g_assert_cmpint(data4.n, ==, data4.max);
642 g_assert(data1.bh == NULL);
643 g_assert(data2.bh == NULL);
644 g_assert(data3.bh == NULL);
645 g_assert(data4.bh == NULL);
646}
647
648static void test_source_bh_flush(void)
649{
650 BHTestData data = { .n = 0 };
651 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
652
653 qemu_bh_schedule(data.bh);
654 g_assert_cmpint(data.n, ==, 0);
655
656 g_assert(g_main_context_iteration(NULL, true));
657 g_assert_cmpint(data.n, ==, 1);
658
659 g_assert(!g_main_context_iteration(NULL, false));
660 g_assert_cmpint(data.n, ==, 1);
661 qemu_bh_delete(data.bh);
662}
663
664static void test_source_set_event_notifier(void)
665{
666 EventNotifierTestData data = { .n = 0, .active = 0 };
667 event_notifier_init(&data.e, false);
f2e5dca4 668 aio_set_event_notifier(ctx, &data.e, event_ready_cb);
b2ea25d7
PB
669 while (g_main_context_iteration(NULL, false));
670 g_assert_cmpint(data.n, ==, 0);
671
f2e5dca4 672 aio_set_event_notifier(ctx, &data.e, NULL);
b2ea25d7
PB
673 while (g_main_context_iteration(NULL, false));
674 g_assert_cmpint(data.n, ==, 0);
675 event_notifier_cleanup(&data.e);
676}
677
678static void test_source_wait_event_notifier(void)
679{
680 EventNotifierTestData data = { .n = 0, .active = 1 };
681 event_notifier_init(&data.e, false);
f2e5dca4 682 aio_set_event_notifier(ctx, &data.e, event_ready_cb);
b2ea25d7
PB
683 g_assert(g_main_context_iteration(NULL, false));
684 g_assert_cmpint(data.n, ==, 0);
685 g_assert_cmpint(data.active, ==, 1);
686
687 event_notifier_set(&data.e);
688 g_assert(g_main_context_iteration(NULL, false));
689 g_assert_cmpint(data.n, ==, 1);
690 g_assert_cmpint(data.active, ==, 0);
691
692 while (g_main_context_iteration(NULL, false));
693 g_assert_cmpint(data.n, ==, 1);
694 g_assert_cmpint(data.active, ==, 0);
695
f2e5dca4 696 aio_set_event_notifier(ctx, &data.e, NULL);
b2ea25d7
PB
697 while (g_main_context_iteration(NULL, false));
698 g_assert_cmpint(data.n, ==, 1);
699
700 event_notifier_cleanup(&data.e);
701}
702
703static void test_source_flush_event_notifier(void)
704{
705 EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
706 event_notifier_init(&data.e, false);
f2e5dca4 707 aio_set_event_notifier(ctx, &data.e, event_ready_cb);
b2ea25d7
PB
708 g_assert(g_main_context_iteration(NULL, false));
709 g_assert_cmpint(data.n, ==, 0);
710 g_assert_cmpint(data.active, ==, 10);
711
712 event_notifier_set(&data.e);
713 g_assert(g_main_context_iteration(NULL, false));
714 g_assert_cmpint(data.n, ==, 1);
715 g_assert_cmpint(data.active, ==, 9);
716 g_assert(g_main_context_iteration(NULL, false));
717
718 while (g_main_context_iteration(NULL, false));
719 g_assert_cmpint(data.n, ==, 10);
720 g_assert_cmpint(data.active, ==, 0);
721 g_assert(!g_main_context_iteration(NULL, false));
722
f2e5dca4 723 aio_set_event_notifier(ctx, &data.e, NULL);
b2ea25d7
PB
724 while (g_main_context_iteration(NULL, false));
725 event_notifier_cleanup(&data.e);
726}
727
728static void test_source_wait_event_notifier_noflush(void)
729{
730 EventNotifierTestData data = { .n = 0 };
731 EventNotifierTestData dummy = { .n = 0, .active = 1 };
732
733 event_notifier_init(&data.e, false);
f2e5dca4 734 aio_set_event_notifier(ctx, &data.e, event_ready_cb);
b2ea25d7
PB
735
736 while (g_main_context_iteration(NULL, false));
737 g_assert_cmpint(data.n, ==, 0);
738
739 /* Until there is an active descriptor, glib may or may not call
740 * event_ready_cb. Still, it must not block. */
741 event_notifier_set(&data.e);
742 g_main_context_iteration(NULL, true);
743 data.n = 0;
744
745 /* An active event notifier forces aio_poll to look at EventNotifiers. */
746 event_notifier_init(&dummy.e, false);
f2e5dca4 747 aio_set_event_notifier(ctx, &dummy.e, event_ready_cb);
b2ea25d7
PB
748
749 event_notifier_set(&data.e);
750 g_assert(g_main_context_iteration(NULL, false));
751 g_assert_cmpint(data.n, ==, 1);
752 g_assert(!g_main_context_iteration(NULL, false));
753 g_assert_cmpint(data.n, ==, 1);
754
755 event_notifier_set(&data.e);
756 g_assert(g_main_context_iteration(NULL, false));
757 g_assert_cmpint(data.n, ==, 2);
758 g_assert(!g_main_context_iteration(NULL, false));
759 g_assert_cmpint(data.n, ==, 2);
760
761 event_notifier_set(&dummy.e);
762 while (g_main_context_iteration(NULL, false));
763 g_assert_cmpint(data.n, ==, 2);
764 g_assert_cmpint(dummy.n, ==, 1);
765 g_assert_cmpint(dummy.active, ==, 0);
766
f2e5dca4 767 aio_set_event_notifier(ctx, &dummy.e, NULL);
b2ea25d7
PB
768 event_notifier_cleanup(&dummy.e);
769
f2e5dca4 770 aio_set_event_notifier(ctx, &data.e, NULL);
b2ea25d7
PB
771 while (g_main_context_iteration(NULL, false));
772 g_assert_cmpint(data.n, ==, 2);
773
774 event_notifier_cleanup(&data.e);
775}
776
08757094
SW
777#if !defined(_WIN32)
778
b53edf97
AB
779static void test_source_timer_schedule(void)
780{
781 TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
782 .max = 2,
783 .clock_type = QEMU_CLOCK_VIRTUAL };
784 int pipefd[2];
785 int64_t expiry;
786
787 /* aio_poll will not block to wait for timers to complete unless it has
788 * an fd to wait on. Fixing this breaks other tests. So create a dummy one.
789 */
a94a3fac
AB
790 g_assert(!qemu_pipe(pipefd));
791 qemu_set_nonblock(pipefd[0]);
792 qemu_set_nonblock(pipefd[1]);
793
b53edf97 794 aio_set_fd_handler(ctx, pipefd[0],
91c68f14 795 dummy_io_handler_read, NULL, NULL);
b53edf97
AB
796 do {} while (g_main_context_iteration(NULL, false));
797
798 aio_timer_init(ctx, &data.timer, data.clock_type,
799 SCALE_NS, timer_test_cb, &data);
800 expiry = qemu_clock_get_ns(data.clock_type) +
801 data.ns;
802 timer_mod(&data.timer, expiry);
803
804 g_assert_cmpint(data.n, ==, 0);
805
fcdda211 806 g_usleep(1 * G_USEC_PER_SEC);
b53edf97
AB
807 g_assert_cmpint(data.n, ==, 0);
808
809 g_assert(g_main_context_iteration(NULL, false));
810 g_assert_cmpint(data.n, ==, 1);
811
812 /* The comment above was not kidding when it said this wakes up itself */
813 do {
814 g_assert(g_main_context_iteration(NULL, true));
815 } while (qemu_clock_get_ns(data.clock_type) <= expiry);
fcdda211 816 g_usleep(1 * G_USEC_PER_SEC);
b53edf97
AB
817 g_main_context_iteration(NULL, false);
818
819 g_assert_cmpint(data.n, ==, 2);
820
821 aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL);
822 close(pipefd[0]);
823 close(pipefd[1]);
824
825 timer_del(&data.timer);
826}
827
08757094
SW
828#endif /* !_WIN32 */
829
b53edf97 830
b2ea25d7
PB
831/* End of tests. */
832
833int main(int argc, char **argv)
834{
835 GSource *src;
836
dae21b98
AB
837 init_clocks();
838
b2ea25d7
PB
839 ctx = aio_context_new();
840 src = aio_get_g_source(ctx);
841 g_source_attach(src, NULL);
842 g_source_unref(src);
843
844 while (g_main_context_iteration(NULL, false));
845
846 g_test_init(&argc, &argv, NULL);
847 g_test_add_func("/aio/notify", test_notify);
98563fc3 848 g_test_add_func("/aio/acquire", test_acquire);
b2ea25d7
PB
849 g_test_add_func("/aio/bh/schedule", test_bh_schedule);
850 g_test_add_func("/aio/bh/schedule10", test_bh_schedule10);
851 g_test_add_func("/aio/bh/cancel", test_bh_cancel);
852 g_test_add_func("/aio/bh/delete", test_bh_delete);
853 g_test_add_func("/aio/bh/callback-delete/one", test_bh_delete_from_cb);
854 g_test_add_func("/aio/bh/callback-delete/many", test_bh_delete_from_cb_many);
855 g_test_add_func("/aio/bh/flush", test_bh_flush);
856 g_test_add_func("/aio/event/add-remove", test_set_event_notifier);
857 g_test_add_func("/aio/event/wait", test_wait_event_notifier);
858 g_test_add_func("/aio/event/wait/no-flush-cb", test_wait_event_notifier_noflush);
859 g_test_add_func("/aio/event/flush", test_flush_event_notifier);
08757094 860#if !defined(_WIN32)
b53edf97 861 g_test_add_func("/aio/timer/schedule", test_timer_schedule);
08757094 862#endif
b2ea25d7
PB
863
864 g_test_add_func("/aio-gsource/notify", test_source_notify);
865 g_test_add_func("/aio-gsource/flush", test_source_flush);
866 g_test_add_func("/aio-gsource/bh/schedule", test_source_bh_schedule);
867 g_test_add_func("/aio-gsource/bh/schedule10", test_source_bh_schedule10);
868 g_test_add_func("/aio-gsource/bh/cancel", test_source_bh_cancel);
869 g_test_add_func("/aio-gsource/bh/delete", test_source_bh_delete);
870 g_test_add_func("/aio-gsource/bh/callback-delete/one", test_source_bh_delete_from_cb);
871 g_test_add_func("/aio-gsource/bh/callback-delete/many", test_source_bh_delete_from_cb_many);
872 g_test_add_func("/aio-gsource/bh/flush", test_source_bh_flush);
873 g_test_add_func("/aio-gsource/event/add-remove", test_source_set_event_notifier);
874 g_test_add_func("/aio-gsource/event/wait", test_source_wait_event_notifier);
875 g_test_add_func("/aio-gsource/event/wait/no-flush-cb", test_source_wait_event_notifier_noflush);
876 g_test_add_func("/aio-gsource/event/flush", test_source_flush_event_notifier);
08757094 877#if !defined(_WIN32)
b53edf97 878 g_test_add_func("/aio-gsource/timer/schedule", test_source_timer_schedule);
08757094 879#endif
b2ea25d7
PB
880 return g_test_run();
881}