diff options
| author | Vincent Rischmann <vincent@rischmann.fr> | 2022-05-16 19:02:22 +0200 |
|---|---|---|
| committer | Vincent Rischmann <vincent@rischmann.fr> | 2022-05-25 13:53:09 +0200 |
| commit | 52dd468cc3e279e7d1a764c2c3f6fde13a404a14 (patch) | |
| tree | d929de65162c14a889d875f6457bd821d46a390e | |
| parent | 7b3e5ce0b3d3e6c8e24dd147d23eec3fe5088d74 (diff) | |
| download | zig-52dd468cc3e279e7d1a764c2c3f6fde13a404a14.tar.gz zig-52dd468cc3e279e7d1a764c2c3f6fde13a404a14.zip | |
io_uring: change read() to use a ReadBuffer instead
Reads can be done in two ways with io_uring:
* using a simple buffer
* using a automatic buffer selection which requires the user to have
provided a number of buffers before
ReadBuffer let's the caller choose where the data should be read.
| -rw-r--r-- | lib/std/os/linux/io_uring.zig | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/lib/std/os/linux/io_uring.zig b/lib/std/os/linux/io_uring.zig index 9646a923d7..74e6416102 100644 --- a/lib/std/os/linux/io_uring.zig +++ b/lib/std/os/linux/io_uring.zig @@ -358,17 +358,38 @@ pub const IO_Uring = struct { return sqe; } + /// Used to select how the read should be handled. + pub const ReadBuffer = union(enum) { + /// io_uring will read directly into this buffer + buffer: []u8, + + /// io_uring will select a buffer that has previously been provided with `provide_buffers`. + /// The buffer group reference by `group_id` must contain at least one buffer for the read to work. + /// `len` controls the number of bytes to read into the selected buffer. + buffer_selection: struct { + group_id: u16, + len: usize, + }, + }; + /// Queues (but does not submit) an SQE to perform a `read(2)`. /// Returns a pointer to the SQE. pub fn read( self: *IO_Uring, user_data: u64, fd: os.fd_t, - buffer: []u8, + buffer: ReadBuffer, offset: u64, ) !*io_uring_sqe { const sqe = try self.get_sqe(); - io_uring_prep_read(sqe, fd, buffer, offset); + switch (buffer) { + .buffer => |slice| io_uring_prep_read(sqe, fd, slice, offset), + .buffer_selection => |selection| { + io_uring_prep_rw(.READ, sqe, fd, 0, selection.len, offset); + sqe.flags |= linux.IOSQE_BUFFER_SELECT; + sqe.buf_index = selection.group_id; + }, + } sqe.user_data = user_data; return sqe; } @@ -1778,7 +1799,7 @@ test "write/read" { try testing.expectEqual(linux.IORING_OP.WRITE, sqe_write.opcode); try testing.expectEqual(@as(u64, 10), sqe_write.off); sqe_write.flags |= linux.IOSQE_IO_LINK; - const sqe_read = try ring.read(0x22222222, fd, buffer_read[0..], 10); + const sqe_read = try ring.read(0x22222222, fd, .{ .buffer = buffer_read[0..] }, 10); try testing.expectEqual(linux.IORING_OP.READ, sqe_read.opcode); try testing.expectEqual(@as(u64, 10), sqe_read.off); try testing.expectEqual(@as(u32, 2), try ring.submit()); @@ -2520,7 +2541,7 @@ test "register_files_update" { var buffer = [_]u8{42} ** 128; { - const sqe = try ring.read(0xcccccccc, fd_index, &buffer, 0); + const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0); try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); sqe.flags |= linux.IOSQE_FIXED_FILE; @@ -2541,7 +2562,7 @@ test "register_files_update" { { // Next read should still work since fd_index in the registered file descriptors hasn't been updated yet. - const sqe = try ring.read(0xcccccccc, fd_index, &buffer, 0); + const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0); try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); sqe.flags |= linux.IOSQE_FIXED_FILE; @@ -2558,7 +2579,7 @@ test "register_files_update" { { // Now this should fail since both fds are sparse (-1) - const sqe = try ring.read(0xcccccccc, fd_index, &buffer, 0); + const sqe = try ring.read(0xcccccccc, fd_index, .{ .buffer = &buffer }, 0); try testing.expectEqual(linux.IORING_OP.READ, sqe.opcode); sqe.flags |= linux.IOSQE_FIXED_FILE; |
