authorgravatar for constantin.pestka@web.deCPestka <constantin.pestka@web.de> 2024-01-31 00:46:47+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-12 12:58:33-08:00
log0c725a354a801c84100011db5eb53ae6c58086c9
tree3a980f15c67c94f10e93a1f7778e26a7e150e5eb
parent51d67c7c8f20e89b70a62f0b82abf77a95868bec

Replaced loop with memcpys


1 files changed, 18 insertions(+), 13 deletions(-)

lib/std/os/linux/io_uring.zig+18-13
...@@ -268,29 +268,34 @@ pub const IO_Uring = struct {...@@ -268,29 +268,34 @@ pub const IO_Uring = struct {
268 /// See https://github.com/axboe/liburing/issues/103#issuecomment-686665007.268 /// See https://github.com/axboe/liburing/issues/103#issuecomment-686665007.
269 /// Matches the implementation of io_uring_peek_batch_cqe() in liburing, but supports waiting.269 /// Matches the implementation of io_uring_peek_batch_cqe() in liburing, but supports waiting.
270 pub fn copy_cqes(self: *IO_Uring, cqes: []linux.io_uring_cqe, wait_nr: u32) !u32 {270 pub fn copy_cqes(self: *IO_Uring, cqes: []linux.io_uring_cqe, wait_nr: u32) !u32 {
271 const count = self.copy_cqes_ready(cqes, wait_nr);271 const count = self.copy_cqes_ready(cqes);
272 if (count > 0) return count;272 if (count > 0) return count;
273 if (self.cq_ring_needs_flush() or wait_nr > 0) {273 if (self.cq_ring_needs_flush() or wait_nr > 0) {
274 _ = try self.enter(0, wait_nr, linux.IORING_ENTER_GETEVENTS);274 _ = try self.enter(0, wait_nr, linux.IORING_ENTER_GETEVENTS);
275 return self.copy_cqes_ready(cqes, wait_nr);275 return self.copy_cqes_ready(cqes);
276 }276 }
277 return 0;277 return 0;
278 }278 }
279279
280 fn copy_cqes_ready(self: *IO_Uring, cqes: []linux.io_uring_cqe, wait_nr: u32) u32 {280 fn copy_cqes_ready(self: *IO_Uring, cqes: []linux.io_uring_cqe) u32 {
281 _ = wait_nr;
282 const ready = self.cq_ready();281 const ready = self.cq_ready();
283 const count = @min(cqes.len, ready);282 const count = @min(cqes.len, ready);
284 var head = self.cq.head.*;283 const head = self.cq.head.* & self.cq.mask;
285 const tail = head +% count;284 const tail = (self.cq.head.* +% count) & self.cq.mask;
286 // TODO Optimize this by using 1 or 2 memcpy's (if the tail wraps) rather than a loop.285
287 var i: usize = 0;286 if (head <= tail) {
288 // Do not use "less-than" operator since head and tail may wrap:287 // head behind tail -> no wrapping
289 while (head != tail) {288 @memcpy(cqes[0..count], self.cq.cqes[head..tail]);
290 cqes[i] = self.cq.cqes[head & self.cq.mask]; // Copy struct by value.289 } else {
291 head +%= 1;290 // head in front of tail -> buffer wraps
292 i += 1;291 const two_copies_required: bool = self.cq.cqes.len - head < count;
292 const amount_to_copy_in_first = if (two_copies_required) self.cq.cqes.len - head else count;
293 @memcpy(cqes[0..amount_to_copy_in_first], self.cq.cqes[head .. head + amount_to_copy_in_first]);
294 if (two_copies_required) {
295 @memcpy(cqes[amount_to_copy_in_first..count], self.cq.cqes[0..tail]);
296 }
293 }297 }
298
294 self.cq_advance(count);299 self.cq_advance(count);
295 return count;300 return count;
296 }301 }