| ... | ... | @@ -108,7 +108,7 @@ pub const IO_Uring = struct { |
| 108 | 108 | // Check that our starting state is as we expect. |
| 109 | 109 | assert(sq.head.* == 0); |
| 110 | 110 | assert(sq.tail.* == 0); |
| 111 | | assert(sq.mask.* == p.sq_entries - 1); |
| 111 | assert(sq.mask == p.sq_entries - 1); |
| 112 | 112 | // Allow flags.* to be non-zero, since the kernel may set IORING_SQ_NEED_WAKEUP at any time. |
| 113 | 113 | assert(sq.dropped.* == 0); |
| 114 | 114 | assert(sq.array.len == p.sq_entries); |
| ... | ... | @@ -118,7 +118,7 @@ pub const IO_Uring = struct { |
| 118 | 118 | |
| 119 | 119 | assert(cq.head.* == 0); |
| 120 | 120 | assert(cq.tail.* == 0); |
| 121 | | assert(cq.mask.* == p.cq_entries - 1); |
| 121 | assert(cq.mask == p.cq_entries - 1); |
| 122 | 122 | assert(cq.overflow.* == 0); |
| 123 | 123 | assert(cq.cqes.len == p.cq_entries); |
| 124 | 124 | |
| ... | ... | @@ -152,7 +152,7 @@ pub const IO_Uring = struct { |
| 152 | 152 | // We must therefore use wrapping addition and subtraction to avoid a runtime crash. |
| 153 | 153 | const next = self.sq.sqe_tail +% 1; |
| 154 | 154 | if (next -% head > self.sq.sqes.len) return error.SubmissionQueueFull; |
| 155 | | var sqe = &self.sq.sqes[self.sq.sqe_tail & self.sq.mask.*]; |
| 155 | var sqe = &self.sq.sqes[self.sq.sqe_tail & self.sq.mask]; |
| 156 | 156 | self.sq.sqe_tail = next; |
| 157 | 157 | // We zero the SQE slot here in a single place, rather than in many `queue_` methods. |
| 158 | 158 | @memset(@ptrCast([*]u8, sqe), 0, @sizeOf(io_uring_sqe)); |
| ... | ... | @@ -224,11 +224,10 @@ pub const IO_Uring = struct { |
| 224 | 224 | if (self.sq.sqe_head != self.sq.sqe_tail) { |
| 225 | 225 | // Fill in SQEs that we have queued up, adding them to the kernel ring. |
| 226 | 226 | const to_submit = self.sq.sqe_tail -% self.sq.sqe_head; |
| 227 | | const mask = self.sq.mask.*; |
| 228 | 227 | var tail = self.sq.tail.*; |
| 229 | 228 | var i: usize = 0; |
| 230 | 229 | while (i < to_submit) : (i += 1) { |
| 231 | | self.sq.array[tail & mask] = self.sq.sqe_head & mask; |
| 230 | self.sq.array[tail & self.sq.mask] = self.sq.sqe_head & self.sq.mask; |
| 232 | 231 | tail +%= 1; |
| 233 | 232 | self.sq.sqe_head +%= 1; |
| 234 | 233 | } |
| ... | ... | @@ -292,14 +291,13 @@ pub const IO_Uring = struct { |
| 292 | 291 | fn copy_cqes_ready(self: *IO_Uring, cqes: []io_uring_cqe, wait_nr: u32) u32 { |
| 293 | 292 | const ready = self.cq_ready(); |
| 294 | 293 | const count = std.math.min(cqes.len, ready); |
| 295 | | const mask = self.cq.mask.*; |
| 296 | 294 | var head = self.cq.head.*; |
| 297 | 295 | var tail = head +% count; |
| 298 | 296 | // TODO Optimize this by using 1 or 2 memcpy's (if the tail wraps) rather than a loop. |
| 299 | 297 | var i: usize = 0; |
| 300 | 298 | // Do not use "less-than" operator since head and tail may wrap: |
| 301 | 299 | while (head != tail) { |
| 302 | | cqes[i] = self.cq.cqes[head & mask]; // Copy struct by value. |
| 300 | cqes[i] = self.cq.cqes[head & self.cq.mask]; // Copy struct by value. |
| 303 | 301 | head +%= 1; |
| 304 | 302 | i += 1; |
| 305 | 303 | } |
| ... | ... | @@ -560,7 +558,7 @@ pub const IO_Uring = struct { |
| 560 | 558 | pub const SubmissionQueue = struct { |
| 561 | 559 | head: *u32, |
| 562 | 560 | tail: *u32, |
| 563 | | mask: *u32, |
| 561 | mask: u32, |
| 564 | 562 | flags: *u32, |
| 565 | 563 | dropped: *u32, |
| 566 | 564 | array: []u32, |
| ... | ... | @@ -618,7 +616,7 @@ pub const SubmissionQueue = struct { |
| 618 | 616 | return SubmissionQueue { |
| 619 | 617 | .head = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.sq_off.head])), |
| 620 | 618 | .tail = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.sq_off.tail])), |
| 621 | | .mask = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.sq_off.ring_mask])), |
| 619 | .mask = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.sq_off.ring_mask])).*, |
| 622 | 620 | .flags = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.sq_off.flags])), |
| 623 | 621 | .dropped = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.sq_off.dropped])), |
| 624 | 622 | .array = array[0..p.sq_entries], |
| ... | ... | @@ -637,7 +635,7 @@ pub const SubmissionQueue = struct { |
| 637 | 635 | pub const CompletionQueue = struct { |
| 638 | 636 | head: *u32, |
| 639 | 637 | tail: *u32, |
| 640 | | mask: *u32, |
| 638 | mask: u32, |
| 641 | 639 | overflow: *u32, |
| 642 | 640 | cqes: []io_uring_cqe, |
| 643 | 641 | |
| ... | ... | @@ -656,7 +654,7 @@ pub const CompletionQueue = struct { |
| 656 | 654 | return CompletionQueue { |
| 657 | 655 | .head = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.cq_off.head])), |
| 658 | 656 | .tail = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.cq_off.tail])), |
| 659 | | .mask = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.cq_off.ring_mask])), |
| 657 | .mask = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.cq_off.ring_mask])).*, |
| 660 | 658 | .overflow = @ptrCast(*u32, @alignCast(@alignOf(u32), &mmap[p.cq_off.overflow])), |
| 661 | 659 | .cqes = cqes[0..p.cq_entries] |
| 662 | 660 | }; |
| ... | ... | @@ -670,7 +668,7 @@ pub const CompletionQueue = struct { |
| 670 | 668 | |
| 671 | 669 | test "structs and offsets" { |
| 672 | 670 | if (builtin.os.tag != .linux) return error.SkipZigTest; |
| 673 | | |
| 671 | |
| 674 | 672 | testing.expectEqual(@as(usize, 120), @sizeOf(io_uring_params)); |
| 675 | 673 | testing.expectEqual(@as(usize, 64), @sizeOf(io_uring_sqe)); |
| 676 | 674 | testing.expectEqual(@as(usize, 16), @sizeOf(io_uring_cqe)); |