diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2011-08-22 08:12:53 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2011-09-01 13:12:33 -0500 |
commit | 4d88a2ac8643265108ef1fb47ceee5d7b28e19f2 (patch) | |
tree | 414fdb0116a621018747b0e5def57f10ff6e6ee4 | |
parent | 69e5bb68a5e95286edd59c3ce34c6f7bae5b5548 (diff) |
main: switch qemu_set_fd_handler to g_io_add_watch
This patch changes qemu_set_fd_handler to be implemented in terms of
g_io_add_watch(). The semantics are a bit different so some glue is required.
qemu_set_fd_handler2 is much harder to convert because of its use of polling.
The glib main loop has the major of advantage of having a proven thread safe
architecture. By using the glib main loop instead of our own, it will allow us
to eventually introduce multiple I/O threads.
I'm pretty sure that this will work on Win32, but I would appreciate some help
testing. I think the semantics of g_io_channel_unix_new() are really just tied
to the notion of a "unix fd" and not necessarily unix itself.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r-- | iohandler.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/iohandler.c b/iohandler.c index 4deae1e6ab..5ef66fb6e8 100644 --- a/iohandler.c +++ b/iohandler.c @@ -80,12 +80,67 @@ int qemu_set_fd_handler2(int fd, return 0; } +typedef struct IOTrampoline +{ + GIOChannel *chan; + IOHandler *fd_read; + IOHandler *fd_write; + void *opaque; + guint tag; +} IOTrampoline; + +static gboolean fd_trampoline(GIOChannel *chan, GIOCondition cond, gpointer opaque) +{ + IOTrampoline *tramp = opaque; + + if (tramp->opaque == NULL) { + return FALSE; + } + + if ((cond & G_IO_IN) && tramp->fd_read) { + tramp->fd_read(tramp->opaque); + } + + if ((cond & G_IO_OUT) && tramp->fd_write) { + tramp->fd_write(tramp->opaque); + } + + return TRUE; +} + int qemu_set_fd_handler(int fd, IOHandler *fd_read, IOHandler *fd_write, void *opaque) { - return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); + static IOTrampoline fd_trampolines[FD_SETSIZE]; + IOTrampoline *tramp = &fd_trampolines[fd]; + + if (tramp->tag != 0) { + g_io_channel_unref(tramp->chan); + g_source_remove(tramp->tag); + } + + if (opaque) { + GIOCondition cond = 0; + + tramp->fd_read = fd_read; + tramp->fd_write = fd_write; + tramp->opaque = opaque; + + if (fd_read) { + cond |= G_IO_IN | G_IO_ERR; + } + + if (fd_write) { + cond |= G_IO_OUT | G_IO_ERR; + } + + tramp->chan = g_io_channel_unix_new(fd); + tramp->tag = g_io_add_watch(tramp->chan, cond, fd_trampoline, tramp); + } + + return 0; } void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) |