]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
io: Make qio_channel_yield() interruptible
authorKevin Wolf <kwolf@redhat.com>
Mon, 18 Feb 2019 13:09:32 +0000 (14:09 +0100)
committerKevin Wolf <kwolf@redhat.com>
Mon, 25 Feb 2019 14:03:19 +0000 (15:03 +0100)
Similar to how qemu_co_sleep_ns() allows preemption from an external
coroutine entry, allow reentering qio_channel_yield() early.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
include/io/channel.h
io/channel.c

index da2f1382002a59bcb429de5ee988388bb62f828e..59460cb1ec7a82d88f00991728cb0579793a71d1 100644 (file)
@@ -739,10 +739,13 @@ void qio_channel_detach_aio_context(QIOChannel *ioc);
  * addition, no two coroutine can be waiting on the same condition
  * and channel at the same time.
  *
- * This must only be called from coroutine context
+ * This must only be called from coroutine context. It is safe to
+ * reenter the coroutine externally while it is waiting; in this
+ * case the function will return even if @condition is not yet
+ * available.
  */
-void qio_channel_yield(QIOChannel *ioc,
-                       GIOCondition condition);
+void coroutine_fn qio_channel_yield(QIOChannel *ioc,
+                                    GIOCondition condition);
 
 /**
  * qio_channel_wait:
index 8dd0684f5d50cfa29fc65a653f72ea7086536fdc..303376e08d18395d3aa720287f4f5ce674f78675 100644 (file)
@@ -469,6 +469,16 @@ void coroutine_fn qio_channel_yield(QIOChannel *ioc,
     }
     qio_channel_set_aio_fd_handlers(ioc);
     qemu_coroutine_yield();
+
+    /* Allow interrupting the operation by reentering the coroutine other than
+     * through the aio_fd_handlers. */
+    if (condition == G_IO_IN && ioc->read_coroutine) {
+        ioc->read_coroutine = NULL;
+        qio_channel_set_aio_fd_handlers(ioc);
+    } else if (condition == G_IO_OUT && ioc->write_coroutine) {
+        ioc->write_coroutine = NULL;
+        qio_channel_set_aio_fd_handlers(ioc);
+    }
 }