aboutsummaryrefslogtreecommitdiff
path: root/io
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2017-09-05 14:11:12 -0500
committerEric Blake <eblake@redhat.com>2017-09-06 10:10:58 -0500
commit9ffb8270205a274a18ee4f8a735e2fccaf957246 (patch)
tree6ec3d166399cf431b720d44cf53489cce3187047 /io
parent3f5c4076f118072ac7403ca092d63a1766cd5e04 (diff)
downloadqemu-9ffb8270205a274a18ee4f8a735e2fccaf957246.zip
qemu-9ffb8270205a274a18ee4f8a735e2fccaf957246.tar.gz
qemu-9ffb8270205a274a18ee4f8a735e2fccaf957246.tar.bz2
io: Yield rather than wait when already in coroutine
The new qio_channel_{read,write}{,v}_all functions are documented as yielding until data is available. When used on a blocking channel, this yield is done via qio_channel_wait() which spawns a nested event loop under the hood (so it is that secondary loop which yields as needed); but if we are already in a coroutine (at which point QIO_CHANNEL_ERR_BLOCK is only possible if we are a non-blocking channel), we want to yield the current coroutine instead of spawning a nested event loop. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <20170905191114.5959-2-eblake@redhat.com> Acked-by: Daniel P. Berrange <berrange@redhat.com> [commit message updated] Signed-off-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'io')
-rw-r--r--io/channel.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/io/channel.c b/io/channel.c
index 5e8c2f0..9e62794 100644
--- a/io/channel.c
+++ b/io/channel.c
@@ -105,7 +105,11 @@ int qio_channel_readv_all(QIOChannel *ioc,
ssize_t len;
len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp);
if (len == QIO_CHANNEL_ERR_BLOCK) {
- qio_channel_wait(ioc, G_IO_IN);
+ if (qemu_in_coroutine()) {
+ qio_channel_yield(ioc, G_IO_IN);
+ } else {
+ qio_channel_wait(ioc, G_IO_IN);
+ }
continue;
} else if (len < 0) {
goto cleanup;
@@ -143,7 +147,11 @@ int qio_channel_writev_all(QIOChannel *ioc,
ssize_t len;
len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp);
if (len == QIO_CHANNEL_ERR_BLOCK) {
- qio_channel_wait(ioc, G_IO_OUT);
+ if (qemu_in_coroutine()) {
+ qio_channel_yield(ioc, G_IO_OUT);
+ } else {
+ qio_channel_wait(ioc, G_IO_OUT);
+ }
continue;
}
if (len < 0) {