authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-12 12:20:12-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-02-12 12:20:12-08:00
logfad5e7a997344eddc45511df581472acaf0e880e
treea41a45dd60ee56c574bdcd92a88c71c05b2cf244
parent0c1b9992fd1d3c20595304c9e9b87c6053c24f45
parentd2789908ed02c286ef968d2d90cc38fd24ca0e10
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18898 from psnszsn/iouring_waitid

io_uring: add waitid operation

2 files changed, 63 insertions(+), 0 deletions(-)

lib/std/os/linux.zig+7
......@@ -4300,6 +4300,13 @@ pub const IORING_OP = enum(u8) {
43004300 URING_CMD,
43014301 SEND_ZC,
43024302 SENDMSG_ZC,
4303 READ_MULTISHOT,
4304 WAITID,
4305 FUTEX_WAIT,
4306 FUTEX_WAKE,
4307 FUTEX_WAITV,
4308 FIXED_FD_INSTALL,
4309 FTRUNCATE,
43034310
43044311 _,
43054312};
lib/std/os/linux/io_uring.zig+56
......@@ -1114,6 +1114,23 @@ pub const IO_Uring = struct {
11141114 return sqe;
11151115 }
11161116
1117 /// Queues (but does not submit) an SQE to perform a `waitid(2)`.
1118 /// Returns a pointer to the SQE.
1119 pub fn waitid(
1120 self: *IO_Uring,
1121 user_data: u64,
1122 id_type: linux.P,
1123 id: i32,
1124 infop: *linux.siginfo_t,
1125 options: u32,
1126 flags: u32,
1127 ) !*linux.io_uring_sqe {
1128 const sqe = try self.get_sqe();
1129 io_uring_prep_waitid(sqe, id_type, id, infop, options, flags);
1130 sqe.user_data = user_data;
1131 return sqe;
1132 }
1133
11171134 /// Registers an array of file descriptors.
11181135 /// Every time a file descriptor is put in an SQE and submitted to the kernel, the kernel must
11191136 /// retrieve a reference to the file, and once I/O has completed the file reference must be
......@@ -1962,6 +1979,19 @@ pub fn io_uring_prep_socket_direct_alloc(
19621979 __io_uring_set_target_fixed_file(sqe, linux.IORING_FILE_INDEX_ALLOC);
19631980}
19641981
1982pub fn io_uring_prep_waitid(
1983 sqe: *linux.io_uring_sqe,
1984 id_type: linux.P,
1985 id: i32,
1986 infop: *linux.siginfo_t,
1987 options: u32,
1988 flags: u32,
1989) void {
1990 io_uring_prep_rw(.WAITID, sqe, id, 0, @intFromEnum(id_type), @intFromPtr(infop));
1991 sqe.rw_flags = flags;
1992 sqe.splice_fd_in = @bitCast(options);
1993}
1994
19651995test "structs/offsets/entries" {
19661996 if (builtin.os.tag != .linux) return error.SkipZigTest;
19671997
......@@ -4148,6 +4178,32 @@ test "openat_direct/close_direct" {
41484178 try ring.unregister_files();
41494179}
41504180
4181test "waitid" {
4182 try skipKernelLessThan(.{ .major = 6, .minor = 7, .patch = 0 });
4183
4184 var ring = IO_Uring.init(16, 0) catch |err| switch (err) {
4185 error.SystemOutdated => return error.SkipZigTest,
4186 error.PermissionDenied => return error.SkipZigTest,
4187 else => return err,
4188 };
4189 defer ring.deinit();
4190
4191 const pid = try os.fork();
4192 if (pid == 0) {
4193 os.exit(7);
4194 }
4195
4196 var siginfo: os.siginfo_t = undefined;
4197 _ = try ring.waitid(0, .PID, pid, &siginfo, os.W.EXITED, 0);
4198
4199 try testing.expectEqual(1, try ring.submit());
4200
4201 const cqe_waitid = try ring.copy_cqe();
4202 try testing.expectEqual(0, cqe_waitid.res);
4203 try testing.expectEqual(pid, siginfo.fields.common.first.piduid.pid);
4204 try testing.expectEqual(7, siginfo.fields.common.second.sigchld.status);
4205}
4206
41514207/// For use in tests. Returns SkipZigTest is kernel version is less than required.
41524208inline fn skipKernelLessThan(required: std.SemanticVersion) !void {
41534209 if (builtin.os.tag != .linux) return error.SkipZigTest;