This is in preparation for making qio_channel_yield work on AioContexts other than the main one.
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- include/io/channel.h | 42 ++++++++++++++++++++++++++++++++++++++++++ io/channel-socket.c | 16 +++++++++++----- io/channel-tls.c | 12 ++++++++++++ io/channel-watch.c | 6 ++++++ io/channel.c | 25 +++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 5 deletions(-) diff --git a/include/io/channel.h b/include/io/channel.h index 32a9470..248bc76 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -23,6 +23,7 @@ #include "qemu-common.h" #include "qom/object.h" +#include "block/aio.h" #define TYPE_QIO_CHANNEL "qio-channel" #define QIO_CHANNEL(obj) \ @@ -58,6 +59,8 @@ typedef gboolean (*QIOChannelFunc)(QIOChannel *ioc, GIOCondition condition, gpointer data); +typedef struct QIOChannelRestart QIOChannelRestart; + /** * QIOChannel: * @@ -80,6 +83,9 @@ struct QIOChannel { Object parent; unsigned int features; /* bitmask of QIOChannelFeatures */ char *name; + AioContext *ctx; + QIOChannelRestart *read_coroutine; + QIOChannelRestart *write_coroutine; #ifdef _WIN32 HANDLE event; /* For use with GSource on Win32 */ #endif @@ -132,6 +138,11 @@ struct QIOChannelClass { off_t offset, int whence, Error **errp); + void (*io_set_fd_handler)(QIOChannel *ioc, + AioContext *ctx, + IOHandler *io_read, + IOHandler *io_write, + void *opaque); }; /* General I/O handling functions */ @@ -497,6 +508,18 @@ guint qio_channel_add_watch(QIOChannel *ioc, /** + * qio_channel_set_aio_context: + * @ioc: the channel object + * @ctx: the #AioContext to set the handlers on + * + * Request that qio_channel_yield() sets I/O handlers on + * the given #AioContext. If @ctx is %NULL, qio_channel_yield() + * uses QEMU's main thread event loop. + */ +void qio_channel_set_aio_context(QIOChannel *ioc, + AioContext *ctx); + +/** * qio_channel_yield: * @ioc: the channel object * @condition: the I/O condition to wait for @@ -525,4 +548,23 @@ void qio_channel_yield(QIOChannel *ioc, void qio_channel_wait(QIOChannel *ioc, GIOCondition condition); +/** + * qio_channel_set_fd_handler: + * @ioc: the channel object + * @ctx: the AioContext to set the handlers on + * @io_read: the read handler + * @io_write: the write handler + * @opaque: the opaque value passed to the handler + * + * This is used internally by qio_channel_yield(). It can + * be used by channel implementations to forward the handlers + * to another channel (e.g. from #QIOChannelTLS to the + * underlying socket). + */ +void qio_channel_set_fd_handler(QIOChannel *ioc, + AioContext *ctx, + IOHandler *io_read, + IOHandler *io_write, + void *opaque); + #endif /* QIO_CHANNEL_H */ diff --git a/io/channel-socket.c b/io/channel-socket.c index d7e03f6..4d5f180 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -661,11 +661,6 @@ qio_channel_socket_set_blocking(QIOChannel *ioc, qemu_set_block(sioc->fd); } else { qemu_set_nonblock(sioc->fd); -#ifdef WIN32 - WSAEventSelect(sioc->fd, ioc->event, - FD_READ | FD_ACCEPT | FD_CLOSE | - FD_CONNECT | FD_WRITE | FD_OOB); -#endif } return 0; } @@ -745,6 +740,16 @@ qio_channel_socket_shutdown(QIOChannel *ioc, return 0; } +static GSource *qio_channel_socket_set_fd_handler(QIOChannel *ioc, + AioContext *ctx, + IOHandler *io_read, + IOHandler *io_write, + void *opaque) +{ + QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); + aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, opaque); +} + static GSource *qio_channel_socket_create_watch(QIOChannel *ioc, GIOCondition condition) { @@ -767,6 +772,7 @@ static void qio_channel_socket_class_init(ObjectClass *klass, ioc_klass->io_set_cork = qio_channel_socket_set_cork; ioc_klass->io_set_delay = qio_channel_socket_set_delay; ioc_klass->io_create_watch = qio_channel_socket_create_watch; + ioc_klass->io_set_fd_handler = qio_channel_socket_set_fd_handler; } static const TypeInfo qio_channel_socket_info = { diff --git a/io/channel-tls.c b/io/channel-tls.c index d24dc8c..bd2239c 100644 --- a/io/channel-tls.c +++ b/io/channel-tls.c @@ -349,6 +349,17 @@ static int qio_channel_tls_close(QIOChannel *ioc, return qio_channel_close(tioc->master, errp); } +static void qio_channel_tls_set_fd_handler(QIOChannel *ioc, + AioContext *ctx, + IOHandler *io_read, + IOHandler *io_write, + void *opaque) +{ + QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc); + + qio_channel_set_fd_handler(tioc->master, ctx, io_read, io_write, opaque); +} + static GSource *qio_channel_tls_create_watch(QIOChannel *ioc, GIOCondition condition) { @@ -376,6 +387,7 @@ static void qio_channel_tls_class_init(ObjectClass *klass, ioc_klass->io_close = qio_channel_tls_close; ioc_klass->io_shutdown = qio_channel_tls_shutdown; ioc_klass->io_create_watch = qio_channel_tls_create_watch; + ioc_klass->io_set_fd_handler = qio_channel_tls_set_fd_handler; } static const TypeInfo qio_channel_tls_info = { diff --git a/io/channel-watch.c b/io/channel-watch.c index cf1cdff..8640d1c 100644 --- a/io/channel-watch.c +++ b/io/channel-watch.c @@ -285,6 +285,12 @@ GSource *qio_channel_create_socket_watch(QIOChannel *ioc, GSource *source; QIOChannelSocketSource *ssource; +#ifdef WIN32 + WSAEventSelect(socket, ioc->event, + FD_READ | FD_ACCEPT | FD_CLOSE | + FD_CONNECT | FD_WRITE | FD_OOB); +#endif + source = g_source_new(&qio_channel_socket_source_funcs, sizeof(QIOChannelSocketSource)); ssource = (QIOChannelSocketSource *)source; diff --git a/io/channel.c b/io/channel.c index 80924c1..9ef683c 100644 --- a/io/channel.c +++ b/io/channel.c @@ -154,6 +154,17 @@ GSource *qio_channel_create_watch(QIOChannel *ioc, } +void qio_channel_set_fd_handler(QIOChannel *ioc, + AioContext *ctx, + IOHandler *io_read, + IOHandler *io_write, + void *opaque) +{ + QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); + + klass->io_set_fd_handler(ioc, ctx, io_read, io_write, opaque); +} + guint qio_channel_add_watch(QIOChannel *ioc, GIOCondition condition, QIOChannelFunc func, @@ -244,6 +255,20 @@ static gboolean qio_channel_yield_enter(QIOChannel *ioc, } +void qio_channel_set_aio_context(QIOChannel *ioc, + AioContext *ctx) +{ + if (ioc->ctx == ctx) { + return; + } + + qio_channel_set_fd_handler(ioc, + ioc->ctx ? ioc->ctx : iohandler_get_aio_context(), + NULL, NULL, NULL); + ioc->ctx = ctx; + qio_channel_set_fd_handlers(ioc); +} + void coroutine_fn qio_channel_yield(QIOChannel *ioc, GIOCondition condition) { -- 2.9.3