@@ -16,6 +16,8 @@ sq: Sq,
1616cq : Cq ,
1717flags : uflags.Setup ,
1818features : uflags.Features ,
19+ /// matches int_flags in liburing
20+ init_flags : uflags.Init ,
1921
2022/// A friendly way to setup an io_uring, with default linux.io_uring_params.
2123/// `entries` must be a power of two between 1 and 32768, although the kernel
@@ -131,6 +133,7 @@ pub fn init_params(entries: u16, p: *Params) !IoUring {
131133 .cq = cq ,
132134 .flags = p .flags ,
133135 .features = p .features ,
136+ .init_flags = .{},
134137 };
135138}
136139
@@ -182,7 +185,7 @@ pub fn submit(self: *IoUring) !u32 {
182185/// Matches the implementation of `io_uring_submit_and_wait()` in liburing.
183186pub fn submit_and_wait (self : * IoUring , wait_nr : u32 ) ! u32 {
184187 const submitted = self .flush_sq ();
185- var flags : uflags.Enter = .{} ;
188+ var flags : uflags.Enter = self . enter_flags () ;
186189 if (self .sq_ring_needs_enter (& flags ) or wait_nr > 0 ) {
187190 if (wait_nr > 0 or self .flags .iopoll ) {
188191 flags .getevents = true ;
@@ -264,7 +267,7 @@ pub fn flush_sq(self: *IoUring) u32 {
264267/// awakened. For the latter case, we set the SQ thread wakeup flag.
265268/// Matches the implementation of `sq_ring_needs_enter()` in liburing.
266269pub fn sq_ring_needs_enter (self : * IoUring , flags : * uflags.Enter ) bool {
267- assert (flags .* .empty ());
270+ assert (flags .* .no_init_flags ());
268271 if (! self .flags .sqpoll ) return true ;
269272 if (@atomicLoad (Sq .Flags , self .sq .flags , .unordered ).need_wakeup ) {
270273 flags .* .sq_wakeup = true ;
@@ -309,7 +312,12 @@ pub fn copy_cqes(self: *IoUring, cqes: []Cqe, wait_nr: u32) !u32 {
309312 const count = self .copy_cqes_ready (cqes );
310313 if (count > 0 ) return count ;
311314 if (self .cq_ring_needs_flush () or wait_nr > 0 ) {
312- _ = try self .enter (0 , wait_nr , .{ .getevents = true });
315+ const flags = blk : {
316+ var flags = self .enter_flags ();
317+ flags .getevents = true ;
318+ break :blk flags ;
319+ };
320+ _ = try self .enter (0 , wait_nr , flags );
313321 return self .copy_cqes_ready (cqes );
314322 }
315323 return 0 ;
@@ -374,6 +382,23 @@ pub fn cq_advance(self: *IoUring, count: u32) void {
374382 }
375383}
376384
385+ /// Enable/disable setting of iowait by the kernel.
386+ pub fn set_io_wait (self : * IoUring , enable_iowait : bool ) ! void {
387+ if (! self .features .no_iowait ) {
388+ return error .SystemOutdated ;
389+ }
390+ if (enable_iowait ) {
391+ self .init_flags .toggle_iowait ();
392+ } else {
393+ self .init_flags .no_iowait = true ;
394+ }
395+ }
396+
397+ /// matches `ring_enter_flags()` in liburing
398+ pub fn enter_flags (self : * IoUring ) uflags.Enter {
399+ return self .init_flags .enter_flags ();
400+ }
401+
377402/// Queues (but does not submit) an SQE to perform a `splice(2)`
378403/// Either `fd_in` or `fd_out` must be a pipe.
379404/// If `fd_in` refers to a pipe, `off_in` is ignored and must be set to
@@ -4190,13 +4215,46 @@ pub const uflags = struct {
41904215 no_iowait : bool = false ,
41914216 _9 : u24 = 0 ,
41924217
4193- pub fn empty (enter_flags : Enter ) bool {
4194- return @as (u32 , @bitCast (enter_flags )) == 0 ;
4218+ /// check that flags that match flags in `Init` aren't set
4219+ pub fn no_init_flags (flags : Enter ) bool {
4220+ if (flags .registered_ring or flags .no_iowait ) return false ;
4221+ return true ;
4222+ }
4223+
4224+ pub fn empty (flags : Enter ) bool {
4225+ return @as (u32 , @bitCast (flags )) == 0 ;
4226+ }
4227+ };
4228+
4229+ /// matches INT_FLAG_* in liburing
4230+ pub const Init = packed struct (u8 ) {
4231+ reg_reg_ring : bool = false ,
4232+ app_mem : bool = false ,
4233+ cq_enter : bool = false ,
4234+ _4 : u1 = 0 ,
4235+ /// matches `registered_ring` flag in `Enter`
4236+ reg_ring : bool = false ,
4237+ _6 : u2 = 0 ,
4238+ /// matches `no_iowait` flag in `Enter`
4239+ no_iowait : bool = false ,
4240+
4241+ const init_flags_mask : Init = .{ .reg_ring = true , .no_iowait = true };
4242+
4243+ pub fn toggle_iowait (self : * Init ) void {
4244+ const old_flags : u8 = @bitCast (self );
4245+ const iowait_flag : u8 = @bitCast (Init { .no_iowait = true });
4246+ self .* = @bitCast (old_flags & ~ iowait_flag );
4247+ }
4248+
4249+ pub fn enter_flags (self : Init ) Enter {
4250+ const flags : u8 = @bitCast (self );
4251+ const enter_flags_mask : u8 = @bitCast (init_flags_mask );
4252+ return @bitCast (@as (u32 , @intCast (flags & enter_flags_mask )));
41954253 }
41964254 };
41974255
41984256 /// io_uring_params.features flags
4199- const Features = packed struct (u32 ) {
4257+ pub const Features = packed struct (u32 ) {
42004258 single_mmap : bool = false ,
42014259 nodrop : bool = false ,
42024260 submit_stable : bool = false ,
@@ -4223,6 +4281,7 @@ pub const uflags = struct {
42234281 }
42244282 };
42254283};
4284+
42264285/// `io_uring_register(2)` opcodes and arguments
42274286/// matches `io_uring_register_op` in liburing
42284287pub const RegisterOp = enum (u8 ) {
0 commit comments