| ... | ... | @@ -1114,6 +1114,23 @@ pub const IO_Uring = struct { |
| 1114 | 1114 | return sqe; |
| 1115 | 1115 | } |
| 1116 | 1116 | |
| 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 | |
| 1117 | 1134 | /// Registers an array of file descriptors. |
| 1118 | 1135 | /// Every time a file descriptor is put in an SQE and submitted to the kernel, the kernel must |
| 1119 | 1136 | /// 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( |
| 1962 | 1979 | __io_uring_set_target_fixed_file(sqe, linux.IORING_FILE_INDEX_ALLOC); |
| 1963 | 1980 | } |
| 1964 | 1981 | |
| 1982 | pub 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 | |
| 1965 | 1995 | test "structs/offsets/entries" { |
| 1966 | 1996 | if (builtin.os.tag != .linux) return error.SkipZigTest; |
| 1967 | 1997 | |
| ... | ... | @@ -4148,6 +4178,32 @@ test "openat_direct/close_direct" { |
| 4148 | 4178 | try ring.unregister_files(); |
| 4149 | 4179 | } |
| 4150 | 4180 | |
| 4181 | test "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 | |
| 4151 | 4207 | /// For use in tests. Returns SkipZigTest is kernel version is less than required. |
| 4152 | 4208 | inline fn skipKernelLessThan(required: std.SemanticVersion) !void { |
| 4153 | 4209 | if (builtin.os.tag != .linux) return error.SkipZigTest; |