X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=aio-posix.c;h=bd06f33c7824184d56ccd7e6149cc1fa1e56448d;hb=60aad298cb6de52f2716b2e82e1353ea9de95fd6;hp=35131a3ef733d4c893e985fcd58c395a1dd49002;hpb=d0c8d2c05f67a1a007d87fa3b99254abfa42d06d;p=qemu.git diff --git a/aio-posix.c b/aio-posix.c index 35131a3ef..bd06f33c7 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -23,8 +23,8 @@ struct AioHandler GPollFD pfd; IOHandler *io_read; IOHandler *io_write; - AioFlushHandler *io_flush; int deleted; + int pollfds_idx; void *opaque; QLIST_ENTRY(AioHandler) node; }; @@ -46,7 +46,6 @@ void aio_set_fd_handler(AioContext *ctx, int fd, IOHandler *io_read, IOHandler *io_write, - AioFlushHandler *io_flush, void *opaque) { AioHandler *node; @@ -83,11 +82,11 @@ void aio_set_fd_handler(AioContext *ctx, /* Update handler with latest information */ node->io_read = io_read; node->io_write = io_write; - node->io_flush = io_flush; node->opaque = opaque; + node->pollfds_idx = -1; - node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP : 0); - node->pfd.events |= (io_write ? G_IO_OUT : 0); + node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0); + node->pfd.events |= (io_write ? G_IO_OUT | G_IO_ERR : 0); } aio_notify(ctx); @@ -95,12 +94,10 @@ void aio_set_fd_handler(AioContext *ctx, void aio_set_event_notifier(AioContext *ctx, EventNotifier *notifier, - EventNotifierHandler *io_read, - AioFlushEventNotifierHandler *io_flush) + EventNotifierHandler *io_read) { aio_set_fd_handler(ctx, event_notifier_get_fd(notifier), - (IOHandler *)io_read, NULL, - (AioFlushHandler *)io_flush, notifier); + (IOHandler *)io_read, NULL, notifier); } bool aio_pending(AioContext *ctx) @@ -110,13 +107,6 @@ bool aio_pending(AioContext *ctx) QLIST_FOREACH(node, &ctx->aio_handlers, node) { int revents; - /* - * FIXME: right now we cannot get G_IO_HUP and G_IO_ERR because - * main-loop.c is still select based (due to the slirp legacy). - * If main-loop.c ever switches to poll, G_IO_ERR should be - * tested too. Dispatching G_IO_ERR to both handlers should be - * okay, since handlers need to be ready for spurious wakeups. - */ revents = node->pfd.revents & node->pfd.events; if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) { return true; @@ -148,12 +138,15 @@ static bool aio_dispatch(AioContext *ctx) revents = node->pfd.revents & node->pfd.events; node->pfd.revents = 0; - /* See comment in aio_pending. */ if (!node->deleted && (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) && node->io_read) { node->io_read(node->opaque); - progress = true; + + /* aio_notify() does not count as progress */ + if (node->opaque != &ctx->notifier) { + progress = true; + } } if (!node->deleted && (revents & (G_IO_OUT | G_IO_ERR)) && @@ -172,17 +165,18 @@ static bool aio_dispatch(AioContext *ctx) g_free(tmp); } } + + /* Run our timers */ + progress |= timerlistgroup_run_timers(&ctx->tlg); + return progress; } bool aio_poll(AioContext *ctx, bool blocking) { - static struct timeval tv0; AioHandler *node; - fd_set rdfds, wrfds; - int max_fd = -1; int ret; - bool busy, progress; + bool progress; progress = false; @@ -206,77 +200,48 @@ bool aio_poll(AioContext *ctx, bool blocking) ctx->walking_handlers++; - FD_ZERO(&rdfds); - FD_ZERO(&wrfds); + g_array_set_size(ctx->pollfds, 0); - /* fill fd sets */ - busy = false; + /* fill pollfds */ QLIST_FOREACH(node, &ctx->aio_handlers, node) { - /* If there aren't pending AIO operations, don't invoke callbacks. - * Otherwise, if there are no AIO requests, qemu_aio_wait() would - * wait indefinitely. - */ - if (!node->deleted && node->io_flush) { - if (node->io_flush(node->opaque) == 0) { - continue; - } - busy = true; - } - if (!node->deleted && node->io_read) { - FD_SET(node->pfd.fd, &rdfds); - max_fd = MAX(max_fd, node->pfd.fd + 1); - } - if (!node->deleted && node->io_write) { - FD_SET(node->pfd.fd, &wrfds); - max_fd = MAX(max_fd, node->pfd.fd + 1); + node->pollfds_idx = -1; + if (!node->deleted && node->pfd.events) { + GPollFD pfd = { + .fd = node->pfd.fd, + .events = node->pfd.events, + }; + node->pollfds_idx = ctx->pollfds->len; + g_array_append_val(ctx->pollfds, pfd); } } ctx->walking_handlers--; - /* No AIO operations? Get us out of here */ - if (!busy) { + /* early return if we only have the aio_notify() fd */ + if (ctx->pollfds->len == 1) { return progress; } /* wait until next event */ - ret = select(max_fd, &rdfds, &wrfds, NULL, blocking ? NULL : &tv0); + ret = qemu_poll_ns((GPollFD *)ctx->pollfds->data, + ctx->pollfds->len, + blocking ? timerlistgroup_deadline_ns(&ctx->tlg) : 0); /* if we have any readable fds, dispatch event */ if (ret > 0) { - /* we have to walk very carefully in case - * qemu_aio_set_fd_handler is called while we're walking */ - node = QLIST_FIRST(&ctx->aio_handlers); - while (node) { - AioHandler *tmp; - - ctx->walking_handlers++; - - if (!node->deleted && - FD_ISSET(node->pfd.fd, &rdfds) && - node->io_read) { - node->io_read(node->opaque); - progress = true; - } - if (!node->deleted && - FD_ISSET(node->pfd.fd, &wrfds) && - node->io_write) { - node->io_write(node->opaque); - progress = true; - } - - tmp = node; - node = QLIST_NEXT(node, node); - - ctx->walking_handlers--; - - if (!ctx->walking_handlers && tmp->deleted) { - QLIST_REMOVE(tmp, node); - g_free(tmp); + QLIST_FOREACH(node, &ctx->aio_handlers, node) { + if (node->pollfds_idx != -1) { + GPollFD *pfd = &g_array_index(ctx->pollfds, GPollFD, + node->pollfds_idx); + node->pfd.revents = pfd->revents; } } } - assert(progress || busy); - return true; + /* Run dispatch even if there were no readable fds to run timers */ + if (aio_dispatch(ctx)) { + progress = true; + } + + return progress; }