| ... | @@ -95,6 +95,7 @@ pub const IO_Uring = struct { | ... | @@ -95,6 +95,7 @@ pub const IO_Uring = struct { |
| 95 | assert(p.*.resv[0] == 0); | 95 | assert(p.*.resv[0] == 0); |
| 96 | assert(p.*.resv[1] == 0); | 96 | assert(p.*.resv[1] == 0); |
| 97 | assert(p.*.resv[2] == 0); | 97 | assert(p.*.resv[2] == 0); |
| | 98 | if (!supported) return error.IO_UringKernelNotSupported; |
| 98 | | 99 | |
| 99 | const res = linux.io_uring_setup(entries, p); | 100 | const res = linux.io_uring_setup(entries, p); |
| 100 | try check_errno(res); | 101 | try check_errno(res); |
| ... | @@ -346,6 +347,7 @@ pub const IO_Uring = struct { | ... | @@ -346,6 +347,7 @@ pub const IO_Uring = struct { |
| 346 | addrlen: *os.socklen_t, | 347 | addrlen: *os.socklen_t, |
| 347 | accept_flags: u32 | 348 | accept_flags: u32 |
| 348 | ) !*io_uring_sqe { | 349 | ) !*io_uring_sqe { |
| | 350 | if (!can_accept) return error.IO_UringKernelCannotAccept; |
| 349 | // "sqe->fd is the file descriptor, sqe->addr holds a pointer to struct sockaddr, | 351 | // "sqe->fd is the file descriptor, sqe->addr holds a pointer to struct sockaddr, |
| 350 | // sqe->addr2 holds a pointer to socklen_t, and finally sqe->accept_flags holds the flags | 352 | // sqe->addr2 holds a pointer to socklen_t, and finally sqe->accept_flags holds the flags |
| 351 | // for accept(4)." - https://lwn.net/ml/linux-block/20191025173037.13486-1-axboe@kernel.dk/ | 353 | // for accept(4)." - https://lwn.net/ml/linux-block/20191025173037.13486-1-axboe@kernel.dk/ |
| ... | @@ -403,6 +405,7 @@ pub const IO_Uring = struct { | ... | @@ -403,6 +405,7 @@ pub const IO_Uring = struct { |
| 403 | buffer: []u8, | 405 | buffer: []u8, |
| 404 | offset: u64 | 406 | offset: u64 |
| 405 | ) !*io_uring_sqe { | 407 | ) !*io_uring_sqe { |
| | 408 | if (!can_read) return error.IO_UringKernelCannotRead; |
| 406 | const sqe = try self.get_sqe(); | 409 | const sqe = try self.get_sqe(); |
| 407 | sqe.* = .{ | 410 | sqe.* = .{ |
| 408 | .opcode = .READ, | 411 | .opcode = .READ, |
| ... | @@ -424,6 +427,7 @@ pub const IO_Uring = struct { | ... | @@ -424,6 +427,7 @@ pub const IO_Uring = struct { |
| 424 | buffer: []const u8, | 427 | buffer: []const u8, |
| 425 | offset: u64 | 428 | offset: u64 |
| 426 | ) !*io_uring_sqe { | 429 | ) !*io_uring_sqe { |
| | 430 | if (!can_write) return error.IO_UringKernelCannotWrite; |
| 427 | const sqe = try self.get_sqe(); | 431 | const sqe = try self.get_sqe(); |
| 428 | sqe.* = .{ | 432 | sqe.* = .{ |
| 429 | .opcode = .WRITE, | 433 | .opcode = .WRITE, |
| ... | @@ -662,8 +666,15 @@ inline fn check_errno(res: usize) !void { | ... | @@ -662,8 +666,15 @@ inline fn check_errno(res: usize) !void { |
| 662 | if (errno != 0) return os.unexpectedErrno(errno); | 666 | if (errno != 0) return os.unexpectedErrno(errno); |
| 663 | } | 667 | } |
| 664 | | 668 | |
| | 669 | const minimum = std.Target.current.os.isAtLeast; |
| | 670 | pub const can_single_mmap = comptime minimum(.linux, .{ .major = 5, .minor = 4 }) == true; |
| | 671 | pub const can_accept = comptime minimum(.linux, .{ .major = 5, .minor = 5 }) == true; |
| | 672 | pub const can_read = comptime minimum(.linux, .{ .major = 5, .minor = 6 }) == true; |
| | 673 | pub const can_write = comptime minimum(.linux, .{ .major = 5, .minor = 6 }) == true; |
| | 674 | pub const supported = can_single_mmap; |
| | 675 | |
| 665 | test "queue_nop" { | 676 | test "queue_nop" { |
| 666 | if (builtin.os.tag != .linux) return error.SkipZigTest; | 677 | if (!supported) return error.SkipZigTest; |
| 667 | | 678 | |
| 668 | var ring = try IO_Uring.init(1, 0); | 679 | var ring = try IO_Uring.init(1, 0); |
| 669 | defer { | 680 | defer { |
| ... | @@ -726,7 +737,7 @@ test "queue_nop" { | ... | @@ -726,7 +737,7 @@ test "queue_nop" { |
| 726 | } | 737 | } |
| 727 | | 738 | |
| 728 | test "queue_readv" { | 739 | test "queue_readv" { |
| 729 | if (builtin.os.tag != .linux) return error.SkipZigTest; | 740 | if (!supported) return error.SkipZigTest; |
| 730 | | 741 | |
| 731 | var ring = try IO_Uring.init(1, 0); | 742 | var ring = try IO_Uring.init(1, 0); |
| 732 | defer ring.deinit(); | 743 | defer ring.deinit(); |
| ... | @@ -758,7 +769,7 @@ test "queue_readv" { | ... | @@ -758,7 +769,7 @@ test "queue_readv" { |
| 758 | } | 769 | } |
| 759 | | 770 | |
| 760 | test "queue_writev/queue_fsync" { | 771 | test "queue_writev/queue_fsync" { |
| 761 | if (builtin.os.tag != .linux) return error.SkipZigTest; | 772 | if (!supported) return error.SkipZigTest; |
| 762 | | 773 | |
| 763 | var ring = try IO_Uring.init(2, 0); | 774 | var ring = try IO_Uring.init(2, 0); |
| 764 | defer ring.deinit(); | 775 | defer ring.deinit(); |
| ... | @@ -799,8 +810,7 @@ test "queue_writev/queue_fsync" { | ... | @@ -799,8 +810,7 @@ test "queue_writev/queue_fsync" { |
| 799 | } | 810 | } |
| 800 | | 811 | |
| 801 | test "queue_write/queue_read" { | 812 | test "queue_write/queue_read" { |
| 802 | if (builtin.os.tag != .linux) return error.SkipZigTest; | 813 | if (!can_read or !can_write) return error.SkipZigTest; |
| 803 | // This test may require newer kernel versions. | | |
| 804 | | 814 | |
| 805 | var ring = try IO_Uring.init(2, 0); | 815 | var ring = try IO_Uring.init(2, 0); |
| 806 | defer ring.deinit(); | 816 | defer ring.deinit(); |