authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-10 00:43:47-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-06-10 00:43:47-04:00
log9c2ed8d103ee3c8cf6e8a07ad7c9653137a89784
tree63cffb4db7fa29da822d00cb4a7802cb0c34922c
parent6c160b8856921e5e1d0a437794b3b7ee7e1a4d0b
parent4565f50efe69cb394aed7d26341b917d2089b9d5
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #2525 from daurnimator/uring

std: linux uring kernel interfaces

4 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}
688688
689pub fn isPowerOfTwo(v: var) bool {
690 assert(v != 0);
691 return (v & (v - 1)) == 0;
692}
693
689pub fn floorPowerOfTwo(comptime T: type, value: T) T {694pub fn floorPowerOfTwo(comptime T: type, value: T) T {
690 var x = value;695 var x = value;
691696
std/os/bits/linux.zig+143
...@@ -119,6 +119,23 @@ pub const O_RDONLY = 0o0;...@@ -119,6 +119,23 @@ pub const O_RDONLY = 0o0;
119pub const O_WRONLY = 0o1;119pub const O_WRONLY = 0o1;
120pub const O_RDWR = 0o2;120pub const O_RDWR = 0o2;
121121
122pub const kernel_rwf = u32;
123
124/// high priority request, poll if possible
125pub const RWF_HIPRI = kernel_rwf(0x00000001);
126
127/// per-IO O_DSYNC
128pub const RWF_DSYNC = kernel_rwf(0x00000002);
129
130/// per-IO O_SYNC
131pub const RWF_SYNC = kernel_rwf(0x00000004);
132
133/// per-IO, return -EAGAIN if operation would block
134pub const RWF_NOWAIT = kernel_rwf(0x00000008);
135
136/// per-IO O_APPEND
137pub const RWF_APPEND = kernel_rwf(0x00000010);
138
122pub const SEEK_SET = 0;139pub const SEEK_SET = 0;
123pub const SEEK_CUR = 1;140pub const SEEK_CUR = 1;
124pub const SEEK_END = 2;141pub 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
971pub 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
985pub const IORING_SETUP_IOPOLL = (1 << 0);
986
987/// SQ poll thread
988pub const IORING_SETUP_SQPOLL = (1 << 1);
989
990/// sq_thread_cpu is valid
991pub const IORING_SETUP_SQ_AFF = (1 << 2);
992
993pub 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
1022pub const IORING_SQ_NEED_WAKEUP = 1 << 0;
1023
1024pub 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
1034pub 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
1059pub const IOSQE_FIXED_FILE = (1 << 0);
1060
1061pub const IORING_OP_NOP = 0;
1062pub const IORING_OP_READV = 1;
1063pub const IORING_OP_WRITEV = 2;
1064pub const IORING_OP_FSYNC = 3;
1065pub const IORING_OP_READ_FIXED = 4;
1066pub const IORING_OP_WRITE_FIXED = 5;
1067pub const IORING_OP_POLL_ADD = 6;
1068pub const IORING_OP_POLL_REMOVE = 7;
1069
1070// io_uring_sqe.fsync_flags
1071pub const IORING_FSYNC_DATASYNC = (1 << 0);
1072
1073// IO completion data structure (Completion Queue Entry)
1074pub 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
1083pub const IORING_OFF_SQ_RING = 0;
1084pub const IORING_OFF_CQ_RING = 0x8000000;
1085pub const IORING_OFF_SQES = 0x10000000;
1086
1087// io_uring_enter flags
1088pub const IORING_ENTER_GETEVENTS = (1 << 0);
1089pub const IORING_ENTER_SQ_WAKEUP = (1 << 1);
1090
1091// io_uring_register opcodes and arguments
1092pub const IORING_REGISTER_BUFFERS = 0;
1093pub const IORING_UNREGISTER_BUFFERS = 1;
1094pub const IORING_REGISTER_FILES = 2;
1095pub 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}
191191
192pub 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
192pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {196pub 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}
203207
208pub 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/265212// TODO https://github.com/ziglang/zig/issues/265
205pub fn rmdir(path: [*]const u8) usize {213pub 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}
889897
898pub fn io_uring_setup(entries: u32, p: *io_uring_params) usize {
899 return syscall2(SYS_io_uring_setup, entries, @ptrToInt(p));
900}
901
902pub 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
906pub 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
890test "" {910test "" {
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 {
7878
79 TypeId.Array => |array| expectEqualSlices(array.child, &expected, &actual),79 TypeId.Array => |array| expectEqualSlices(array.child, &expected, &actual),
8080
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 },
8486
85 TypeId.Union => |union_info| {87 TypeId.Union => |union_info| {