aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2024-09-30 19:44:27 +0200
committerGitHub <noreply@github.com>2024-09-30 19:44:27 +0200
commitbcc6d1c1fce27de9d6d34cc21d37f7c3e5b9d40d (patch)
tree8cf27005219e89ad7db9bf1ceb366ef6ead26e17 /src
parent675a5a53960a3535b7061acd2fd9aa96aadd1b1b (diff)
downloadlibuv-bcc6d1c1fce27de9d6d34cc21d37f7c3e5b9d40d.tar.gz
libuv-bcc6d1c1fce27de9d6d34cc21d37f7c3e5b9d40d.zip
linux: use IORING_SETUP_NO_SQARRAY when available (#4553)
Introduced in Linux 6.6, it tells the kernel to omit the sqarray from the ring buffer. Libuv initalizes the array once to an identity mapping and then forgets about it, so not only does it save a little memory (ca. 1 KiB per ring) but it also makes things more efficient kernel-side because it removes a level of indirection.
Diffstat (limited to 'src')
-rw-r--r--src/unix/linux.c19
-rw-r--r--src/uv-common.h1
2 files changed, 15 insertions, 5 deletions
diff --git a/src/unix/linux.c b/src/unix/linux.c
index a5f74e89..2f726294 100644
--- a/src/unix/linux.c
+++ b/src/unix/linux.c
@@ -126,6 +126,7 @@
enum {
UV__IORING_SETUP_SQPOLL = 2u,
+ UV__IORING_SETUP_NO_SQARRAY = 0x10000u,
};
enum {
@@ -509,10 +510,13 @@ static void uv__iou_init(int epollfd,
size_t sqlen;
size_t maxlen;
size_t sqelen;
+ unsigned kernel_version;
+ uint32_t* sqarray;
uint32_t i;
char* sq;
char* sqe;
int ringfd;
+ int no_sqarray;
sq = MAP_FAILED;
sqe = MAP_FAILED;
@@ -520,11 +524,15 @@ static void uv__iou_init(int epollfd,
if (!uv__use_io_uring())
return;
+ kernel_version = uv__kernel_version();
+ no_sqarray =
+ UV__IORING_SETUP_NO_SQARRAY * (kernel_version >= /* 6.6 */0x060600);
+
/* SQPOLL required CAP_SYS_NICE until linux v5.12 relaxed that requirement.
* Mostly academic because we check for a v5.13 kernel afterwards anyway.
*/
memset(&params, 0, sizeof(params));
- params.flags = flags;
+ params.flags = flags | no_sqarray;
if (flags & UV__IORING_SETUP_SQPOLL)
params.sq_thread_idle = 10; /* milliseconds */
@@ -586,7 +594,6 @@ static void uv__iou_init(int epollfd,
iou->sqhead = (uint32_t*) (sq + params.sq_off.head);
iou->sqtail = (uint32_t*) (sq + params.sq_off.tail);
iou->sqmask = *(uint32_t*) (sq + params.sq_off.ring_mask);
- iou->sqarray = (uint32_t*) (sq + params.sq_off.array);
iou->sqflags = (uint32_t*) (sq + params.sq_off.flags);
iou->cqhead = (uint32_t*) (sq + params.cq_off.head);
iou->cqtail = (uint32_t*) (sq + params.cq_off.tail);
@@ -602,11 +609,15 @@ static void uv__iou_init(int epollfd,
iou->in_flight = 0;
iou->flags = 0;
- if (uv__kernel_version() >= /* 5.15.0 */ 0x050F00)
+ if (kernel_version >= /* 5.15.0 */ 0x050F00)
iou->flags |= UV__MKDIRAT_SYMLINKAT_LINKAT;
+ if (no_sqarray)
+ return;
+
+ sqarray = (uint32_t*) (sq + params.sq_off.array);
for (i = 0; i <= iou->sqmask; i++)
- iou->sqarray[i] = i; /* Slot -> sqe identity mapping. */
+ sqarray[i] = i; /* Slot -> sqe identity mapping. */
return;
diff --git a/src/uv-common.h b/src/uv-common.h
index 339e5f37..60bd0087 100644
--- a/src/uv-common.h
+++ b/src/uv-common.h
@@ -400,7 +400,6 @@ void uv__metrics_set_provider_entry_time(uv_loop_t* loop);
struct uv__iou {
uint32_t* sqhead;
uint32_t* sqtail;
- uint32_t* sqarray;
uint32_t sqmask;
uint32_t* sqflags;
uint32_t* cqhead;