An asynchronous IO runtime

ourio: add open op

rockorager.dev ccf5e7fc 78c03abd

verified
+35
+7
src/ourio.zig
··· 494 494 connect, 495 495 statx, 496 496 readv, 497 + open, 497 498 498 499 /// userfd is meant to send file descriptors between Ring instances (using msgRing) 499 500 userfd, ··· 551 552 fd: posix.fd_t, 552 553 vecs: []const posix.iovec, 553 554 }, 555 + open: struct { 556 + path: [:0]const u8, 557 + flags: posix.O, 558 + mode: posix.mode_t, 559 + }, 554 560 555 561 userfd, 556 562 usermsg, ··· 573 579 connect: ResultError!void, 574 580 statx: ResultError!*Statx, 575 581 readv: ResultError!usize, 582 + open: ResultError!posix.fd_t, 576 583 577 584 userfd: anyerror!posix.fd_t, 578 585 usermsg: u16,
+12
src/ourio/Kqueue.zig
··· 332 332 self.synchronous_queue.push(task); 333 333 }, 334 334 335 + .open => |req| { 336 + self.synchronous_queue.push(task); 337 + 338 + if (posix.open(req.path, req.flags, req.mode)) |fd| { 339 + task.result = .{ .open = fd }; 340 + } else |_| task.result = .{ .open = error.Unexpected }; 341 + }, 342 + 335 343 .poll => |req| { 336 344 self.in_flight.push(task); 337 345 if (req.mask & posix.POLL.IN != 0) { ··· 440 448 .close, 441 449 .msg_ring, 442 450 .noop, 451 + .open, 443 452 .socket, 444 453 .statx, 445 454 .userfd, ··· 686 695 .close, 687 696 .msg_ring, 688 697 .noop, 698 + .open, 689 699 .socket, 690 700 .statx, 691 701 .userfd, ··· 719 729 .deadline => .{ .deadline = error.Canceled }, 720 730 .msg_ring => .{ .msg_ring = error.Canceled }, 721 731 .noop => unreachable, 732 + .open => .{ .open = error.Canceled }, 722 733 .poll => .{ .poll = error.Canceled }, 723 734 .readv => .{ .readv = error.Canceled }, 724 735 .recv => .{ .recv = error.Canceled }, ··· 761 772 .deadline, 762 773 .msg_ring, 763 774 .noop, 775 + .open, 764 776 .socket, 765 777 .statx, 766 778 .timer,
+2
src/ourio/Mock.zig
··· 18 18 deadline_cb: ?*const fn (*io.Task) io.Result = null, 19 19 msg_ring_cb: ?*const fn (*io.Task) io.Result = null, 20 20 noop_cb: ?*const fn (*io.Task) io.Result = null, 21 + open_cb: ?*const fn (*io.Task) io.Result = null, 21 22 poll_cb: ?*const fn (*io.Task) io.Result = null, 22 23 readv_cb: ?*const fn (*io.Task) io.Result = null, 23 24 recv_cb: ?*const fn (*io.Task) io.Result = null, ··· 69 70 .deadline => if (self.deadline_cb) |cb| cb(task) else return error.NoMockCallback, 70 71 .msg_ring => if (self.msg_ring_cb) |cb| cb(task) else return error.NoMockCallback, 71 72 .noop => if (self.noop_cb) |cb| cb(task) else return error.NoMockCallback, 73 + .open => if (self.open_cb) |cb| cb(task) else return error.NoMockCallback, 72 74 .poll => if (self.poll_cb) |cb| cb(task) else return error.NoMockCallback, 73 75 .readv => if (self.readv_cb) |cb| cb(task) else return error.NoMockCallback, 74 76 .recv => if (self.recv_cb) |cb| cb(task) else return error.NoMockCallback,
+14
src/ourio/Uring.zig
··· 232 232 self.prepDeadline(task, sqe); 233 233 }, 234 234 235 + .open => |req| { 236 + const sqe = self.getSqe(); 237 + sqe.prep_openat(posix.AT.FDCWD, req.path, req.flags, req.mode); 238 + sqe.user_data = @intFromPtr(task); 239 + self.prepDeadline(task, sqe); 240 + }, 241 + 235 242 // user* is only sent internally between rings and higher level wrappers 236 243 .userfd, .usermsg, .userptr => unreachable, 237 244 } ··· 362 369 } }, 363 370 364 371 .readv => .{ .readv = switch (cqeToE(cqe.res)) { 372 + .SUCCESS => @intCast(cqe.res), 373 + .INVAL => io.ResultError.Invalid, 374 + .CANCELED => io.ResultError.Canceled, 375 + else => |e| unexpectedError(e), 376 + } }, 377 + 378 + .open => .{ .open = switch (cqeToE(cqe.res)) { 365 379 .SUCCESS => @intCast(cqe.res), 366 380 .INVAL => io.ResultError.Invalid, 367 381 .CANCELED => io.ResultError.Canceled,