From 4be3df627a5314726c44f139666044ff83b4986b Mon Sep 17 00:00:00 2001
From: Florian Fischer <florian.fischer@muhq.space>
Date: Wed, 15 Jun 2022 22:04:29 +0200
Subject: [PATCH] [io] set new io_uring taskrun flags on linux 5.19

Linux 5.19 introduces new flags to control how the kernel notifies tasks
running in user space about task_work to run generating completions.
Prior to 5.19 the kernel would interrupt the running tasks the new introduced
flags prevent the forceful interruption and set a flag in io_uring.
The flag signals io_uring_peek to enter the kernel to execute the available
task_work.

The man page claims that setting the flags is beneficial for most applications.
Only downside I see is that io-stealing is less effective since CQEs are
not immediately created.
---
 emper/io/IoContext.cpp | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/emper/io/IoContext.cpp b/emper/io/IoContext.cpp
index d92c9919..8f0acc98 100644
--- a/emper/io/IoContext.cpp
+++ b/emper/io/IoContext.cpp
@@ -590,6 +590,28 @@ IoContext::IoContext(Runtime &runtime, size_t uring_entries, unsigned unboundedI
 		}
 	}
 
+	/*
+	 * Setup io_urings with the IORING_SETUP_COOP_TASKRUN and IORING_SETUP_TASKRUN_FLAG
+	 * flags instroduced with Linux 5.19.
+	 * https://github.com/axboe/liburing/blob/8f4b4af6dba4356366f4441797c51a0f25a62b64/man/io_uring_setup.2#L200
+	 *
+	 * IORING_SETUP_COOP_TASKRUN prevents the kernel from interrupting the task
+	 * running in user space when new completios could be processed and CQEs posted.
+	 *
+	 * IORING_SETUP_TASKRUN_FLAG is a companion flag and leads to the kernel notifying
+	 * liburing to enter the kernel even when using io_uring_peek_cqe.
+	 * https://github.com/axboe/liburing/blob/a9e941d4986261332365292ffabf7f71383a9eef/src/queue.c#L39
+	 * This means we possibly execute scheduled task_work in each dispatch loop
+	 * iterationor when otherwise entering the kernel.
+	 *
+	 * On the other hand not forcefully interupting the task where completions could be
+	 * generated means io-stealing is less efficient since the time a cqe resides in
+	 * a CQ is reduced.
+	 */
+	if (EMPER_LINUX_GE("5.19")) {
+		params.flags |= IORING_SETUP_COOP_TASKRUN | IORING_SETUP_TASKRUN_FLAG;
+	}
+
 	auto ret = io_uring_queue_init_params(uring_entries, &ring, &params);
 	if (ret < 0) {
 		DIE_MSG_ERRNO("io_uring_queue_init failed");
-- 
GitLab