1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * poll(2) file descriptor monitoring
5 * Uses ppoll(2) when available, g_poll() otherwise.
8 #include "qemu/osdep.h"
10 #include "qemu/rcu_queue.h"
13 * These thread-local variables are used only in fdmon_poll_wait() around the
14 * call to the poll() system call. In particular they are not used while
15 * aio_poll is performing callbacks, which makes it much easier to think about
18 * Stack-allocated arrays would be perfect but they have size limitations;
19 * heap allocation is expensive enough that we want to reuse arrays across
20 * calls to aio_poll(). And because poll() has to be called without holding
21 * any lock, the arrays cannot be stored in AioContext. Thread-local data
22 * has none of the disadvantages of these three options.
24 static __thread GPollFD
*pollfds
;
25 static __thread AioHandler
**nodes
;
26 static __thread
unsigned npfd
, nalloc
;
27 static __thread Notifier pollfds_cleanup_notifier
;
29 static void pollfds_cleanup(Notifier
*n
, void *unused
)
37 static void add_pollfd(AioHandler
*node
)
41 pollfds_cleanup_notifier
.notify
= pollfds_cleanup
;
42 qemu_thread_atexit_add(&pollfds_cleanup_notifier
);
45 g_assert(nalloc
<= INT_MAX
);
48 pollfds
= g_renew(GPollFD
, pollfds
, nalloc
);
49 nodes
= g_renew(AioHandler
*, nodes
, nalloc
);
52 pollfds
[npfd
] = (GPollFD
) {
54 .events
= node
->pfd
.events
,
59 static int fdmon_poll_wait(AioContext
*ctx
, AioHandlerList
*ready_list
,
67 QLIST_FOREACH_RCU(node
, &ctx
->aio_handlers
, node
) {
68 if (!QLIST_IS_INSERTED(node
, node_deleted
) && node
->pfd
.events
69 && aio_node_check(ctx
, node
->is_external
)) {
74 /* epoll(7) is faster above a certain number of fds */
75 if (fdmon_epoll_try_upgrade(ctx
, npfd
)) {
76 npfd
= 0; /* we won't need pollfds[], reset npfd */
77 return ctx
->fdmon_ops
->wait(ctx
, ready_list
, timeout
);
80 ret
= qemu_poll_ns(pollfds
, npfd
, timeout
);
84 for (i
= 0; i
< npfd
; i
++) {
85 int revents
= pollfds
[i
].revents
;
88 aio_add_ready_handler(ready_list
, nodes
[i
], revents
);
97 static void fdmon_poll_update(AioContext
*ctx
,
101 /* Do nothing, AioHandler already contains the state we'll need */
104 const FDMonOps fdmon_poll_ops
= {
105 .update
= fdmon_poll_update
,
106 .wait
= fdmon_poll_wait
,
107 .need_wait
= aio_poll_disabled
,