mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 00:33:55 -06:00
io: make qio_channel_yield aware of AioContexts
Support separate coroutines for reading and writing, and place the read/write handlers on the AioContext that the QIOChannel is registered with. Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Fam Zheng <famz@redhat.com> Message-id: 20170213135235.12274-7-pbonzini@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
bf88c1247f
commit
c4c497d27f
2 changed files with 110 additions and 25 deletions
88
io/channel.c
88
io/channel.c
|
@ -21,7 +21,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "io/channel.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
bool qio_channel_has_feature(QIOChannel *ioc,
|
||||
QIOChannelFeature feature)
|
||||
|
@ -238,36 +238,80 @@ off_t qio_channel_io_seek(QIOChannel *ioc,
|
|||
}
|
||||
|
||||
|
||||
typedef struct QIOChannelYieldData QIOChannelYieldData;
|
||||
struct QIOChannelYieldData {
|
||||
QIOChannel *ioc;
|
||||
Coroutine *co;
|
||||
};
|
||||
static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc);
|
||||
|
||||
|
||||
static gboolean qio_channel_yield_enter(QIOChannel *ioc,
|
||||
GIOCondition condition,
|
||||
gpointer opaque)
|
||||
static void qio_channel_restart_read(void *opaque)
|
||||
{
|
||||
QIOChannelYieldData *data = opaque;
|
||||
qemu_coroutine_enter(data->co);
|
||||
return FALSE;
|
||||
QIOChannel *ioc = opaque;
|
||||
Coroutine *co = ioc->read_coroutine;
|
||||
|
||||
ioc->read_coroutine = NULL;
|
||||
qio_channel_set_aio_fd_handlers(ioc);
|
||||
aio_co_wake(co);
|
||||
}
|
||||
|
||||
static void qio_channel_restart_write(void *opaque)
|
||||
{
|
||||
QIOChannel *ioc = opaque;
|
||||
Coroutine *co = ioc->write_coroutine;
|
||||
|
||||
ioc->write_coroutine = NULL;
|
||||
qio_channel_set_aio_fd_handlers(ioc);
|
||||
aio_co_wake(co);
|
||||
}
|
||||
|
||||
static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc)
|
||||
{
|
||||
IOHandler *rd_handler = NULL, *wr_handler = NULL;
|
||||
AioContext *ctx;
|
||||
|
||||
if (ioc->read_coroutine) {
|
||||
rd_handler = qio_channel_restart_read;
|
||||
}
|
||||
if (ioc->write_coroutine) {
|
||||
wr_handler = qio_channel_restart_write;
|
||||
}
|
||||
|
||||
ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
|
||||
qio_channel_set_aio_fd_handler(ioc, ctx, rd_handler, wr_handler, ioc);
|
||||
}
|
||||
|
||||
void qio_channel_attach_aio_context(QIOChannel *ioc,
|
||||
AioContext *ctx)
|
||||
{
|
||||
AioContext *old_ctx;
|
||||
if (ioc->ctx == ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
old_ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
|
||||
qio_channel_set_aio_fd_handler(ioc, old_ctx, NULL, NULL, NULL);
|
||||
ioc->ctx = ctx;
|
||||
qio_channel_set_aio_fd_handlers(ioc);
|
||||
}
|
||||
|
||||
void qio_channel_detach_aio_context(QIOChannel *ioc)
|
||||
{
|
||||
ioc->read_coroutine = NULL;
|
||||
ioc->write_coroutine = NULL;
|
||||
qio_channel_set_aio_fd_handlers(ioc);
|
||||
ioc->ctx = NULL;
|
||||
}
|
||||
|
||||
void coroutine_fn qio_channel_yield(QIOChannel *ioc,
|
||||
GIOCondition condition)
|
||||
{
|
||||
QIOChannelYieldData data;
|
||||
|
||||
assert(qemu_in_coroutine());
|
||||
data.ioc = ioc;
|
||||
data.co = qemu_coroutine_self();
|
||||
qio_channel_add_watch(ioc,
|
||||
condition,
|
||||
qio_channel_yield_enter,
|
||||
&data,
|
||||
NULL);
|
||||
if (condition == G_IO_IN) {
|
||||
assert(!ioc->read_coroutine);
|
||||
ioc->read_coroutine = qemu_coroutine_self();
|
||||
} else if (condition == G_IO_OUT) {
|
||||
assert(!ioc->write_coroutine);
|
||||
ioc->write_coroutine = qemu_coroutine_self();
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
qio_channel_set_aio_fd_handlers(ioc);
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue