authorgravatar for joran@ronomon.comJoran Dirk Greef <joran@ronomon.com> 2020-09-19 18:17:06+02:00
committergravatar for joran@ronomon.comJoran Dirk Greef <joran@ronomon.com> 2020-09-19 18:17:06+02:00
logba18420b277a8de21a760387767dcf2c9227cc5a
tree4112beb727856040101247c70c2b000083539b21
parente7ae6f2fadcafc7a4f0eea96815b7d22049dd2c5

Zero the SQE slot and assign, instead of initializing with default values


1 files changed, 39 insertions(+), 51 deletions(-)

lib/std/os/linux/io_uring.zig+39-51
......@@ -124,13 +124,13 @@ pub const IO_Uring = struct {
124124 self.fd = -1;
125125 }
126126
127 /// Returns a vacant SQE, or an error if the submission queue is full.
127 /// Returns a pointer to a zeroed SQE, or an error if the submission queue is full.
128128 /// We follow the implementation (and atomics) of liburing's `io_uring_get_sqe()` exactly.
129129 /// However, instead of a null we return an error to force safe handling.
130130 /// Any situation where the submission queue is full tends more towards a control flow error,
131131 /// and the null return in liburing is more a C idiom than anything else, for lack of a better
132132 /// alternative. In Zig, we have first-class error handling... so let's use it.
133 /// Matches the implementation of io_uring_get_sqe() in liburing.
133 /// Matches the implementation of io_uring_get_sqe() in liburing, except zeroes for safety.
134134 pub fn get_sqe(self: *IO_Uring) !*io_uring_sqe {
135135 const head = @atomicLoad(u32, self.sq.head, .Acquire);
136136 // Remember that these head and tail offsets wrap around every four billion operations.
......@@ -139,6 +139,8 @@ pub const IO_Uring = struct {
139139 if (next -% head > self.sq.sqes.len) return error.SubmissionQueueFull;
140140 var sqe = &self.sq.sqes[self.sq.sqe_tail & self.sq.mask.*];
141141 self.sq.sqe_tail = next;
142 // We zero the SQE slot here in a single place, rather than in many `queue_` methods.
143 @memset(@ptrCast([*]u8, sqe), 0, @sizeOf(io_uring_sqe));
142144 return sqe;
143145 }
144146
......@@ -312,14 +314,12 @@ pub const IO_Uring = struct {
312314 // sqe->addr2 holds a pointer to socklen_t, and finally sqe->accept_flags holds the flags
313315 // for accept(4)." - https://lwn.net/ml/linux-block/20191025173037.13486-1-axboe@kernel.dk/
314316 const sqe = try self.get_sqe();
315 sqe.* = .{
316 .opcode = .ACCEPT,
317 .fd = fd,
318 .off = @ptrToInt(addrlen), // `addr2` is a newer union member that maps to `off`.
319 .addr = @ptrToInt(addr),
320 .user_data = user_data,
321 .opflags = accept_flags
322 };
317 sqe.opcode = .ACCEPT;
318 sqe.fd = fd;
319 sqe.off = @ptrToInt(addrlen); // `addr2` is a newer union member that maps to `off`.
320 sqe.addr = @ptrToInt(addr);
321 sqe.user_data = user_data;
322 sqe.opflags = accept_flags;
323323 return sqe;
324324 }
325325
......@@ -334,11 +334,9 @@ pub const IO_Uring = struct {
334334 /// or else insert a full write barrier using `drain_previous_sqes()` when queueing an fsync.
335335 pub fn queue_fsync(self: *IO_Uring, user_data: u64, fd: os.fd_t) !*io_uring_sqe {
336336 const sqe = try self.get_sqe();
337 sqe.* = .{
338 .opcode = .FSYNC,
339 .fd = fd,
340 .user_data = user_data
341 };
337 sqe.opcode = .FSYNC;
338 sqe.fd = fd;
339 sqe.user_data = user_data;
342340 return sqe;
343341 }
344342
......@@ -349,10 +347,8 @@ pub const IO_Uring = struct {
349347 /// know when the ring is idle before acting on a kill signal.
350348 pub fn queue_nop(self: *IO_Uring, user_data: u64) !*io_uring_sqe {
351349 const sqe = try self.get_sqe();
352 sqe.* = .{
353 .opcode = .NOP,
354 .user_data = user_data
355 };
350 sqe.opcode = .NOP;
351 sqe.user_data = user_data;
356352 return sqe;
357353 }
358354
......@@ -366,14 +362,12 @@ pub const IO_Uring = struct {
366362 offset: u64
367363 ) !*io_uring_sqe {
368364 const sqe = try self.get_sqe();
369 sqe.* = .{
370 .opcode = .READ,
371 .fd = fd,
372 .off = offset,
373 .addr = @ptrToInt(buffer.ptr),
374 .len = @truncate(u32, buffer.len),
375 .user_data = user_data
376 };
365 sqe.opcode = .READ;
366 sqe.fd = fd;
367 sqe.off = offset;
368 sqe.addr = @ptrToInt(buffer.ptr);
369 sqe.len = @truncate(u32, buffer.len);
370 sqe.user_data = user_data;
377371 return sqe;
378372 }
379373
......@@ -387,14 +381,12 @@ pub const IO_Uring = struct {
387381 offset: u64
388382 ) !*io_uring_sqe {
389383 const sqe = try self.get_sqe();
390 sqe.* = .{
391 .opcode = .WRITE,
392 .fd = fd,
393 .off = offset,
394 .addr = @ptrToInt(buffer.ptr),
395 .len = @truncate(u32, buffer.len),
396 .user_data = user_data
397 };
384 sqe.opcode = .WRITE;
385 sqe.fd = fd;
386 sqe.off = offset;
387 sqe.addr = @ptrToInt(buffer.ptr);
388 sqe.len = @truncate(u32, buffer.len);
389 sqe.user_data = user_data;
398390 return sqe;
399391 }
400392
......@@ -410,14 +402,12 @@ pub const IO_Uring = struct {
410402 offset: u64
411403 ) !*io_uring_sqe {
412404 const sqe = try self.get_sqe();
413 sqe.* = .{
414 .opcode = .READV,
415 .fd = fd,
416 .off = offset,
417 .addr = @ptrToInt(iovecs.ptr),
418 .len = @truncate(u32, iovecs.len),
419 .user_data = user_data
420 };
405 sqe.opcode = .READV;
406 sqe.fd = fd;
407 sqe.off = offset;
408 sqe.addr = @ptrToInt(iovecs.ptr);
409 sqe.len = @truncate(u32, iovecs.len);
410 sqe.user_data = user_data;
421411 return sqe;
422412 }
423413
......@@ -433,14 +423,12 @@ pub const IO_Uring = struct {
433423 offset: u64
434424 ) !*io_uring_sqe {
435425 const sqe = try self.get_sqe();
436 sqe.* = .{
437 .opcode = .WRITEV,
438 .fd = fd,
439 .off = offset,
440 .addr = @ptrToInt(iovecs.ptr),
441 .len = @truncate(u32, iovecs.len),
442 .user_data = user_data
443 };
426 sqe.opcode = .WRITEV;
427 sqe.fd = fd;
428 sqe.off = offset;
429 sqe.addr = @ptrToInt(iovecs.ptr);
430 sqe.len = @truncate(u32, iovecs.len);
431 sqe.user_data = user_data;
444432 return sqe;
445433 }
446434