8
#include "qemu/rcu_queue.h"
12
#define EPOLL_ENABLE_THRESHOLD 64
14
void fdmon_epoll_disable(AioContext *ctx)
16
if (ctx->epollfd >= 0) {
22
ctx->fdmon_ops = &fdmon_poll_ops;
25
static inline int epoll_events_from_pfd(int pfd_events)
27
return (pfd_events & G_IO_IN ? EPOLLIN : 0) |
28
(pfd_events & G_IO_OUT ? EPOLLOUT : 0) |
29
(pfd_events & G_IO_HUP ? EPOLLHUP : 0) |
30
(pfd_events & G_IO_ERR ? EPOLLERR : 0);
33
static void fdmon_epoll_update(AioContext *ctx,
37
struct epoll_event event = {
39
.events = new_node ? epoll_events_from_pfd(new_node->pfd.events) : 0,
44
r = epoll_ctl(ctx->epollfd, EPOLL_CTL_DEL, old_node->pfd.fd, &event);
45
} else if (!old_node) {
46
r = epoll_ctl(ctx->epollfd, EPOLL_CTL_ADD, new_node->pfd.fd, &event);
48
r = epoll_ctl(ctx->epollfd, EPOLL_CTL_MOD, new_node->pfd.fd, &event);
52
fdmon_epoll_disable(ctx);
56
static int fdmon_epoll_wait(AioContext *ctx, AioHandlerList *ready_list,
61
.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR,
65
struct epoll_event events[128];
68
ret = qemu_poll_ns(&pfd, 1, timeout);
73
if (timeout <= 0 || ret > 0) {
74
ret = epoll_wait(ctx->epollfd, events,
80
for (i = 0; i < ret; i++) {
81
int ev = events[i].events;
82
int revents = (ev & EPOLLIN ? G_IO_IN : 0) |
83
(ev & EPOLLOUT ? G_IO_OUT : 0) |
84
(ev & EPOLLHUP ? G_IO_HUP : 0) |
85
(ev & EPOLLERR ? G_IO_ERR : 0);
87
node = events[i].data.ptr;
88
aio_add_ready_handler(ready_list, node, revents);
95
static const FDMonOps fdmon_epoll_ops = {
96
.update = fdmon_epoll_update,
97
.wait = fdmon_epoll_wait,
98
.need_wait = aio_poll_disabled,
101
static bool fdmon_epoll_try_enable(AioContext *ctx)
104
struct epoll_event event;
106
QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) {
108
if (QLIST_IS_INSERTED(node, node_deleted) || !node->pfd.events) {
111
event.events = epoll_events_from_pfd(node->pfd.events);
112
event.data.ptr = node;
113
r = epoll_ctl(ctx->epollfd, EPOLL_CTL_ADD, node->pfd.fd, &event);
119
ctx->fdmon_ops = &fdmon_epoll_ops;
123
bool fdmon_epoll_try_upgrade(AioContext *ctx, unsigned npfd)
127
if (ctx->epollfd < 0) {
131
if (npfd < EPOLL_ENABLE_THRESHOLD) {
136
if (!qemu_lockcnt_dec_if_lock(&ctx->list_lock)) {
140
ok = fdmon_epoll_try_enable(ctx);
142
qemu_lockcnt_inc_and_unlock(&ctx->list_lock);
145
fdmon_epoll_disable(ctx);
150
void fdmon_epoll_setup(AioContext *ctx)
152
ctx->epollfd = epoll_create1(EPOLL_CLOEXEC);
153
if (ctx->epollfd == -1) {
154
fprintf(stderr, "Failed to create epoll instance: %s", strerror(errno));