| author | |
| committer | |
| log | 9c2ed8d103ee3c8cf6e8a07ad7c9653137a89784 |
| tree | 63cffb4db7fa29da822d00cb4a7802cb0c34922c |
| parent | 6c160b8856921e5e1d0a437794b3b7ee7e1a4d0b |
| parent | 4565f50efe69cb394aed7d26341b917d2089b9d5 |
| signature |
std: linux uring kernel interfaces4 files changed, 172 insertions(+), 2 deletions(-)
std/math.zig+5| ... | @@ -686,6 +686,11 @@ pub fn alignCast(comptime alignment: u29, ptr: var) AlignCastError!@typeOf(@alig | ... | @@ -686,6 +686,11 @@ pub fn alignCast(comptime alignment: u29, ptr: var) AlignCastError!@typeOf(@alig |
| 686 | return @alignCast(alignment, ptr); | 686 | return @alignCast(alignment, ptr); |
| 687 | } | 687 | } |
| 688 | 688 | ||
| 689 | pub fn isPowerOfTwo(v: var) bool { | ||
| 690 | assert(v != 0); | ||
| 691 | return (v & (v - 1)) == 0; | ||
| 692 | } | ||
| 693 | |||
| 689 | pub fn floorPowerOfTwo(comptime T: type, value: T) T { | 694 | pub fn floorPowerOfTwo(comptime T: type, value: T) T { |
| 690 | var x = value; | 695 | var x = value; |
| 691 | 696 |
std/os/bits/linux.zig+143| ... | @@ -119,6 +119,23 @@ pub const O_RDONLY = 0o0; | ... | @@ -119,6 +119,23 @@ pub const O_RDONLY = 0o0; |
| 119 | pub const O_WRONLY = 0o1; | 119 | pub const O_WRONLY = 0o1; |
| 120 | pub const O_RDWR = 0o2; | 120 | pub const O_RDWR = 0o2; |
| 121 | 121 | ||
| 122 | pub const kernel_rwf = u32; | ||
| 123 | |||
| 124 | /// high priority request, poll if possible | ||
| 125 | pub const RWF_HIPRI = kernel_rwf(0x00000001); | ||
| 126 | |||
| 127 | /// per-IO O_DSYNC | ||
| 128 | pub const RWF_DSYNC = kernel_rwf(0x00000002); | ||
| 129 | |||
| 130 | /// per-IO O_SYNC | ||
| 131 | pub const RWF_SYNC = kernel_rwf(0x00000004); | ||
| 132 | |||
| 133 | /// per-IO, return -EAGAIN if operation would block | ||
| 134 | pub const RWF_NOWAIT = kernel_rwf(0x00000008); | ||
| 135 | |||
| 136 | /// per-IO O_APPEND | ||
| 137 | pub const RWF_APPEND = kernel_rwf(0x00000010); | ||
| 138 | |||
| 122 | pub const SEEK_SET = 0; | 139 | pub const SEEK_SET = 0; |
| 123 | pub const SEEK_CUR = 1; | 140 | pub const SEEK_CUR = 1; |
| 124 | pub const SEEK_END = 2; | 141 | pub const SEEK_END = 2; |
| ... | @@ -950,3 +967,129 @@ pub const stack_t = extern struct { | ... | @@ -950,3 +967,129 @@ pub const stack_t = extern struct { |
| 950 | ss_flags: i32, | 967 | ss_flags: i32, |
| 951 | ss_size: isize, | 968 | ss_size: isize, |
| 952 | }; | 969 | }; |
| 970 | |||
| 971 | pub const io_uring_params = extern struct { | ||
| 972 | sq_entries: u32, | ||
| 973 | cq_entries: u32, | ||
| 974 | flags: u32, | ||
| 975 | sq_thread_cpu: u32, | ||
| 976 | sq_thread_idle: u32, | ||
| 977 | resv: [5]u32, | ||
| 978 | sq_off: io_sqring_offsets, | ||
| 979 | cq_off: io_cqring_offsets, | ||
| 980 | }; | ||
| 981 | |||
| 982 | // io_uring_params.flags | ||
| 983 | |||
| 984 | /// io_context is polled | ||
| 985 | pub const IORING_SETUP_IOPOLL = (1 << 0); | ||
| 986 | |||
| 987 | /// SQ poll thread | ||
| 988 | pub const IORING_SETUP_SQPOLL = (1 << 1); | ||
| 989 | |||
| 990 | /// sq_thread_cpu is valid | ||
| 991 | pub const IORING_SETUP_SQ_AFF = (1 << 2); | ||
| 992 | |||
| 993 | pub const io_sqring_offsets = extern struct { | ||
| 994 | /// offset of ring head | ||
| 995 | head: u32, | ||
| 996 | |||
| 997 | /// offset of ring tail | ||
| 998 | tail: u32, | ||
| 999 | |||
| 1000 | /// ring mask value | ||
| 1001 | ring_mask: u32, | ||
| 1002 | |||
| 1003 | /// entries in ring | ||
| 1004 | ring_entries: u32, | ||
| 1005 | |||
| 1006 | /// ring flags | ||
| 1007 | flags: u32, | ||
| 1008 | |||
| 1009 | /// number of sqes not submitted | ||
| 1010 | dropped: u32, | ||
| 1011 | |||
| 1012 | /// sqe index array | ||
| 1013 | array: u32, | ||
| 1014 | |||
| 1015 | resv1: u32, | ||
| 1016 | resv2: u64, | ||
| 1017 | }; | ||
| 1018 | |||
| 1019 | // io_sqring_offsets.flags | ||
| 1020 | |||
| 1021 | /// needs io_uring_enter wakeup | ||
| 1022 | pub const IORING_SQ_NEED_WAKEUP = 1 << 0; | ||
| 1023 | |||
| 1024 | pub const io_cqring_offsets = extern struct { | ||
| 1025 | head: u32, | ||
| 1026 | tail: u32, | ||
| 1027 | ring_mask: u32, | ||
| 1028 | ring_entries: u32, | ||
| 1029 | overflow: u32, | ||
| 1030 | cqes: u32, | ||
| 1031 | resv: [2]u64, | ||
| 1032 | }; | ||
| 1033 | |||
| 1034 | pub const io_uring_sqe = extern struct { | ||
| 1035 | opcode: u8, | ||
| 1036 | flags: u8, | ||
| 1037 | ioprio: u16, | ||
| 1038 | fd: i32, | ||
| 1039 | off: u64, | ||
| 1040 | addr: u64, | ||
| 1041 | len: u32, | ||
| 1042 | pub const union1 = extern union { | ||
| 1043 | rw_flags: kernel_rwf, | ||
| 1044 | fsync_flags: u32, | ||
| 1045 | poll_event: u16, | ||
| 1046 | }; | ||
| 1047 | union1: union1, | ||
| 1048 | user_data: u64, | ||
| 1049 | pub const union2 = extern union { | ||
| 1050 | buf_index: u16, | ||
| 1051 | __pad2: [3]u64, | ||
| 1052 | }; | ||
| 1053 | union2: union2, | ||
| 1054 | }; | ||
| 1055 | |||
| 1056 | // io_uring_sqe.flags | ||
| 1057 | |||
| 1058 | /// use fixed fileset | ||
| 1059 | pub const IOSQE_FIXED_FILE = (1 << 0); | ||
| 1060 | |||
| 1061 | pub const IORING_OP_NOP = 0; | ||
| 1062 | pub const IORING_OP_READV = 1; | ||
| 1063 | pub const IORING_OP_WRITEV = 2; | ||
| 1064 | pub const IORING_OP_FSYNC = 3; | ||
| 1065 | pub const IORING_OP_READ_FIXED = 4; | ||
| 1066 | pub const IORING_OP_WRITE_FIXED = 5; | ||
| 1067 | pub const IORING_OP_POLL_ADD = 6; | ||
| 1068 | pub const IORING_OP_POLL_REMOVE = 7; | ||
| 1069 | |||
| 1070 | // io_uring_sqe.fsync_flags | ||
| 1071 | pub const IORING_FSYNC_DATASYNC = (1 << 0); | ||
| 1072 | |||
| 1073 | // IO completion data structure (Completion Queue Entry) | ||
| 1074 | pub const io_uring_cqe = extern struct { | ||
| 1075 | /// io_uring_sqe.data submission passed back | ||
| 1076 | user_data: u64, | ||
| 1077 | |||
| 1078 | /// result code for this event | ||
| 1079 | res: i32, | ||
| 1080 | flags: u32, | ||
| 1081 | }; | ||
| 1082 | |||
| 1083 | pub const IORING_OFF_SQ_RING = 0; | ||
| 1084 | pub const IORING_OFF_CQ_RING = 0x8000000; | ||
| 1085 | pub const IORING_OFF_SQES = 0x10000000; | ||
| 1086 | |||
| 1087 | // io_uring_enter flags | ||
| 1088 | pub const IORING_ENTER_GETEVENTS = (1 << 0); | ||
| 1089 | pub const IORING_ENTER_SQ_WAKEUP = (1 << 1); | ||
| 1090 | |||
| 1091 | // io_uring_register opcodes and arguments | ||
| 1092 | pub const IORING_REGISTER_BUFFERS = 0; | ||
| 1093 | pub const IORING_UNREGISTER_BUFFERS = 1; | ||
| 1094 | pub const IORING_REGISTER_FILES = 2; | ||
| 1095 | pub const IORING_UNREGISTER_FILES = 3; |
std/os/linux.zig+20| ... | @@ -189,6 +189,10 @@ pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { | ... | @@ -189,6 +189,10 @@ pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { |
| 189 | return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); | 189 | return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: u64, flags: kernel_rwf) usize { | ||
| 193 | return syscall5(SYS_preadv2, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset, flags); | ||
| 194 | } | ||
| 195 | |||
| 192 | pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { | 196 | pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { |
| 193 | return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); | 197 | return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); |
| 194 | } | 198 | } |
| ... | @@ -201,6 +205,10 @@ pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) us | ... | @@ -201,6 +205,10 @@ pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) us |
| 201 | return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); | 205 | return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); |
| 202 | } | 206 | } |
| 203 | 207 | ||
| 208 | pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64, flags: kernel_rwf) usize { | ||
| 209 | return syscall5(SYS_pwritev2, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset, flags); | ||
| 210 | } | ||
| 211 | |||
| 204 | // TODO https://github.com/ziglang/zig/issues/265 | 212 | // TODO https://github.com/ziglang/zig/issues/265 |
| 205 | pub fn rmdir(path: [*]const u8) usize { | 213 | pub fn rmdir(path: [*]const u8) usize { |
| 206 | if (@hasDecl(@This(), "SYS_rmdir")) { | 214 | if (@hasDecl(@This(), "SYS_rmdir")) { |
| ... | @@ -887,6 +895,18 @@ pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_inf | ... | @@ -887,6 +895,18 @@ pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_inf |
| 887 | return last_r; | 895 | return last_r; |
| 888 | } | 896 | } |
| 889 | 897 | ||
| 898 | pub fn io_uring_setup(entries: u32, p: *io_uring_params) usize { | ||
| 899 | return syscall2(SYS_io_uring_setup, entries, @ptrToInt(p)); | ||
| 900 | } | ||
| 901 | |||
| 902 | pub fn io_uring_enter(fd: i32, to_submit: u32, min_complete: u32, flags: u32, sig: ?*sigset_t) usize { | ||
| 903 | return syscall6(SYS_io_uring_enter, @bitCast(usize, isize(fd)), to_submit, min_complete, flags, @ptrToInt(sig), NSIG / 8); | ||
| 904 | } | ||
| 905 | |||
| 906 | pub fn io_uring_register(fd: i32, opcode: u32, arg: ?*const c_void, nr_args: u32) usize { | ||
| 907 | return syscall4(SYS_io_uring_register, @bitCast(usize, isize(fd)), opcode, @ptrToInt(arg), nr_args); | ||
| 908 | } | ||
| 909 | |||
| 890 | test "" { | 910 | test "" { |
| 891 | if (is_the_target) { | 911 | if (is_the_target) { |
| 892 | _ = @import("linux/test.zig"); | 912 | _ = @import("linux/test.zig"); |
std/testing.zig+4-2| ... | @@ -78,8 +78,10 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void { | ... | @@ -78,8 +78,10 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void { |
| 78 | 78 | ||
| 79 | TypeId.Array => |array| expectEqualSlices(array.child, &expected, &actual), | 79 | TypeId.Array => |array| expectEqualSlices(array.child, &expected, &actual), |
| 80 | 80 | ||
| 81 | TypeId.Struct => { | 81 | TypeId.Struct => |structType| { |
| 82 | @compileError("TODO implement testing.expectEqual for structs"); | 82 | inline for (structType.fields) |field| { |
| 83 | expectEqual(@field(expected, field.name), @field(actual, field.name)); | ||
| 84 | } | ||
| 83 | }, | 85 | }, |
| 84 | 86 | ||
| 85 | TypeId.Union => |union_info| { | 87 | TypeId.Union => |union_info| { |