diff --git a/CMakeLists.txt b/CMakeLists.txt index 5157406896..48fd6513a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -616,7 +616,6 @@ set(ZIG_STD_FILES "os/bits/wasi.zig" "os/bits/windows.zig" "os/darwin.zig" - "os/epoch.zig" "os/freebsd.zig" "os/linux.zig" "os/linux/arm64.zig" @@ -723,6 +722,7 @@ set(ZIG_STD_FILES "testing.zig" "thread.zig" "time.zig" + "time/epoch.zig" "unicode.zig" "valgrind.zig" "valgrind/callgrind.zig" diff --git a/std/event/loop.zig b/std/event/loop.zig index ae19ebb0f8..2e89e06c20 100644 --- a/std/event/loop.zig +++ b/std/event/loop.zig @@ -32,7 +32,7 @@ pub const Loop = struct { overlapped: Overlapped, pub const overlapped_init = switch (builtin.os) { - builtin.Os.windows => windows.OVERLAPPED{ + .windows => windows.OVERLAPPED{ .Internal = 0, .InternalHigh = 0, .Offset = 0, @@ -50,13 +50,13 @@ pub const Loop = struct { }; pub const EventFd = switch (builtin.os) { - builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => KEventFd, - builtin.Os.linux => struct { + .macosx, .freebsd, .netbsd => KEventFd, + .linux => struct { base: ResumeNode, epoll_op: u32, eventfd: i32, }, - builtin.Os.windows => struct { + .windows => struct { base: ResumeNode, completion_key: usize, }, @@ -69,11 +69,11 @@ pub const Loop = struct { }; pub const Basic = switch (builtin.os) { - builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => KEventBasic, - builtin.Os.linux => struct { + .macosx, .freebsd, .netbsd => KEventBasic, + .linux => struct { base: ResumeNode, }, - builtin.Os.windows => struct { + .windows => struct { base: ResumeNode, }, else => @compileError("unsupported OS"), @@ -147,7 +147,7 @@ pub const Loop = struct { fn initOsData(self: *Loop, extra_thread_count: usize) InitOsDataError!void { switch (builtin.os) { - builtin.Os.linux => { + .linux => { self.os_data.fs_queue = std.atomic.Queue(fs.Request).init(); self.os_data.fs_queue_item = 0; // we need another thread for the file system because Linux does not have an async @@ -221,7 +221,7 @@ pub const Loop = struct { self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun); } }, - builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { + .macosx, .freebsd, .netbsd => { self.os_data.kqfd = try os.bsdKQueue(); errdefer os.close(self.os_data.kqfd); @@ -325,14 +325,14 @@ pub const Loop = struct { self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun); } }, - builtin.Os.windows => { - self.os_data.io_port = try os.windowsCreateIoCompletionPort( + .windows => { + self.os_data.io_port = try windows.CreateIoCompletionPort( windows.INVALID_HANDLE_VALUE, null, undefined, maxInt(windows.DWORD), ); - errdefer os.close(self.os_data.io_port); + errdefer windows.CloseHandle(self.os_data.io_port); for (self.eventfd_resume_nodes) |*eventfd_node, i| { eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{ @@ -361,7 +361,7 @@ pub const Loop = struct { while (i < extra_thread_index) : (i += 1) { while (true) { const overlapped = &self.final_resume_node.overlapped; - os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue; + windows.PostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue; break; } } @@ -380,18 +380,18 @@ pub const Loop = struct { fn deinitOsData(self: *Loop) void { switch (builtin.os) { - builtin.Os.linux => { + .linux => { 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); self.allocator.free(self.eventfd_resume_nodes); }, - builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { + .macosx, .freebsd, .netbsd => { os.close(self.os_data.kqfd); os.close(self.os_data.fs_kqfd); }, - builtin.Os.windows => { - os.close(self.os_data.io_port); + .windows => { + windows.CloseHandle(self.os_data.io_port); }, else => {}, } @@ -501,7 +501,7 @@ pub const Loop = struct { const eventfd_node = &resume_stack_node.data; eventfd_node.base.handle = next_tick_node.data; switch (builtin.os) { - builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { + .macosx, .freebsd, .netbsd => { const kevent_array = (*const [1]os.Kevent)(&eventfd_node.kevent); const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch { @@ -510,7 +510,7 @@ pub const Loop = struct { return; }; }, - builtin.Os.linux => { + .linux => { // the pending count is already accounted for const epoll_events = os.EPOLLONESHOT | os.linux.EPOLLIN | os.linux.EPOLLOUT | os.linux.EPOLLET; @@ -525,8 +525,8 @@ pub const Loop = struct { return; }; }, - builtin.Os.windows => { - os.windowsPostQueuedCompletionStatus( + .windows => { + windows.PostQueuedCompletionStatus( self.os_data.io_port, undefined, undefined, @@ -623,13 +623,13 @@ pub const Loop = struct { if (prev == 1) { // cause all the threads to stop switch (builtin.os) { - builtin.Os.linux => { + .linux => { self.posixFsRequest(&self.os_data.fs_end_request); // writing 8 bytes to an eventfd cannot fail os.write(self.os_data.final_eventfd, wakeup_bytes) catch unreachable; return; }, - builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { + .macosx, .freebsd, .netbsd => { self.posixFsRequest(&self.os_data.fs_end_request); const final_kevent = (*const [1]os.Kevent)(&self.os_data.final_kevent); const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; @@ -637,12 +637,12 @@ pub const Loop = struct { _ = os.bsdKEvent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable; return; }, - builtin.Os.windows => { + .windows => { var i: usize = 0; while (i < self.extra_threads.len + 1) : (i += 1) { while (true) { const overlapped = &self.final_resume_node.overlapped; - os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue; + windows.PostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue; break; } } @@ -663,7 +663,7 @@ pub const Loop = struct { } switch (builtin.os) { - builtin.Os.linux => { + .linux => { // only process 1 event so we don't steal from other threads var events: [1]os.linux.epoll_event = undefined; const count = os.epoll_wait(self.os_data.epollfd, events[0..], -1); @@ -687,7 +687,7 @@ pub const Loop = struct { } } }, - builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { + .macosx, .freebsd, .netbsd => { var eventlist: [1]os.Kevent = undefined; const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable; @@ -713,16 +713,16 @@ pub const Loop = struct { } } }, - builtin.Os.windows => { + .windows => { var completion_key: usize = undefined; const overlapped = while (true) { var nbytes: windows.DWORD = undefined; var overlapped: ?*windows.OVERLAPPED = undefined; - switch (os.windowsGetQueuedCompletionStatus(self.os_data.io_port, &nbytes, &completion_key, &overlapped, windows.INFINITE)) { - os.WindowsWaitResult.Aborted => return, - os.WindowsWaitResult.Normal => {}, - os.WindowsWaitResult.EOF => {}, - os.WindowsWaitResult.Cancelled => continue, + switch (windows.GetQueuedCompletionStatus(self.os_data.io_port, &nbytes, &completion_key, &overlapped, windows.INFINITE)) { + .Aborted => return, + .Normal => {}, + .EOF => {}, + .Cancelled => continue, } if (overlapped) |o| break o; } else unreachable; // TODO else unreachable should not be necessary @@ -831,9 +831,9 @@ pub const Loop = struct { } const OsData = switch (builtin.os) { - builtin.Os.linux => LinuxOsData, - builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => KEventData, - builtin.Os.windows => struct { + .linux => LinuxOsData, + .macosx, .freebsd, .netbsd => KEventData, + .windows => struct { io_port: windows.HANDLE, extra_thread_count: usize, }, diff --git a/std/fs/get_app_data_dir.zig b/std/fs/get_app_data_dir.zig index 713b40b22b..87703592c1 100644 --- a/std/fs/get_app_data_dir.zig +++ b/std/fs/get_app_data_dir.zig @@ -23,7 +23,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD &dir_path_ptr, )) { os.windows.S_OK => { - defer os.windows.CoTaskMemFree(@ptrCast(*c_void, dir_path_ptr)); + defer os.windows.ole32.CoTaskMemFree(@ptrCast(*c_void, dir_path_ptr)); const global_dir = unicode.utf16leToUtf8Alloc(allocator, utf16lePtrSlice(dir_path_ptr)) catch |err| switch (err) { error.UnexpectedSecondSurrogateHalf => return error.AppDataDirUnavailable, error.ExpectedSecondSurrogateHalf => return error.AppDataDirUnavailable, diff --git a/std/heap.zig b/std/heap.zig index 3bae7f3c46..7d7774f453 100644 --- a/std/heap.zig +++ b/std/heap.zig @@ -261,7 +261,7 @@ pub const HeapAllocator = switch (builtin.os) { pub fn deinit(self: *HeapAllocator) void { if (self.heap_handle) |heap_handle| { - _ = os.windows.HeapDestroy(heap_handle); + os.windows.HeapDestroy(heap_handle); } } @@ -274,12 +274,12 @@ pub const HeapAllocator = switch (builtin.os) { const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, builtin.AtomicOrder.SeqCst); const heap_handle = optional_heap_handle orelse blk: { const options = if (builtin.single_threaded) os.windows.HEAP_NO_SERIALIZE else 0; - const hh = os.windows.HeapCreate(options, amt, 0) orelse return error.OutOfMemory; + const hh = os.windows.kernel32.HeapCreate(options, amt, 0) orelse return error.OutOfMemory; const other_hh = @cmpxchgStrong(?HeapHandle, &self.heap_handle, null, hh, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse break :blk hh; - _ = os.windows.HeapDestroy(hh); + os.windows.HeapDestroy(hh); break :blk other_hh.?; // can't be null because of the cmpxchg }; - const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory; + const ptr = os.windows.kernel32.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory; const root_addr = @ptrToInt(ptr); const adjusted_addr = mem.alignForward(root_addr, alignment); const record_addr = adjusted_addr + n; @@ -309,12 +309,12 @@ pub const HeapAllocator = switch (builtin.os) { const old_ptr = @intToPtr(*c_void, root_addr); if (new_size == 0) { - if (os.windows.HeapFree(self.heap_handle.?, 0, old_ptr) == 0) unreachable; + os.windows.HeapFree(self.heap_handle.?, 0, old_ptr); return old_mem[0..0]; } const amt = new_size + new_align + @sizeOf(usize); - const new_ptr = os.windows.HeapReAlloc( + const new_ptr = os.windows.kernel32.HeapReAlloc( self.heap_handle.?, 0, old_ptr, diff --git a/std/os.zig b/std/os.zig index 84e92a15d9..63977312d4 100644 --- a/std/os.zig +++ b/std/os.zig @@ -944,7 +944,7 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void { /// Assumes target is Windows. pub fn renameW(old_path: [*]const u16, new_path: [*]const u16) RenameError!void { const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH; - return windows.MoveFileExW(old_path_w, new_path_w, flags); + return windows.MoveFileExW(old_path, new_path, flags); } pub const MakeDirError = error{ @@ -959,6 +959,8 @@ pub const MakeDirError = error{ NoSpaceLeft, NotDir, ReadOnlyFileSystem, + InvalidUtf8, + BadPathName, Unexpected, }; @@ -2227,6 +2229,9 @@ pub const RealPathError = error{ BadPathName, DeviceBusy, + SharingViolation, + PipeBusy, + /// On Windows, file paths must be valid Unicode. InvalidUtf8, @@ -2294,7 +2299,7 @@ pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPa var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined; const wide_len = try windows.GetFinalPathNameByHandleW(h_file, &wide_buf, wide_buf.len, windows.VOLUME_NAME_DOS); assert(wide_len <= wide_buf.len); - const wide_slice = wide_len[0..wide_len]; + const wide_slice = wide_buf[0..wide_len]; // Windows returns \\?\ prepended to the path. // We strip it to make this function consistent across platforms. @@ -2311,13 +2316,13 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void { if (windows.is_the_target and !builtin.link_libc) { // TODO https://github.com/ziglang/zig/issues/1284 const small_s = math.cast(windows.DWORD, seconds) catch math.maxInt(windows.DWORD); - const ms_from_s = math.mul(small_s, std.time.ms_per_s) catch math.maxInt(windows.DWORD); + const ms_from_s = math.mul(windows.DWORD, small_s, std.time.ms_per_s) catch math.maxInt(windows.DWORD); const ns_per_ms = std.time.ns_per_s / std.time.ms_per_s; const big_ms_from_ns = nanoseconds / ns_per_ms; const ms_from_ns = math.cast(windows.DWORD, big_ms_from_ns) catch math.maxInt(windows.DWORD); - const ms = math.add(ms_from_s, ms_from_ns) catch math.maxInt(windows.DWORD); + const ms = math.add(windows.DWORD, ms_from_s, ms_from_ns) catch math.maxInt(windows.DWORD); windows.kernel32.Sleep(ms); return; } diff --git a/std/os/bits/wasi.zig b/std/os/bits/wasi.zig index a6f96de31a..93d2a82fde 100644 --- a/std/os/bits/wasi.zig +++ b/std/os/bits/wasi.zig @@ -1,5 +1,3 @@ -use @import("../bits.zig"); - pub const STDIN_FILENO = 0; pub const STDOUT_FILENO = 1; pub const STDERR_FILENO = 2; @@ -12,8 +10,6 @@ pub const ADVICE_WILLNEED: advice_t = 3; pub const ADVICE_DONTNEED: advice_t = 4; pub const ADVICE_NOREUSE: advice_t = 5; -pub const ciovec_t = iovec_const; - pub const clockid_t = u32; pub const CLOCK_REALTIME: clockid_t = 0; pub const CLOCK_MONOTONIC: clockid_t = 1; @@ -182,8 +178,6 @@ pub const FILESTAT_SET_MTIM_NOW: fstflags_t = 0x0008; pub const inode_t = u64; -pub const iovec_t = iovec; - pub const linkcount_t = u32; pub const lookupflags_t = u32; diff --git a/std/os/bits/windows.zig b/std/os/bits/windows.zig index 4c94853e2a..d84c1572da 100644 --- a/std/os/bits/windows.zig +++ b/std/os/bits/windows.zig @@ -5,6 +5,13 @@ use @import("../windows/bits.zig"); pub const fd_t = HANDLE; pub const pid_t = HANDLE; +pub const time_t = c_longlong; + +pub const timespec = extern struct { + tv_sec: time_t, + tv_nsec: c_long, +}; + pub const sig_atomic_t = c_int; /// maximum signal number + 1 @@ -153,3 +160,4 @@ pub const EWOULDBLOCK = 140; pub const SIGKILL = @compileError("Windows libc does not have this"); pub const EDQUOT = @compileError("Windows libc does not have this"); pub const TIOCGWINSZ = @compileError("Windows libc does not have this"); +pub const F_OK = 0; diff --git a/std/os/wasi.zig b/std/os/wasi.zig index 1ce0fe0c92..adfe9e821d 100644 --- a/std/os/wasi.zig +++ b/std/os/wasi.zig @@ -5,7 +5,7 @@ const std = @import("std"); const assert = std.debug.assert; pub const is_the_target = builtin.os == .wasi; -pub use @import("bits/wasi.zig"); +pub use @import("bits.zig"); comptime { assert(@alignOf(i8) == 1); @@ -18,6 +18,9 @@ comptime { assert(@alignOf(u64) == 8); } +pub const iovec_t = iovec; +pub const ciovec_t = iovec_const; + pub extern "wasi_unstable" fn args_get(argv: [*][*]u8, argv_buf: [*]u8) errno_t; pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t; diff --git a/std/os/windows.zig b/std/os/windows.zig index ffa647692e..54e7840f31 100644 --- a/std/os/windows.zig +++ b/std/os/windows.zig @@ -134,6 +134,9 @@ pub fn WaitForSingleObject(handle: HANDLE, milliseconds: DWORD) WaitForSingleObj pub const FindFirstFileError = error{ FileNotFound, + InvalidUtf8, + BadPathName, + NameTooLong, Unexpected, }; @@ -192,7 +195,7 @@ pub fn PostQueuedCompletionStatus( ) PostQueuedCompletionStatusError!void { if (kernel32.PostQueuedCompletionStatus(completion_port, bytes_transferred_count, completion_key, lpOverlapped) == 0) { switch (kernel32.GetLastError()) { - else => return unexpectedError(err), + else => |err| return unexpectedError(err), } } } @@ -350,7 +353,7 @@ pub fn DeleteFile(filename: []const u8) DeleteFileError!void { } pub fn DeleteFileW(filename: [*]const u16) DeleteFileError!void { - if (kernel32.DeleteFileW(file_path) == 0) { + if (kernel32.DeleteFileW(filename) == 0) { switch (kernel32.GetLastError()) { ERROR.FILE_NOT_FOUND => return error.FileNotFound, ERROR.ACCESS_DENIED => return error.AccessDenied, @@ -501,7 +504,7 @@ pub fn GetFinalPathNameByHandleW( buf_len: DWORD, flags: DWORD, ) GetFinalPathNameByHandleError!DWORD { - const rc = kernel32.GetFinalPathNameByHandleW(h_file, buf_ptr, buf.len, flags); + const rc = kernel32.GetFinalPathNameByHandleW(hFile, buf_ptr, buf_len, flags); if (rc == 0) { switch (kernel32.GetLastError()) { ERROR.FILE_NOT_FOUND => return error.FileNotFound, @@ -539,7 +542,7 @@ pub fn GetFileAttributes(filename: []const u8) GetFileAttributesError!DWORD { } pub fn GetFileAttributesW(lpFileName: [*]const u16) GetFileAttributesError!DWORD { - const rc = kernel32.GetFileAttributesW(path); + const rc = kernel32.GetFileAttributesW(lpFileName); if (rc == INVALID_FILE_ATTRIBUTES) { switch (kernel32.GetLastError()) { ERROR.FILE_NOT_FOUND => return error.FileNotFound, @@ -705,6 +708,14 @@ pub fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter assert(kernel32.InitOnceExecuteOnce(InitOnce, InitFn, Parameter, Context) != 0); } +pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: *c_void) void { + assert(kernel32.HeapFree(hHeap, dwFlags, lpMem) != 0); +} + +pub fn HeapDestroy(hHeap: HANDLE) void { + assert(kernel32.HeapDestroy(hHeap) != 0); +} + pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 { return sliceToPrefixedFileW(mem.toSliceConst(u8, s)); } diff --git a/std/thread.zig b/std/thread.zig index 53be5a8c2d..e7449f2291 100644 --- a/std/thread.zig +++ b/std/thread.zig @@ -57,7 +57,7 @@ pub const Thread = struct { } else return switch (builtin.os) { .linux => os.linux.gettid(), - .windows => windows.GetCurrentThreadId(), + .windows => windows.kernel32.GetCurrentThreadId(), else => @compileError("Unsupported OS"), }; } @@ -99,9 +99,9 @@ pub const Thread = struct { os.munmap(self.data.memory); }, .windows => { - assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0); - assert(windows.CloseHandle(self.data.handle) != 0); - assert(windows.HeapFree(self.data.heap_handle, 0, self.data.alloc_start) != 0); + windows.WaitForSingleObject(self.data.handle, windows.INFINITE) catch unreachable; + windows.CloseHandle(self.data.handle); + windows.HeapFree(self.data.heap_handle, 0, self.data.alloc_start); }, else => @compileError("Unsupported OS"), } @@ -171,10 +171,10 @@ pub const Thread = struct { } }; - const heap_handle = windows.GetProcessHeap() orelse return error.OutOfMemory; + const heap_handle = windows.kernel32.GetProcessHeap() orelse return error.OutOfMemory; const byte_count = @alignOf(WinThread.OuterContext) + @sizeOf(WinThread.OuterContext); - const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return error.OutOfMemory; - errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0); + const bytes_ptr = windows.kernel32.HeapAlloc(heap_handle, 0, byte_count) orelse return error.OutOfMemory; + errdefer assert(windows.kernel32.HeapFree(heap_handle, 0, bytes_ptr) != 0); const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count]; const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext) catch unreachable; outer_context.* = WinThread.OuterContext{ @@ -189,9 +189,9 @@ pub const Thread = struct { }; const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner); - outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse { - switch (windows.GetLastError()) { - else => |err| windows.unexpectedError(err), + outer_context.thread.data.handle = windows.kernel32.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse { + switch (windows.kernel32.GetLastError()) { + else => |err| return windows.unexpectedError(err), } }; return &outer_context.thread; @@ -333,7 +333,7 @@ pub const Thread = struct { } if (os.windows.is_the_target) { var system_info: windows.SYSTEM_INFO = undefined; - windows.GetSystemInfo(&system_info); + windows.kernel32.GetSystemInfo(&system_info); return @intCast(usize, system_info.dwNumberOfProcessors); } var count: c_int = undefined; diff --git a/std/time.zig b/std/time.zig index d4a349880e..b8f031202c 100644 --- a/std/time.zig +++ b/std/time.zig @@ -4,7 +4,7 @@ const assert = std.debug.assert; const testing = std.testing; const os = std.os; -pub const epoch = @import("epoch.zig"); +pub const epoch = @import("time/epoch.zig"); /// Spurious wakeups are possible and no precision of timing is guaranteed. pub fn sleep(nanoseconds: u64) void { diff --git a/std/os/epoch.zig b/std/time/epoch.zig similarity index 100% rename from std/os/epoch.zig rename to std/time/epoch.zig