aboutsummaryrefslogtreecommitdiff
path: root/iohandler.c
diff options
context:
space:
mode:
authorFam Zheng <famz@redhat.com>2015-09-07 11:28:58 +0800
committerPaolo Bonzini <pbonzini@redhat.com>2015-09-07 18:14:03 +0200
commitf3926945c85689e8af324c0db0b39be771dbbebb (patch)
tree886a0e84aa50d6e34191f4366c2a589b0680f4fa /iohandler.c
parent46036b2462c7ff56c0af6466ea6b9248197a38a8 (diff)
iohandler: Use aio API
iohandler.c shares the same interface with aio, but with duplicated code. It's better to rebase iohandler, also because that aio is a more friendly interface to multi-threads. Create a global AioContext instance and let its GSource handle the iohandler events. Signed-off-by: Fam Zheng <famz@redhat.com> Message-Id: <1441596538-4412-1-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'iohandler.c')
-rw-r--r--iohandler.c111
1 files changed, 15 insertions, 96 deletions
diff --git a/iohandler.c b/iohandler.c
index 826f713e9f..55f8501524 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -32,111 +32,30 @@
#include <sys/wait.h>
#endif
-typedef struct IOHandlerRecord {
- IOHandler *fd_read;
- IOHandler *fd_write;
- void *opaque;
- QLIST_ENTRY(IOHandlerRecord) next;
- int fd;
- int pollfds_idx;
- bool deleted;
-} IOHandlerRecord;
-
-static QLIST_HEAD(, IOHandlerRecord) io_handlers =
- QLIST_HEAD_INITIALIZER(io_handlers);
+/* 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;
-void qemu_set_fd_handler(int fd,
- IOHandler *fd_read,
- IOHandler *fd_write,
- void *opaque)
+static void iohandler_init(void)
{
- 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();
+ if (!iohandler_ctx) {
+ iohandler_ctx = aio_context_new(&error_abort);
}
}
-void qemu_iohandler_fill(GArray *pollfds)
+GSource *iohandler_get_g_source(void)
{
- 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;
- }
- }
+ iohandler_init();
+ return aio_get_g_source(iohandler_ctx);
}
-void qemu_iohandler_poll(GArray *pollfds, int ret)
+void qemu_set_fd_handler(int fd,
+ IOHandler *fd_read,
+ IOHandler *fd_write,
+ void *opaque)
{
- 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