@@ -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,24 @@ pub fn cq_advance(self: *IoUring, count: u32) void {
374382 }
375383}
376384
385+ /// Enable/disable setting of iowait by the kernel.
386+ /// matches `io_uring_set_iowait` in liburing
387+ pub fn set_iowait (self : * IoUring , enable_iowait : bool ) ! void {
388+ if (! self .features .no_iowait ) {
389+ return error .SystemOutdated ;
390+ }
391+ if (enable_iowait ) {
392+ self .init_flags .toggle_iowait ();
393+ } else {
394+ self .init_flags .no_iowait = true ;
395+ }
396+ }
397+
398+ /// matches `ring_enter_flags()` in liburing
399+ pub fn enter_flags (self : * IoUring ) uflags.Enter {
400+ return self .init_flags .enter_flags ();
401+ }
402+
377403/// Queues (but does not submit) an SQE to perform a `splice(2)`
378404/// Either `fd_in` or `fd_out` must be a pipe.
379405/// If `fd_in` refers to a pipe, `off_in` is ignored and must be set to
@@ -4190,13 +4216,46 @@ pub const uflags = struct {
41904216 no_iowait : bool = false ,
41914217 _9 : u24 = 0 ,
41924218
4193- pub fn empty (enter_flags : Enter ) bool {
4194- return @as (u32 , @bitCast (enter_flags )) == 0 ;
4219+ /// check that flags that match flags in `Init` aren't set
4220+ pub fn no_init_flags (flags : Enter ) bool {
4221+ if (flags .registered_ring or flags .no_iowait ) return false ;
4222+ return true ;
4223+ }
4224+
4225+ pub fn empty (flags : Enter ) bool {
4226+ return @as (u32 , @bitCast (flags )) == 0 ;
4227+ }
4228+ };
4229+
4230+ /// matches INT_FLAG_* in liburing
4231+ pub const Init = packed struct (u8 ) {
4232+ reg_reg_ring : bool = false ,
4233+ app_mem : bool = false ,
4234+ cq_enter : bool = false ,
4235+ _4 : u1 = 0 ,
4236+ /// matches `registered_ring` flag in `Enter`
4237+ reg_ring : bool = false ,
4238+ _6 : u2 = 0 ,
4239+ /// matches `no_iowait` flag in `Enter`
4240+ no_iowait : bool = false ,
4241+
4242+ const init_flags_mask : Init = .{ .reg_ring = true , .no_iowait = true };
4243+
4244+ pub fn toggle_iowait (self : * Init ) void {
4245+ const old_flags : u8 = @bitCast (self );
4246+ const iowait_flag : u8 = @bitCast (Init { .no_iowait = true });
4247+ self .* = @bitCast (old_flags & ~ iowait_flag );
4248+ }
4249+
4250+ pub fn enter_flags (self : Init ) Enter {
4251+ const flags : u8 = @bitCast (self );
4252+ const enter_flags_mask : u8 = @bitCast (init_flags_mask );
4253+ return @bitCast (@as (u32 , @intCast (flags & enter_flags_mask )));
41954254 }
41964255 };
41974256
41984257 /// io_uring_params.features flags
4199- const Features = packed struct (u32 ) {
4258+ pub const Features = packed struct (u32 ) {
42004259 single_mmap : bool = false ,
42014260 nodrop : bool = false ,
42024261 submit_stable : bool = false ,
@@ -4223,6 +4282,7 @@ pub const uflags = struct {
42234282 }
42244283 };
42254284};
4285+
42264286/// `io_uring_register(2)` opcodes and arguments
42274287/// matches `io_uring_register_op` in liburing
42284288pub const RegisterOp = enum (u8 ) {
0 commit comments