authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-01-28 01:04:38+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-02-01 15:22:36+02:00
loga4f27e8987ef3e2388839b6452b9f485ab82e7b7
tree6420c218896c0f44dea7353b8a9c00b01461c2ec
parentb0bea72588c685c1d6439f61d2e842756b5fc496

remove std.io.Mode


25 files changed, 119 insertions(+), 579 deletions(-)

lib/std/Build/Step/Compile.zig-5
...@@ -55,7 +55,6 @@ global_base: ?u64 = null,...@@ -55,7 +55,6 @@ global_base: ?u64 = null,
55zig_lib_dir: ?LazyPath,55zig_lib_dir: ?LazyPath,
56exec_cmd_args: ?[]const ?[]const u8,56exec_cmd_args: ?[]const ?[]const u8,
57filter: ?[]const u8,57filter: ?[]const u8,
58test_evented_io: bool = false,
59test_runner: ?[]const u8,58test_runner: ?[]const u8,
60test_server_mode: bool,59test_server_mode: bool,
61wasi_exec_model: ?std.builtin.WasiExecModel = null,60wasi_exec_model: ?std.builtin.WasiExecModel = null,
...@@ -1294,10 +1293,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1294,10 +1293,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1294 try zig_args.append(filter);1293 try zig_args.append(filter);
1295 }1294 }
12961295
1297 if (self.test_evented_io) {
1298 try zig_args.append("--test-evented-io");
1299 }
1300
1301 if (self.test_runner) |test_runner| {1296 if (self.test_runner) |test_runner| {
1302 try zig_args.append("--test-runner");1297 try zig_args.append("--test-runner");
1303 try zig_args.append(b.pathFromRoot(test_runner));1298 try zig_args.append(b.pathFromRoot(test_runner));
lib/std/Build/Step/Run.zig+2-10
...@@ -1147,19 +1147,14 @@ fn evalZigTest(...@@ -1147,19 +1147,14 @@ fn evalZigTest(
1147 test_count = tm_hdr.tests_len;1147 test_count = tm_hdr.tests_len;
11481148
1149 const names_bytes = body[@sizeOf(TmHdr)..][0 .. test_count * @sizeOf(u32)];1149 const names_bytes = body[@sizeOf(TmHdr)..][0 .. test_count * @sizeOf(u32)];
1150 const async_frame_lens_bytes = body[@sizeOf(TmHdr) + names_bytes.len ..][0 .. test_count * @sizeOf(u32)];1150 const expected_panic_msgs_bytes = body[@sizeOf(TmHdr) + names_bytes.len ..][0 .. test_count * @sizeOf(u32)];
1151 const expected_panic_msgs_bytes = body[@sizeOf(TmHdr) + names_bytes.len + async_frame_lens_bytes.len ..][0 .. test_count * @sizeOf(u32)];1151 const string_bytes = body[@sizeOf(TmHdr) + names_bytes.len + expected_panic_msgs_bytes.len ..][0..tm_hdr.string_bytes_len];
1152 const string_bytes = body[@sizeOf(TmHdr) + names_bytes.len + async_frame_lens_bytes.len + expected_panic_msgs_bytes.len ..][0..tm_hdr.string_bytes_len];
11531152
1154 const names = std.mem.bytesAsSlice(u32, names_bytes);1153 const names = std.mem.bytesAsSlice(u32, names_bytes);
1155 const async_frame_lens = std.mem.bytesAsSlice(u32, async_frame_lens_bytes);
1156 const expected_panic_msgs = std.mem.bytesAsSlice(u32, expected_panic_msgs_bytes);1154 const expected_panic_msgs = std.mem.bytesAsSlice(u32, expected_panic_msgs_bytes);
1157 const names_aligned = try arena.alloc(u32, names.len);1155 const names_aligned = try arena.alloc(u32, names.len);
1158 for (names_aligned, names) |*dest, src| dest.* = src;1156 for (names_aligned, names) |*dest, src| dest.* = src;
11591157
1160 const async_frame_lens_aligned = try arena.alloc(u32, async_frame_lens.len);
1161 for (async_frame_lens_aligned, async_frame_lens) |*dest, src| dest.* = src;
1162
1163 const expected_panic_msgs_aligned = try arena.alloc(u32, expected_panic_msgs.len);1158 const expected_panic_msgs_aligned = try arena.alloc(u32, expected_panic_msgs.len);
1164 for (expected_panic_msgs_aligned, expected_panic_msgs) |*dest, src| dest.* = src;1159 for (expected_panic_msgs_aligned, expected_panic_msgs) |*dest, src| dest.* = src;
11651160
...@@ -1167,7 +1162,6 @@ fn evalZigTest(...@@ -1167,7 +1162,6 @@ fn evalZigTest(
1167 metadata = .{1162 metadata = .{
1168 .string_bytes = try arena.dupe(u8, string_bytes),1163 .string_bytes = try arena.dupe(u8, string_bytes),
1169 .names = names_aligned,1164 .names = names_aligned,
1170 .async_frame_lens = async_frame_lens_aligned,
1171 .expected_panic_msgs = expected_panic_msgs_aligned,1165 .expected_panic_msgs = expected_panic_msgs_aligned,
1172 .next_index = 0,1166 .next_index = 0,
1173 .prog_node = prog_node,1167 .prog_node = prog_node,
...@@ -1237,7 +1231,6 @@ fn evalZigTest(...@@ -1237,7 +1231,6 @@ fn evalZigTest(
12371231
1238const TestMetadata = struct {1232const TestMetadata = struct {
1239 names: []const u32,1233 names: []const u32,
1240 async_frame_lens: []const u32,
1241 expected_panic_msgs: []const u32,1234 expected_panic_msgs: []const u32,
1242 string_bytes: []const u8,1235 string_bytes: []const u8,
1243 next_index: u32,1236 next_index: u32,
...@@ -1253,7 +1246,6 @@ fn requestNextTest(in: fs.File, metadata: *TestMetadata, sub_prog_node: *?std.Pr...@@ -1253,7 +1246,6 @@ fn requestNextTest(in: fs.File, metadata: *TestMetadata, sub_prog_node: *?std.Pr
1253 const i = metadata.next_index;1246 const i = metadata.next_index;
1254 metadata.next_index += 1;1247 metadata.next_index += 1;
12551248
1256 if (metadata.async_frame_lens[i] != 0) continue;
1257 if (metadata.expected_panic_msgs[i] != 0) continue;1249 if (metadata.expected_panic_msgs[i] != 0) continue;
12581250
1259 const name = metadata.testName(i);1251 const name = metadata.testName(i);
lib/std/builtin.zig-1
...@@ -732,7 +732,6 @@ pub const CompilerBackend = enum(u64) {...@@ -732,7 +732,6 @@ pub const CompilerBackend = enum(u64) {
732pub const TestFn = struct {732pub const TestFn = struct {
733 name: []const u8,733 name: []const u8,
734 func: *const fn () anyerror!void,734 func: *const fn () anyerror!void,
735 async_frame_size: ?usize,
736};735};
737736
738/// This function type is used by the Zig language code generation and737/// This function type is used by the Zig language code generation and
lib/std/child_process.zig+3-12
...@@ -493,7 +493,7 @@ pub const ChildProcess = struct {...@@ -493,7 +493,7 @@ pub const ChildProcess = struct {
493 }493 }
494494
495 fn spawnPosix(self: *ChildProcess) SpawnError!void {495 fn spawnPosix(self: *ChildProcess) SpawnError!void {
496 const pipe_flags = if (io.is_async) os.O.NONBLOCK else 0;496 const pipe_flags = 0;
497 const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try os.pipe2(pipe_flags) else undefined;497 const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try os.pipe2(pipe_flags) else undefined;
498 errdefer if (self.stdin_behavior == StdIo.Pipe) {498 errdefer if (self.stdin_behavior == StdIo.Pipe) {
499 destroyPipe(stdin_pipe);499 destroyPipe(stdin_pipe);
...@@ -665,7 +665,6 @@ pub const ChildProcess = struct {...@@ -665,7 +665,6 @@ pub const ChildProcess = struct {
665 .share_access = windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE,665 .share_access = windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE,
666 .sa = &saAttr,666 .sa = &saAttr,
667 .creation = windows.OPEN_EXISTING,667 .creation = windows.OPEN_EXISTING,
668 .io_mode = .blocking,
669 }) catch |err| switch (err) {668 }) catch |err| switch (err) {
670 error.PathAlreadyExists => unreachable, // not possible for "NUL"669 error.PathAlreadyExists => unreachable, // not possible for "NUL"
671 error.PipeBusy => unreachable, // not possible for "NUL"670 error.PipeBusy => unreachable, // not possible for "NUL"
...@@ -1491,20 +1490,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {...@@ -1491,20 +1490,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
1491const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);1490const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
14921491
1493fn writeIntFd(fd: i32, value: ErrInt) !void {1492fn writeIntFd(fd: i32, value: ErrInt) !void {
1494 const file = File{1493 const file = File{ .handle = fd };
1495 .handle = fd,
1496 .capable_io_mode = .blocking,
1497 .intended_io_mode = .blocking,
1498 };
1499 file.writer().writeInt(u64, @intCast(value), .little) catch return error.SystemResources;1494 file.writer().writeInt(u64, @intCast(value), .little) catch return error.SystemResources;
1500}1495}
15011496
1502fn readIntFd(fd: i32) !ErrInt {1497fn readIntFd(fd: i32) !ErrInt {
1503 const file = File{1498 const file = File{ .handle = fd };
1504 .handle = fd,
1505 .capable_io_mode = .blocking,
1506 .intended_io_mode = .blocking,
1507 };
1508 return @as(ErrInt, @intCast(file.reader().readInt(u64, .little) catch return error.SystemResources));1499 return @as(ErrInt, @intCast(file.reader().readInt(u64, .little) catch return error.SystemResources));
1509}1500}
15101501
lib/std/debug.zig+5-8
...@@ -1141,8 +1141,8 @@ pub fn readElfDebugInfo(...@@ -1141,8 +1141,8 @@ pub fn readElfDebugInfo(
1141) !ModuleDebugInfo {1141) !ModuleDebugInfo {
1142 nosuspend {1142 nosuspend {
1143 const elf_file = (if (elf_filename) |filename| blk: {1143 const elf_file = (if (elf_filename) |filename| blk: {
1144 break :blk fs.cwd().openFile(filename, .{ .intended_io_mode = .blocking });1144 break :blk fs.cwd().openFile(filename, .{});
1145 } else fs.openSelfExe(.{ .intended_io_mode = .blocking })) catch |err| switch (err) {1145 } else fs.openSelfExe(.{})) catch |err| switch (err) {
1146 error.FileNotFound => return error.MissingDebugInfo,1146 error.FileNotFound => return error.MissingDebugInfo,
1147 else => return err,1147 else => return err,
1148 };1148 };
...@@ -1452,7 +1452,7 @@ fn readMachODebugInfo(allocator: mem.Allocator, macho_file: File) !ModuleDebugIn...@@ -1452,7 +1452,7 @@ fn readMachODebugInfo(allocator: mem.Allocator, macho_file: File) !ModuleDebugIn
1452fn printLineFromFileAnyOs(out_stream: anytype, line_info: LineInfo) !void {1452fn printLineFromFileAnyOs(out_stream: anytype, line_info: LineInfo) !void {
1453 // Need this to always block even in async I/O mode, because this could potentially1453 // Need this to always block even in async I/O mode, because this could potentially
1454 // be called from e.g. the event loop code crashing.1454 // be called from e.g. the event loop code crashing.
1455 var f = try fs.cwd().openFile(line_info.file_name, .{ .intended_io_mode = .blocking });1455 var f = try fs.cwd().openFile(line_info.file_name, .{});
1456 defer f.close();1456 defer f.close();
1457 // TODO fstat and make sure that the file has the correct size1457 // TODO fstat and make sure that the file has the correct size
14581458
...@@ -1640,7 +1640,6 @@ const MachoSymbol = struct {...@@ -1640,7 +1640,6 @@ const MachoSymbol = struct {
1640 }1640 }
1641};1641};
16421642
1643/// `file` is expected to have been opened with .intended_io_mode == .blocking.
1644/// Takes ownership of file, even on error.1643/// Takes ownership of file, even on error.
1645/// TODO it's weird to take ownership even on error, rework this code.1644/// TODO it's weird to take ownership even on error, rework this code.
1646fn mapWholeFile(file: File) ![]align(mem.page_size) const u8 {1645fn mapWholeFile(file: File) ![]align(mem.page_size) const u8 {
...@@ -1824,9 +1823,7 @@ pub const DebugInfo = struct {...@@ -1824,9 +1823,7 @@ pub const DebugInfo = struct {
1824 errdefer self.allocator.destroy(obj_di);1823 errdefer self.allocator.destroy(obj_di);
18251824
1826 const macho_path = mem.sliceTo(std.c._dyld_get_image_name(i), 0);1825 const macho_path = mem.sliceTo(std.c._dyld_get_image_name(i), 0);
1827 const macho_file = fs.cwd().openFile(macho_path, .{1826 const macho_file = fs.cwd().openFile(macho_path, .{}) catch |err| switch (err) {
1828 .intended_io_mode = .blocking,
1829 }) catch |err| switch (err) {
1830 error.FileNotFound => return error.MissingDebugInfo,1827 error.FileNotFound => return error.MissingDebugInfo,
1831 else => return err,1828 else => return err,
1832 };1829 };
...@@ -2162,7 +2159,7 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -2162,7 +2159,7 @@ pub const ModuleDebugInfo = switch (native_os) {
2162 }2159 }
21632160
2164 fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !*OFileInfo {2161 fn loadOFile(self: *@This(), allocator: mem.Allocator, o_file_path: []const u8) !*OFileInfo {
2165 const o_file = try fs.cwd().openFile(o_file_path, .{ .intended_io_mode = .blocking });2162 const o_file = try fs.cwd().openFile(o_file_path, .{});
2166 const mapped_mem = try mapWholeFile(o_file);2163 const mapped_mem = try mapWholeFile(o_file);
21672164
2168 const hdr: *const macho.mach_header_64 = @ptrCast(@alignCast(mapped_mem.ptr));2165 const hdr: *const macho.mach_header_64 = @ptrCast(@alignCast(mapped_mem.ptr));
lib/std/fs.zig-7
...@@ -84,13 +84,6 @@ pub const base64_encoder = base64.Base64Encoder.init(base64_alphabet, null);...@@ -84,13 +84,6 @@ pub const base64_encoder = base64.Base64Encoder.init(base64_alphabet, null);
84/// Base64 decoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.84/// Base64 decoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.
85pub const base64_decoder = base64.Base64Decoder.init(base64_alphabet, null);85pub const base64_decoder = base64.Base64Decoder.init(base64_alphabet, null);
8686
87/// Whether or not async file system syscalls need a dedicated thread because the operating
88/// system does not support non-blocking I/O on the file system.
89pub const need_async_thread = std.io.is_async and switch (builtin.os.tag) {
90 .windows, .other => false,
91 else => true,
92};
93
94/// TODO remove the allocator requirement from this API87/// TODO remove the allocator requirement from this API
95/// TODO move to Dir88/// TODO move to Dir
96pub fn atomicSymLink(allocator: Allocator, existing_path: []const u8, new_path: []const u8) !void {89pub fn atomicSymLink(allocator: Allocator, existing_path: []const u8, new_path: []const u8) !void {
lib/std/fs/Dir.zig+12-59
...@@ -751,11 +751,7 @@ pub const OpenError = error{...@@ -751,11 +751,7 @@ pub const OpenError = error{
751} || posix.UnexpectedError;751} || posix.UnexpectedError;
752752
753pub fn close(self: *Dir) void {753pub fn close(self: *Dir) void {
754 if (fs.need_async_thread) {754 posix.close(self.fd);
755 std.event.Loop.instance.?.close(self.fd);
756 } else {
757 posix.close(self.fd);
758 }
759 self.* = undefined;755 self.* = undefined;
760}756}
761757
...@@ -837,10 +833,7 @@ pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File...@@ -837,10 +833,7 @@ pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File
837 .write_only => @as(u32, posix.O.WRONLY),833 .write_only => @as(u32, posix.O.WRONLY),
838 .read_write => @as(u32, posix.O.RDWR),834 .read_write => @as(u32, posix.O.RDWR),
839 };835 };
840 const fd = if (flags.intended_io_mode != .blocking)836 const fd = try posix.openatZ(self.fd, sub_path, os_flags, 0);
841 try std.event.Loop.instance.?.openatZ(self.fd, sub_path, os_flags, 0)
842 else
843 try posix.openatZ(self.fd, sub_path, os_flags, 0);
844 errdefer posix.close(fd);837 errdefer posix.close(fd);
845838
846 // WASI doesn't have posix.flock so we intetinally check OS prior to the inner if block839 // WASI doesn't have posix.flock so we intetinally check OS prior to the inner if block
...@@ -877,11 +870,7 @@ pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File...@@ -877,11 +870,7 @@ pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File
877 };870 };
878 }871 }
879872
880 return File{873 return File{ .handle = fd };
881 .handle = fd,
882 .capable_io_mode = .blocking,
883 .intended_io_mode = flags.intended_io_mode,
884 };
885}874}
886875
887/// Same as `openFile` but Windows-only and the path parameter is876/// Same as `openFile` but Windows-only and the path parameter is
...@@ -895,10 +884,7 @@ pub fn openFileW(self: Dir, sub_path_w: []const u16, flags: File.OpenFlags) File...@@ -895,10 +884,7 @@ pub fn openFileW(self: Dir, sub_path_w: []const u16, flags: File.OpenFlags) File
895 (if (flags.isRead()) @as(u32, w.GENERIC_READ) else 0) |884 (if (flags.isRead()) @as(u32, w.GENERIC_READ) else 0) |
896 (if (flags.isWrite()) @as(u32, w.GENERIC_WRITE) else 0),885 (if (flags.isWrite()) @as(u32, w.GENERIC_WRITE) else 0),
897 .creation = w.FILE_OPEN,886 .creation = w.FILE_OPEN,
898 .io_mode = flags.intended_io_mode,
899 }),887 }),
900 .capable_io_mode = std.io.default_mode,
901 .intended_io_mode = flags.intended_io_mode,
902 };888 };
903 errdefer file.close();889 errdefer file.close();
904 var io: w.IO_STATUS_BLOCK = undefined;890 var io: w.IO_STATUS_BLOCK = undefined;
...@@ -994,10 +980,7 @@ pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags...@@ -994,10 +980,7 @@ pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags
994 (if (flags.truncate) @as(u32, posix.O.TRUNC) else 0) |980 (if (flags.truncate) @as(u32, posix.O.TRUNC) else 0) |
995 (if (flags.read) @as(u32, posix.O.RDWR) else posix.O.WRONLY) |981 (if (flags.read) @as(u32, posix.O.RDWR) else posix.O.WRONLY) |
996 (if (flags.exclusive) @as(u32, posix.O.EXCL) else 0);982 (if (flags.exclusive) @as(u32, posix.O.EXCL) else 0);
997 const fd = if (flags.intended_io_mode != .blocking)983 const fd = try posix.openatZ(self.fd, sub_path_c, os_flags, flags.mode);
998 try std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, os_flags, flags.mode)
999 else
1000 try posix.openatZ(self.fd, sub_path_c, os_flags, flags.mode);
1001 errdefer posix.close(fd);984 errdefer posix.close(fd);
1002985
1003 // WASI doesn't have posix.flock so we intetinally check OS prior to the inner if block986 // WASI doesn't have posix.flock so we intetinally check OS prior to the inner if block
...@@ -1034,11 +1017,7 @@ pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags...@@ -1034,11 +1017,7 @@ pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags
1034 };1017 };
1035 }1018 }
10361019
1037 return File{1020 return File{ .handle = fd };
1038 .handle = fd,
1039 .capable_io_mode = .blocking,
1040 .intended_io_mode = flags.intended_io_mode,
1041 };
1042}1021}
10431022
1044/// Same as `createFile` but Windows-only and the path parameter is1023/// Same as `createFile` but Windows-only and the path parameter is
...@@ -1056,10 +1035,7 @@ pub fn createFileW(self: Dir, sub_path_w: []const u16, flags: File.CreateFlags)...@@ -1056,10 +1035,7 @@ pub fn createFileW(self: Dir, sub_path_w: []const u16, flags: File.CreateFlags)
1056 @as(u32, w.FILE_OVERWRITE_IF)1035 @as(u32, w.FILE_OVERWRITE_IF)
1057 else1036 else
1058 @as(u32, w.FILE_OPEN_IF),1037 @as(u32, w.FILE_OPEN_IF),
1059 .io_mode = flags.intended_io_mode,
1060 }),1038 }),
1061 .capable_io_mode = std.io.default_mode,
1062 .intended_io_mode = flags.intended_io_mode,
1063 };1039 };
1064 errdefer file.close();1040 errdefer file.close();
1065 var io: w.IO_STATUS_BLOCK = undefined;1041 var io: w.IO_STATUS_BLOCK = undefined;
...@@ -1276,7 +1252,6 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) ![]u8 {...@@ -1276,7 +1252,6 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) ![]u8 {
1276 .access_mask = access_mask,1252 .access_mask = access_mask,
1277 .share_access = share_access,1253 .share_access = share_access,
1278 .creation = creation,1254 .creation = creation,
1279 .io_mode = .blocking,
1280 .filter = .any,1255 .filter = .any,
1281 }) catch |err| switch (err) {1256 }) catch |err| switch (err) {
1282 error.WouldBlock => unreachable,1257 error.WouldBlock => unreachable,
...@@ -1449,11 +1424,7 @@ pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenDirOptions) Ope...@@ -1449,11 +1424,7 @@ pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenDirOptions) Ope
14491424
1450/// `flags` must contain `posix.O.DIRECTORY`.1425/// `flags` must contain `posix.O.DIRECTORY`.
1451fn openDirFlagsZ(self: Dir, sub_path_c: [*:0]const u8, flags: u32) OpenError!Dir {1426fn openDirFlagsZ(self: Dir, sub_path_c: [*:0]const u8, flags: u32) OpenError!Dir {
1452 const result = if (fs.need_async_thread)1427 const fd = posix.openatZ(self.fd, sub_path_c, flags, 0) catch |err| switch (err) {
1453 std.event.Loop.instance.?.openatZ(self.fd, sub_path_c, flags, 0)
1454 else
1455 posix.openatZ(self.fd, sub_path_c, flags, 0);
1456 const fd = result catch |err| switch (err) {
1457 error.FileTooBig => unreachable, // can't happen for directories1428 error.FileTooBig => unreachable, // can't happen for directories
1458 error.IsDir => unreachable, // we're providing O.DIRECTORY1429 error.IsDir => unreachable, // we're providing O.DIRECTORY
1459 error.NoSpaceLeft => unreachable, // not providing O.CREAT1430 error.NoSpaceLeft => unreachable, // not providing O.CREAT
...@@ -2270,10 +2241,7 @@ pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) Access...@@ -2270,10 +2241,7 @@ pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) Access
2270 .write_only => @as(u32, posix.W_OK),2241 .write_only => @as(u32, posix.W_OK),
2271 .read_write => @as(u32, posix.R_OK | posix.W_OK),2242 .read_write => @as(u32, posix.R_OK | posix.W_OK),
2272 };2243 };
2273 const result = if (fs.need_async_thread and flags.intended_io_mode != .blocking)2244 const result = posix.faccessatZ(self.fd, sub_path, os_mode, 0);
2274 std.event.Loop.instance.?.faccessatZ(self.fd, sub_path, os_mode, 0)
2275 else
2276 posix.faccessatZ(self.fd, sub_path, os_mode, 0);
2277 return result;2245 return result;
2278}2246}
22792247
...@@ -2457,10 +2425,7 @@ pub const Stat = File.Stat;...@@ -2457,10 +2425,7 @@ pub const Stat = File.Stat;
2457pub const StatError = File.StatError;2425pub const StatError = File.StatError;
24582426
2459pub fn stat(self: Dir) StatError!Stat {2427pub fn stat(self: Dir) StatError!Stat {
2460 const file: File = .{2428 const file: File = .{ .handle = self.fd };
2461 .handle = self.fd,
2462 .capable_io_mode = .blocking,
2463 };
2464 return file.stat();2429 return file.stat();
2465}2430}
24662431
...@@ -2496,10 +2461,7 @@ pub const ChmodError = File.ChmodError;...@@ -2496,10 +2461,7 @@ pub const ChmodError = File.ChmodError;
2496/// of the directory. Additionally, the directory must have been opened2461/// of the directory. Additionally, the directory must have been opened
2497/// with `OpenDirOptions{ .iterate = true }`.2462/// with `OpenDirOptions{ .iterate = true }`.
2498pub fn chmod(self: Dir, new_mode: File.Mode) ChmodError!void {2463pub fn chmod(self: Dir, new_mode: File.Mode) ChmodError!void {
2499 const file: File = .{2464 const file: File = .{ .handle = self.fd };
2500 .handle = self.fd,
2501 .capable_io_mode = .blocking,
2502 };
2503 try file.chmod(new_mode);2465 try file.chmod(new_mode);
2504}2466}
25052467
...@@ -2510,10 +2472,7 @@ pub fn chmod(self: Dir, new_mode: File.Mode) ChmodError!void {...@@ -2510,10 +2472,7 @@ pub fn chmod(self: Dir, new_mode: File.Mode) ChmodError!void {
2510/// must have been opened with `OpenDirOptions{ .iterate = true }`. If the2472/// must have been opened with `OpenDirOptions{ .iterate = true }`. If the
2511/// owner or group is specified as `null`, the ID is not changed.2473/// owner or group is specified as `null`, the ID is not changed.
2512pub fn chown(self: Dir, owner: ?File.Uid, group: ?File.Gid) ChownError!void {2474pub fn chown(self: Dir, owner: ?File.Uid, group: ?File.Gid) ChownError!void {
2513 const file: File = .{2475 const file: File = .{ .handle = self.fd };
2514 .handle = self.fd,
2515 .capable_io_mode = .blocking,
2516 };
2517 try file.chown(owner, group);2476 try file.chown(owner, group);
2518}2477}
25192478
...@@ -2525,10 +2484,7 @@ pub const SetPermissionsError = File.SetPermissionsError;...@@ -2525,10 +2484,7 @@ pub const SetPermissionsError = File.SetPermissionsError;
2525/// Sets permissions according to the provided `Permissions` struct.2484/// Sets permissions according to the provided `Permissions` struct.
2526/// This method is *NOT* available on WASI2485/// This method is *NOT* available on WASI
2527pub fn setPermissions(self: Dir, permissions: Permissions) SetPermissionsError!void {2486pub fn setPermissions(self: Dir, permissions: Permissions) SetPermissionsError!void {
2528 const file: File = .{2487 const file: File = .{ .handle = self.fd };
2529 .handle = self.fd,
2530 .capable_io_mode = .blocking,
2531 };
2532 try file.setPermissions(permissions);2488 try file.setPermissions(permissions);
2533}2489}
25342490
...@@ -2537,10 +2493,7 @@ pub const MetadataError = File.MetadataError;...@@ -2537,10 +2493,7 @@ pub const MetadataError = File.MetadataError;
25372493
2538/// Returns a `Metadata` struct, representing the permissions on the directory2494/// Returns a `Metadata` struct, representing the permissions on the directory
2539pub fn metadata(self: Dir) MetadataError!Metadata {2495pub fn metadata(self: Dir) MetadataError!Metadata {
2540 const file: File = .{2496 const file: File = .{ .handle = self.fd };
2541 .handle = self.fd,
2542 .capable_io_mode = .blocking,
2543 };
2544 return try file.metadata();2497 return try file.metadata();
2545}2498}
25462499
lib/std/fs/File.zig+16-80
...@@ -1,20 +1,6 @@...@@ -1,20 +1,6 @@
1/// The OS-specific file descriptor or file handle.1/// The OS-specific file descriptor or file handle.
2handle: Handle,2handle: Handle,
33
4/// On some systems, such as Linux, file system file descriptors are incapable
5/// of non-blocking I/O. This forces us to perform asynchronous I/O on a dedicated thread,
6/// to achieve non-blocking file-system I/O. To do this, `File` must be aware of whether
7/// it is a file system file descriptor, or, more specifically, whether the I/O is always
8/// blocking.
9capable_io_mode: io.ModeOverride = io.default_mode,
10
11/// Furthermore, even when `std.options.io_mode` is async, it is still sometimes desirable
12/// to perform blocking I/O, although not by default. For example, when printing a
13/// stack trace to stderr. This field tracks both by acting as an overriding I/O mode.
14/// When not building in async I/O mode, the type only has the `.blocking` tag, making
15/// it a zero-bit type.
16intended_io_mode: io.ModeOverride = io.default_mode,
17
18pub const Handle = posix.fd_t;4pub const Handle = posix.fd_t;
19pub const Mode = posix.mode_t;5pub const Mode = posix.mode_t;
20pub const INode = posix.ino_t;6pub const INode = posix.ino_t;
...@@ -108,16 +94,8 @@ pub const OpenFlags = struct {...@@ -108,16 +94,8 @@ pub const OpenFlags = struct {
108 /// Sets whether or not to wait until the file is locked to return. If set to true,94 /// Sets whether or not to wait until the file is locked to return. If set to true,
109 /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file95 /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file
110 /// is available to proceed.96 /// is available to proceed.
111 /// In async I/O mode, non-blocking at the OS level is
112 /// determined by `intended_io_mode`, and `true` means `error.WouldBlock` is returned,
113 /// and `false` means `error.WouldBlock` is handled by the event loop.
114 lock_nonblocking: bool = false,97 lock_nonblocking: bool = false,
11598
116 /// Setting this to `.blocking` prevents `O.NONBLOCK` from being passed even
117 /// if `std.io.is_async`. It allows the use of `nosuspend` when calling functions
118 /// related to opening the file, reading, writing, and locking.
119 intended_io_mode: io.ModeOverride = io.default_mode,
120
121 /// Set this to allow the opened file to automatically become the99 /// Set this to allow the opened file to automatically become the
122 /// controlling TTY for the current process.100 /// controlling TTY for the current process.
123 allow_ctty: bool = false,101 allow_ctty: bool = false,
...@@ -172,19 +150,11 @@ pub const CreateFlags = struct {...@@ -172,19 +150,11 @@ pub const CreateFlags = struct {
172 /// Sets whether or not to wait until the file is locked to return. If set to true,150 /// Sets whether or not to wait until the file is locked to return. If set to true,
173 /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file151 /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file
174 /// is available to proceed.152 /// is available to proceed.
175 /// In async I/O mode, non-blocking at the OS level is
176 /// determined by `intended_io_mode`, and `true` means `error.WouldBlock` is returned,
177 /// and `false` means `error.WouldBlock` is handled by the event loop.
178 lock_nonblocking: bool = false,153 lock_nonblocking: bool = false,
179154
180 /// For POSIX systems this is the file system mode the file will155 /// For POSIX systems this is the file system mode the file will
181 /// be created with. On other systems this is always 0.156 /// be created with. On other systems this is always 0.
182 mode: Mode = default_mode,157 mode: Mode = default_mode,
183
184 /// Setting this to `.blocking` prevents `O.NONBLOCK` from being passed even
185 /// if `std.io.is_async`. It allows the use of `nosuspend` when calling functions
186 /// related to opening the file, reading, writing, and locking.
187 intended_io_mode: io.ModeOverride = io.default_mode,
188};158};
189159
190/// Upon success, the stream is in an uninitialized state. To continue using it,160/// Upon success, the stream is in an uninitialized state. To continue using it,
...@@ -192,8 +162,6 @@ pub const CreateFlags = struct {...@@ -192,8 +162,6 @@ pub const CreateFlags = struct {
192pub fn close(self: File) void {162pub fn close(self: File) void {
193 if (is_windows) {163 if (is_windows) {
194 windows.CloseHandle(self.handle);164 windows.CloseHandle(self.handle);
195 } else if (self.capable_io_mode != self.intended_io_mode) {
196 std.event.Loop.instance.?.close(self.handle);
197 } else {165 } else {
198 posix.close(self.handle);166 posix.close(self.handle);
199 }167 }
...@@ -1013,14 +981,10 @@ pub const PReadError = posix.PReadError;...@@ -1013,14 +981,10 @@ pub const PReadError = posix.PReadError;
1013981
1014pub fn read(self: File, buffer: []u8) ReadError!usize {982pub fn read(self: File, buffer: []u8) ReadError!usize {
1015 if (is_windows) {983 if (is_windows) {
1016 return windows.ReadFile(self.handle, buffer, null, self.intended_io_mode);984 return windows.ReadFile(self.handle, buffer, null);
1017 }985 }
1018986
1019 if (self.intended_io_mode == .blocking) {987 return posix.read(self.handle, buffer);
1020 return posix.read(self.handle, buffer);
1021 } else {
1022 return std.event.Loop.instance.?.read(self.handle, buffer, self.capable_io_mode != self.intended_io_mode);
1023 }
1024}988}
1025989
1026/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it990/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
...@@ -1039,14 +1003,10 @@ pub fn readAll(self: File, buffer: []u8) ReadError!usize {...@@ -1039,14 +1003,10 @@ pub fn readAll(self: File, buffer: []u8) ReadError!usize {
1039/// https://github.com/ziglang/zig/issues/127831003/// https://github.com/ziglang/zig/issues/12783
1040pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {1004pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
1041 if (is_windows) {1005 if (is_windows) {
1042 return windows.ReadFile(self.handle, buffer, offset, self.intended_io_mode);1006 return windows.ReadFile(self.handle, buffer, offset);
1043 }1007 }
10441008
1045 if (self.intended_io_mode == .blocking) {1009 return posix.pread(self.handle, buffer, offset);
1046 return posix.pread(self.handle, buffer, offset);
1047 } else {
1048 return std.event.Loop.instance.?.pread(self.handle, buffer, offset, self.capable_io_mode != self.intended_io_mode);
1049 }
1050}1010}
10511011
1052/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it1012/// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
...@@ -1069,14 +1029,10 @@ pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {...@@ -1069,14 +1029,10 @@ pub fn readv(self: File, iovecs: []const posix.iovec) ReadError!usize {
1069 // TODO improve this to use ReadFileScatter1029 // TODO improve this to use ReadFileScatter
1070 if (iovecs.len == 0) return @as(usize, 0);1030 if (iovecs.len == 0) return @as(usize, 0);
1071 const first = iovecs[0];1031 const first = iovecs[0];
1072 return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], null, self.intended_io_mode);1032 return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], null);
1073 }1033 }
10741034
1075 if (self.intended_io_mode == .blocking) {1035 return posix.readv(self.handle, iovecs);
1076 return posix.readv(self.handle, iovecs);
1077 } else {
1078 return std.event.Loop.instance.?.readv(self.handle, iovecs, self.capable_io_mode != self.intended_io_mode);
1079 }
1080}1036}
10811037
1082/// Returns the number of bytes read. If the number read is smaller than the total bytes1038/// Returns the number of bytes read. If the number read is smaller than the total bytes
...@@ -1129,14 +1085,10 @@ pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!u...@@ -1129,14 +1085,10 @@ pub fn preadv(self: File, iovecs: []const posix.iovec, offset: u64) PReadError!u
1129 // TODO improve this to use ReadFileScatter1085 // TODO improve this to use ReadFileScatter
1130 if (iovecs.len == 0) return @as(usize, 0);1086 if (iovecs.len == 0) return @as(usize, 0);
1131 const first = iovecs[0];1087 const first = iovecs[0];
1132 return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], offset, self.intended_io_mode);1088 return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], offset);
1133 }1089 }
11341090
1135 if (self.intended_io_mode == .blocking) {1091 return posix.preadv(self.handle, iovecs, offset);
1136 return posix.preadv(self.handle, iovecs, offset);
1137 } else {
1138 return std.event.Loop.instance.?.preadv(self.handle, iovecs, offset, self.capable_io_mode != self.intended_io_mode);
1139 }
1140}1092}
11411093
1142/// Returns the number of bytes read. If the number read is smaller than the total bytes1094/// Returns the number of bytes read. If the number read is smaller than the total bytes
...@@ -1173,14 +1125,10 @@ pub const PWriteError = posix.PWriteError;...@@ -1173,14 +1125,10 @@ pub const PWriteError = posix.PWriteError;
11731125
1174pub fn write(self: File, bytes: []const u8) WriteError!usize {1126pub fn write(self: File, bytes: []const u8) WriteError!usize {
1175 if (is_windows) {1127 if (is_windows) {
1176 return windows.WriteFile(self.handle, bytes, null, self.intended_io_mode);1128 return windows.WriteFile(self.handle, bytes, null);
1177 }1129 }
11781130
1179 if (self.intended_io_mode == .blocking) {1131 return posix.write(self.handle, bytes);
1180 return posix.write(self.handle, bytes);
1181 } else {
1182 return std.event.Loop.instance.?.write(self.handle, bytes, self.capable_io_mode != self.intended_io_mode);
1183 }
1184}1132}
11851133
1186pub fn writeAll(self: File, bytes: []const u8) WriteError!void {1134pub fn writeAll(self: File, bytes: []const u8) WriteError!void {
...@@ -1194,14 +1142,10 @@ pub fn writeAll(self: File, bytes: []const u8) WriteError!void {...@@ -1194,14 +1142,10 @@ pub fn writeAll(self: File, bytes: []const u8) WriteError!void {
1194/// https://github.com/ziglang/zig/issues/127831142/// https://github.com/ziglang/zig/issues/12783
1195pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {1143pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {
1196 if (is_windows) {1144 if (is_windows) {
1197 return windows.WriteFile(self.handle, bytes, offset, self.intended_io_mode);1145 return windows.WriteFile(self.handle, bytes, offset);
1198 }1146 }
11991147
1200 if (self.intended_io_mode == .blocking) {1148 return posix.pwrite(self.handle, bytes, offset);
1201 return posix.pwrite(self.handle, bytes, offset);
1202 } else {
1203 return std.event.Loop.instance.?.pwrite(self.handle, bytes, offset, self.capable_io_mode != self.intended_io_mode);
1204 }
1205}1149}
12061150
1207/// On Windows, this function currently does alter the file pointer.1151/// On Windows, this function currently does alter the file pointer.
...@@ -1220,14 +1164,10 @@ pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {...@@ -1220,14 +1164,10 @@ pub fn writev(self: File, iovecs: []const posix.iovec_const) WriteError!usize {
1220 // TODO improve this to use WriteFileScatter1164 // TODO improve this to use WriteFileScatter
1221 if (iovecs.len == 0) return @as(usize, 0);1165 if (iovecs.len == 0) return @as(usize, 0);
1222 const first = iovecs[0];1166 const first = iovecs[0];
1223 return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], null, self.intended_io_mode);1167 return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], null);
1224 }1168 }
12251169
1226 if (self.intended_io_mode == .blocking) {1170 return posix.writev(self.handle, iovecs);
1227 return posix.writev(self.handle, iovecs);
1228 } else {
1229 return std.event.Loop.instance.?.writev(self.handle, iovecs, self.capable_io_mode != self.intended_io_mode);
1230 }
1231}1171}
12321172
1233/// The `iovecs` parameter is mutable because:1173/// The `iovecs` parameter is mutable because:
...@@ -1271,14 +1211,10 @@ pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError...@@ -1271,14 +1211,10 @@ pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError
1271 // TODO improve this to use WriteFileScatter1211 // TODO improve this to use WriteFileScatter
1272 if (iovecs.len == 0) return @as(usize, 0);1212 if (iovecs.len == 0) return @as(usize, 0);
1273 const first = iovecs[0];1213 const first = iovecs[0];
1274 return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], offset, self.intended_io_mode);1214 return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], offset);
1275 }1215 }
12761216
1277 if (self.intended_io_mode == .blocking) {1217 return posix.pwritev(self.handle, iovecs, offset);
1278 return posix.pwritev(self.handle, iovecs, offset);
1279 } else {
1280 return std.event.Loop.instance.?.pwritev(self.handle, iovecs, offset, self.capable_io_mode != self.intended_io_mode);
1281 }
1282}1218}
12831219
1284/// The `iovecs` parameter is mutable because this function needs to mutate the fields in1220/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
lib/std/fs/test.zig-5
...@@ -1508,11 +1508,6 @@ test "open file with exclusive and shared nonblocking lock" {...@@ -1508,11 +1508,6 @@ test "open file with exclusive and shared nonblocking lock" {
1508test "open file with exclusive lock twice, make sure second lock waits" {1508test "open file with exclusive lock twice, make sure second lock waits" {
1509 if (builtin.single_threaded) return error.SkipZigTest;1509 if (builtin.single_threaded) return error.SkipZigTest;
15101510
1511 if (std.io.is_async) {
1512 // This test starts its own threads and is not compatible with async I/O.
1513 return error.SkipZigTest;
1514 }
1515
1516 try testWithAllSupportedPathTypes(struct {1511 try testWithAllSupportedPathTypes(struct {
1517 fn impl(ctx: *TestContext) !void {1512 fn impl(ctx: *TestContext) !void {
1518 const filename = try ctx.transformPath("file_lock_test.txt");1513 const filename = try ctx.transformPath("file_lock_test.txt");
lib/std/io.zig+3-36
...@@ -12,21 +12,6 @@ const meta = std.meta;...@@ -12,21 +12,6 @@ const meta = std.meta;
12const File = std.fs.File;12const File = std.fs.File;
13const Allocator = std.mem.Allocator;13const Allocator = std.mem.Allocator;
1414
15pub const Mode = enum {
16 /// I/O operates normally, waiting for the operating system syscalls to complete.
17 blocking,
18
19 /// I/O functions are generated async and rely on a global event loop. Event-based I/O.
20 evented,
21};
22
23pub const is_async = false;
24
25/// This is an enum value to use for I/O mode at runtime, since it takes up zero bytes at runtime,
26/// and makes expressions comptime-known when `is_async` is `false`.
27pub const ModeOverride = if (is_async) Mode else enum { blocking };
28pub const default_mode: ModeOverride = if (is_async) Mode.evented else .blocking;
29
30fn getStdOutHandle() os.fd_t {15fn getStdOutHandle() os.fd_t {
31 if (builtin.os.tag == .windows) {16 if (builtin.os.tag == .windows) {
32 if (builtin.zig_backend == .stage2_aarch64) {17 if (builtin.zig_backend == .stage2_aarch64) {
...@@ -43,14 +28,8 @@ fn getStdOutHandle() os.fd_t {...@@ -43,14 +28,8 @@ fn getStdOutHandle() os.fd_t {
43 return os.STDOUT_FILENO;28 return os.STDOUT_FILENO;
44}29}
4530
46/// TODO: async stdout on windows without a dedicated thread.
47/// https://github.com/ziglang/zig/pull/4816#issuecomment-604521023
48pub fn getStdOut() File {31pub fn getStdOut() File {
49 return File{32 return File{ .handle = getStdOutHandle() };
50 .handle = getStdOutHandle(),
51 .capable_io_mode = .blocking,
52 .intended_io_mode = default_mode,
53 };
54}33}
5534
56fn getStdErrHandle() os.fd_t {35fn getStdErrHandle() os.fd_t {
...@@ -69,14 +48,8 @@ fn getStdErrHandle() os.fd_t {...@@ -69,14 +48,8 @@ fn getStdErrHandle() os.fd_t {
69 return os.STDERR_FILENO;48 return os.STDERR_FILENO;
70}49}
7150
72/// This returns a `File` that is configured to block with every write, in order
73/// to facilitate better debugging. This can be changed by modifying the `intended_io_mode` field.
74pub fn getStdErr() File {51pub fn getStdErr() File {
75 return File{52 return File{ .handle = getStdErrHandle() };
76 .handle = getStdErrHandle(),
77 .capable_io_mode = .blocking,
78 .intended_io_mode = .blocking,
79 };
80}53}
8154
82fn getStdInHandle() os.fd_t {55fn getStdInHandle() os.fd_t {
...@@ -95,14 +68,8 @@ fn getStdInHandle() os.fd_t {...@@ -95,14 +68,8 @@ fn getStdInHandle() os.fd_t {
95 return os.STDIN_FILENO;68 return os.STDIN_FILENO;
96}69}
9770
98/// TODO: async stdin on windows without a dedicated thread.
99/// https://github.com/ziglang/zig/pull/4816#issuecomment-604521023
100pub fn getStdIn() File {71pub fn getStdIn() File {
101 return File{72 return File{ .handle = getStdInHandle() };
102 .handle = getStdInHandle(),
103 .capable_io_mode = .blocking,
104 .intended_io_mode = default_mode,
105 };
106}73}
10774
108pub fn GenericReader(75pub fn GenericReader(
lib/std/net.zig+16-63
...@@ -651,7 +651,7 @@ pub const Ip6Address = extern struct {...@@ -651,7 +651,7 @@ pub const Ip6Address = extern struct {
651};651};
652652
653pub fn connectUnixSocket(path: []const u8) !Stream {653pub fn connectUnixSocket(path: []const u8) !Stream {
654 const opt_non_block = if (std.io.is_async) os.SOCK.NONBLOCK else 0;654 const opt_non_block = 0;
655 const sockfd = try os.socket(655 const sockfd = try os.socket(
656 os.AF.UNIX,656 os.AF.UNIX,
657 os.SOCK.STREAM | os.SOCK.CLOEXEC | opt_non_block,657 os.SOCK.STREAM | os.SOCK.CLOEXEC | opt_non_block,
...@@ -660,17 +660,9 @@ pub fn connectUnixSocket(path: []const u8) !Stream {...@@ -660,17 +660,9 @@ pub fn connectUnixSocket(path: []const u8) !Stream {
660 errdefer os.closeSocket(sockfd);660 errdefer os.closeSocket(sockfd);
661661
662 var addr = try std.net.Address.initUnix(path);662 var addr = try std.net.Address.initUnix(path);
663 try os.connect(sockfd, &addr.any, addr.getOsSockLen());
663664
664 if (std.io.is_async) {665 return Stream{ .handle = sockfd };
665 const loop = std.event.Loop.instance orelse return error.WouldBlock;
666 try loop.connect(sockfd, &addr.any, addr.getOsSockLen());
667 } else {
668 try os.connect(sockfd, &addr.any, addr.getOsSockLen());
669 }
670
671 return Stream{
672 .handle = sockfd,
673 };
674}666}
675667
676fn if_nametoindex(name: []const u8) IPv6InterfaceError!u32 {668fn if_nametoindex(name: []const u8) IPv6InterfaceError!u32 {
...@@ -742,18 +734,13 @@ pub fn tcpConnectToHost(allocator: mem.Allocator, name: []const u8, port: u16) T...@@ -742,18 +734,13 @@ pub fn tcpConnectToHost(allocator: mem.Allocator, name: []const u8, port: u16) T
742pub const TcpConnectToAddressError = std.os.SocketError || std.os.ConnectError;734pub const TcpConnectToAddressError = std.os.SocketError || std.os.ConnectError;
743735
744pub fn tcpConnectToAddress(address: Address) TcpConnectToAddressError!Stream {736pub fn tcpConnectToAddress(address: Address) TcpConnectToAddressError!Stream {
745 const nonblock = if (std.io.is_async) os.SOCK.NONBLOCK else 0;737 const nonblock = 0;
746 const sock_flags = os.SOCK.STREAM | nonblock |738 const sock_flags = os.SOCK.STREAM | nonblock |
747 (if (builtin.target.os.tag == .windows) 0 else os.SOCK.CLOEXEC);739 (if (builtin.target.os.tag == .windows) 0 else os.SOCK.CLOEXEC);
748 const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO.TCP);740 const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO.TCP);
749 errdefer os.closeSocket(sockfd);741 errdefer os.closeSocket(sockfd);
750742
751 if (std.io.is_async) {743 try os.connect(sockfd, &address.any, address.getOsSockLen());
752 const loop = std.event.Loop.instance orelse return error.WouldBlock;
753 try loop.connect(sockfd, &address.any, address.getOsSockLen());
754 } else {
755 try os.connect(sockfd, &address.any, address.getOsSockLen());
756 }
757744
758 return Stream{ .handle = sockfd };745 return Stream{ .handle = sockfd };
759}746}
...@@ -1618,11 +1605,7 @@ fn resMSendRc(...@@ -1618,11 +1605,7 @@ fn resMSendRc(
1618 if (answers[i].len == 0) {1605 if (answers[i].len == 0) {
1619 var j: usize = 0;1606 var j: usize = 0;
1620 while (j < ns.len) : (j += 1) {1607 while (j < ns.len) : (j += 1) {
1621 if (std.io.is_async) {1608 _ = os.sendto(fd, queries[i], os.MSG.NOSIGNAL, &ns[j].any, sl) catch undefined;
1622 _ = std.event.Loop.instance.?.sendto(fd, queries[i], os.MSG.NOSIGNAL, &ns[j].any, sl) catch undefined;
1623 } else {
1624 _ = os.sendto(fd, queries[i], os.MSG.NOSIGNAL, &ns[j].any, sl) catch undefined;
1625 }
1626 }1609 }
1627 }1610 }
1628 }1611 }
...@@ -1637,10 +1620,7 @@ fn resMSendRc(...@@ -1637,10 +1620,7 @@ fn resMSendRc(
16371620
1638 while (true) {1621 while (true) {
1639 var sl_copy = sl;1622 var sl_copy = sl;
1640 const rlen = if (std.io.is_async)1623 const rlen = os.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break;
1641 std.event.Loop.instance.?.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break
1642 else
1643 os.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break;
16441624
1645 // Ignore non-identifiable packets1625 // Ignore non-identifiable packets
1646 if (rlen < 4) continue;1626 if (rlen < 4) continue;
...@@ -1666,11 +1646,7 @@ fn resMSendRc(...@@ -1666,11 +1646,7 @@ fn resMSendRc(
1666 0, 3 => {},1646 0, 3 => {},
1667 2 => if (servfail_retry != 0) {1647 2 => if (servfail_retry != 0) {
1668 servfail_retry -= 1;1648 servfail_retry -= 1;
1669 if (std.io.is_async) {1649 _ = os.sendto(fd, queries[i], os.MSG.NOSIGNAL, &ns[j].any, sl) catch undefined;
1670 _ = std.event.Loop.instance.?.sendto(fd, queries[i], os.MSG.NOSIGNAL, &ns[j].any, sl) catch undefined;
1671 } else {
1672 _ = os.sendto(fd, queries[i], os.MSG.NOSIGNAL, &ns[j].any, sl) catch undefined;
1673 }
1674 },1650 },
1675 else => continue,1651 else => continue,
1676 }1652 }
...@@ -1778,14 +1754,10 @@ pub const Stream = struct {...@@ -1778,14 +1754,10 @@ pub const Stream = struct {
17781754
1779 pub fn read(self: Stream, buffer: []u8) ReadError!usize {1755 pub fn read(self: Stream, buffer: []u8) ReadError!usize {
1780 if (builtin.os.tag == .windows) {1756 if (builtin.os.tag == .windows) {
1781 return os.windows.ReadFile(self.handle, buffer, null, io.default_mode);1757 return os.windows.ReadFile(self.handle, buffer, null);
1782 }1758 }
17831759
1784 if (std.io.is_async) {1760 return os.read(self.handle, buffer);
1785 return std.event.Loop.instance.?.read(self.handle, buffer, false);
1786 } else {
1787 return os.read(self.handle, buffer);
1788 }
1789 }1761 }
17901762
1791 pub fn readv(s: Stream, iovecs: []const os.iovec) ReadError!usize {1763 pub fn readv(s: Stream, iovecs: []const os.iovec) ReadError!usize {
...@@ -1793,7 +1765,7 @@ pub const Stream = struct {...@@ -1793,7 +1765,7 @@ pub const Stream = struct {
1793 // TODO improve this to use ReadFileScatter1765 // TODO improve this to use ReadFileScatter
1794 if (iovecs.len == 0) return @as(usize, 0);1766 if (iovecs.len == 0) return @as(usize, 0);
1795 const first = iovecs[0];1767 const first = iovecs[0];
1796 return os.windows.ReadFile(s.handle, first.iov_base[0..first.iov_len], null, io.default_mode);1768 return os.windows.ReadFile(s.handle, first.iov_base[0..first.iov_len], null);
1797 }1769 }
17981770
1799 return os.readv(s.handle, iovecs);1771 return os.readv(s.handle, iovecs);
...@@ -1827,14 +1799,10 @@ pub const Stream = struct {...@@ -1827,14 +1799,10 @@ pub const Stream = struct {
1827 /// use non-blocking I/O.1799 /// use non-blocking I/O.
1828 pub fn write(self: Stream, buffer: []const u8) WriteError!usize {1800 pub fn write(self: Stream, buffer: []const u8) WriteError!usize {
1829 if (builtin.os.tag == .windows) {1801 if (builtin.os.tag == .windows) {
1830 return os.windows.WriteFile(self.handle, buffer, null, io.default_mode);1802 return os.windows.WriteFile(self.handle, buffer, null);
1831 }1803 }
18321804
1833 if (std.io.is_async) {1805 return os.write(self.handle, buffer);
1834 return std.event.Loop.instance.?.write(self.handle, buffer, false);
1835 } else {
1836 return os.write(self.handle, buffer);
1837 }
1838 }1806 }
18391807
1840 pub fn writeAll(self: Stream, bytes: []const u8) WriteError!void {1808 pub fn writeAll(self: Stream, bytes: []const u8) WriteError!void {
...@@ -1847,15 +1815,7 @@ pub const Stream = struct {...@@ -1847,15 +1815,7 @@ pub const Stream = struct {
1847 /// See https://github.com/ziglang/zig/issues/76991815 /// See https://github.com/ziglang/zig/issues/7699
1848 /// See equivalent function: `std.fs.File.writev`.1816 /// See equivalent function: `std.fs.File.writev`.
1849 pub fn writev(self: Stream, iovecs: []const os.iovec_const) WriteError!usize {1817 pub fn writev(self: Stream, iovecs: []const os.iovec_const) WriteError!usize {
1850 if (std.io.is_async) {1818 return os.writev(self.handle, iovecs);
1851 // TODO improve to actually take advantage of writev syscall, if available.
1852 if (iovecs.len == 0) return 0;
1853 const first_buffer = iovecs[0].iov_base[0..iovecs[0].iov_len];
1854 try self.write(first_buffer);
1855 return first_buffer.len;
1856 } else {
1857 return os.writev(self.handle, iovecs);
1858 }
1859 }1819 }
18601820
1861 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in1821 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in
...@@ -1927,7 +1887,7 @@ pub const StreamServer = struct {...@@ -1927,7 +1887,7 @@ pub const StreamServer = struct {
1927 }1887 }
19281888
1929 pub fn listen(self: *StreamServer, address: Address) !void {1889 pub fn listen(self: *StreamServer, address: Address) !void {
1930 const nonblock = if (std.io.is_async) os.SOCK.NONBLOCK else 0;1890 const nonblock = 0;
1931 const sock_flags = os.SOCK.STREAM | os.SOCK.CLOEXEC | nonblock;1891 const sock_flags = os.SOCK.STREAM | os.SOCK.CLOEXEC | nonblock;
1932 var use_sock_flags: u32 = sock_flags;1892 var use_sock_flags: u32 = sock_flags;
1933 if (self.force_nonblocking) use_sock_flags |= os.SOCK.NONBLOCK;1893 if (self.force_nonblocking) use_sock_flags |= os.SOCK.NONBLOCK;
...@@ -2016,14 +1976,7 @@ pub const StreamServer = struct {...@@ -2016,14 +1976,7 @@ pub const StreamServer = struct {
2016 pub fn accept(self: *StreamServer) AcceptError!Connection {1976 pub fn accept(self: *StreamServer) AcceptError!Connection {
2017 var accepted_addr: Address = undefined;1977 var accepted_addr: Address = undefined;
2018 var adr_len: os.socklen_t = @sizeOf(Address);1978 var adr_len: os.socklen_t = @sizeOf(Address);
2019 const accept_result = blk: {1979 const accept_result = os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK.CLOEXEC);
2020 if (std.io.is_async) {
2021 const loop = std.event.Loop.instance orelse return error.UnexpectedError;
2022 break :blk loop.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK.CLOEXEC);
2023 } else {
2024 break :blk os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK.CLOEXEC);
2025 }
2026 };
20271980
2028 if (accept_result) |fd| {1981 if (accept_result) |fd| {
2029 return Connection{1982 return Connection{
lib/std/net/test.zig-48
...@@ -207,54 +207,6 @@ test "listen on a port, send bytes, receive bytes" {...@@ -207,54 +207,6 @@ test "listen on a port, send bytes, receive bytes" {
207 try testing.expectEqualSlices(u8, "Hello world!", buf[0..n]);207 try testing.expectEqualSlices(u8, "Hello world!", buf[0..n]);
208}208}
209209
210test "listen on a port, send bytes, receive bytes, async-only" {
211 if (!std.io.is_async) return error.SkipZigTest;
212
213 if (builtin.os.tag != .linux and !builtin.os.tag.isDarwin()) {
214 // TODO build abstractions for other operating systems
215 return error.SkipZigTest;
216 }
217
218 // TODO doing this at comptime crashed the compiler
219 const localhost = try net.Address.parseIp("127.0.0.1", 0);
220
221 var server = net.StreamServer.init(net.StreamServer.Options{});
222 defer server.deinit();
223 try server.listen(localhost);
224
225 var server_frame = async testServer(&server);
226 var client_frame = async testClient(server.listen_address);
227
228 try await server_frame;
229 try await client_frame;
230}
231
232test "listen on ipv4 try connect on ipv6 then ipv4" {
233 if (!std.io.is_async) return error.SkipZigTest;
234
235 if (builtin.os.tag != .linux and !builtin.os.tag.isDarwin()) {
236 // TODO build abstractions for other operating systems
237 return error.SkipZigTest;
238 }
239
240 // TODO doing this at comptime crashed the compiler
241 const localhost = try net.Address.parseIp("127.0.0.1", 0);
242
243 var server = net.StreamServer.init(net.StreamServer.Options{});
244 defer server.deinit();
245 try server.listen(localhost);
246
247 var server_frame = async testServer(&server);
248 var client_frame = async testClientToHost(
249 testing.allocator,
250 "localhost",
251 server.listen_address.getPort(),
252 );
253
254 try await server_frame;
255 try await client_frame;
256}
257
258test "listen on an in use port" {210test "listen on an in use port" {
259 if (builtin.os.tag != .linux and comptime !builtin.os.tag.isDarwin()) {211 if (builtin.os.tag != .linux and comptime !builtin.os.tag.isDarwin()) {
260 // TODO build abstractions for other operating systems212 // TODO build abstractions for other operating systems
lib/std/os.zig+6-29
...@@ -683,11 +683,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {...@@ -683,11 +683,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
683 return error.NoDevice;683 return error.NoDevice;
684 }684 }
685685
686 const file = std.fs.File{686 const file = std.fs.File{ .handle = fd };
687 .handle = fd,
688 .capable_io_mode = .blocking,
689 .intended_io_mode = .blocking,
690 };
691 const stream = file.reader();687 const stream = file.reader();
692 stream.readNoEof(buf) catch return error.Unexpected;688 stream.readNoEof(buf) catch return error.Unexpected;
693}689}
...@@ -856,7 +852,7 @@ pub const ReadError = error{...@@ -856,7 +852,7 @@ pub const ReadError = error{
856pub fn read(fd: fd_t, buf: []u8) ReadError!usize {852pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
857 if (buf.len == 0) return 0;853 if (buf.len == 0) return 0;
858 if (builtin.os.tag == .windows) {854 if (builtin.os.tag == .windows) {
859 return windows.ReadFile(fd, buf, null, std.io.default_mode);855 return windows.ReadFile(fd, buf, null);
860 }856 }
861 if (builtin.os.tag == .wasi and !builtin.link_libc) {857 if (builtin.os.tag == .wasi and !builtin.link_libc) {
862 const iovs = [1]iovec{iovec{858 const iovs = [1]iovec{iovec{
...@@ -995,7 +991,7 @@ pub const PReadError = ReadError || error{Unseekable};...@@ -995,7 +991,7 @@ pub const PReadError = ReadError || error{Unseekable};
995pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {991pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
996 if (buf.len == 0) return 0;992 if (buf.len == 0) return 0;
997 if (builtin.os.tag == .windows) {993 if (builtin.os.tag == .windows) {
998 return windows.ReadFile(fd, buf, offset, std.io.default_mode);994 return windows.ReadFile(fd, buf, offset);
999 }995 }
1000 if (builtin.os.tag == .wasi and !builtin.link_libc) {996 if (builtin.os.tag == .wasi and !builtin.link_libc) {
1001 const iovs = [1]iovec{iovec{997 const iovs = [1]iovec{iovec{
...@@ -1257,7 +1253,7 @@ pub const WriteError = error{...@@ -1257,7 +1253,7 @@ pub const WriteError = error{
1257pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {1253pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
1258 if (bytes.len == 0) return 0;1254 if (bytes.len == 0) return 0;
1259 if (builtin.os.tag == .windows) {1255 if (builtin.os.tag == .windows) {
1260 return windows.WriteFile(fd, bytes, null, std.io.default_mode);1256 return windows.WriteFile(fd, bytes, null);
1261 }1257 }
12621258
1263 if (builtin.os.tag == .wasi and !builtin.link_libc) {1259 if (builtin.os.tag == .wasi and !builtin.link_libc) {
...@@ -1415,7 +1411,7 @@ pub const PWriteError = WriteError || error{Unseekable};...@@ -1415,7 +1411,7 @@ pub const PWriteError = WriteError || error{Unseekable};
1415pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {1411pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
1416 if (bytes.len == 0) return 0;1412 if (bytes.len == 0) return 0;
1417 if (builtin.os.tag == .windows) {1413 if (builtin.os.tag == .windows) {
1418 return windows.WriteFile(fd, bytes, offset, std.io.default_mode);1414 return windows.WriteFile(fd, bytes, offset);
1419 }1415 }
1420 if (builtin.os.tag == .wasi and !builtin.link_libc) {1416 if (builtin.os.tag == .wasi and !builtin.link_libc) {
1421 const ciovs = [1]iovec_const{iovec_const{1417 const ciovs = [1]iovec_const{iovec_const{
...@@ -1711,7 +1707,6 @@ fn openOptionsFromFlagsWindows(flags: u32) windows.OpenFileOptions {...@@ -1711,7 +1707,6 @@ fn openOptionsFromFlagsWindows(flags: u32) windows.OpenFileOptions {
17111707
1712 return .{1708 return .{
1713 .access_mask = access_mask,1709 .access_mask = access_mask,
1714 .io_mode = .blocking,
1715 .creation = creation,1710 .creation = creation,
1716 .filter = filter,1711 .filter = filter,
1717 .follow_symlinks = follow_symlinks,1712 .follow_symlinks = follow_symlinks,
...@@ -2797,7 +2792,6 @@ pub fn renameatW(...@@ -2797,7 +2792,6 @@ pub fn renameatW(
2797 .dir = old_dir_fd,2792 .dir = old_dir_fd,
2798 .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE,2793 .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE,
2799 .creation = windows.FILE_OPEN,2794 .creation = windows.FILE_OPEN,
2800 .io_mode = .blocking,
2801 .filter = .any, // This function is supposed to rename both files and directories.2795 .filter = .any, // This function is supposed to rename both files and directories.
2802 .follow_symlinks = false,2796 .follow_symlinks = false,
2803 }) catch |err| switch (err) {2797 }) catch |err| switch (err) {
...@@ -2962,7 +2956,6 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: []const u16, mode: u32) MakeDirError!v...@@ -2962,7 +2956,6 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: []const u16, mode: u32) MakeDirError!v
2962 .dir = dir_fd,2956 .dir = dir_fd,
2963 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,2957 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
2964 .creation = windows.FILE_CREATE,2958 .creation = windows.FILE_CREATE,
2965 .io_mode = .blocking,
2966 .filter = .dir_only,2959 .filter = .dir_only,
2967 }) catch |err| switch (err) {2960 }) catch |err| switch (err) {
2968 error.IsDir => unreachable,2961 error.IsDir => unreachable,
...@@ -3042,7 +3035,6 @@ pub fn mkdirW(dir_path_w: []const u16, mode: u32) MakeDirError!void {...@@ -3042,7 +3035,6 @@ pub fn mkdirW(dir_path_w: []const u16, mode: u32) MakeDirError!void {
3042 .dir = std.fs.cwd().fd,3035 .dir = std.fs.cwd().fd,
3043 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,3036 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
3044 .creation = windows.FILE_CREATE,3037 .creation = windows.FILE_CREATE,
3045 .io_mode = .blocking,
3046 .filter = .dir_only,3038 .filter = .dir_only,
3047 }) catch |err| switch (err) {3039 }) catch |err| switch (err) {
3048 error.IsDir => unreachable,3040 error.IsDir => unreachable,
...@@ -5440,7 +5432,6 @@ pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPat...@@ -5440,7 +5432,6 @@ pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
5440 .access_mask = access_mask,5432 .access_mask = access_mask,
5441 .share_access = share_access,5433 .share_access = share_access,
5442 .creation = creation,5434 .creation = creation,
5443 .io_mode = .blocking,
5444 .filter = .any,5435 .filter = .any,
5445 }) catch |err| switch (err) {5436 }) catch |err| switch (err) {
5446 error.WouldBlock => unreachable,5437 error.WouldBlock => unreachable,
...@@ -6404,12 +6395,7 @@ pub fn sendfile(...@@ -6404,12 +6395,7 @@ pub fn sendfile(
6404 // manually, the same as ENOSYS.6395 // manually, the same as ENOSYS.
6405 break :sf;6396 break :sf;
6406 },6397 },
6407 .AGAIN => if (std.event.Loop.instance) |loop| {6398 .AGAIN => return error.WouldBlock,
6408 loop.waitUntilFdWritable(out_fd);
6409 continue;
6410 } else {
6411 return error.WouldBlock;
6412 },
6413 .IO => return error.InputOutput,6399 .IO => return error.InputOutput,
6414 .PIPE => return error.BrokenPipe,6400 .PIPE => return error.BrokenPipe,
6415 .NOMEM => return error.SystemResources,6401 .NOMEM => return error.SystemResources,
...@@ -6476,18 +6462,12 @@ pub fn sendfile(...@@ -6476,18 +6462,12 @@ pub fn sendfile(
64766462
6477 .AGAIN => if (amt != 0) {6463 .AGAIN => if (amt != 0) {
6478 return amt;6464 return amt;
6479 } else if (std.event.Loop.instance) |loop| {
6480 loop.waitUntilFdWritable(out_fd);
6481 continue;
6482 } else {6465 } else {
6483 return error.WouldBlock;6466 return error.WouldBlock;
6484 },6467 },
64856468
6486 .BUSY => if (amt != 0) {6469 .BUSY => if (amt != 0) {
6487 return amt;6470 return amt;
6488 } else if (std.event.Loop.instance) |loop| {
6489 loop.waitUntilFdReadable(in_fd);
6490 continue;
6491 } else {6471 } else {
6492 return error.WouldBlock;6472 return error.WouldBlock;
6493 },6473 },
...@@ -6550,9 +6530,6 @@ pub fn sendfile(...@@ -6550,9 +6530,6 @@ pub fn sendfile(
65506530
6551 .AGAIN => if (amt != 0) {6531 .AGAIN => if (amt != 0) {
6552 return amt;6532 return amt;
6553 } else if (std.event.Loop.instance) |loop| {
6554 loop.waitUntilFdWritable(out_fd);
6555 continue;
6556 } else {6533 } else {
6557 return error.WouldBlock;6534 return error.WouldBlock;
6558 },6535 },
lib/std/os/windows.zig+50-150
...@@ -49,7 +49,6 @@ pub const OpenFileOptions = struct {...@@ -49,7 +49,6 @@ pub const OpenFileOptions = struct {
49 sa: ?*SECURITY_ATTRIBUTES = null,49 sa: ?*SECURITY_ATTRIBUTES = null,
50 share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,50 share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
51 creation: ULONG,51 creation: ULONG,
52 io_mode: std.io.ModeOverride,
53 /// If true, tries to open path as a directory.52 /// If true, tries to open path as a directory.
54 /// Defaults to false.53 /// Defaults to false.
55 filter: Filter = .file_only,54 filter: Filter = .file_only,
...@@ -95,7 +94,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -95,7 +94,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
95 .SecurityQualityOfService = null,94 .SecurityQualityOfService = null,
96 };95 };
97 var io: IO_STATUS_BLOCK = undefined;96 var io: IO_STATUS_BLOCK = undefined;
98 const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;97 const blocking_flag: ULONG = FILE_SYNCHRONOUS_IO_NONALERT;
99 const file_or_dir_flag: ULONG = switch (options.filter) {98 const file_or_dir_flag: ULONG = switch (options.filter) {
100 .file_only => FILE_NON_DIRECTORY_FILE,99 .file_only => FILE_NON_DIRECTORY_FILE,
101 .dir_only => FILE_DIRECTORY_FILE,100 .dir_only => FILE_DIRECTORY_FILE,
...@@ -119,12 +118,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -119,12 +118,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
119 0,118 0,
120 );119 );
121 switch (rc) {120 switch (rc) {
122 .SUCCESS => {121 .SUCCESS => return result,
123 if (std.io.is_async and options.io_mode == .evented) {
124 _ = CreateIoCompletionPort(result, std.event.Loop.instance.?.os_data.io_port, undefined, undefined) catch undefined;
125 }
126 return result;
127 },
128 .OBJECT_NAME_INVALID => unreachable,122 .OBJECT_NAME_INVALID => unreachable,
129 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,123 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
130 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,124 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
...@@ -457,81 +451,36 @@ pub const ReadFileError = error{...@@ -457,81 +451,36 @@ pub const ReadFileError = error{
457451
458/// If buffer's length exceeds what a Windows DWORD integer can hold, it will be broken into452/// If buffer's length exceeds what a Windows DWORD integer can hold, it will be broken into
459/// multiple non-atomic reads.453/// multiple non-atomic reads.
460pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64, io_mode: std.io.ModeOverride) ReadFileError!usize {454pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64) ReadFileError!usize {
461 if (io_mode != .blocking) {455 while (true) {
462 const loop = std.event.Loop.instance.?;456 const want_read_count: DWORD = @min(@as(DWORD, maxInt(DWORD)), buffer.len);
463 // TODO make getting the file position non-blocking457 var amt_read: DWORD = undefined;
464 const off = if (offset) |o| o else try SetFilePointerEx_CURRENT_get(in_hFile);458 var overlapped_data: OVERLAPPED = undefined;
465 var resume_node = std.event.Loop.ResumeNode.Basic{459 const overlapped: ?*OVERLAPPED = if (offset) |off| blk: {
466 .base = .{460 overlapped_data = .{
467 .id = .Basic,461 .Internal = 0,
468 .handle = @frame(),462 .InternalHigh = 0,
469 .overlapped = OVERLAPPED{463 .DUMMYUNIONNAME = .{
470 .Internal = 0,464 .DUMMYSTRUCTNAME = .{
471 .InternalHigh = 0,465 .Offset = @as(u32, @truncate(off)),
472 .DUMMYUNIONNAME = .{466 .OffsetHigh = @as(u32, @truncate(off >> 32)),
473 .DUMMYSTRUCTNAME = .{
474 .Offset = @as(u32, @truncate(off)),
475 .OffsetHigh = @as(u32, @truncate(off >> 32)),
476 },
477 },467 },
478 .hEvent = null,
479 },468 },
480 },469 .hEvent = null,
481 };470 };
482 loop.beginOneEvent();471 break :blk &overlapped_data;
483 suspend {472 } else null;
484 // TODO handle buffer bigger than DWORD can hold473 if (kernel32.ReadFile(in_hFile, buffer.ptr, want_read_count, &amt_read, overlapped) == 0) {
485 _ = kernel32.ReadFile(in_hFile, buffer.ptr, @as(DWORD, @intCast(buffer.len)), null, &resume_node.base.overlapped);
486 }
487 var bytes_transferred: DWORD = undefined;
488 if (kernel32.GetOverlappedResult(in_hFile, &resume_node.base.overlapped, &bytes_transferred, FALSE) == 0) {
489 switch (kernel32.GetLastError()) {474 switch (kernel32.GetLastError()) {
490 .IO_PENDING => unreachable,475 .IO_PENDING => unreachable,
491 .OPERATION_ABORTED => return error.OperationAborted,476 .OPERATION_ABORTED => continue,
492 .BROKEN_PIPE => return error.BrokenPipe,477 .BROKEN_PIPE => return 0,
478 .HANDLE_EOF => return 0,
493 .NETNAME_DELETED => return error.NetNameDeleted,479 .NETNAME_DELETED => return error.NetNameDeleted,
494 .HANDLE_EOF => return @as(usize, bytes_transferred),
495 else => |err| return unexpectedError(err),480 else => |err| return unexpectedError(err),
496 }481 }
497 }482 }
498 if (offset == null) {483 return amt_read;
499 // TODO make setting the file position non-blocking
500 const new_off = off + bytes_transferred;
501 try SetFilePointerEx_CURRENT(in_hFile, @as(i64, @bitCast(new_off)));
502 }
503 return @as(usize, bytes_transferred);
504 } else {
505 while (true) {
506 const want_read_count: DWORD = @min(@as(DWORD, maxInt(DWORD)), buffer.len);
507 var amt_read: DWORD = undefined;
508 var overlapped_data: OVERLAPPED = undefined;
509 const overlapped: ?*OVERLAPPED = if (offset) |off| blk: {
510 overlapped_data = .{
511 .Internal = 0,
512 .InternalHigh = 0,
513 .DUMMYUNIONNAME = .{
514 .DUMMYSTRUCTNAME = .{
515 .Offset = @as(u32, @truncate(off)),
516 .OffsetHigh = @as(u32, @truncate(off >> 32)),
517 },
518 },
519 .hEvent = null,
520 };
521 break :blk &overlapped_data;
522 } else null;
523 if (kernel32.ReadFile(in_hFile, buffer.ptr, want_read_count, &amt_read, overlapped) == 0) {
524 switch (kernel32.GetLastError()) {
525 .IO_PENDING => unreachable,
526 .OPERATION_ABORTED => continue,
527 .BROKEN_PIPE => return 0,
528 .HANDLE_EOF => return 0,
529 .NETNAME_DELETED => return error.NetNameDeleted,
530 else => |err| return unexpectedError(err),
531 }
532 }
533 return amt_read;
534 }
535 }484 }
536}485}
537486
...@@ -550,85 +499,38 @@ pub fn WriteFile(...@@ -550,85 +499,38 @@ pub fn WriteFile(
550 handle: HANDLE,499 handle: HANDLE,
551 bytes: []const u8,500 bytes: []const u8,
552 offset: ?u64,501 offset: ?u64,
553 io_mode: std.io.ModeOverride,
554) WriteFileError!usize {502) WriteFileError!usize {
555 if (std.event.Loop.instance != null and io_mode != .blocking) {503 var bytes_written: DWORD = undefined;
556 const loop = std.event.Loop.instance.?;504 var overlapped_data: OVERLAPPED = undefined;
557 // TODO make getting the file position non-blocking505 const overlapped: ?*OVERLAPPED = if (offset) |off| blk: {
558 const off = if (offset) |o| o else try SetFilePointerEx_CURRENT_get(handle);506 overlapped_data = .{
559 var resume_node = std.event.Loop.ResumeNode.Basic{507 .Internal = 0,
560 .base = .{508 .InternalHigh = 0,
561 .id = .Basic,509 .DUMMYUNIONNAME = .{
562 .handle = @frame(),510 .DUMMYSTRUCTNAME = .{
563 .overlapped = OVERLAPPED{511 .Offset = @as(u32, @truncate(off)),
564 .Internal = 0,512 .OffsetHigh = @as(u32, @truncate(off >> 32)),
565 .InternalHigh = 0,
566 .DUMMYUNIONNAME = .{
567 .DUMMYSTRUCTNAME = .{
568 .Offset = @as(u32, @truncate(off)),
569 .OffsetHigh = @as(u32, @truncate(off >> 32)),
570 },
571 },
572 .hEvent = null,
573 },513 },
574 },514 },
515 .hEvent = null,
575 };516 };
576 loop.beginOneEvent();517 break :blk &overlapped_data;
577 suspend {518 } else null;
578 const adjusted_len = math.cast(DWORD, bytes.len) orelse maxInt(DWORD);519 const adjusted_len = math.cast(u32, bytes.len) orelse maxInt(u32);
579 _ = kernel32.WriteFile(handle, bytes.ptr, adjusted_len, null, &resume_node.base.overlapped);520 if (kernel32.WriteFile(handle, bytes.ptr, adjusted_len, &bytes_written, overlapped) == 0) {
580 }521 switch (kernel32.GetLastError()) {
581 var bytes_transferred: DWORD = undefined;522 .INVALID_USER_BUFFER => return error.SystemResources,
582 if (kernel32.GetOverlappedResult(handle, &resume_node.base.overlapped, &bytes_transferred, FALSE) == 0) {523 .NOT_ENOUGH_MEMORY => return error.SystemResources,
583 switch (kernel32.GetLastError()) {524 .OPERATION_ABORTED => return error.OperationAborted,
584 .IO_PENDING => unreachable,525 .NOT_ENOUGH_QUOTA => return error.SystemResources,
585 .INVALID_USER_BUFFER => return error.SystemResources,526 .IO_PENDING => unreachable,
586 .NOT_ENOUGH_MEMORY => return error.SystemResources,527 .BROKEN_PIPE => return error.BrokenPipe,
587 .OPERATION_ABORTED => return error.OperationAborted,528 .INVALID_HANDLE => return error.NotOpenForWriting,
588 .NOT_ENOUGH_QUOTA => return error.SystemResources,529 .LOCK_VIOLATION => return error.LockViolation,
589 .BROKEN_PIPE => return error.BrokenPipe,530 else => |err| return unexpectedError(err),
590 else => |err| return unexpectedError(err),
591 }
592 }
593 if (offset == null) {
594 // TODO make setting the file position non-blocking
595 const new_off = off + bytes_transferred;
596 try SetFilePointerEx_CURRENT(handle, @as(i64, @bitCast(new_off)));
597 }
598 return bytes_transferred;
599 } else {
600 var bytes_written: DWORD = undefined;
601 var overlapped_data: OVERLAPPED = undefined;
602 const overlapped: ?*OVERLAPPED = if (offset) |off| blk: {
603 overlapped_data = .{
604 .Internal = 0,
605 .InternalHigh = 0,
606 .DUMMYUNIONNAME = .{
607 .DUMMYSTRUCTNAME = .{
608 .Offset = @as(u32, @truncate(off)),
609 .OffsetHigh = @as(u32, @truncate(off >> 32)),
610 },
611 },
612 .hEvent = null,
613 };
614 break :blk &overlapped_data;
615 } else null;
616 const adjusted_len = math.cast(u32, bytes.len) orelse maxInt(u32);
617 if (kernel32.WriteFile(handle, bytes.ptr, adjusted_len, &bytes_written, overlapped) == 0) {
618 switch (kernel32.GetLastError()) {
619 .INVALID_USER_BUFFER => return error.SystemResources,
620 .NOT_ENOUGH_MEMORY => return error.SystemResources,
621 .OPERATION_ABORTED => return error.OperationAborted,
622 .NOT_ENOUGH_QUOTA => return error.SystemResources,
623 .IO_PENDING => unreachable,
624 .BROKEN_PIPE => return error.BrokenPipe,
625 .INVALID_HANDLE => return error.NotOpenForWriting,
626 .LOCK_VIOLATION => return error.LockViolation,
627 else => |err| return unexpectedError(err),
628 }
629 }531 }
630 return bytes_written;
631 }532 }
533 return bytes_written;
632}534}
633535
634pub const SetCurrentDirectoryError = error{536pub const SetCurrentDirectoryError = error{
...@@ -732,7 +634,6 @@ pub fn CreateSymbolicLink(...@@ -732,7 +634,6 @@ pub fn CreateSymbolicLink(
732 .access_mask = SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,634 .access_mask = SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
733 .dir = dir,635 .dir = dir,
734 .creation = FILE_CREATE,636 .creation = FILE_CREATE,
735 .io_mode = .blocking,
736 .filter = if (is_directory) .dir_only else .file_only,637 .filter = if (is_directory) .dir_only else .file_only,
737 }) catch |err| switch (err) {638 }) catch |err| switch (err) {
738 error.IsDir => return error.PathAlreadyExists,639 error.IsDir => return error.PathAlreadyExists,
...@@ -1256,7 +1157,6 @@ pub fn GetFinalPathNameByHandle(...@@ -1256,7 +1157,6 @@ pub fn GetFinalPathNameByHandle(
1256 .access_mask = SYNCHRONIZE,1157 .access_mask = SYNCHRONIZE,
1257 .share_access = FILE_SHARE_READ | FILE_SHARE_WRITE,1158 .share_access = FILE_SHARE_READ | FILE_SHARE_WRITE,
1258 .creation = FILE_OPEN,1159 .creation = FILE_OPEN,
1259 .io_mode = .blocking,
1260 }) catch |err| switch (err) {1160 }) catch |err| switch (err) {
1261 error.IsDir => unreachable,1161 error.IsDir => unreachable,
1262 error.NotDir => unreachable,1162 error.NotDir => unreachable,
lib/std/pdb.zig+1-1
...@@ -513,7 +513,7 @@ pub const Pdb = struct {...@@ -513,7 +513,7 @@ pub const Pdb = struct {
513 };513 };
514514
515 pub fn init(allocator: mem.Allocator, path: []const u8) !Pdb {515 pub fn init(allocator: mem.Allocator, path: []const u8) !Pdb {
516 const file = try fs.cwd().openFile(path, .{ .intended_io_mode = .blocking });516 const file = try fs.cwd().openFile(path, .{});
517 errdefer file.close();517 errdefer file.close();
518518
519 return Pdb{519 return Pdb{
lib/std/time.zig-5
...@@ -9,11 +9,6 @@ pub const epoch = @import("time/epoch.zig");...@@ -9,11 +9,6 @@ pub const epoch = @import("time/epoch.zig");
99
10/// Spurious wakeups are possible and no precision of timing is guaranteed.10/// Spurious wakeups are possible and no precision of timing is guaranteed.
11pub fn sleep(nanoseconds: u64) void {11pub fn sleep(nanoseconds: u64) void {
12 // TODO: opting out of async sleeping?
13 if (std.io.is_async) {
14 return std.event.Loop.instance.?.sleep(nanoseconds);
15 }
16
17 if (builtin.os.tag == .windows) {12 if (builtin.os.tag == .windows) {
18 const big_ms_from_ns = nanoseconds / ns_per_ms;13 const big_ms_from_ns = nanoseconds / ns_per_ms;
19 const ms = math.cast(os.windows.DWORD, big_ms_from_ns) orelse math.maxInt(os.windows.DWORD);14 const ms = math.cast(os.windows.DWORD, big_ms_from_ns) orelse math.maxInt(os.windows.DWORD);
lib/std/zig/Server.zig+2-7
...@@ -38,8 +38,6 @@ pub const Message = struct {...@@ -38,8 +38,6 @@ pub const Message = struct {
38 /// Trailing:38 /// Trailing:
39 /// * name: [tests_len]u3239 /// * name: [tests_len]u32
40 /// - null-terminated string_bytes index40 /// - null-terminated string_bytes index
41 /// * async_frame_len: [tests_len]u32,
42 /// - 0 means not async
43 /// * expected_panic_msg: [tests_len]u32,41 /// * expected_panic_msg: [tests_len]u32,
44 /// - null-terminated string_bytes index42 /// - null-terminated string_bytes index
45 /// - 0 means does not expect pani43 /// - 0 means does not expect pani
...@@ -210,7 +208,6 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {...@@ -210,7 +208,6 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
210208
211pub const TestMetadata = struct {209pub const TestMetadata = struct {
212 names: []u32,210 names: []u32,
213 async_frame_sizes: []u32,
214 expected_panic_msgs: []u32,211 expected_panic_msgs: []u32,
215 string_bytes: []const u8,212 string_bytes: []const u8,
216};213};
...@@ -220,17 +217,16 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {...@@ -220,17 +217,16 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {
220 .tests_len = bswap(@as(u32, @intCast(test_metadata.names.len))),217 .tests_len = bswap(@as(u32, @intCast(test_metadata.names.len))),
221 .string_bytes_len = bswap(@as(u32, @intCast(test_metadata.string_bytes.len))),218 .string_bytes_len = bswap(@as(u32, @intCast(test_metadata.string_bytes.len))),
222 };219 };
220 const trailing = 2;
223 const bytes_len = @sizeOf(OutMessage.TestMetadata) +221 const bytes_len = @sizeOf(OutMessage.TestMetadata) +
224 3 * 4 * test_metadata.names.len + test_metadata.string_bytes.len;222 trailing * @sizeOf(u32) * test_metadata.names.len + test_metadata.string_bytes.len;
225223
226 if (need_bswap) {224 if (need_bswap) {
227 bswap_u32_array(test_metadata.names);225 bswap_u32_array(test_metadata.names);
228 bswap_u32_array(test_metadata.async_frame_sizes);
229 bswap_u32_array(test_metadata.expected_panic_msgs);226 bswap_u32_array(test_metadata.expected_panic_msgs);
230 }227 }
231 defer if (need_bswap) {228 defer if (need_bswap) {
232 bswap_u32_array(test_metadata.names);229 bswap_u32_array(test_metadata.names);
233 bswap_u32_array(test_metadata.async_frame_sizes);
234 bswap_u32_array(test_metadata.expected_panic_msgs);230 bswap_u32_array(test_metadata.expected_panic_msgs);
235 };231 };
236232
...@@ -241,7 +237,6 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {...@@ -241,7 +237,6 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {
241 std.mem.asBytes(&header),237 std.mem.asBytes(&header),
242 // TODO: implement @ptrCast between slices changing the length238 // TODO: implement @ptrCast between slices changing the length
243 std.mem.sliceAsBytes(test_metadata.names),239 std.mem.sliceAsBytes(test_metadata.names),
244 std.mem.sliceAsBytes(test_metadata.async_frame_sizes),
245 std.mem.sliceAsBytes(test_metadata.expected_panic_msgs),240 std.mem.sliceAsBytes(test_metadata.expected_panic_msgs),
246 test_metadata.string_bytes,241 test_metadata.string_bytes,
247 });242 });
lib/std/zig/system/linux.zig+1-1
...@@ -328,7 +328,7 @@ fn CpuinfoParser(comptime impl: anytype) type {...@@ -328,7 +328,7 @@ fn CpuinfoParser(comptime impl: anytype) type {
328}328}
329329
330pub fn detectNativeCpuAndFeatures() ?Target.Cpu {330pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
331 var f = fs.openFileAbsolute("/proc/cpuinfo", .{ .intended_io_mode = .blocking }) catch |err| switch (err) {331 var f = fs.openFileAbsolute("/proc/cpuinfo", .{}) catch |err| switch (err) {
332 else => return null,332 else => return null,
333 };333 };
334 defer f.close();334 defer f.close();
lib/test_runner.zig+2-26
...@@ -4,7 +4,6 @@ const io = std.io;...@@ -4,7 +4,6 @@ const io = std.io;
4const builtin = @import("builtin");4const builtin = @import("builtin");
55
6pub const std_options = .{6pub const std_options = .{
7 .io_mode = builtin.test_io_mode,
8 .logFn = log,7 .logFn = log,
9};8};
109
...@@ -65,24 +64,19 @@ fn mainServer() !void {...@@ -65,24 +64,19 @@ fn mainServer() !void {
65 const test_fns = builtin.test_functions;64 const test_fns = builtin.test_functions;
66 const names = try std.testing.allocator.alloc(u32, test_fns.len);65 const names = try std.testing.allocator.alloc(u32, test_fns.len);
67 defer std.testing.allocator.free(names);66 defer std.testing.allocator.free(names);
68 const async_frame_sizes = try std.testing.allocator.alloc(u32, test_fns.len);
69 defer std.testing.allocator.free(async_frame_sizes);
70 const expected_panic_msgs = try std.testing.allocator.alloc(u32, test_fns.len);67 const expected_panic_msgs = try std.testing.allocator.alloc(u32, test_fns.len);
71 defer std.testing.allocator.free(expected_panic_msgs);68 defer std.testing.allocator.free(expected_panic_msgs);
7269
73 for (test_fns, names, async_frame_sizes, expected_panic_msgs) |test_fn, *name, *async_frame_size, *expected_panic_msg| {70 for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| {
74 name.* = @as(u32, @intCast(string_bytes.items.len));71 name.* = @as(u32, @intCast(string_bytes.items.len));
75 try string_bytes.ensureUnusedCapacity(std.testing.allocator, test_fn.name.len + 1);72 try string_bytes.ensureUnusedCapacity(std.testing.allocator, test_fn.name.len + 1);
76 string_bytes.appendSliceAssumeCapacity(test_fn.name);73 string_bytes.appendSliceAssumeCapacity(test_fn.name);
77 string_bytes.appendAssumeCapacity(0);74 string_bytes.appendAssumeCapacity(0);
78
79 async_frame_size.* = @as(u32, @intCast(test_fn.async_frame_size orelse 0));
80 expected_panic_msg.* = 0;75 expected_panic_msg.* = 0;
81 }76 }
8277
83 try server.serveTestMetadata(.{78 try server.serveTestMetadata(.{
84 .names = names,79 .names = names,
85 .async_frame_sizes = async_frame_sizes,
86 .expected_panic_msgs = expected_panic_msgs,80 .expected_panic_msgs = expected_panic_msgs,
87 .string_bytes = string_bytes.items,81 .string_bytes = string_bytes.items,
88 });82 });
...@@ -93,8 +87,6 @@ fn mainServer() !void {...@@ -93,8 +87,6 @@ fn mainServer() !void {
93 log_err_count = 0;87 log_err_count = 0;
94 const index = try server.receiveBody_u32();88 const index = try server.receiveBody_u32();
95 const test_fn = builtin.test_functions[index];89 const test_fn = builtin.test_functions[index];
96 if (test_fn.async_frame_size != null)
97 @panic("TODO test runner implement async tests");
98 var fail = false;90 var fail = false;
99 var skip = false;91 var skip = false;
100 var leak = false;92 var leak = false;
...@@ -163,23 +155,7 @@ fn mainTerminal() void {...@@ -163,23 +155,7 @@ fn mainTerminal() void {
163 if (!have_tty) {155 if (!have_tty) {
164 std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name });156 std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name });
165 }157 }
166 const result = if (test_fn.async_frame_size) |size| switch (std.options.io_mode) {158 if (test_fn.func()) |_| {
167 .evented => blk: {
168 if (async_frame_buffer.len < size) {
169 std.heap.page_allocator.free(async_frame_buffer);
170 async_frame_buffer = std.heap.page_allocator.alignedAlloc(u8, std.Target.stack_align, size) catch @panic("out of memory");
171 }
172 const casted_fn = @as(fn () callconv(.Async) anyerror!void, @ptrCast(test_fn.func));
173 break :blk await @asyncCall(async_frame_buffer, {}, casted_fn, .{});
174 },
175 .blocking => {
176 skip_count += 1;
177 test_node.end();
178 progress.log("SKIP (async test)\n", .{});
179 continue;
180 },
181 } else test_fn.func();
182 if (result) |_| {
183 ok_count += 1;159 ok_count += 1;
184 test_node.end();160 test_node.end();
185 if (!have_tty) std.debug.print("OK\n", .{});161 if (!have_tty) std.debug.print("OK\n", .{});
src/Builtin.zig-12
...@@ -3,7 +3,6 @@ zig_backend: std.builtin.CompilerBackend,...@@ -3,7 +3,6 @@ zig_backend: std.builtin.CompilerBackend,
3output_mode: std.builtin.OutputMode,3output_mode: std.builtin.OutputMode,
4link_mode: std.builtin.LinkMode,4link_mode: std.builtin.LinkMode,
5is_test: bool,5is_test: bool,
6test_evented_io: bool,
7single_threaded: bool,6single_threaded: bool,
8link_libc: bool,7link_libc: bool,
9link_libcpp: bool,8link_libcpp: bool,
...@@ -222,17 +221,6 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -222,17 +221,6 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
222 \\pub var test_functions: []const std.builtin.TestFn = undefined; // overwritten later221 \\pub var test_functions: []const std.builtin.TestFn = undefined; // overwritten later
223 \\222 \\
224 );223 );
225 if (opts.test_evented_io) {
226 try buffer.appendSlice(
227 \\pub const test_io_mode = .evented;
228 \\
229 );
230 } else {
231 try buffer.appendSlice(
232 \\pub const test_io_mode = .blocking;
233 \\
234 );
235 }
236 }224 }
237}225}
238226
src/Compilation.zig-2
...@@ -1607,7 +1607,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1607,7 +1607,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1607 hash.add(options.config.use_lib_llvm);1607 hash.add(options.config.use_lib_llvm);
1608 hash.add(options.config.dll_export_fns);1608 hash.add(options.config.dll_export_fns);
1609 hash.add(options.config.is_test);1609 hash.add(options.config.is_test);
1610 hash.add(options.config.test_evented_io);
1611 hash.addOptionalBytes(options.test_filter);1610 hash.addOptionalBytes(options.test_filter);
1612 hash.addOptionalBytes(options.test_name_prefix);1611 hash.addOptionalBytes(options.test_name_prefix);
1613 hash.add(options.skip_linker_dependencies);1612 hash.add(options.skip_linker_dependencies);
...@@ -2471,7 +2470,6 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -2471,7 +2470,6 @@ fn addNonIncrementalStuffToCacheManifest(
2471 try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.root_mod, mod.main_mod, .{ .files = man });2470 try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.root_mod, mod.main_mod, .{ .files = man });
24722471
2473 // Synchronize with other matching comments: ZigOnlyHashStuff2472 // Synchronize with other matching comments: ZigOnlyHashStuff
2474 man.hash.add(comp.config.test_evented_io);
2475 man.hash.addOptionalBytes(comp.test_filter);2473 man.hash.addOptionalBytes(comp.test_filter);
2476 man.hash.addOptionalBytes(comp.test_name_prefix);2474 man.hash.addOptionalBytes(comp.test_name_prefix);
2477 man.hash.add(comp.skip_linker_dependencies);2475 man.hash.add(comp.skip_linker_dependencies);
src/Compilation/Config.zig-3
...@@ -54,7 +54,6 @@ import_memory: bool,...@@ -54,7 +54,6 @@ import_memory: bool,
54export_memory: bool,54export_memory: bool,
55shared_memory: bool,55shared_memory: bool,
56is_test: bool,56is_test: bool,
57test_evented_io: bool,
58debug_format: DebugFormat,57debug_format: DebugFormat,
59root_strip: bool,58root_strip: bool,
60root_error_tracing: bool,59root_error_tracing: bool,
...@@ -104,7 +103,6 @@ pub const Options = struct {...@@ -104,7 +103,6 @@ pub const Options = struct {
104 import_memory: ?bool = null,103 import_memory: ?bool = null,
105 export_memory: ?bool = null,104 export_memory: ?bool = null,
106 shared_memory: ?bool = null,105 shared_memory: ?bool = null,
107 test_evented_io: bool = false,
108 debug_format: ?DebugFormat = null,106 debug_format: ?DebugFormat = null,
109 dll_export_fns: ?bool = null,107 dll_export_fns: ?bool = null,
110 rdynamic: ?bool = null,108 rdynamic: ?bool = null,
...@@ -477,7 +475,6 @@ pub fn resolve(options: Options) ResolveError!Config {...@@ -477,7 +475,6 @@ pub fn resolve(options: Options) ResolveError!Config {
477 .output_mode = options.output_mode,475 .output_mode = options.output_mode,
478 .have_zcu = options.have_zcu,476 .have_zcu = options.have_zcu,
479 .is_test = options.is_test,477 .is_test = options.is_test,
480 .test_evented_io = options.test_evented_io,
481 .link_mode = link_mode,478 .link_mode = link_mode,
482 .link_libc = link_libc,479 .link_libc = link_libc,
483 .link_libcpp = link_libcpp,480 .link_libcpp = link_libcpp,
src/Module.zig-6
...@@ -5237,10 +5237,6 @@ pub fn populateTestFunctions(...@@ -5237,10 +5237,6 @@ pub fn populateTestFunctions(
5237 }5237 }
5238 const decl = mod.declPtr(decl_index);5238 const decl = mod.declPtr(decl_index);
5239 const test_fn_ty = decl.ty.slicePtrFieldType(mod).childType(mod);5239 const test_fn_ty = decl.ty.slicePtrFieldType(mod).childType(mod);
5240 const null_usize = try mod.intern(.{ .opt = .{
5241 .ty = try mod.intern(.{ .opt_type = .usize_type }),
5242 .val = .none,
5243 } });
52445240
5245 const array_decl_index = d: {5241 const array_decl_index = d: {
5246 // Add mod.test_functions to an array decl then make the test_functions5242 // Add mod.test_functions to an array decl then make the test_functions
...@@ -5289,8 +5285,6 @@ pub fn populateTestFunctions(...@@ -5289,8 +5285,6 @@ pub fn populateTestFunctions(
5289 } }),5285 } }),
5290 .addr = .{ .decl = test_decl_index },5286 .addr = .{ .decl = test_decl_index },
5291 } }),5287 } }),
5292 // async_frame_size
5293 null_usize,
5294 };5288 };
5295 test_fn_val.* = try mod.intern(.{ .aggregate = .{5289 test_fn_val.* = try mod.intern(.{ .aggregate = .{
5296 .ty = test_fn_ty.toIntern(),5290 .ty = test_fn_ty.toIntern(),
src/Package/Module.zig-1
...@@ -349,7 +349,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -349,7 +349,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
349 .output_mode = options.global.output_mode,349 .output_mode = options.global.output_mode,
350 .link_mode = options.global.link_mode,350 .link_mode = options.global.link_mode,
351 .is_test = options.global.is_test,351 .is_test = options.global.is_test,
352 .test_evented_io = options.global.test_evented_io,
353 .single_threaded = single_threaded,352 .single_threaded = single_threaded,
354 .link_libc = options.global.link_libc,353 .link_libc = options.global.link_libc,
355 .link_libcpp = options.global.link_libcpp,354 .link_libcpp = options.global.link_libcpp,
src/main.zig-2
...@@ -1322,8 +1322,6 @@ fn buildOutputType(...@@ -1322,8 +1322,6 @@ fn buildOutputType(
1322 create_module.each_lib_rpath = false;1322 create_module.each_lib_rpath = false;
1323 } else if (mem.eql(u8, arg, "--test-cmd-bin")) {1323 } else if (mem.eql(u8, arg, "--test-cmd-bin")) {
1324 try test_exec_args.append(null);1324 try test_exec_args.append(null);
1325 } else if (mem.eql(u8, arg, "--test-evented-io")) {
1326 create_module.opts.test_evented_io = true;
1327 } else if (mem.eql(u8, arg, "--test-no-exec")) {1325 } else if (mem.eql(u8, arg, "--test-no-exec")) {
1328 test_no_exec = true;1326 test_no_exec = true;
1329 } else if (mem.eql(u8, arg, "-ftime-report")) {1327 } else if (mem.eql(u8, arg, "-ftime-report")) {