1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * fdmon-epoll tests
4  *
5  * Copyright (c) 2020 Red Hat, Inc.
6  */
7 
8 #include "qemu/osdep.h"
9 #include "block/aio.h"
10 #include "qapi/error.h"
11 #include "qemu/main-loop.h"
12 
13 static AioContext *ctx;
14 
dummy_fd_handler(EventNotifier * notifier)15 static void dummy_fd_handler(EventNotifier *notifier)
16 {
17     event_notifier_test_and_clear(notifier);
18 }
19 
add_event_notifiers(EventNotifier * notifiers,size_t n)20 static void add_event_notifiers(EventNotifier *notifiers, size_t n)
21 {
22     for (size_t i = 0; i < n; i++) {
23         event_notifier_init(&notifiers[i], false);
24         aio_set_event_notifier(ctx, &notifiers[i], false,
25                                dummy_fd_handler, NULL);
26     }
27 }
28 
remove_event_notifiers(EventNotifier * notifiers,size_t n)29 static void remove_event_notifiers(EventNotifier *notifiers, size_t n)
30 {
31     for (size_t i = 0; i < n; i++) {
32         aio_set_event_notifier(ctx, &notifiers[i], false, NULL, NULL);
33         event_notifier_cleanup(&notifiers[i]);
34     }
35 }
36 
37 /* Check that fd handlers work when external clients are disabled */
test_external_disabled(void)38 static void test_external_disabled(void)
39 {
40     EventNotifier notifiers[100];
41 
42     /* fdmon-epoll is only enabled when many fd handlers are registered */
43     add_event_notifiers(notifiers, G_N_ELEMENTS(notifiers));
44 
45     event_notifier_set(&notifiers[0]);
46     assert(aio_poll(ctx, true));
47 
48     aio_disable_external(ctx);
49     event_notifier_set(&notifiers[0]);
50     assert(aio_poll(ctx, true));
51     aio_enable_external(ctx);
52 
53     remove_event_notifiers(notifiers, G_N_ELEMENTS(notifiers));
54 }
55 
main(int argc,char ** argv)56 int main(int argc, char **argv)
57 {
58     /*
59      * This code relies on the fact that fdmon-io_uring disables itself when
60      * the glib main loop is in use. The main loop uses fdmon-poll and upgrades
61      * to fdmon-epoll when the number of fds exceeds a threshold.
62      */
63     qemu_init_main_loop(&error_fatal);
64     ctx = qemu_get_aio_context();
65 
66     while (g_main_context_iteration(NULL, false)) {
67         /* Do nothing */
68     }
69 
70     g_test_init(&argc, &argv, NULL);
71     g_test_add_func("/fdmon-epoll/external-disabled", test_external_disabled);
72     return g_test_run();
73 }
74