Skip to content

Commit c43fdb4

Browse files
committed
Implement set_io_wait functionality
closes #25566 closes #25604 and IoUring enter_flags() helper function add typed Init flags which match int_flags in liburing Signed-off-by: Bernard Assan <mega.alpha100@gmail.com>
1 parent dff9f36 commit c43fdb4

File tree

1 file changed

+65
-6
lines changed

1 file changed

+65
-6
lines changed

lib/std/os/linux/IoUring.zig

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ sq: Sq,
1616
cq: Cq,
1717
flags: uflags.Setup,
1818
features: 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.
183186
pub 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.
266269
pub 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
42284287
pub const RegisterOp = enum(u8) {

0 commit comments

Comments
 (0)