test-aio.c (28466B)
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 "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.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/* Wait until event notifier becomes inactive */ 32static void wait_until_inactive(EventNotifierTestData *data) 33{ 34 while (data->active > 0) { 35 aio_poll(ctx, true); 36 } 37} 38 39/* Simple callbacks for testing. */ 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/* Tests using aio_*. */ 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 /* Wait for other thread to let us start */ 114 qemu_mutex_lock(&data->start_lock); 115 qemu_mutex_unlock(&data->start_lock); 116 117 /* event_notifier_set might be called either before or after 118 * the main thread's call to poll(). The test case's outcome 119 * should be the same in either case. 120 */ 121 event_notifier_set(&data->notifier); 122 aio_context_acquire(ctx); 123 aio_context_release(ctx); 124 125 data->thread_acquired = true; /* success, we got here */ 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, false, handler, 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 /* Dummy event notifier ensures aio_poll() will block */ 147 event_notifier_init(&data.notifier, false); 148 set_event_notifier(ctx, &data.notifier, dummy_notifier_read); 149 g_assert(!aio_poll(ctx, false)); /* consume aio_notify() */ 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 /* Block in aio_poll(), let other thread kick us and acquire context */ 160 aio_context_acquire(ctx); 161 qemu_mutex_unlock(&data.start_lock); /* let the thread run */ 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_aio_external_client(void) 387{ 388 int i, j; 389 390 for (i = 1; i < 3; i++) { 391 EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true }; 392 event_notifier_init(&data.e, false); 393 aio_set_event_notifier(ctx, &data.e, true, event_ready_cb, NULL); 394 event_notifier_set(&data.e); 395 for (j = 0; j < i; j++) { 396 aio_disable_external(ctx); 397 } 398 for (j = 0; j < i; j++) { 399 assert(!aio_poll(ctx, false)); 400 assert(event_notifier_test_and_clear(&data.e)); 401 event_notifier_set(&data.e); 402 aio_enable_external(ctx); 403 } 404 assert(aio_poll(ctx, false)); 405 set_event_notifier(ctx, &data.e, NULL); 406 event_notifier_cleanup(&data.e); 407 } 408} 409 410static void test_wait_event_notifier_noflush(void) 411{ 412 EventNotifierTestData data = { .n = 0 }; 413 EventNotifierTestData dummy = { .n = 0, .active = 1 }; 414 415 event_notifier_init(&data.e, false); 416 set_event_notifier(ctx, &data.e, event_ready_cb); 417 418 g_assert(!aio_poll(ctx, false)); 419 g_assert_cmpint(data.n, ==, 0); 420 421 /* Until there is an active descriptor, aio_poll may or may not call 422 * event_ready_cb. Still, it must not block. */ 423 event_notifier_set(&data.e); 424 g_assert(aio_poll(ctx, true)); 425 data.n = 0; 426 427 /* An active event notifier forces aio_poll to look at EventNotifiers. */ 428 event_notifier_init(&dummy.e, false); 429 set_event_notifier(ctx, &dummy.e, event_ready_cb); 430 431 event_notifier_set(&data.e); 432 g_assert(aio_poll(ctx, false)); 433 g_assert_cmpint(data.n, ==, 1); 434 g_assert(!aio_poll(ctx, false)); 435 g_assert_cmpint(data.n, ==, 1); 436 437 event_notifier_set(&data.e); 438 g_assert(aio_poll(ctx, false)); 439 g_assert_cmpint(data.n, ==, 2); 440 g_assert(!aio_poll(ctx, false)); 441 g_assert_cmpint(data.n, ==, 2); 442 443 event_notifier_set(&dummy.e); 444 wait_until_inactive(&dummy); 445 g_assert_cmpint(data.n, ==, 2); 446 g_assert_cmpint(dummy.n, ==, 1); 447 g_assert_cmpint(dummy.active, ==, 0); 448 449 set_event_notifier(ctx, &dummy.e, NULL); 450 event_notifier_cleanup(&dummy.e); 451 452 set_event_notifier(ctx, &data.e, NULL); 453 g_assert(!aio_poll(ctx, false)); 454 g_assert_cmpint(data.n, ==, 2); 455 456 event_notifier_cleanup(&data.e); 457} 458 459static void test_timer_schedule(void) 460{ 461 TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL, 462 .max = 2, 463 .clock_type = QEMU_CLOCK_REALTIME }; 464 EventNotifier e; 465 466 /* aio_poll will not block to wait for timers to complete unless it has 467 * an fd to wait on. Fixing this breaks other tests. So create a dummy one. 468 */ 469 event_notifier_init(&e, false); 470 set_event_notifier(ctx, &e, dummy_io_handler_read); 471 aio_poll(ctx, false); 472 473 aio_timer_init(ctx, &data.timer, data.clock_type, 474 SCALE_NS, timer_test_cb, &data); 475 timer_mod(&data.timer, 476 qemu_clock_get_ns(data.clock_type) + 477 data.ns); 478 479 g_assert_cmpint(data.n, ==, 0); 480 481 /* timer_mod may well cause an event notifer to have gone off, 482 * so clear that 483 */ 484 do {} while (aio_poll(ctx, false)); 485 486 g_assert(!aio_poll(ctx, false)); 487 g_assert_cmpint(data.n, ==, 0); 488 489 g_usleep(1 * G_USEC_PER_SEC); 490 g_assert_cmpint(data.n, ==, 0); 491 492 g_assert(aio_poll(ctx, false)); 493 g_assert_cmpint(data.n, ==, 1); 494 495 /* timer_mod called by our callback */ 496 do {} while (aio_poll(ctx, false)); 497 498 g_assert(!aio_poll(ctx, false)); 499 g_assert_cmpint(data.n, ==, 1); 500 501 g_assert(aio_poll(ctx, true)); 502 g_assert_cmpint(data.n, ==, 2); 503 504 /* As max is now 2, an event notifier should not have gone off */ 505 506 g_assert(!aio_poll(ctx, false)); 507 g_assert_cmpint(data.n, ==, 2); 508 509 set_event_notifier(ctx, &e, NULL); 510 event_notifier_cleanup(&e); 511 512 timer_del(&data.timer); 513} 514 515/* Now the same tests, using the context as a GSource. They are 516 * very similar to the ones above, with g_main_context_iteration 517 * replacing aio_poll. However: 518 * - sometimes both the AioContext and the glib main loop wake 519 * themselves up. Hence, some "g_assert(!aio_poll(ctx, false));" 520 * are replaced by "while (g_main_context_iteration(NULL, false));". 521 * - there is no exact replacement for a blocking wait. 522 * "while (g_main_context_iteration(NULL, true)" seems to work, 523 * but it is not documented _why_ it works. For these tests a 524 * non-blocking loop like "while (g_main_context_iteration(NULL, false)" 525 * works well, and that's what I am using. 526 */ 527 528static void test_source_flush(void) 529{ 530 g_assert(!g_main_context_iteration(NULL, false)); 531 aio_notify(ctx); 532 while (g_main_context_iteration(NULL, false)); 533 g_assert(!g_main_context_iteration(NULL, false)); 534} 535 536static void test_source_bh_schedule(void) 537{ 538 BHTestData data = { .n = 0 }; 539 data.bh = aio_bh_new(ctx, bh_test_cb, &data); 540 541 qemu_bh_schedule(data.bh); 542 g_assert_cmpint(data.n, ==, 0); 543 544 g_assert(g_main_context_iteration(NULL, true)); 545 g_assert_cmpint(data.n, ==, 1); 546 547 g_assert(!g_main_context_iteration(NULL, false)); 548 g_assert_cmpint(data.n, ==, 1); 549 qemu_bh_delete(data.bh); 550} 551 552static void test_source_bh_schedule10(void) 553{ 554 BHTestData data = { .n = 0, .max = 10 }; 555 data.bh = aio_bh_new(ctx, bh_test_cb, &data); 556 557 qemu_bh_schedule(data.bh); 558 g_assert_cmpint(data.n, ==, 0); 559 560 g_assert(g_main_context_iteration(NULL, false)); 561 g_assert_cmpint(data.n, ==, 1); 562 563 g_assert(g_main_context_iteration(NULL, true)); 564 g_assert_cmpint(data.n, ==, 2); 565 566 while (g_main_context_iteration(NULL, false)); 567 g_assert_cmpint(data.n, ==, 10); 568 569 g_assert(!g_main_context_iteration(NULL, false)); 570 g_assert_cmpint(data.n, ==, 10); 571 qemu_bh_delete(data.bh); 572} 573 574static void test_source_bh_cancel(void) 575{ 576 BHTestData data = { .n = 0 }; 577 data.bh = aio_bh_new(ctx, bh_test_cb, &data); 578 579 qemu_bh_schedule(data.bh); 580 g_assert_cmpint(data.n, ==, 0); 581 582 qemu_bh_cancel(data.bh); 583 g_assert_cmpint(data.n, ==, 0); 584 585 while (g_main_context_iteration(NULL, false)); 586 g_assert_cmpint(data.n, ==, 0); 587 qemu_bh_delete(data.bh); 588} 589 590static void test_source_bh_delete(void) 591{ 592 BHTestData data = { .n = 0 }; 593 data.bh = aio_bh_new(ctx, bh_test_cb, &data); 594 595 qemu_bh_schedule(data.bh); 596 g_assert_cmpint(data.n, ==, 0); 597 598 qemu_bh_delete(data.bh); 599 g_assert_cmpint(data.n, ==, 0); 600 601 while (g_main_context_iteration(NULL, false)); 602 g_assert_cmpint(data.n, ==, 0); 603} 604 605static void test_source_bh_delete_from_cb(void) 606{ 607 BHTestData data1 = { .n = 0, .max = 1 }; 608 609 data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1); 610 611 qemu_bh_schedule(data1.bh); 612 g_assert_cmpint(data1.n, ==, 0); 613 614 g_main_context_iteration(NULL, true); 615 g_assert_cmpint(data1.n, ==, data1.max); 616 g_assert(data1.bh == NULL); 617 618 assert(g_main_context_iteration(NULL, false)); 619 assert(!g_main_context_iteration(NULL, false)); 620} 621 622static void test_source_bh_delete_from_cb_many(void) 623{ 624 BHTestData data1 = { .n = 0, .max = 1 }; 625 BHTestData data2 = { .n = 0, .max = 3 }; 626 BHTestData data3 = { .n = 0, .max = 2 }; 627 BHTestData data4 = { .n = 0, .max = 4 }; 628 629 data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1); 630 data2.bh = aio_bh_new(ctx, bh_delete_cb, &data2); 631 data3.bh = aio_bh_new(ctx, bh_delete_cb, &data3); 632 data4.bh = aio_bh_new(ctx, bh_delete_cb, &data4); 633 634 qemu_bh_schedule(data1.bh); 635 qemu_bh_schedule(data2.bh); 636 qemu_bh_schedule(data3.bh); 637 qemu_bh_schedule(data4.bh); 638 g_assert_cmpint(data1.n, ==, 0); 639 g_assert_cmpint(data2.n, ==, 0); 640 g_assert_cmpint(data3.n, ==, 0); 641 g_assert_cmpint(data4.n, ==, 0); 642 643 g_assert(g_main_context_iteration(NULL, false)); 644 g_assert_cmpint(data1.n, ==, 1); 645 g_assert_cmpint(data2.n, ==, 1); 646 g_assert_cmpint(data3.n, ==, 1); 647 g_assert_cmpint(data4.n, ==, 1); 648 g_assert(data1.bh == NULL); 649 650 while (g_main_context_iteration(NULL, false)); 651 g_assert_cmpint(data1.n, ==, data1.max); 652 g_assert_cmpint(data2.n, ==, data2.max); 653 g_assert_cmpint(data3.n, ==, data3.max); 654 g_assert_cmpint(data4.n, ==, data4.max); 655 g_assert(data1.bh == NULL); 656 g_assert(data2.bh == NULL); 657 g_assert(data3.bh == NULL); 658 g_assert(data4.bh == NULL); 659} 660 661static void test_source_bh_flush(void) 662{ 663 BHTestData data = { .n = 0 }; 664 data.bh = aio_bh_new(ctx, bh_test_cb, &data); 665 666 qemu_bh_schedule(data.bh); 667 g_assert_cmpint(data.n, ==, 0); 668 669 g_assert(g_main_context_iteration(NULL, true)); 670 g_assert_cmpint(data.n, ==, 1); 671 672 g_assert(!g_main_context_iteration(NULL, false)); 673 g_assert_cmpint(data.n, ==, 1); 674 qemu_bh_delete(data.bh); 675} 676 677static void test_source_set_event_notifier(void) 678{ 679 EventNotifierTestData data = { .n = 0, .active = 0 }; 680 event_notifier_init(&data.e, false); 681 set_event_notifier(ctx, &data.e, event_ready_cb); 682 while (g_main_context_iteration(NULL, false)); 683 g_assert_cmpint(data.n, ==, 0); 684 685 set_event_notifier(ctx, &data.e, NULL); 686 while (g_main_context_iteration(NULL, false)); 687 g_assert_cmpint(data.n, ==, 0); 688 event_notifier_cleanup(&data.e); 689} 690 691static void test_source_wait_event_notifier(void) 692{ 693 EventNotifierTestData data = { .n = 0, .active = 1 }; 694 event_notifier_init(&data.e, false); 695 set_event_notifier(ctx, &data.e, event_ready_cb); 696 while (g_main_context_iteration(NULL, false)); 697 g_assert_cmpint(data.n, ==, 0); 698 g_assert_cmpint(data.active, ==, 1); 699 700 event_notifier_set(&data.e); 701 g_assert(g_main_context_iteration(NULL, false)); 702 g_assert_cmpint(data.n, ==, 1); 703 g_assert_cmpint(data.active, ==, 0); 704 705 while (g_main_context_iteration(NULL, false)); 706 g_assert_cmpint(data.n, ==, 1); 707 g_assert_cmpint(data.active, ==, 0); 708 709 set_event_notifier(ctx, &data.e, NULL); 710 while (g_main_context_iteration(NULL, false)); 711 g_assert_cmpint(data.n, ==, 1); 712 713 event_notifier_cleanup(&data.e); 714} 715 716static void test_source_flush_event_notifier(void) 717{ 718 EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true }; 719 event_notifier_init(&data.e, false); 720 set_event_notifier(ctx, &data.e, event_ready_cb); 721 while (g_main_context_iteration(NULL, false)); 722 g_assert_cmpint(data.n, ==, 0); 723 g_assert_cmpint(data.active, ==, 10); 724 725 event_notifier_set(&data.e); 726 g_assert(g_main_context_iteration(NULL, false)); 727 g_assert_cmpint(data.n, ==, 1); 728 g_assert_cmpint(data.active, ==, 9); 729 g_assert(g_main_context_iteration(NULL, false)); 730 731 while (g_main_context_iteration(NULL, false)); 732 g_assert_cmpint(data.n, ==, 10); 733 g_assert_cmpint(data.active, ==, 0); 734 g_assert(!g_main_context_iteration(NULL, false)); 735 736 set_event_notifier(ctx, &data.e, NULL); 737 while (g_main_context_iteration(NULL, false)); 738 event_notifier_cleanup(&data.e); 739} 740 741static void test_source_wait_event_notifier_noflush(void) 742{ 743 EventNotifierTestData data = { .n = 0 }; 744 EventNotifierTestData dummy = { .n = 0, .active = 1 }; 745 746 event_notifier_init(&data.e, false); 747 set_event_notifier(ctx, &data.e, event_ready_cb); 748 749 while (g_main_context_iteration(NULL, false)); 750 g_assert_cmpint(data.n, ==, 0); 751 752 /* Until there is an active descriptor, glib may or may not call 753 * event_ready_cb. Still, it must not block. */ 754 event_notifier_set(&data.e); 755 g_main_context_iteration(NULL, true); 756 data.n = 0; 757 758 /* An active event notifier forces aio_poll to look at EventNotifiers. */ 759 event_notifier_init(&dummy.e, false); 760 set_event_notifier(ctx, &dummy.e, event_ready_cb); 761 762 event_notifier_set(&data.e); 763 g_assert(g_main_context_iteration(NULL, false)); 764 g_assert_cmpint(data.n, ==, 1); 765 g_assert(!g_main_context_iteration(NULL, false)); 766 g_assert_cmpint(data.n, ==, 1); 767 768 event_notifier_set(&data.e); 769 g_assert(g_main_context_iteration(NULL, false)); 770 g_assert_cmpint(data.n, ==, 2); 771 g_assert(!g_main_context_iteration(NULL, false)); 772 g_assert_cmpint(data.n, ==, 2); 773 774 event_notifier_set(&dummy.e); 775 while (g_main_context_iteration(NULL, false)); 776 g_assert_cmpint(data.n, ==, 2); 777 g_assert_cmpint(dummy.n, ==, 1); 778 g_assert_cmpint(dummy.active, ==, 0); 779 780 set_event_notifier(ctx, &dummy.e, NULL); 781 event_notifier_cleanup(&dummy.e); 782 783 set_event_notifier(ctx, &data.e, NULL); 784 while (g_main_context_iteration(NULL, false)); 785 g_assert_cmpint(data.n, ==, 2); 786 787 event_notifier_cleanup(&data.e); 788} 789 790static void test_source_timer_schedule(void) 791{ 792 TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL, 793 .max = 2, 794 .clock_type = QEMU_CLOCK_REALTIME }; 795 EventNotifier e; 796 int64_t expiry; 797 798 /* aio_poll will not block to wait for timers to complete unless it has 799 * an fd to wait on. Fixing this breaks other tests. So create a dummy one. 800 */ 801 event_notifier_init(&e, false); 802 set_event_notifier(ctx, &e, dummy_io_handler_read); 803 do {} while (g_main_context_iteration(NULL, false)); 804 805 aio_timer_init(ctx, &data.timer, data.clock_type, 806 SCALE_NS, timer_test_cb, &data); 807 expiry = qemu_clock_get_ns(data.clock_type) + 808 data.ns; 809 timer_mod(&data.timer, expiry); 810 811 g_assert_cmpint(data.n, ==, 0); 812 813 g_usleep(1 * G_USEC_PER_SEC); 814 g_assert_cmpint(data.n, ==, 0); 815 816 g_assert(g_main_context_iteration(NULL, true)); 817 g_assert_cmpint(data.n, ==, 1); 818 expiry += data.ns; 819 820 while (data.n < 2) { 821 g_main_context_iteration(NULL, true); 822 } 823 824 g_assert_cmpint(data.n, ==, 2); 825 g_assert(qemu_clock_get_ns(data.clock_type) > expiry); 826 827 set_event_notifier(ctx, &e, NULL); 828 event_notifier_cleanup(&e); 829 830 timer_del(&data.timer); 831} 832 833/* 834 * Check that aio_co_enter() can chain many times 835 * 836 * Two coroutines should be able to invoke each other via aio_co_enter() many 837 * times without hitting a limit like stack exhaustion. In other words, the 838 * calls should be chained instead of nested. 839 */ 840 841typedef struct { 842 Coroutine *other; 843 unsigned i; 844 unsigned max; 845} ChainData; 846 847static void coroutine_fn chain(void *opaque) 848{ 849 ChainData *data = opaque; 850 851 for (data->i = 0; data->i < data->max; data->i++) { 852 /* Queue up the other coroutine... */ 853 aio_co_enter(ctx, data->other); 854 855 /* ...and give control to it */ 856 qemu_coroutine_yield(); 857 } 858} 859 860static void test_queue_chaining(void) 861{ 862 /* This number of iterations hit stack exhaustion in the past: */ 863 ChainData data_a = { .max = 25000 }; 864 ChainData data_b = { .max = 25000 }; 865 866 data_b.other = qemu_coroutine_create(chain, &data_a); 867 data_a.other = qemu_coroutine_create(chain, &data_b); 868 869 qemu_coroutine_enter(data_b.other); 870 871 g_assert_cmpint(data_a.i, ==, data_a.max); 872 g_assert_cmpint(data_b.i, ==, data_b.max - 1); 873 874 /* Allow the second coroutine to terminate */ 875 qemu_coroutine_enter(data_a.other); 876 877 g_assert_cmpint(data_b.i, ==, data_b.max); 878} 879 880static void co_check_current_thread(void *opaque) 881{ 882 QemuThread *main_thread = opaque; 883 assert(qemu_thread_is_self(main_thread)); 884} 885 886static void *test_aio_co_enter(void *co) 887{ 888 /* 889 * qemu_get_current_aio_context() should not to be the main thread 890 * AioContext, because this is a worker thread that has not taken 891 * the BQL. So aio_co_enter will schedule the coroutine in the 892 * main thread AioContext. 893 */ 894 aio_co_enter(qemu_get_aio_context(), co); 895 return NULL; 896} 897 898static void test_worker_thread_co_enter(void) 899{ 900 QemuThread this_thread, worker_thread; 901 Coroutine *co; 902 903 qemu_thread_get_self(&this_thread); 904 co = qemu_coroutine_create(co_check_current_thread, &this_thread); 905 906 qemu_thread_create(&worker_thread, "test_acquire_thread", 907 test_aio_co_enter, 908 co, QEMU_THREAD_JOINABLE); 909 910 /* Test aio_co_enter from a worker thread. */ 911 qemu_thread_join(&worker_thread); 912 g_assert(aio_poll(ctx, true)); 913 g_assert(!aio_poll(ctx, false)); 914} 915 916/* End of tests. */ 917 918int main(int argc, char **argv) 919{ 920 qemu_init_main_loop(&error_fatal); 921 ctx = qemu_get_aio_context(); 922 923 while (g_main_context_iteration(NULL, false)); 924 925 g_test_init(&argc, &argv, NULL); 926 g_test_add_func("/aio/acquire", test_acquire); 927 g_test_add_func("/aio/bh/schedule", test_bh_schedule); 928 g_test_add_func("/aio/bh/schedule10", test_bh_schedule10); 929 g_test_add_func("/aio/bh/cancel", test_bh_cancel); 930 g_test_add_func("/aio/bh/delete", test_bh_delete); 931 g_test_add_func("/aio/bh/callback-delete/one", test_bh_delete_from_cb); 932 g_test_add_func("/aio/bh/callback-delete/many", test_bh_delete_from_cb_many); 933 g_test_add_func("/aio/bh/flush", test_bh_flush); 934 g_test_add_func("/aio/event/add-remove", test_set_event_notifier); 935 g_test_add_func("/aio/event/wait", test_wait_event_notifier); 936 g_test_add_func("/aio/event/wait/no-flush-cb", test_wait_event_notifier_noflush); 937 g_test_add_func("/aio/event/flush", test_flush_event_notifier); 938 g_test_add_func("/aio/external-client", test_aio_external_client); 939 g_test_add_func("/aio/timer/schedule", test_timer_schedule); 940 941 g_test_add_func("/aio/coroutine/queue-chaining", test_queue_chaining); 942 g_test_add_func("/aio/coroutine/worker-thread-co-enter", test_worker_thread_co_enter); 943 944 g_test_add_func("/aio-gsource/flush", test_source_flush); 945 g_test_add_func("/aio-gsource/bh/schedule", test_source_bh_schedule); 946 g_test_add_func("/aio-gsource/bh/schedule10", test_source_bh_schedule10); 947 g_test_add_func("/aio-gsource/bh/cancel", test_source_bh_cancel); 948 g_test_add_func("/aio-gsource/bh/delete", test_source_bh_delete); 949 g_test_add_func("/aio-gsource/bh/callback-delete/one", test_source_bh_delete_from_cb); 950 g_test_add_func("/aio-gsource/bh/callback-delete/many", test_source_bh_delete_from_cb_many); 951 g_test_add_func("/aio-gsource/bh/flush", test_source_bh_flush); 952 g_test_add_func("/aio-gsource/event/add-remove", test_source_set_event_notifier); 953 g_test_add_func("/aio-gsource/event/wait", test_source_wait_event_notifier); 954 g_test_add_func("/aio-gsource/event/wait/no-flush-cb", test_source_wait_event_notifier_noflush); 955 g_test_add_func("/aio-gsource/event/flush", test_source_flush_event_notifier); 956 g_test_add_func("/aio-gsource/timer/schedule", test_source_timer_schedule); 957 return g_test_run(); 958}