From c369817ab8bd529432047107967d88fd5674eae0 Mon Sep 17 00:00:00 2001 From: Vsevolod Strukchinsky Date: Sun, 12 Jul 2026 16:05:15 +0500 Subject: [PATCH] loop: expose io_uring setup flags through Options Resolves the io_uring backend's init TODO: callers that own the ring's threading discipline can request e.g. IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_COOP_TASKRUN | IORING_SETUP_DEFER_TASKRUN. Default 0 keeps today's behavior. The Options doc records the DEFER_TASKRUN contract: completion task-work only flushes on GETEVENTS entries, so such a loop must run in a waiting mode. --- src/backend/io_uring.zig | 5 +---- src/loop.zig | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/backend/io_uring.zig b/src/backend/io_uring.zig index 6891bc3a..b38c84ec 100644 --- a/src/backend/io_uring.zig +++ b/src/backend/io_uring.zig @@ -66,10 +66,7 @@ pub const Loop = struct { return error.TooManyEntries; var result: Loop = .{ - // TODO(mitchellh): add an init_advanced function or something - // for people using the io_uring API directly to be able to set - // the flags for this. - .ring = try linux.IoUring.init(entries, 0), + .ring = try linux.IoUring.init(entries, options.io_uring_flags), }; result.update_now(); diff --git a/src/loop.zig b/src/loop.zig index 5f809982..780ea8f1 100644 --- a/src/loop.zig +++ b/src/loop.zig @@ -15,6 +15,22 @@ pub const Options = struct { /// Backends: io_uring entries: u32 = 256, + /// Additional flags OR'd into io_uring_setup(2), e.g. + /// IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN for a + /// loop whose ring is only ever touched from one thread. + /// + /// The caller owns kernel-version compatibility: on kernels that + /// reject a flag, Loop.init fails with error.ArgumentsInvalid rather + /// than silently degrading — retry without flags to degrade. + /// + /// Note for IORING_SETUP_DEFER_TASKRUN: completion task-work is only + /// flushed by kernel entries with IORING_ENTER_GETEVENTS, so the loop + /// must be run in a mode that waits (`until_done`/`once`); a pure + /// `no_wait` spin may never observe its completions. + /// + /// Backends: io_uring + io_uring_flags: u32 = 0, + /// A thread pool to use for blocking operations. If the backend doesn't /// need to perform any blocking operations then no threads will ever /// be spawned. If the backend does need to perform blocking operations