The IORING_SETUP_COOP_TASKRUN flag reduces interprocessor interrupts
when an io_uring event occurs on a different CPU. The idea is that the
QEMU thread will wait for a CQE anyway, so there is no need to interrupt
the CPU that it is on.
The IORING_SETUP_TASKRUN_FLAG ensures that QEMU's io_uring CQ ring
polling still works with COOP_TASKRUN. The kernel will set a flag in the
SQ ring (this is not a typo, the flag is located in the SQ ring even
though it pertains to the CQ ring) that can be polled from userspace.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
util/fdmon-io_uring.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/util/fdmon-io_uring.c b/util/fdmon-io_uring.c
index 4798439097..649dc18907 100644
--- a/util/fdmon-io_uring.c
+++ b/util/fdmon-io_uring.c
@@ -428,13 +428,16 @@ static int fdmon_io_uring_wait(AioContext *ctx, AioHandlerList *ready_list,
static bool fdmon_io_uring_need_wait(AioContext *ctx)
{
+ struct io_uring *ring = &ctx->fdmon_io_uring;
+
/* Have io_uring events completed? */
- if (io_uring_cq_ready(&ctx->fdmon_io_uring)) {
+ if (io_uring_cq_ready(ring) ||
+ IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_TASKRUN) {
return true;
}
/* Are there pending sqes to submit? */
- if (io_uring_sq_ready(&ctx->fdmon_io_uring)) {
+ if (io_uring_sq_ready(ring)) {
return true;
}
@@ -465,7 +468,7 @@ void fdmon_io_uring_setup(AioContext *ctx, Error **errp)
{
int ret;
/* TODO only enable these flags if they are available in the host's kernel headers */
- unsigned flags = 0;
+ unsigned flags = IORING_SETUP_COOP_TASKRUN | IORING_SETUP_TASKRUN_FLAG;
ctx->io_uring_fd_tag = NULL;
--
2.50.1