1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "block/aio.h"
15#include "qapi/error.h"
16#include "qemu/timer.h"
17#include "qemu/sockets.h"
18#include "qemu/error-report.h"
19#include "qemu/coroutine-core.h"
20#include "qemu/main-loop.h"
21
22static AioContext *ctx;
23
24typedef struct {
25 EventNotifier e;
26 int n;
27 int active;
28 bool auto_set;
29} EventNotifierTestData;
30
31
32static void wait_until_inactive(EventNotifierTestData *data)
33{
34 while (data->active > 0) {
35 aio_poll(ctx, true);
36 }
37}
38
39
40
41typedef struct {
42 QEMUBH *bh;
43 int n;
44 int max;
45} BHTestData;
46
47typedef struct {
48 QEMUTimer timer;
49 QEMUClockType clock_type;
50 int n;
51 int max;
52 int64_t ns;
53 AioContext *ctx;
54} TimerTestData;
55
56static void bh_test_cb(void *opaque)
57{
58 BHTestData *data = opaque;
59 if (++data->n < data->max) {
60 qemu_bh_schedule(data->bh);
61 }
62}
63
64static void timer_test_cb(void *opaque)
65{
66 TimerTestData *data = opaque;
67 if (++data->n < data->max) {
68 timer_mod(&data->timer,
69 qemu_clock_get_ns(data->clock_type) + data->ns);
70 }
71}
72
73static void dummy_io_handler_read(EventNotifier *e)
74{
75}
76
77static void bh_delete_cb(void *opaque)
78{
79 BHTestData *data = opaque;
80 if (++data->n < data->max) {
81 qemu_bh_schedule(data->bh);
82 } else {
83 qemu_bh_delete(data->bh);
84 data->bh = NULL;
85 }
86}
87
88static void event_ready_cb(EventNotifier *e)
89{
90 EventNotifierTestData *data = container_of(e, EventNotifierTestData, e);
91 g_assert(event_notifier_test_and_clear(e));
92 data->n++;
93 if (data->active > 0) {
94 data->active--;
95 }
96 if (data->auto_set && data->active) {
97 event_notifier_set(e);
98 }
99}
100
101
102
103typedef struct {
104 QemuMutex start_lock;
105 EventNotifier notifier;
106 bool thread_acquired;
107} AcquireTestData;
108
109static void *test_acquire_thread(void *opaque)
110{
111 AcquireTestData *data = opaque;
112
113
114 qemu_mutex_lock(&data->start_lock);
115 qemu_mutex_unlock(&data->start_lock);
116
117
118
119
120
121 event_notifier_set(&data->notifier);
122 aio_context_acquire(ctx);
123 aio_context_release(ctx);
124
125 data->thread_acquired = true;
126
127 return NULL;
128}
129
130static void set_event_notifier(AioContext *ctx, EventNotifier *notifier,
131 EventNotifierHandler *handler)
132{
133 aio_set_event_notifier(ctx, notifier, handler, NULL, NULL);
134}
135
136static void dummy_notifier_read(EventNotifier *n)
137{
138 event_notifier_test_and_clear(n);
139}
140
141static void test_acquire(void)
142{
143 QemuThread thread;
144 AcquireTestData data;
145
146
147 event_notifier_init(&data.notifier, false);
148 set_event_notifier(ctx, &data.notifier, dummy_notifier_read);
149 g_assert(!aio_poll(ctx, false));
150
151 qemu_mutex_init(&data.start_lock);
152 qemu_mutex_lock(&data.start_lock);
153 data.thread_acquired = false;
154
155 qemu_thread_create(&thread, "test_acquire_thread",
156 test_acquire_thread,
157 &data, QEMU_THREAD_JOINABLE);
158
159
160 aio_context_acquire(ctx);
161 qemu_mutex_unlock(&data.start_lock);
162 g_assert(aio_poll(ctx, true));
163 g_assert(!data.thread_acquired);
164 aio_context_release(ctx);
165
166 qemu_thread_join(&thread);
167 set_event_notifier(ctx, &data.notifier, NULL);
168 event_notifier_cleanup(&data.notifier);
169
170 g_assert(data.thread_acquired);
171}
172
173static void test_bh_schedule(void)
174{
175 BHTestData data = { .n = 0 };
176 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
177
178 qemu_bh_schedule(data.bh);
179 g_assert_cmpint(data.n, ==, 0);
180
181 g_assert(aio_poll(ctx, true));
182 g_assert_cmpint(data.n, ==, 1);
183
184 g_assert(!aio_poll(ctx, false));
185 g_assert_cmpint(data.n, ==, 1);
186 qemu_bh_delete(data.bh);
187}
188
189static void test_bh_schedule10(void)
190{
191 BHTestData data = { .n = 0, .max = 10 };
192 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
193
194 qemu_bh_schedule(data.bh);
195 g_assert_cmpint(data.n, ==, 0);
196
197 g_assert(aio_poll(ctx, false));
198 g_assert_cmpint(data.n, ==, 1);
199
200 g_assert(aio_poll(ctx, true));
201 g_assert_cmpint(data.n, ==, 2);
202
203 while (data.n < 10) {
204 aio_poll(ctx, true);
205 }
206 g_assert_cmpint(data.n, ==, 10);
207
208 g_assert(!aio_poll(ctx, false));
209 g_assert_cmpint(data.n, ==, 10);
210 qemu_bh_delete(data.bh);
211}
212
213static void test_bh_cancel(void)
214{
215 BHTestData data = { .n = 0 };
216 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
217
218 qemu_bh_schedule(data.bh);
219 g_assert_cmpint(data.n, ==, 0);
220
221 qemu_bh_cancel(data.bh);
222 g_assert_cmpint(data.n, ==, 0);
223
224 g_assert(!aio_poll(ctx, false));
225 g_assert_cmpint(data.n, ==, 0);
226 qemu_bh_delete(data.bh);
227}
228
229static void test_bh_delete(void)
230{
231 BHTestData data = { .n = 0 };
232 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
233
234 qemu_bh_schedule(data.bh);
235 g_assert_cmpint(data.n, ==, 0);
236
237 qemu_bh_delete(data.bh);
238 g_assert_cmpint(data.n, ==, 0);
239
240 g_assert(!aio_poll(ctx, false));
241 g_assert_cmpint(data.n, ==, 0);
242}
243
244static void test_bh_delete_from_cb(void)
245{
246 BHTestData data1 = { .n = 0, .max = 1 };
247
248 data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
249
250 qemu_bh_schedule(data1.bh);
251 g_assert_cmpint(data1.n, ==, 0);
252
253 while (data1.n < data1.max) {
254 aio_poll(ctx, true);
255 }
256 g_assert_cmpint(data1.n, ==, data1.max);
257 g_assert(data1.bh == NULL);
258
259 g_assert(!aio_poll(ctx, false));
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
290 while (data1.n < data1.max ||
291 data2.n < data2.max ||
292 data3.n < data3.max ||
293 data4.n < data4.max) {
294 aio_poll(ctx, true);
295 }
296 g_assert_cmpint(data1.n, ==, data1.max);
297 g_assert_cmpint(data2.n, ==, data2.max);
298 g_assert_cmpint(data3.n, ==, data3.max);
299 g_assert_cmpint(data4.n, ==, data4.max);
300 g_assert(data1.bh == NULL);
301 g_assert(data2.bh == NULL);
302 g_assert(data3.bh == NULL);
303 g_assert(data4.bh == NULL);
304}
305
306static void test_bh_flush(void)
307{
308 BHTestData data = { .n = 0 };
309 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
310
311 qemu_bh_schedule(data.bh);
312 g_assert_cmpint(data.n, ==, 0);
313
314 g_assert(aio_poll(ctx, true));
315 g_assert_cmpint(data.n, ==, 1);
316
317 g_assert(!aio_poll(ctx, false));
318 g_assert_cmpint(data.n, ==, 1);
319 qemu_bh_delete(data.bh);
320}
321
322static void test_set_event_notifier(void)
323{
324 EventNotifierTestData data = { .n = 0, .active = 0 };
325 event_notifier_init(&data.e, false);
326 set_event_notifier(ctx, &data.e, event_ready_cb);
327 g_assert(!aio_poll(ctx, false));
328 g_assert_cmpint(data.n, ==, 0);
329
330 set_event_notifier(ctx, &data.e, NULL);
331 g_assert(!aio_poll(ctx, false));
332 g_assert_cmpint(data.n, ==, 0);
333 event_notifier_cleanup(&data.e);
334}
335
336static void test_wait_event_notifier(void)
337{
338 EventNotifierTestData data = { .n = 0, .active = 1 };
339 event_notifier_init(&data.e, false);
340 set_event_notifier(ctx, &data.e, event_ready_cb);
341 while (aio_poll(ctx, false));
342 g_assert_cmpint(data.n, ==, 0);
343 g_assert_cmpint(data.active, ==, 1);
344
345 event_notifier_set(&data.e);
346 g_assert(aio_poll(ctx, false));
347 g_assert_cmpint(data.n, ==, 1);
348 g_assert_cmpint(data.active, ==, 0);
349
350 g_assert(!aio_poll(ctx, false));
351 g_assert_cmpint(data.n, ==, 1);
352 g_assert_cmpint(data.active, ==, 0);
353
354 set_event_notifier(ctx, &data.e, NULL);
355 g_assert(!aio_poll(ctx, false));
356 g_assert_cmpint(data.n, ==, 1);
357
358 event_notifier_cleanup(&data.e);
359}
360
361static void test_flush_event_notifier(void)
362{
363 EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
364 event_notifier_init(&data.e, false);
365 set_event_notifier(ctx, &data.e, event_ready_cb);
366 while (aio_poll(ctx, false));
367 g_assert_cmpint(data.n, ==, 0);
368 g_assert_cmpint(data.active, ==, 10);
369
370 event_notifier_set(&data.e);
371 g_assert(aio_poll(ctx, false));
372 g_assert_cmpint(data.n, ==, 1);
373 g_assert_cmpint(data.active, ==, 9);
374 g_assert(aio_poll(ctx, false));
375
376 wait_until_inactive(&data);
377 g_assert_cmpint(data.n, ==, 10);
378 g_assert_cmpint(data.active, ==, 0);
379 g_assert(!aio_poll(ctx, false));
380
381 set_event_notifier(ctx, &data.e, NULL);
382 g_assert(!aio_poll(ctx, false));
383 event_notifier_cleanup(&data.e);
384}
385
386static void test_wait_event_notifier_noflush(void)
387{
388 EventNotifierTestData data = { .n = 0 };
389 EventNotifierTestData dummy = { .n = 0, .active = 1 };
390
391 event_notifier_init(&data.e, false);
392 set_event_notifier(ctx, &data.e, event_ready_cb);
393
394 g_assert(!aio_poll(ctx, false));
395 g_assert_cmpint(data.n, ==, 0);
396
397
398
399 event_notifier_set(&data.e);
400 g_assert(aio_poll(ctx, true));
401 data.n = 0;
402
403
404 event_notifier_init(&dummy.e, false);
405 set_event_notifier(ctx, &dummy.e, event_ready_cb);
406
407 event_notifier_set(&data.e);
408 g_assert(aio_poll(ctx, false));
409 g_assert_cmpint(data.n, ==, 1);
410 g_assert(!aio_poll(ctx, false));
411 g_assert_cmpint(data.n, ==, 1);
412
413 event_notifier_set(&data.e);
414 g_assert(aio_poll(ctx, false));
415 g_assert_cmpint(data.n, ==, 2);
416 g_assert(!aio_poll(ctx, false));
417 g_assert_cmpint(data.n, ==, 2);
418
419 event_notifier_set(&dummy.e);
420 wait_until_inactive(&dummy);
421 g_assert_cmpint(data.n, ==, 2);
422 g_assert_cmpint(dummy.n, ==, 1);
423 g_assert_cmpint(dummy.active, ==, 0);
424
425 set_event_notifier(ctx, &dummy.e, NULL);
426 event_notifier_cleanup(&dummy.e);
427
428 set_event_notifier(ctx, &data.e, NULL);
429 g_assert(!aio_poll(ctx, false));
430 g_assert_cmpint(data.n, ==, 2);
431
432 event_notifier_cleanup(&data.e);
433}
434
435static void test_timer_schedule(void)
436{
437 TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
438 .max = 2,
439 .clock_type = QEMU_CLOCK_REALTIME };
440 EventNotifier e;
441
442
443
444
445 event_notifier_init(&e, false);
446 set_event_notifier(ctx, &e, dummy_io_handler_read);
447 aio_poll(ctx, false);
448
449 aio_timer_init(ctx, &data.timer, data.clock_type,
450 SCALE_NS, timer_test_cb, &data);
451 timer_mod(&data.timer,
452 qemu_clock_get_ns(data.clock_type) +
453 data.ns);
454
455 g_assert_cmpint(data.n, ==, 0);
456
457
458
459
460 do {} while (aio_poll(ctx, false));
461
462 g_assert(!aio_poll(ctx, false));
463 g_assert_cmpint(data.n, ==, 0);
464
465 g_usleep(1 * G_USEC_PER_SEC);
466 g_assert_cmpint(data.n, ==, 0);
467
468 g_assert(aio_poll(ctx, false));
469 g_assert_cmpint(data.n, ==, 1);
470
471
472 do {} while (aio_poll(ctx, false));
473
474 g_assert(!aio_poll(ctx, false));
475 g_assert_cmpint(data.n, ==, 1);
476
477 g_assert(aio_poll(ctx, true));
478 g_assert_cmpint(data.n, ==, 2);
479
480
481
482 g_assert(!aio_poll(ctx, false));
483 g_assert_cmpint(data.n, ==, 2);
484
485 set_event_notifier(ctx, &e, NULL);
486 event_notifier_cleanup(&e);
487
488 timer_del(&data.timer);
489}
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504static void test_source_flush(void)
505{
506 g_assert(!g_main_context_iteration(NULL, false));
507 aio_notify(ctx);
508 while (g_main_context_iteration(NULL, false));
509 g_assert(!g_main_context_iteration(NULL, false));
510}
511
512static void test_source_bh_schedule(void)
513{
514 BHTestData data = { .n = 0 };
515 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
516
517 qemu_bh_schedule(data.bh);
518 g_assert_cmpint(data.n, ==, 0);
519
520 g_assert(g_main_context_iteration(NULL, true));
521 g_assert_cmpint(data.n, ==, 1);
522
523 g_assert(!g_main_context_iteration(NULL, false));
524 g_assert_cmpint(data.n, ==, 1);
525 qemu_bh_delete(data.bh);
526}
527
528static void test_source_bh_schedule10(void)
529{
530 BHTestData data = { .n = 0, .max = 10 };
531 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
532
533 qemu_bh_schedule(data.bh);
534 g_assert_cmpint(data.n, ==, 0);
535
536 g_assert(g_main_context_iteration(NULL, false));
537 g_assert_cmpint(data.n, ==, 1);
538
539 g_assert(g_main_context_iteration(NULL, true));
540 g_assert_cmpint(data.n, ==, 2);
541
542 while (g_main_context_iteration(NULL, false));
543 g_assert_cmpint(data.n, ==, 10);
544
545 g_assert(!g_main_context_iteration(NULL, false));
546 g_assert_cmpint(data.n, ==, 10);
547 qemu_bh_delete(data.bh);
548}
549
550static void test_source_bh_cancel(void)
551{
552 BHTestData data = { .n = 0 };
553 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
554
555 qemu_bh_schedule(data.bh);
556 g_assert_cmpint(data.n, ==, 0);
557
558 qemu_bh_cancel(data.bh);
559 g_assert_cmpint(data.n, ==, 0);
560
561 while (g_main_context_iteration(NULL, false));
562 g_assert_cmpint(data.n, ==, 0);
563 qemu_bh_delete(data.bh);
564}
565
566static void test_source_bh_delete(void)
567{
568 BHTestData data = { .n = 0 };
569 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
570
571 qemu_bh_schedule(data.bh);
572 g_assert_cmpint(data.n, ==, 0);
573
574 qemu_bh_delete(data.bh);
575 g_assert_cmpint(data.n, ==, 0);
576
577 while (g_main_context_iteration(NULL, false));
578 g_assert_cmpint(data.n, ==, 0);
579}
580
581static void test_source_bh_delete_from_cb(void)
582{
583 BHTestData data1 = { .n = 0, .max = 1 };
584
585 data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
586
587 qemu_bh_schedule(data1.bh);
588 g_assert_cmpint(data1.n, ==, 0);
589
590 g_main_context_iteration(NULL, true);
591 g_assert_cmpint(data1.n, ==, data1.max);
592 g_assert(data1.bh == NULL);
593
594 assert(g_main_context_iteration(NULL, false));
595 assert(!g_main_context_iteration(NULL, false));
596}
597
598static void test_source_bh_delete_from_cb_many(void)
599{
600 BHTestData data1 = { .n = 0, .max = 1 };
601 BHTestData data2 = { .n = 0, .max = 3 };
602 BHTestData data3 = { .n = 0, .max = 2 };
603 BHTestData data4 = { .n = 0, .max = 4 };
604
605 data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
606 data2.bh = aio_bh_new(ctx, bh_delete_cb, &data2);
607 data3.bh = aio_bh_new(ctx, bh_delete_cb, &data3);
608 data4.bh = aio_bh_new(ctx, bh_delete_cb, &data4);
609
610 qemu_bh_schedule(data1.bh);
611 qemu_bh_schedule(data2.bh);
612 qemu_bh_schedule(data3.bh);
613 qemu_bh_schedule(data4.bh);
614 g_assert_cmpint(data1.n, ==, 0);
615 g_assert_cmpint(data2.n, ==, 0);
616 g_assert_cmpint(data3.n, ==, 0);
617 g_assert_cmpint(data4.n, ==, 0);
618
619 g_assert(g_main_context_iteration(NULL, false));
620 g_assert_cmpint(data1.n, ==, 1);
621 g_assert_cmpint(data2.n, ==, 1);
622 g_assert_cmpint(data3.n, ==, 1);
623 g_assert_cmpint(data4.n, ==, 1);
624 g_assert(data1.bh == NULL);
625
626 while (g_main_context_iteration(NULL, false));
627 g_assert_cmpint(data1.n, ==, data1.max);
628 g_assert_cmpint(data2.n, ==, data2.max);
629 g_assert_cmpint(data3.n, ==, data3.max);
630 g_assert_cmpint(data4.n, ==, data4.max);
631 g_assert(data1.bh == NULL);
632 g_assert(data2.bh == NULL);
633 g_assert(data3.bh == NULL);
634 g_assert(data4.bh == NULL);
635}
636
637static void test_source_bh_flush(void)
638{
639 BHTestData data = { .n = 0 };
640 data.bh = aio_bh_new(ctx, bh_test_cb, &data);
641
642 qemu_bh_schedule(data.bh);
643 g_assert_cmpint(data.n, ==, 0);
644
645 g_assert(g_main_context_iteration(NULL, true));
646 g_assert_cmpint(data.n, ==, 1);
647
648 g_assert(!g_main_context_iteration(NULL, false));
649 g_assert_cmpint(data.n, ==, 1);
650 qemu_bh_delete(data.bh);
651}
652
653static void test_source_set_event_notifier(void)
654{
655 EventNotifierTestData data = { .n = 0, .active = 0 };
656 event_notifier_init(&data.e, false);
657 set_event_notifier(ctx, &data.e, event_ready_cb);
658 while (g_main_context_iteration(NULL, false));
659 g_assert_cmpint(data.n, ==, 0);
660
661 set_event_notifier(ctx, &data.e, NULL);
662 while (g_main_context_iteration(NULL, false));
663 g_assert_cmpint(data.n, ==, 0);
664 event_notifier_cleanup(&data.e);
665}
666
667static void test_source_wait_event_notifier(void)
668{
669 EventNotifierTestData data = { .n = 0, .active = 1 };
670 event_notifier_init(&data.e, false);
671 set_event_notifier(ctx, &data.e, event_ready_cb);
672 while (g_main_context_iteration(NULL, false));
673 g_assert_cmpint(data.n, ==, 0);
674 g_assert_cmpint(data.active, ==, 1);
675
676 event_notifier_set(&data.e);
677 g_assert(g_main_context_iteration(NULL, false));
678 g_assert_cmpint(data.n, ==, 1);
679 g_assert_cmpint(data.active, ==, 0);
680
681 while (g_main_context_iteration(NULL, false));
682 g_assert_cmpint(data.n, ==, 1);
683 g_assert_cmpint(data.active, ==, 0);
684
685 set_event_notifier(ctx, &data.e, NULL);
686 while (g_main_context_iteration(NULL, false));
687 g_assert_cmpint(data.n, ==, 1);
688
689 event_notifier_cleanup(&data.e);
690}
691
692static void test_source_flush_event_notifier(void)
693{
694 EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
695 event_notifier_init(&data.e, false);
696 set_event_notifier(ctx, &data.e, event_ready_cb);
697 while (g_main_context_iteration(NULL, false));
698 g_assert_cmpint(data.n, ==, 0);
699 g_assert_cmpint(data.active, ==, 10);
700
701 event_notifier_set(&data.e);
702 g_assert(g_main_context_iteration(NULL, false));
703 g_assert_cmpint(data.n, ==, 1);
704 g_assert_cmpint(data.active, ==, 9);
705 g_assert(g_main_context_iteration(NULL, false));
706
707 while (g_main_context_iteration(NULL, false));
708 g_assert_cmpint(data.n, ==, 10);
709 g_assert_cmpint(data.active, ==, 0);
710 g_assert(!g_main_context_iteration(NULL, false));
711
712 set_event_notifier(ctx, &data.e, NULL);
713 while (g_main_context_iteration(NULL, false));
714 event_notifier_cleanup(&data.e);
715}
716
717static void test_source_wait_event_notifier_noflush(void)
718{
719 EventNotifierTestData data = { .n = 0 };
720 EventNotifierTestData dummy = { .n = 0, .active = 1 };
721
722 event_notifier_init(&data.e, false);
723 set_event_notifier(ctx, &data.e, event_ready_cb);
724
725 while (g_main_context_iteration(NULL, false));
726 g_assert_cmpint(data.n, ==, 0);
727
728
729
730 event_notifier_set(&data.e);
731 g_main_context_iteration(NULL, true);
732 data.n = 0;
733
734
735 event_notifier_init(&dummy.e, false);
736 set_event_notifier(ctx, &dummy.e, event_ready_cb);
737
738 event_notifier_set(&data.e);
739 g_assert(g_main_context_iteration(NULL, false));
740 g_assert_cmpint(data.n, ==, 1);
741 g_assert(!g_main_context_iteration(NULL, false));
742 g_assert_cmpint(data.n, ==, 1);
743
744 event_notifier_set(&data.e);
745 g_assert(g_main_context_iteration(NULL, false));
746 g_assert_cmpint(data.n, ==, 2);
747 g_assert(!g_main_context_iteration(NULL, false));
748 g_assert_cmpint(data.n, ==, 2);
749
750 event_notifier_set(&dummy.e);
751 while (g_main_context_iteration(NULL, false));
752 g_assert_cmpint(data.n, ==, 2);
753 g_assert_cmpint(dummy.n, ==, 1);
754 g_assert_cmpint(dummy.active, ==, 0);
755
756 set_event_notifier(ctx, &dummy.e, NULL);
757 event_notifier_cleanup(&dummy.e);
758
759 set_event_notifier(ctx, &data.e, NULL);
760 while (g_main_context_iteration(NULL, false));
761 g_assert_cmpint(data.n, ==, 2);
762
763 event_notifier_cleanup(&data.e);
764}
765
766static void test_source_timer_schedule(void)
767{
768 TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
769 .max = 2,
770 .clock_type = QEMU_CLOCK_REALTIME };
771 EventNotifier e;
772 int64_t expiry;
773
774
775
776
777 event_notifier_init(&e, false);
778 set_event_notifier(ctx, &e, dummy_io_handler_read);
779 do {} while (g_main_context_iteration(NULL, false));
780
781 aio_timer_init(ctx, &data.timer, data.clock_type,
782 SCALE_NS, timer_test_cb, &data);
783 expiry = qemu_clock_get_ns(data.clock_type) +
784 data.ns;
785 timer_mod(&data.timer, expiry);
786
787 g_assert_cmpint(data.n, ==, 0);
788
789 g_usleep(1 * G_USEC_PER_SEC);
790 g_assert_cmpint(data.n, ==, 0);
791
792 g_assert(g_main_context_iteration(NULL, true));
793 g_assert_cmpint(data.n, ==, 1);
794 expiry += data.ns;
795
796 while (data.n < 2) {
797 g_main_context_iteration(NULL, true);
798 }
799
800 g_assert_cmpint(data.n, ==, 2);
801 g_assert(qemu_clock_get_ns(data.clock_type) > expiry);
802
803 set_event_notifier(ctx, &e, NULL);
804 event_notifier_cleanup(&e);
805
806 timer_del(&data.timer);
807}
808
809
810
811
812
813
814
815
816
817typedef struct {
818 Coroutine *other;
819 unsigned i;
820 unsigned max;
821} ChainData;
822
823static void coroutine_fn chain(void *opaque)
824{
825 ChainData *data = opaque;
826
827 for (data->i = 0; data->i < data->max; data->i++) {
828
829 aio_co_enter(ctx, data->other);
830
831
832 qemu_coroutine_yield();
833 }
834}
835
836static void test_queue_chaining(void)
837{
838
839 ChainData data_a = { .max = 25000 };
840 ChainData data_b = { .max = 25000 };
841
842 data_b.other = qemu_coroutine_create(chain, &data_a);
843 data_a.other = qemu_coroutine_create(chain, &data_b);
844
845 qemu_coroutine_enter(data_b.other);
846
847 g_assert_cmpint(data_a.i, ==, data_a.max);
848 g_assert_cmpint(data_b.i, ==, data_b.max - 1);
849
850
851 qemu_coroutine_enter(data_a.other);
852
853 g_assert_cmpint(data_b.i, ==, data_b.max);
854}
855
856static void co_check_current_thread(void *opaque)
857{
858 QemuThread *main_thread = opaque;
859 assert(qemu_thread_is_self(main_thread));
860}
861
862static void *test_aio_co_enter(void *co)
863{
864
865
866
867
868
869
870 aio_co_enter(qemu_get_aio_context(), co);
871 return NULL;
872}
873
874static void test_worker_thread_co_enter(void)
875{
876 QemuThread this_thread, worker_thread;
877 Coroutine *co;
878
879 qemu_thread_get_self(&this_thread);
880 co = qemu_coroutine_create(co_check_current_thread, &this_thread);
881
882 qemu_thread_create(&worker_thread, "test_acquire_thread",
883 test_aio_co_enter,
884 co, QEMU_THREAD_JOINABLE);
885
886
887 qemu_thread_join(&worker_thread);
888 g_assert(aio_poll(ctx, true));
889 g_assert(!aio_poll(ctx, false));
890}
891
892
893
894int main(int argc, char **argv)
895{
896 qemu_init_main_loop(&error_fatal);
897 ctx = qemu_get_aio_context();
898
899 while (g_main_context_iteration(NULL, false));
900
901 g_test_init(&argc, &argv, NULL);
902 g_test_add_func("/aio/acquire", test_acquire);
903 g_test_add_func("/aio/bh/schedule", test_bh_schedule);
904 g_test_add_func("/aio/bh/schedule10", test_bh_schedule10);
905 g_test_add_func("/aio/bh/cancel", test_bh_cancel);
906 g_test_add_func("/aio/bh/delete", test_bh_delete);
907 g_test_add_func("/aio/bh/callback-delete/one", test_bh_delete_from_cb);
908 g_test_add_func("/aio/bh/callback-delete/many", test_bh_delete_from_cb_many);
909 g_test_add_func("/aio/bh/flush", test_bh_flush);
910 g_test_add_func("/aio/event/add-remove", test_set_event_notifier);
911 g_test_add_func("/aio/event/wait", test_wait_event_notifier);
912 g_test_add_func("/aio/event/wait/no-flush-cb", test_wait_event_notifier_noflush);
913 g_test_add_func("/aio/event/flush", test_flush_event_notifier);
914 g_test_add_func("/aio/timer/schedule", test_timer_schedule);
915
916 g_test_add_func("/aio/coroutine/queue-chaining", test_queue_chaining);
917 g_test_add_func("/aio/coroutine/worker-thread-co-enter", test_worker_thread_co_enter);
918
919 g_test_add_func("/aio-gsource/flush", test_source_flush);
920 g_test_add_func("/aio-gsource/bh/schedule", test_source_bh_schedule);
921 g_test_add_func("/aio-gsource/bh/schedule10", test_source_bh_schedule10);
922 g_test_add_func("/aio-gsource/bh/cancel", test_source_bh_cancel);
923 g_test_add_func("/aio-gsource/bh/delete", test_source_bh_delete);
924 g_test_add_func("/aio-gsource/bh/callback-delete/one", test_source_bh_delete_from_cb);
925 g_test_add_func("/aio-gsource/bh/callback-delete/many", test_source_bh_delete_from_cb_many);
926 g_test_add_func("/aio-gsource/bh/flush", test_source_bh_flush);
927 g_test_add_func("/aio-gsource/event/add-remove", test_source_set_event_notifier);
928 g_test_add_func("/aio-gsource/event/wait", test_source_wait_event_notifier);
929 g_test_add_func("/aio-gsource/event/wait/no-flush-cb", test_source_wait_event_notifier_noflush);
930 g_test_add_func("/aio-gsource/event/flush", test_source_flush_event_notifier);
931 g_test_add_func("/aio-gsource/timer/schedule", test_source_timer_schedule);
932 return g_test_run();
933}
934