Commit 2272a07ca0
Changed files (6)
lib
lib/std/event/loop.zig
@@ -4,19 +4,27 @@ const root = @import("root");
const assert = std.debug.assert;
const testing = std.testing;
const mem = std.mem;
-const AtomicRmwOp = builtin.AtomicRmwOp;
-const AtomicOrder = builtin.AtomicOrder;
const os = std.os;
const windows = os.windows;
const maxInt = std.math.maxInt;
const Thread = std.Thread;
+const is_windows = std.Target.current.os.tag == .windows;
+
pub const Loop = struct {
next_tick_queue: std.atomic.Queue(anyframe),
os_data: OsData,
final_resume_node: ResumeNode,
pending_event_count: usize,
extra_threads: []*Thread,
+ /// TODO change this to a pool of configurable number of threads
+ /// and rename it to be not file-system-specific. it will become
+ /// a thread pool for turning non-CPU-bound blocking things into
+ /// async things. A fallback for any missing OS-specific API.
+ fs_thread: *Thread,
+ fs_queue: std.atomic.Queue(Request),
+ fs_end_request: Request.Node,
+ fs_thread_wakeup: std.ResetEvent,
/// For resources that have the same lifetime as the `Loop`.
/// This is only used by `Loop` for the thread pool and associated resources.
@@ -143,7 +151,12 @@ pub const Loop = struct {
.handle = undefined,
.overlapped = ResumeNode.overlapped_init,
},
+ .fs_end_request = .{ .data = .{ .msg = .end, .finish = .NoAction } },
+ .fs_queue = std.atomic.Queue(Request).init(),
+ .fs_thread = undefined,
+ .fs_thread_wakeup = std.ResetEvent.init(),
};
+ errdefer self.fs_thread_wakeup.deinit();
errdefer self.arena.deinit();
// We need at least one of these in case the fs thread wants to use onNextTick
@@ -158,10 +171,19 @@ pub const Loop = struct {
try self.initOsData(extra_thread_count);
errdefer self.deinitOsData();
+
+ if (!builtin.single_threaded) {
+ self.fs_thread = try Thread.spawn(self, posixFsRun);
+ }
+ errdefer if (!builtin.single_threaded) {
+ self.posixFsRequest(&self.fs_end_request);
+ self.fs_thread.wait();
+ };
}
pub fn deinit(self: *Loop) void {
self.deinitOsData();
+ self.fs_thread_wakeup.deinit();
self.arena.deinit();
self.* = undefined;
}
@@ -173,21 +195,10 @@ pub const Loop = struct {
const wakeup_bytes = [_]u8{0x1} ** 8;
fn initOsData(self: *Loop, extra_thread_count: usize) InitOsDataError!void {
- switch (builtin.os.tag) {
+ noasync switch (builtin.os.tag) {
.linux => {
- self.os_data.fs_queue = std.atomic.Queue(Request).init();
- self.os_data.fs_queue_item = 0;
- // we need another thread for the file system because Linux does not have an async
- // file system I/O API.
- self.os_data.fs_end_request = Request.Node{
- .data = Request{
- .msg = .end,
- .finish = .NoAction,
- },
- };
-
errdefer {
- while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd);
+ while (self.available_eventfd_resume_nodes.pop()) |node| os.close(node.data.eventfd);
}
for (self.eventfd_resume_nodes) |*eventfd_node| {
eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{
@@ -206,10 +217,10 @@ pub const Loop = struct {
}
self.os_data.epollfd = try os.epoll_create1(os.EPOLL_CLOEXEC);
- errdefer noasync os.close(self.os_data.epollfd);
+ errdefer os.close(self.os_data.epollfd);
self.os_data.final_eventfd = try os.eventfd(0, os.EFD_CLOEXEC | os.EFD_NONBLOCK);
- errdefer noasync os.close(self.os_data.final_eventfd);
+ errdefer os.close(self.os_data.final_eventfd);
self.os_data.final_eventfd_event = os.epoll_event{
.events = os.EPOLLIN,
@@ -222,12 +233,6 @@ pub const Loop = struct {
&self.os_data.final_eventfd_event,
);
- self.os_data.fs_thread = try Thread.spawn(self, posixFsRun);
- errdefer {
- self.posixFsRequest(&self.os_data.fs_end_request);
- self.os_data.fs_thread.wait();
- }
-
if (builtin.single_threaded) {
assert(extra_thread_count == 0);
return;
@@ -236,7 +241,7 @@ pub const Loop = struct {
var extra_thread_index: usize = 0;
errdefer {
// writing 8 bytes to an eventfd cannot fail
- const amt = noasync os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable;
+ const amt = os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable;
assert(amt == wakeup_bytes.len);
while (extra_thread_index != 0) {
extra_thread_index -= 1;
@@ -249,22 +254,7 @@ pub const Loop = struct {
},
.macosx, .freebsd, .netbsd, .dragonfly => {
self.os_data.kqfd = try os.kqueue();
- errdefer noasync os.close(self.os_data.kqfd);
-
- self.os_data.fs_kqfd = try os.kqueue();
- errdefer noasync os.close(self.os_data.fs_kqfd);
-
- self.os_data.fs_queue = std.atomic.Queue(Request).init();
- // we need another thread for the file system because Darwin does not have an async
- // file system I/O API.
- self.os_data.fs_end_request = Request.Node{
- .prev = undefined,
- .next = undefined,
- .data = Request{
- .msg = .end,
- .finish = .NoAction,
- },
- };
+ errdefer os.close(self.os_data.kqfd);
const empty_kevs = &[0]os.Kevent{};
@@ -310,30 +300,6 @@ pub const Loop = struct {
self.os_data.final_kevent.flags = os.EV_ENABLE;
self.os_data.final_kevent.fflags = os.NOTE_TRIGGER;
- self.os_data.fs_kevent_wake = os.Kevent{
- .ident = 0,
- .filter = os.EVFILT_USER,
- .flags = os.EV_ADD | os.EV_ENABLE,
- .fflags = os.NOTE_TRIGGER,
- .data = 0,
- .udata = undefined,
- };
-
- self.os_data.fs_kevent_wait = os.Kevent{
- .ident = 0,
- .filter = os.EVFILT_USER,
- .flags = os.EV_ADD | os.EV_CLEAR,
- .fflags = 0,
- .data = 0,
- .udata = undefined,
- };
-
- self.os_data.fs_thread = try Thread.spawn(self, posixFsRun);
- errdefer {
- self.posixFsRequest(&self.os_data.fs_end_request);
- self.os_data.fs_thread.wait();
- }
-
if (builtin.single_threaded) {
assert(extra_thread_count == 0);
return;
@@ -401,25 +367,24 @@ pub const Loop = struct {
}
},
else => {},
- }
+ };
}
fn deinitOsData(self: *Loop) void {
- switch (builtin.os.tag) {
+ noasync switch (builtin.os.tag) {
.linux => {
- noasync os.close(self.os_data.final_eventfd);
- while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd);
- noasync os.close(self.os_data.epollfd);
+ os.close(self.os_data.final_eventfd);
+ while (self.available_eventfd_resume_nodes.pop()) |node| os.close(node.data.eventfd);
+ os.close(self.os_data.epollfd);
},
.macosx, .freebsd, .netbsd, .dragonfly => {
- noasync os.close(self.os_data.kqfd);
- noasync os.close(self.os_data.fs_kqfd);
+ os.close(self.os_data.kqfd);
},
.windows => {
windows.CloseHandle(self.os_data.io_port);
},
else => {},
- }
+ };
}
/// resume_node must live longer than the anyframe that it holds a reference to.
@@ -635,7 +600,7 @@ pub const Loop = struct {
.freebsd,
.netbsd,
.dragonfly,
- => self.os_data.fs_thread.wait(),
+ => self.fs_thread.wait(),
else => {},
}
@@ -672,23 +637,25 @@ pub const Loop = struct {
/// call finishOneEvent when done
pub fn beginOneEvent(self: *Loop) void {
- _ = @atomicRmw(usize, &self.pending_event_count, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
+ _ = @atomicRmw(usize, &self.pending_event_count, .Add, 1, .SeqCst);
}
pub fn finishOneEvent(self: *Loop) void {
- const prev = @atomicRmw(usize, &self.pending_event_count, AtomicRmwOp.Sub, 1, AtomicOrder.SeqCst);
- if (prev == 1) {
+ noasync {
+ const prev = @atomicRmw(usize, &self.pending_event_count, .Sub, 1, .SeqCst);
+ if (prev != 1) return;
+
// cause all the threads to stop
+ self.posixFsRequest(&self.fs_end_request);
+
switch (builtin.os.tag) {
.linux => {
- self.posixFsRequest(&self.os_data.fs_end_request);
// writing 8 bytes to an eventfd cannot fail
- const amt = noasync os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable;
+ const amt = os.write(self.os_data.final_eventfd, &wakeup_bytes) catch unreachable;
assert(amt == wakeup_bytes.len);
return;
},
.macosx, .freebsd, .netbsd, .dragonfly => {
- self.posixFsRequest(&self.os_data.fs_end_request);
const final_kevent = @as(*const [1]os.Kevent, &self.os_data.final_kevent);
const empty_kevs = &[0]os.Kevent{};
// cannot fail because we already added it and this just enables it
@@ -1041,73 +1008,55 @@ pub const Loop = struct {
fn posixFsRequest(self: *Loop, request_node: *Request.Node) void {
self.beginOneEvent(); // finished in posixFsRun after processing the msg
- self.os_data.fs_queue.put(request_node);
- switch (builtin.os.tag) {
- .macosx, .freebsd, .netbsd, .dragonfly => {
- const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wake);
- const empty_kevs = &[0]os.Kevent{};
- _ = os.kevent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
- },
- .linux => {
- @atomicStore(i32, &self.os_data.fs_queue_item, 1, AtomicOrder.SeqCst);
- const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1);
- switch (os.linux.getErrno(rc)) {
- 0 => {},
- os.EINVAL => unreachable,
- else => unreachable,
- }
- },
- else => @compileError("Unsupported OS"),
- }
+ self.fs_queue.put(request_node);
+ self.fs_thread_wakeup.set();
}
fn posixFsCancel(self: *Loop, request_node: *Request.Node) void {
- if (self.os_data.fs_queue.remove(request_node)) {
+ if (self.fs_queue.remove(request_node)) {
self.finishOneEvent();
}
}
- // TODO make this whole function noasync
- // https://github.com/ziglang/zig/issues/3157
fn posixFsRun(self: *Loop) void {
- while (true) {
- if (builtin.os.tag == .linux) {
- @atomicStore(i32, &self.os_data.fs_queue_item, 0, .SeqCst);
- }
- while (self.os_data.fs_queue.get()) |node| {
+ noasync while (true) {
+ self.fs_thread_wakeup.reset();
+ while (self.fs_queue.get()) |node| {
switch (node.data.msg) {
.end => return,
.read => |*msg| {
- msg.result = noasync os.read(msg.fd, msg.buf);
+ msg.result = os.read(msg.fd, msg.buf);
},
.readv => |*msg| {
- msg.result = noasync os.readv(msg.fd, msg.iov);
+ msg.result = os.readv(msg.fd, msg.iov);
},
.write => |*msg| {
- msg.result = noasync os.write(msg.fd, msg.bytes);
+ msg.result = os.write(msg.fd, msg.bytes);
},
.writev => |*msg| {
- msg.result = noasync os.writev(msg.fd, msg.iov);
+ msg.result = os.writev(msg.fd, msg.iov);
},
.pwritev => |*msg| {
- msg.result = noasync os.pwritev(msg.fd, msg.iov, msg.offset);
+ msg.result = os.pwritev(msg.fd, msg.iov, msg.offset);
},
.pread => |*msg| {
- msg.result = noasync os.pread(msg.fd, msg.buf, msg.offset);
+ msg.result = os.pread(msg.fd, msg.buf, msg.offset);
},
.preadv => |*msg| {
- msg.result = noasync os.preadv(msg.fd, msg.iov, msg.offset);
+ msg.result = os.preadv(msg.fd, msg.iov, msg.offset);
},
.open => |*msg| {
- msg.result = noasync os.openZ(msg.path, msg.flags, msg.mode);
+ if (is_windows) unreachable; // TODO
+ msg.result = os.openZ(msg.path, msg.flags, msg.mode);
},
.openat => |*msg| {
- msg.result = noasync os.openatZ(msg.fd, msg.path, msg.flags, msg.mode);
+ if (is_windows) unreachable; // TODO
+ msg.result = os.openatZ(msg.fd, msg.path, msg.flags, msg.mode);
},
.faccessat => |*msg| {
- msg.result = noasync os.faccessatZ(msg.dirfd, msg.path, msg.mode, msg.flags);
+ msg.result = os.faccessatZ(msg.dirfd, msg.path, msg.mode, msg.flags);
},
- .close => |*msg| noasync os.close(msg.fd),
+ .close => |*msg| os.close(msg.fd),
}
switch (node.data.finish) {
.TickNode => |*tick_node| self.onNextTick(tick_node),
@@ -1115,22 +1064,8 @@ pub const Loop = struct {
}
self.finishOneEvent();
}
- switch (builtin.os.tag) {
- .linux => {
- const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null);
- switch (os.linux.getErrno(rc)) {
- 0, os.EINTR, os.EAGAIN => continue,
- else => unreachable,
- }
- },
- .macosx, .freebsd, .netbsd, .dragonfly => {
- const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wait);
- var out_kevs: [1]os.Kevent = undefined;
- _ = os.kevent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
- },
- else => @compileError("Unsupported OS"),
- }
- }
+ self.fs_thread_wakeup.wait();
+ };
}
const OsData = switch (builtin.os.tag) {
@@ -1146,22 +1081,12 @@ pub const Loop = struct {
const KEventData = struct {
kqfd: i32,
final_kevent: os.Kevent,
- fs_kevent_wake: os.Kevent,
- fs_kevent_wait: os.Kevent,
- fs_thread: *Thread,
- fs_kqfd: i32,
- fs_queue: std.atomic.Queue(Request),
- fs_end_request: Request.Node,
};
const LinuxOsData = struct {
epollfd: i32,
final_eventfd: i32,
final_eventfd_event: os.linux.epoll_event,
- fs_thread: *Thread,
- fs_queue_item: i32,
- fs_queue: std.atomic.Queue(Request),
- fs_end_request: Request.Node,
};
pub const Request = struct {
@@ -1302,11 +1227,11 @@ test "std.event.Loop - basic" {
loop.run();
}
-async fn testEventLoop() i32 {
+fn testEventLoop() i32 {
return 1234;
}
-async fn testEventLoop2(h: anyframe->i32, did_it: *bool) void {
+fn testEventLoop2(h: anyframe->i32, did_it: *bool) void {
const value = await h;
testing.expect(value == 1234);
did_it.* = true;
lib/std/os/windows.zig
@@ -116,10 +116,10 @@ pub const OpenFileOptions = struct {
/// TODO when share_access_nonblocking is false, this implementation uses
/// untinterruptible sleep() to block. This is not the final iteration of the API.
pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE {
- if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
+ if (mem.eql(u16, sub_path_w, ".")) {
return error.IsDir;
}
- if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
+ if (mem.eql(u16, sub_path_w, "..")) {
return error.IsDir;
}
lib/std/debug.zig
@@ -112,39 +112,43 @@ pub fn detectTTYConfig() TTY.Config {
/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
/// TODO multithreaded awareness
pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
- const stderr = getStderrStream();
- if (builtin.strip_debug_info) {
- noasync stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
- return;
+ noasync {
+ const stderr = getStderrStream();
+ if (builtin.strip_debug_info) {
+ stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
+ return;
+ }
+ const debug_info = getSelfDebugInfo() catch |err| {
+ stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
+ return;
+ };
+ writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| {
+ stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return;
+ return;
+ };
}
- const debug_info = getSelfDebugInfo() catch |err| {
- noasync stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
- return;
- };
- writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| {
- noasync stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return;
- return;
- };
}
/// Tries to print the stack trace starting from the supplied base pointer to stderr,
/// unbuffered, and ignores any error returned.
/// TODO multithreaded awareness
pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
- const stderr = getStderrStream();
- if (builtin.strip_debug_info) {
- noasync stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
- return;
- }
- const debug_info = getSelfDebugInfo() catch |err| {
- noasync stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
- return;
- };
- const tty_config = detectTTYConfig();
- printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return;
- var it = StackIterator.init(null, bp);
- while (it.next()) |return_address| {
- printSourceAtAddress(debug_info, stderr, return_address - 1, tty_config) catch return;
+ noasync {
+ const stderr = getStderrStream();
+ if (builtin.strip_debug_info) {
+ stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
+ return;
+ }
+ const debug_info = getSelfDebugInfo() catch |err| {
+ stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
+ return;
+ };
+ const tty_config = detectTTYConfig();
+ printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return;
+ var it = StackIterator.init(null, bp);
+ while (it.next()) |return_address| {
+ printSourceAtAddress(debug_info, stderr, return_address - 1, tty_config) catch return;
+ }
}
}
@@ -199,19 +203,21 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace
/// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
/// TODO multithreaded awareness
pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void {
- const stderr = getStderrStream();
- if (builtin.strip_debug_info) {
- noasync stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
- return;
+ noasync {
+ const stderr = getStderrStream();
+ if (builtin.strip_debug_info) {
+ stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
+ return;
+ }
+ const debug_info = getSelfDebugInfo() catch |err| {
+ stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
+ return;
+ };
+ writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig()) catch |err| {
+ stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return;
+ return;
+ };
}
- const debug_info = getSelfDebugInfo() catch |err| {
- noasync stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
- return;
- };
- writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig()) catch |err| {
- noasync stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return;
- return;
- };
}
/// This function invokes undefined behavior when `ok` is `false`.
@@ -255,7 +261,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
resetSegfaultHandler();
}
- switch (panic_stage) {
+ noasync switch (panic_stage) {
0 => {
panic_stage = 1;
@@ -267,7 +273,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
defer held.release();
const stderr = getStderrStream();
- noasync stderr.print(format ++ "\n", args) catch os.abort();
+ stderr.print(format ++ "\n", args) catch os.abort();
if (trace) |t| {
dumpStackTrace(t.*);
}
@@ -292,12 +298,12 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
// we're still holding the mutex but that's fine as we're going to
// call abort()
const stderr = getStderrStream();
- noasync stderr.print("Panicked during a panic. Aborting.\n", .{}) catch os.abort();
+ stderr.print("Panicked during a panic. Aborting.\n", .{}) catch os.abort();
},
else => {
// Panicked while printing "Panicked during a panic."
},
- }
+ };
os.abort();
}
lib/std/fs.zig
@@ -734,7 +734,7 @@ pub const Dir = struct {
.dir = self.fd,
.access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE | read_flag,
.share_access = switch (flags.lock) {
- .None => @as(?w.ULONG, null),
+ .None => w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE,
.Shared => w.FILE_SHARE_READ | w.FILE_SHARE_DELETE,
.Exclusive => w.FILE_SHARE_DELETE,
},
lib/std/os.zig
@@ -854,8 +854,11 @@ pub const OpenError = error{
/// Open and possibly create a file. Keeps trying if it gets interrupted.
/// See also `openC`.
-/// TODO support windows
pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {
+ if (std.Target.current.os.tag == .windows) {
+ const file_path_w = try windows.sliceToPrefixedFileW(file_path);
+ return openW(&file_path_w, flags, perm);
+ }
const file_path_c = try toPosixPath(file_path);
return openZ(&file_path_c, flags, perm);
}
@@ -864,8 +867,11 @@ pub const openC = @compileError("deprecated: renamed to openZ");
/// Open and possibly create a file. Keeps trying if it gets interrupted.
/// See also `open`.
-/// TODO support windows
pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {
+ if (std.Target.current.os.tag == .windows) {
+ const file_path_w = try windows.cStrToPrefixedFileW(file_path);
+ return openW(&file_path_w, flags, perm);
+ }
while (true) {
const rc = system.open(file_path, flags, perm);
switch (errno(rc)) {
@@ -895,6 +901,13 @@ pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {
}
}
+/// Windows-only. The path parameter is
+/// [WTF-16](https://simonsapin.github.io/wtf-8/#potentially-ill-formed-utf-16) encoded.
+/// Translates the POSIX open API call to a Windows API call.
+pub fn openW(file_path_w: []const u16, flags: u32, perm: usize) OpenError!fd_t {
+ @compileError("TODO implement openW for windows");
+}
+
/// Open and possibly create a file. Keeps trying if it gets interrupted.
/// `file_path` is relative to the open directory handle `dir_fd`.
/// See also `openatC`.
@@ -1683,7 +1696,7 @@ pub fn renameatW(
.dir = old_dir_fd,
.access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE,
.creation = windows.FILE_OPEN,
- .enable_async_io = false,
+ .io_mode = .blocking,
}) catch |err| switch (err) {
error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`.
else => |e| return e,
lib/std/reset_event.zig
@@ -52,7 +52,7 @@ pub const ResetEvent = struct {
/// Wait for the event to be set by blocking the current thread.
/// A timeout in nanoseconds can be provided as a hint for how
- /// long the thread should block on the unset event before throwind error.TimedOut.
+ /// long the thread should block on the unset event before throwing error.TimedOut.
pub fn timedWait(self: *ResetEvent, timeout_ns: u64) !void {
return self.os_event.wait(timeout_ns);
}