diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index bc18ca30e4..99769093fc 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -203,6 +203,7 @@ void qemu_set_fd_handler(int fd, IOHandler *fd_write, void *opaque); +GSource *iohandler_get_g_source(void); #ifdef CONFIG_POSIX /** * qemu_add_child_watch: Register a child process for reaping. @@ -265,8 +266,6 @@ void qemu_mutex_unlock_iothread(void); /* internal interfaces */ void qemu_fd_register(int fd); -void qemu_iohandler_fill(GArray *pollfds); -void qemu_iohandler_poll(GArray *pollfds, int rc); QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); void qemu_bh_schedule_idle(QEMUBH *bh); diff --git a/iohandler.c b/iohandler.c index 826f713e9f..55f8501524 100644 --- a/iohandler.c +++ b/iohandler.c @@ -32,111 +32,30 @@ #include #endif -typedef struct IOHandlerRecord { - IOHandler *fd_read; - IOHandler *fd_write; - void *opaque; - QLIST_ENTRY(IOHandlerRecord) next; - int fd; - int pollfds_idx; - bool deleted; -} IOHandlerRecord; +/* This context runs on top of main loop. We can't reuse qemu_aio_context + * because iohandlers mustn't be polled by aio_poll(qemu_aio_context). */ +static AioContext *iohandler_ctx; -static QLIST_HEAD(, IOHandlerRecord) io_handlers = - QLIST_HEAD_INITIALIZER(io_handlers); +static void iohandler_init(void) +{ + if (!iohandler_ctx) { + iohandler_ctx = aio_context_new(&error_abort); + } +} + +GSource *iohandler_get_g_source(void) +{ + iohandler_init(); + return aio_get_g_source(iohandler_ctx); +} void qemu_set_fd_handler(int fd, IOHandler *fd_read, IOHandler *fd_write, void *opaque) { - IOHandlerRecord *ioh; - - assert(fd >= 0); - - if (!fd_read && !fd_write) { - QLIST_FOREACH(ioh, &io_handlers, next) { - if (ioh->fd == fd) { - ioh->deleted = 1; - break; - } - } - } else { - QLIST_FOREACH(ioh, &io_handlers, next) { - if (ioh->fd == fd) - goto found; - } - ioh = g_malloc0(sizeof(IOHandlerRecord)); - QLIST_INSERT_HEAD(&io_handlers, ioh, next); - found: - ioh->fd = fd; - ioh->fd_read = fd_read; - ioh->fd_write = fd_write; - ioh->opaque = opaque; - ioh->pollfds_idx = -1; - ioh->deleted = 0; - qemu_notify_event(); - } -} - -void qemu_iohandler_fill(GArray *pollfds) -{ - IOHandlerRecord *ioh; - - QLIST_FOREACH(ioh, &io_handlers, next) { - int events = 0; - - if (ioh->deleted) - continue; - if (ioh->fd_read) { - events |= G_IO_IN | G_IO_HUP | G_IO_ERR; - } - if (ioh->fd_write) { - events |= G_IO_OUT | G_IO_ERR; - } - if (events) { - GPollFD pfd = { - .fd = ioh->fd, - .events = events, - }; - ioh->pollfds_idx = pollfds->len; - g_array_append_val(pollfds, pfd); - } else { - ioh->pollfds_idx = -1; - } - } -} - -void qemu_iohandler_poll(GArray *pollfds, int ret) -{ - if (ret > 0) { - IOHandlerRecord *pioh, *ioh; - - QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { - int revents = 0; - - if (!ioh->deleted && ioh->pollfds_idx != -1) { - GPollFD *pfd = &g_array_index(pollfds, GPollFD, - ioh->pollfds_idx); - revents = pfd->revents; - } - - if (!ioh->deleted && ioh->fd_read && - (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) { - ioh->fd_read(ioh->opaque); - } - if (!ioh->deleted && ioh->fd_write && - (revents & (G_IO_OUT | G_IO_ERR))) { - ioh->fd_write(ioh->opaque); - } - - /* Do this last in case read/write handlers marked it for deletion */ - if (ioh->deleted) { - QLIST_REMOVE(ioh, next); - g_free(ioh); - } - } - } + iohandler_init(); + aio_set_fd_handler(iohandler_ctx, fd, fd_read, fd_write, opaque); } /* reaping of zombies. right now we're not passing the status to diff --git a/main-loop.c b/main-loop.c index 39970437f8..db600a37f1 100644 --- a/main-loop.c +++ b/main-loop.c @@ -161,6 +161,9 @@ int qemu_init_main_loop(Error **errp) src = aio_get_g_source(qemu_aio_context); g_source_attach(src, NULL); g_source_unref(src); + src = iohandler_get_g_source(); + g_source_attach(src, NULL); + g_source_unref(src); return 0; } @@ -487,7 +490,6 @@ int main_loop_wait(int nonblocking) #ifdef CONFIG_SLIRP slirp_pollfds_fill(gpollfds, &timeout); #endif - qemu_iohandler_fill(gpollfds); if (timeout == UINT32_MAX) { timeout_ns = -1; @@ -500,7 +502,6 @@ int main_loop_wait(int nonblocking) &main_loop_tlg)); ret = os_host_main_loop_wait(timeout_ns); - qemu_iohandler_poll(gpollfds, ret); #ifdef CONFIG_SLIRP slirp_pollfds_poll(gpollfds, (ret < 0)); #endif