Commit ca6debcaf4

Andrew Kelley <andrew@ziglang.org>
2019-05-25 04:52:07
starting to fix the regressions
1 parent 3d61e42
std/atomic/queue.zig
@@ -220,7 +220,7 @@ fn startPuts(ctx: *Context) u8 {
     var put_count: usize = puts_per_thread;
     var r = std.rand.DefaultPrng.init(0xdeadbeef);
     while (put_count != 0) : (put_count -= 1) {
-        std.os.time.sleep(1); // let the os scheduler be our fuzz
+        std.time.sleep(1); // let the os scheduler be our fuzz
         const x = @bitCast(i32, r.random.scalar(u32));
         const node = ctx.allocator.create(Queue(i32).Node) catch unreachable;
         node.* = Queue(i32).Node{
@@ -239,7 +239,7 @@ fn startGets(ctx: *Context) u8 {
         const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
 
         while (ctx.queue.get()) |node| {
-            std.os.time.sleep(1); // let the os scheduler be our fuzz
+            std.time.sleep(1); // let the os scheduler be our fuzz
             _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
             _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
         }
std/atomic/stack.zig
@@ -154,7 +154,7 @@ fn startPuts(ctx: *Context) u8 {
     var put_count: usize = puts_per_thread;
     var r = std.rand.DefaultPrng.init(0xdeadbeef);
     while (put_count != 0) : (put_count -= 1) {
-        std.os.time.sleep(1); // let the os scheduler be our fuzz
+        std.time.sleep(1); // let the os scheduler be our fuzz
         const x = @bitCast(i32, r.random.scalar(u32));
         const node = ctx.allocator.create(Stack(i32).Node) catch unreachable;
         node.* = Stack(i32).Node{
@@ -172,7 +172,7 @@ fn startGets(ctx: *Context) u8 {
         const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
 
         while (ctx.stack.pop()) |node| {
-            std.os.time.sleep(1); // let the os scheduler be our fuzz
+            std.time.sleep(1); // let the os scheduler be our fuzz
             _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
             _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
         }
std/crypto/throughput_test.zig
@@ -1,6 +1,6 @@
 const builtin = @import("builtin");
 const std = @import("std");
-const time = std.os.time;
+const time = std.time;
 const Timer = time.Timer;
 const crypto = @import("../crypto.zig");
 
std/event/fs.zig
@@ -9,6 +9,7 @@ const posix = os.posix;
 const windows = os.windows;
 const Loop = event.Loop;
 const fd_t = posix.fd_t;
+const File = std.fs.File;
 
 pub const RequestNode = std.atomic.Queue(Request).Node;
 
@@ -52,20 +53,20 @@ pub const Request = struct {
             /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
             path: []const u8,
             flags: u32,
-            mode: os.File.Mode,
+            mode: File.Mode,
             result: Error!fd_t,
 
-            pub const Error = os.File.OpenError;
+            pub const Error = File.OpenError;
         };
 
         pub const WriteFile = struct {
             /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
             path: []const u8,
             contents: []const u8,
-            mode: os.File.Mode,
+            mode: File.Mode,
             result: Error!void,
 
-            pub const Error = os.File.OpenError || os.File.WriteError;
+            pub const Error = File.OpenError || File.WriteError;
         };
 
         pub const Close = struct {
@@ -74,7 +75,7 @@ pub const Request = struct {
     };
 };
 
-pub const PWriteVError = error{OutOfMemory} || os.File.WriteError;
+pub const PWriteVError = error{OutOfMemory} || File.WriteError;
 
 /// data - just the inner references - must live until pwritev promise completes.
 pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: usize) PWriteVError!void {
@@ -209,7 +210,7 @@ pub async fn pwritevPosix(
     return req_node.data.msg.PWriteV.result;
 }
 
-pub const PReadVError = error{OutOfMemory} || os.File.ReadError;
+pub const PReadVError = error{OutOfMemory} || File.ReadError;
 
 /// data - just the inner references - must live until preadv promise completes.
 pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PReadVError!usize {
@@ -361,8 +362,8 @@ pub async fn openPosix(
     loop: *Loop,
     path: []const u8,
     flags: u32,
-    mode: os.File.Mode,
-) os.File.OpenError!fd_t {
+    mode: File.Mode,
+) File.OpenError!fd_t {
     // workaround for https://github.com/ziglang/zig/issues/1194
     suspend {
         resume @handle();
@@ -401,11 +402,11 @@ pub async fn openPosix(
     return req_node.data.msg.Open.result;
 }
 
-pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {
+pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t {
     switch (builtin.os) {
         builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
             const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
-            return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
+            return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
         },
 
         builtin.Os.windows => return os.windowsOpen(
@@ -422,12 +423,12 @@ pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {
 
 /// Creates if does not exist. Truncates the file if it exists.
 /// Uses the default mode.
-pub async fn openWrite(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {
-    return await (async openWriteMode(loop, path, os.File.default_mode) catch unreachable);
+pub async fn openWrite(loop: *Loop, path: []const u8) File.OpenError!fd_t {
+    return await (async openWriteMode(loop, path, File.default_mode) catch unreachable);
 }
 
 /// Creates if does not exist. Truncates the file if it exists.
-pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os.File.OpenError!fd_t {
+pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File.OpenError!fd_t {
     switch (builtin.os) {
         builtin.Os.macosx,
         builtin.Os.linux,
@@ -435,7 +436,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
         builtin.Os.netbsd,
         => {
             const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
-            return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
+            return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
         },
         builtin.Os.windows => return os.windowsOpen(
             path,
@@ -452,8 +453,8 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
 pub async fn openReadWrite(
     loop: *Loop,
     path: []const u8,
-    mode: os.File.Mode,
-) os.File.OpenError!fd_t {
+    mode: File.Mode,
+) File.OpenError!fd_t {
     switch (builtin.os) {
         builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
             const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
@@ -605,11 +606,11 @@ pub const CloseOperation = struct {
 /// contents must remain alive until writeFile completes.
 /// TODO make this atomic or provide writeFileAtomic and rename this one to writeFileTruncate
 pub async fn writeFile(loop: *Loop, path: []const u8, contents: []const u8) !void {
-    return await (async writeFileMode(loop, path, contents, os.File.default_mode) catch unreachable);
+    return await (async writeFileMode(loop, path, contents, File.default_mode) catch unreachable);
 }
 
 /// contents must remain alive until writeFile completes.
-pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, mode: os.File.Mode) !void {
+pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, mode: File.Mode) !void {
     switch (builtin.os) {
         builtin.Os.linux,
         builtin.Os.macosx,
@@ -634,7 +635,7 @@ async fn writeFileWindows(loop: *Loop, path: []const u8, contents: []const u8) !
     try await (async pwriteWindows(loop, handle, contents, 0) catch unreachable);
 }
 
-async fn writeFileModeThread(loop: *Loop, path: []const u8, contents: []const u8, mode: os.File.Mode) !void {
+async fn writeFileModeThread(loop: *Loop, path: []const u8, contents: []const u8, mode: File.Mode) !void {
     // workaround for https://github.com/ziglang/zig/issues/1194
     suspend {
         resume @handle();
@@ -1363,7 +1364,7 @@ async fn testFsWatch(loop: *Loop) !void {
     defer if (!ev_consumed) cancel ev;
 
     // overwrite line 2
-    const fd = try await try async openReadWrite(loop, file_path, os.File.default_mode);
+    const fd = try await try async openReadWrite(loop, file_path, File.default_mode);
     {
         defer os.close(fd);
 
@@ -1390,7 +1391,7 @@ pub const OutStream = struct {
     loop: *Loop,
     offset: usize,
 
-    pub const Error = os.File.WriteError;
+    pub const Error = File.WriteError;
     pub const Stream = event.io.OutStream(Error);
 
     pub fn init(loop: *Loop, fd: fd_t, offset: usize) OutStream {
std/event/group.zig
@@ -155,7 +155,7 @@ async fn testGroup(loop: *Loop) void {
 }
 
 async fn sleepALittle(count: *usize) void {
-    std.os.time.sleep(1 * std.os.time.millisecond);
+    std.time.sleep(1 * std.time.millisecond);
     _ = @atomicRmw(usize, count, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
 }
 
std/event/loop.zig
@@ -789,13 +789,13 @@ pub const Loop = struct {
                         msg.result = os.posix_preadv(msg.fd, msg.iov.ptr, msg.iov.len, msg.offset);
                     },
                     @TagType(fs.Request.Msg).Open => |*msg| {
-                        msg.result = os.posixOpenC(msg.path.ptr, msg.flags, msg.mode);
+                        msg.result = os.openC(msg.path.ptr, msg.flags, msg.mode);
                     },
                     @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd),
                     @TagType(fs.Request.Msg).WriteFile => |*msg| blk: {
                         const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT |
                             posix.O_CLOEXEC | posix.O_TRUNC;
-                        const fd = os.posixOpenC(msg.path.ptr, flags, msg.mode) catch |err| {
+                        const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| {
                             msg.result = err;
                             break :blk;
                         };
std/event/net.zig
@@ -6,11 +6,12 @@ const mem = std.mem;
 const os = std.os;
 const posix = os.posix;
 const Loop = std.event.Loop;
+const File = std.fs.File;
 
 const fd_t = posix.fd_t;
 
 pub const Server = struct {
-    handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, os.File) void,
+    handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void,
 
     loop: *Loop,
     sockfd: ?i32,
@@ -42,7 +43,7 @@ pub const Server = struct {
     pub fn listen(
         self: *Server,
         address: *const std.net.Address,
-        handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, os.File) void,
+        handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void,
     ) !void {
         self.handleRequestFn = handleRequestFn;
 
@@ -83,7 +84,7 @@ pub const Server = struct {
                     suspend; // we will get resumed by epoll_wait in the event loop
                     continue;
                 }
-                var socket = os.File.openHandle(accepted_fd);
+                var socket = File.openHandle(accepted_fd);
                 _ = async<self.loop.allocator> self.handleRequestFn(self, &accepted_addr, socket) catch |err| switch (err) {
                     error.OutOfMemory => {
                         socket.close();
@@ -250,7 +251,7 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {
     return await (async readvPosix(loop, fd, iovecs.ptr, data.len) catch unreachable);
 }
 
-pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
+pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File {
     var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592
 
     const sockfd = try os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
@@ -260,7 +261,7 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
     try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
     try os.posixGetSockOptConnectError(sockfd);
 
-    return os.File.openHandle(sockfd);
+    return File.openHandle(sockfd);
 }
 
 test "listen on a port, send bytes, receive bytes" {
@@ -276,7 +277,7 @@ test "listen on a port, send bytes, receive bytes" {
         tcp_server: Server,
 
         const Self = @This();
-        async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: os.File) void {
+        async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: File) void {
             const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
             var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
             defer socket.close();
@@ -289,7 +290,7 @@ test "listen on a port, send bytes, receive bytes" {
                 cancel @handle();
             }
         }
-        async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: os.File) !void {
+        async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: File) !void {
             const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/1592
             var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
 
std/event/rwlock.zig
@@ -271,7 +271,7 @@ async fn writeRunner(lock: *RwLock) void {
 
     var i: usize = 0;
     while (i < shared_test_data.len) : (i += 1) {
-        std.os.time.sleep(100 * std.os.time.microsecond);
+        std.time.sleep(100 * std.time.microsecond);
         const lock_promise = async lock.acquireWrite() catch @panic("out of memory");
         const handle = await lock_promise;
         defer handle.release();
@@ -286,7 +286,7 @@ async fn writeRunner(lock: *RwLock) void {
 
 async fn readRunner(lock: *RwLock) void {
     suspend; // resumed by onNextTick
-    std.os.time.sleep(1);
+    std.time.sleep(1);
 
     var i: usize = 0;
     while (i < shared_test_data.len) : (i += 1) {
std/io/c_out_stream.zig
@@ -1,13 +1,13 @@
 const std = @import("../std.zig");
+const os = std.os;
 const OutStream = std.io.OutStream;
 const builtin = @import("builtin");
-const posix = std.os.posix;
 
-/// TODO make std.os.FILE use *FILE when linking libc and this just becomes
-/// std.io.FileOutStream because std.os.File.write would do this when linking
+/// TODO make a proposal to make `std.fs.File` use *FILE when linking libc and this just becomes
+/// std.io.FileOutStream because std.fs.File.write would do this when linking
 /// libc.
 pub const COutStream = struct {
-    pub const Error = std.os.File.WriteError;
+    pub const Error = std.fs.File.WriteError;
     pub const Stream = OutStream(Error);
 
     stream: Stream,
@@ -24,25 +24,20 @@ pub const COutStream = struct {
         const self = @fieldParentPtr(COutStream, "stream", out_stream);
         const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);
         if (amt_written == bytes.len) return;
-        // TODO errno on windows. should we have a posix layer for windows?
-        if (builtin.os == .windows) {
-            return error.InputOutput;
-        }
-        const errno = std.c._errno().*;
-        switch (errno) {
+        switch (std.c._errno().*) {
             0 => unreachable,
-            posix.EINVAL => unreachable,
-            posix.EFAULT => unreachable,
-            posix.EAGAIN => unreachable, // this is a blocking API
-            posix.EBADF => unreachable, // always a race condition
-            posix.EDESTADDRREQ => unreachable, // connect was never called
-            posix.EDQUOT => return error.DiskQuota,
-            posix.EFBIG => return error.FileTooBig,
-            posix.EIO => return error.InputOutput,
-            posix.ENOSPC => return error.NoSpaceLeft,
-            posix.EPERM => return error.AccessDenied,
-            posix.EPIPE => return error.BrokenPipe,
-            else => return std.os.unexpectedErrorPosix(@intCast(usize, errno)),
+            os.EINVAL => unreachable,
+            os.EFAULT => unreachable,
+            os.EAGAIN => unreachable, // this is a blocking API
+            os.EBADF => unreachable, // always a race condition
+            os.EDESTADDRREQ => unreachable, // connect was never called
+            os.EDQUOT => return error.DiskQuota,
+            os.EFBIG => return error.FileTooBig,
+            os.EIO => return error.InputOutput,
+            os.ENOSPC => return error.NoSpaceLeft,
+            os.EPERM => return error.AccessDenied,
+            os.EPIPE => return error.BrokenPipe,
+            else => return os.unexpectedErrno(@intCast(usize, errno)),
         }
     }
 };
std/io/test.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
 const std = @import("../std.zig");
 const io = std.io;
 const meta = std.meta;
@@ -7,7 +8,7 @@ const expect = std.testing.expect;
 const expectError = std.testing.expectError;
 const mem = std.mem;
 const os = std.os;
-const builtin = @import("builtin");
+const File = std.fs.File;
 
 test "write a file, read it, then delete it" {
     var raw_bytes: [200 * 1024]u8 = undefined;
@@ -18,11 +19,11 @@ test "write a file, read it, then delete it" {
     prng.random.bytes(data[0..]);
     const tmp_file_name = "temp_test_file.txt";
     {
-        var file = try os.File.openWrite(tmp_file_name);
+        var file = try File.openWrite(tmp_file_name);
         defer file.close();
 
         var file_out_stream = file.outStream();
-        var buf_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);
+        var buf_stream = io.BufferedOutStream(File.WriteError).init(&file_out_stream.stream);
         const st = &buf_stream.stream;
         try st.print("begin");
         try st.write(data[0..]);
@@ -32,15 +33,15 @@ test "write a file, read it, then delete it" {
 
     {
         // make sure openWriteNoClobber doesn't harm the file
-        if (os.File.openWriteNoClobber(tmp_file_name, os.File.default_mode)) |file| {
+        if (File.openWriteNoClobber(tmp_file_name, File.default_mode)) |file| {
             unreachable;
         } else |err| {
-            std.debug.assert(err == os.File.OpenError.PathAlreadyExists);
+            std.debug.assert(err == File.OpenError.PathAlreadyExists);
         }
     }
 
     {
-        var file = try os.File.openRead(tmp_file_name);
+        var file = try File.openRead(tmp_file_name);
         defer file.close();
 
         const file_size = try file.getEndPos();
@@ -48,7 +49,7 @@ test "write a file, read it, then delete it" {
         expect(file_size == expected_file_size);
 
         var file_in_stream = file.inStream();
-        var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);
+        var buf_stream = io.BufferedInStream(File.ReadError).init(&file_in_stream.stream);
         const st = &buf_stream.stream;
         const contents = try st.readAllAlloc(allocator, 2 * 1024);
         defer allocator.free(contents);
@@ -273,12 +274,12 @@ test "BitOutStream" {
 test "BitStreams with File Stream" {
     const tmp_file_name = "temp_test_file.txt";
     {
-        var file = try os.File.openWrite(tmp_file_name);
+        var file = try File.openWrite(tmp_file_name);
         defer file.close();
 
         var file_out = file.outStream();
         var file_out_stream = &file_out.stream;
-        const OutError = os.File.WriteError;
+        const OutError = File.WriteError;
         var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
 
         try bit_stream.writeBits(u2(1), 1);
@@ -290,12 +291,12 @@ test "BitStreams with File Stream" {
         try bit_stream.flushBits();
     }
     {
-        var file = try os.File.openRead(tmp_file_name);
+        var file = try File.openRead(tmp_file_name);
         defer file.close();
 
         var file_in = file.inStream();
         var file_in_stream = &file_in.stream;
-        const InError = os.File.ReadError;
+        const InError = File.ReadError;
         var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
 
         var out_bits: usize = undefined;
std/os/bits/linux.zig
@@ -1,4 +1,4 @@
-pub use @import("errno.zig");
+pub use @import("linux/errno.zig");
 pub use switch (builtin.arch) {
     .x86_64 => @import("linux/x86_64.zig"),
     .aarch64 => @import("linux/arm64.zig"),
@@ -744,16 +744,6 @@ pub const sockaddr_un = extern struct {
     path: [108]u8,
 };
 
-pub const iovec = extern struct {
-    iov_base: [*]u8,
-    iov_len: usize,
-};
-
-pub const iovec_const = extern struct {
-    iov_base: [*]const u8,
-    iov_len: usize,
-};
-
 pub const mmsghdr = extern struct {
     msg_hdr: msghdr,
     msg_len: u32,
std/os/test.zig
@@ -4,6 +4,7 @@ const testing = std.testing;
 const expect = std.testing.expect;
 const io = std.io;
 const mem = std.mem;
+const File = std.fs.File;
 
 const a = std.debug.global_allocator;
 
@@ -25,14 +26,14 @@ test "makePath, put some files in it, deleteTree" {
 
 test "access file" {
     try os.makePath(a, "os_test_tmp");
-    if (os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {
+    if (File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {
         @panic("expected error");
     } else |err| {
         expect(err == error.FileNotFound);
     }
 
     try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", "");
-    try os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt");
+    try File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt");
     try os.deleteTree(a, "os_test_tmp");
 }
 
@@ -102,7 +103,7 @@ test "AtomicFile" {
         \\ this is a test file
     ;
     {
-        var af = try os.AtomicFile.init(test_out_file, os.File.default_mode);
+        var af = try os.AtomicFile.init(test_out_file, File.default_mode);
         defer af.deinit();
         try af.file.write(test_content);
         try af.finish();
std/os/windows.zig
@@ -753,6 +753,10 @@ pub fn CloseHandle(hObject: HANDLE) void {
     assert(kernel32.CloseHandle(hObject) != 0);
 }
 
+pub fn FindClose(hFindFile: HANDLE) void {
+    assert(kernel32.FindClose(hFindFile) != 0);
+}
+
 pub const ReadFileError = error{Unexpected};
 
 pub fn ReadFile(in_hFile: HANDLE, buffer: []u8) ReadFileError!usize {
@@ -1063,6 +1067,28 @@ pub fn GetFileAttributesW(lpFileName: [*]const u16) GetFileAttributesError!DWORD
     return rc;
 }
 
+const GetModuleFileNameError = error{Unexpected};
+
+pub fn GetModuleFileNameW(hModule: ?HMODULE, buf_ptr: [*]u16, buf_len: DWORD) GetModuleFileNameError![]u16 {
+    const rc = kernel32.GetModuleFileNameW(hModule, buf_ptr, buf_len);
+    if (rc == 0) {
+        switch (kernel32.GetLastError()) {
+            else => |err| return unexpectedError(err),
+        }
+    }
+    return buf_ptr[0..rc];
+}
+
+pub const TerminateProcessError = error{Unexpected};
+
+pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError!void {
+    if (kernel32.TerminateProcess(hProcess, uExitCode) == 0) {
+        switch (kernel32.GetLastError()) {
+            else => |err| return unexpectedError(err),
+        }
+    }
+}
+
 pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {
     return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
 }
std/special/build_runner.zig
@@ -8,6 +8,7 @@ const Builder = std.build.Builder;
 const mem = std.mem;
 const ArrayList = std.ArrayList;
 const warn = std.debug.warn;
+const File = std.fs.File;
 
 pub fn main() !void {
     var arg_it = os.args();
@@ -48,14 +49,14 @@ pub fn main() !void {
     var prefix: ?[]const u8 = null;
 
     var stderr_file = io.getStdErr();
-    var stderr_file_stream: os.File.OutStream = undefined;
+    var stderr_file_stream: File.OutStream = undefined;
     var stderr_stream = if (stderr_file) |f| x: {
         stderr_file_stream = f.outStream();
         break :x &stderr_file_stream.stream;
     } else |err| err;
 
     var stdout_file = io.getStdOut();
-    var stdout_file_stream: os.File.OutStream = undefined;
+    var stdout_file_stream: File.OutStream = undefined;
     var stdout_stream = if (stdout_file) |f| x: {
         stdout_file_stream = f.outStream();
         break :x &stdout_file_stream.stream;
std/zig/bench.zig
@@ -10,7 +10,7 @@ var fixed_buffer_mem: [10 * 1024 * 1024]u8 = undefined;
 
 pub fn main() !void {
     var i: usize = 0;
-    var timer = try std.os.time.Timer.start();
+    var timer = try std.time.Timer.start();
     const start = timer.lap();
     const iterations = 100;
     var memory_used: usize = 0;
@@ -19,7 +19,7 @@ pub fn main() !void {
     }
     const end = timer.read();
     memory_used /= iterations;
-    const elapsed_s = @intToFloat(f64, end - start) / std.os.time.ns_per_s;
+    const elapsed_s = @intToFloat(f64, end - start) / std.time.ns_per_s;
     const bytes_per_sec = @intToFloat(f64, source.len * iterations) / elapsed_s;
     const mb_per_sec = bytes_per_sec / (1024 * 1024);
 
std/build.zig
@@ -14,6 +14,7 @@ const Term = os.ChildProcess.Term;
 const BufSet = std.BufSet;
 const BufMap = std.BufMap;
 const fmt_lib = std.fmt;
+const File = std.fs.File;
 
 pub const FmtStep = @import("build/fmt.zig").FmtStep;
 
@@ -668,10 +669,10 @@ pub const Builder = struct {
     }
 
     fn copyFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void {
-        return self.copyFileMode(source_path, dest_path, os.File.default_mode);
+        return self.copyFileMode(source_path, dest_path, File.default_mode);
     }
 
-    fn copyFileMode(self: *Builder, source_path: []const u8, dest_path: []const u8, mode: os.File.Mode) !void {
+    fn copyFileMode(self: *Builder, source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
         if (self.verbose) {
             warn("cp {} {}\n", source_path, dest_path);
         }
std/c.zig
@@ -75,7 +75,7 @@ pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usi
 pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;
 pub extern "c" fn socket(domain: c_int, sock_type: c_int, protocol: c_int) c_int;
 pub extern "c" fn kill(pid: pid_t, sig: c_int) c_int;
-pub extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) usize;
+pub extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) isize;
 pub extern "c" fn openat(fd: c_int, path: [*]const u8, flags: c_int) c_int;
 pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
 pub extern "c" fn setuid(uid: c_uint) c_int;
std/child_process.zig
@@ -3,7 +3,7 @@ const cstr = std.cstr;
 const unicode = std.unicode;
 const io = std.io;
 const os = std.os;
-const posix = os.posix;
+const File = std.fs.File;
 const windows = os.windows;
 const mem = std.mem;
 const debug = std.debug;
@@ -23,9 +23,9 @@ pub const ChildProcess = struct {
 
     pub allocator: *mem.Allocator,
 
-    pub stdin: ?os.File,
-    pub stdout: ?os.File,
-    pub stderr: ?os.File,
+    pub stdin: ?File,
+    pub stdout: ?File,
+    pub stderr: ?File,
 
     pub term: ?(SpawnError!Term),
 
@@ -148,12 +148,7 @@ pub const ChildProcess = struct {
             return term;
         }
 
-        if (!windows.TerminateProcess(self.handle, exit_code)) {
-            const err = windows.GetLastError();
-            return switch (err) {
-                else => os.unexpectedErrorWindows(err),
-            };
-        }
+        try windows.TerminateProcess(self.handle, exit_code);
         try self.waitUnwrappedWindows();
         return self.term.?;
     }
@@ -163,16 +158,7 @@ pub const ChildProcess = struct {
             self.cleanupStreams();
             return term;
         }
-        const ret = posix.kill(self.pid, posix.SIGTERM);
-        const err = posix.getErrno(ret);
-        if (err > 0) {
-            return switch (err) {
-                posix.EINVAL => unreachable,
-                posix.EPERM => error.PermissionDenied,
-                posix.ESRCH => error.ProcessNotFound,
-                else => os.unexpectedErrorPosix(err),
-            };
-        }
+        try os.kill(self.pid, os.SIGTERM);
         self.waitUnwrapped();
         return self.term.?;
     }
@@ -267,19 +253,9 @@ pub const ChildProcess = struct {
     }
 
     fn waitUnwrapped(self: *ChildProcess) void {
-        var status: i32 = undefined;
-        while (true) {
-            const err = posix.getErrno(posix.waitpid(self.pid, &status, 0));
-            if (err > 0) {
-                switch (err) {
-                    posix.EINTR => continue,
-                    else => unreachable,
-                }
-            }
-            self.cleanupStreams();
-            self.handleWaitResult(status);
-            return;
-        }
+        const status = os.waitpid(self.pid, 0);
+        self.cleanupStreams();
+        self.handleWaitResult(status);
     }
 
     fn handleWaitResult(self: *ChildProcess, status: i32) void {
@@ -324,34 +300,34 @@ pub const ChildProcess = struct {
     }
 
     fn statusToTerm(status: i32) Term {
-        return if (posix.WIFEXITED(status))
-            Term{ .Exited = posix.WEXITSTATUS(status) }
-        else if (posix.WIFSIGNALED(status))
-            Term{ .Signal = posix.WTERMSIG(status) }
-        else if (posix.WIFSTOPPED(status))
-            Term{ .Stopped = posix.WSTOPSIG(status) }
+        return if (os.WIFEXITED(status))
+            Term{ .Exited = os.WEXITSTATUS(status) }
+        else if (os.WIFSIGNALED(status))
+            Term{ .Signal = os.WTERMSIG(status) }
+        else if (os.WIFSTOPPED(status))
+            Term{ .Stopped = os.WSTOPSIG(status) }
         else
             Term{ .Unknown = status };
     }
 
     fn spawnPosix(self: *ChildProcess) !void {
-        const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined;
+        const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try os.pipe() else undefined;
         errdefer if (self.stdin_behavior == StdIo.Pipe) {
             destroyPipe(stdin_pipe);
         };
 
-        const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined;
+        const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try os.pipe() else undefined;
         errdefer if (self.stdout_behavior == StdIo.Pipe) {
             destroyPipe(stdout_pipe);
         };
 
-        const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined;
+        const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try os.pipe() else undefined;
         errdefer if (self.stderr_behavior == StdIo.Pipe) {
             destroyPipe(stderr_pipe);
         };
 
         const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
-        const dev_null_fd = if (any_ignore) try os.posixOpenC(c"/dev/null", posix.O_RDWR, 0) else undefined;
+        const dev_null_fd = if (any_ignore) try os.openC(c"/dev/null", os.O_RDWR, 0) else undefined;
         defer {
             if (any_ignore) os.close(dev_null_fd);
         }
@@ -372,7 +348,7 @@ pub const ChildProcess = struct {
 
         // This pipe is used to communicate errors between the time of fork
         // and execve from the child process to the parent process.
-        const err_pipe = try makePipe();
+        const err_pipe = try os.pipe();
         errdefer destroyPipe(err_pipe);
 
         const pid_result = try posix.fork();
@@ -413,17 +389,17 @@ pub const ChildProcess = struct {
         // we are the parent
         const pid = @intCast(i32, pid_result);
         if (self.stdin_behavior == StdIo.Pipe) {
-            self.stdin = os.File.openHandle(stdin_pipe[1]);
+            self.stdin = File.openHandle(stdin_pipe[1]);
         } else {
             self.stdin = null;
         }
         if (self.stdout_behavior == StdIo.Pipe) {
-            self.stdout = os.File.openHandle(stdout_pipe[0]);
+            self.stdout = File.openHandle(stdout_pipe[0]);
         } else {
             self.stdout = null;
         }
         if (self.stderr_behavior == StdIo.Pipe) {
-            self.stderr = os.File.openHandle(stderr_pipe[0]);
+            self.stderr = File.openHandle(stderr_pipe[0]);
         } else {
             self.stderr = null;
         }
@@ -608,17 +584,17 @@ pub const ChildProcess = struct {
         };
 
         if (g_hChildStd_IN_Wr) |h| {
-            self.stdin = os.File.openHandle(h);
+            self.stdin = File.openHandle(h);
         } else {
             self.stdin = null;
         }
         if (g_hChildStd_OUT_Rd) |h| {
-            self.stdout = os.File.openHandle(h);
+            self.stdout = File.openHandle(h);
         } else {
             self.stdout = null;
         }
         if (g_hChildStd_ERR_Rd) |h| {
-            self.stderr = os.File.openHandle(h);
+            self.stderr = File.openHandle(h);
         } else {
             self.stderr = null;
         }
@@ -751,18 +727,6 @@ fn windowsMakePipeOut(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const
     wr.* = wr_h;
 }
 
-fn makePipe() ![2]i32 {
-    var fds: [2]i32 = undefined;
-    const err = posix.getErrno(posix.pipe(&fds));
-    if (err > 0) {
-        return switch (err) {
-            posix.EMFILE, posix.ENFILE => error.SystemResources,
-            else => os.unexpectedErrorPosix(err),
-        };
-    }
-    return fds;
-}
-
 fn destroyPipe(pipe: [2]i32) void {
     os.close(pipe[0]);
     os.close(pipe[1]);
@@ -778,12 +742,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
 const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
 
 fn writeIntFd(fd: i32, value: ErrInt) !void {
-    const stream = &os.File.openHandle(fd).outStream().stream;
+    const stream = &File.openHandle(fd).outStream().stream;
     stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
 }
 
 fn readIntFd(fd: i32) !ErrInt {
-    const stream = &os.File.openHandle(fd).inStream().stream;
+    const stream = &File.openHandle(fd).inStream().stream;
     return stream.readIntNative(ErrInt) catch return error.SystemResources;
 }
 
std/coff.zig
@@ -3,6 +3,7 @@ const std = @import("std.zig");
 const io = std.io;
 const mem = std.mem;
 const os = std.os;
+const File = std.fs.File;
 
 const ArrayList = std.ArrayList;
 
@@ -28,7 +29,7 @@ pub const CoffError = error{
 };
 
 pub const Coff = struct {
-    in_file: os.File,
+    in_file: File,
     allocator: *mem.Allocator,
 
     coff_header: CoffHeader,
@@ -77,7 +78,7 @@ pub const Coff = struct {
         try self.loadOptionalHeader(&file_stream);
     }
 
-    fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
+    fn loadOptionalHeader(self: *Coff, file_stream: *File.InStream) !void {
         const in = &file_stream.stream;
         self.pe_header.magic = try in.readIntLittle(u16);
         // For now we're only interested in finding the reference to the .pdb,
std/debug.zig
@@ -12,6 +12,7 @@ const windows = os.windows;
 const ArrayList = std.ArrayList;
 const builtin = @import("builtin");
 const maxInt = std.math.maxInt;
+const File = std.fs.File;
 
 const leb = @import("debug/leb128.zig");
 
@@ -36,10 +37,10 @@ const Module = struct {
 
 /// Tries to write to stderr, unbuffered, and ignores any error returned.
 /// Does not append a newline.
-var stderr_file: os.File = undefined;
-var stderr_file_out_stream: os.File.OutStream = undefined;
+var stderr_file: File = undefined;
+var stderr_file_out_stream: File.OutStream = undefined;
 
-var stderr_stream: ?*io.OutStream(os.File.WriteError) = null;
+var stderr_stream: ?*io.OutStream(File.WriteError) = null;
 var stderr_mutex = std.Mutex.init();
 pub fn warn(comptime fmt: []const u8, args: ...) void {
     const held = stderr_mutex.acquire();
@@ -48,7 +49,7 @@ pub fn warn(comptime fmt: []const u8, args: ...) void {
     stderr.print(fmt, args) catch return;
 }
 
-pub fn getStderrStream() !*io.OutStream(os.File.WriteError) {
+pub fn getStderrStream() !*io.OutStream(File.WriteError) {
     if (stderr_stream) |st| {
         return st;
     } else {
@@ -1003,7 +1004,7 @@ pub fn openElfDebugInfo(
 
 fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
     const S = struct {
-        var self_exe_file: os.File = undefined;
+        var self_exe_file: File = undefined;
         var self_exe_mmap_seekable: io.SliceSeekableInStream = undefined;
     };
 
@@ -1112,7 +1113,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
 }
 
 fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
-    var f = try os.File.openRead(line_info.file_name);
+    var f = try File.openRead(line_info.file_name);
     defer f.close();
     // TODO fstat and make sure that the file has the correct size
 
std/dynamic_library.zig
@@ -1,5 +1,4 @@
 const builtin = @import("builtin");
-const Os = builtin.Os;
 
 const std = @import("std.zig");
 const mem = std.mem;
@@ -8,14 +7,13 @@ const os = std.os;
 const assert = std.debug.assert;
 const testing = std.testing;
 const elf = std.elf;
-const linux = os.linux;
 const windows = os.windows;
 const win_util = @import("os/windows/util.zig");
 const maxInt = std.math.maxInt;
 
 pub const DynLib = switch (builtin.os) {
-    Os.linux => LinuxDynLib,
-    Os.windows => WindowsDynLib,
+    .linux => LinuxDynLib,
+    .windows => WindowsDynLib,
     else => void,
 };
 
@@ -110,20 +108,20 @@ pub const LinuxDynLib = struct {
 
     /// Trusts the file
     pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
-        const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
+        const fd = try os.open(path, 0, os.O_RDONLY | os.O_CLOEXEC);
         errdefer std.os.close(fd);
 
         const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
 
-        const addr = linux.mmap(
+        const addr = os.mmap(
             null,
             size,
-            linux.PROT_READ | linux.PROT_EXEC,
-            linux.MAP_PRIVATE | linux.MAP_LOCKED,
+            os.PROT_READ | os.PROT_EXEC,
+            os.MAP_PRIVATE | os.MAP_LOCKED,
             fd,
             0,
         );
-        errdefer _ = linux.munmap(addr, size);
+        errdefer os.munmap(addr, size);
 
         const bytes = @intToPtr([*]align(mem.page_size) u8, addr)[0..size];
 
@@ -136,7 +134,7 @@ pub const LinuxDynLib = struct {
     }
 
     pub fn close(self: *DynLib) void {
-        _ = linux.munmap(self.map_addr, self.map_size);
+        os.munmap(self.map_addr, self.map_size);
         std.os.close(self.fd);
         self.* = undefined;
     }
@@ -149,7 +147,7 @@ pub const LinuxDynLib = struct {
 pub const ElfLib = struct {
     strings: [*]u8,
     syms: [*]elf.Sym,
-    hashtab: [*]linux.Elf_Symndx,
+    hashtab: [*]os.Elf_Symndx,
     versym: ?[*]u16,
     verdef: ?*elf.Verdef,
     base: usize,
@@ -184,7 +182,7 @@ pub const ElfLib = struct {
 
         var maybe_strings: ?[*]u8 = null;
         var maybe_syms: ?[*]elf.Sym = null;
-        var maybe_hashtab: ?[*]linux.Elf_Symndx = null;
+        var maybe_hashtab: ?[*]os.Elf_Symndx = null;
         var maybe_versym: ?[*]u16 = null;
         var maybe_verdef: ?*elf.Verdef = null;
 
@@ -195,7 +193,7 @@ pub const ElfLib = struct {
                 switch (dynv[i]) {
                     elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),
                     elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),
-                    elf.DT_HASH => maybe_hashtab = @intToPtr([*]linux.Elf_Symndx, p),
+                    elf.DT_HASH => maybe_hashtab = @intToPtr([*]os.Elf_Symndx, p),
                     elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
                     elf.DT_VERDEF => maybe_verdef = @intToPtr(*elf.Verdef, p),
                     else => {},
@@ -283,8 +281,8 @@ pub const WindowsDynLib = struct {
 
 test "dynamic_library" {
     const libname = switch (builtin.os) {
-        Os.linux => "invalid_so.so",
-        Os.windows => "invalid_dll.dll",
+        .linux => "invalid_so.so",
+        .windows => "invalid_dll.dll",
         else => return,
     };
 
std/elf.zig
@@ -6,6 +6,7 @@ const math = std.math;
 const mem = std.mem;
 const debug = std.debug;
 const InStream = std.stream.InStream;
+const File = std.fs.File;
 
 pub const AT_NULL = 0;
 pub const AT_IGNORE = 1;
@@ -367,7 +368,7 @@ pub const Elf = struct {
     string_section: *SectionHeader,
     section_headers: []SectionHeader,
     allocator: *mem.Allocator,
-    prealloc_file: os.File,
+    prealloc_file: File,
 
     /// Call close when done.
     pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {
@@ -375,7 +376,7 @@ pub const Elf = struct {
     }
 
     /// Call close when done.
-    pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void {
+    pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: File) !void {
         @compileError("TODO implement");
     }
 
std/fs.zig
@@ -11,6 +11,7 @@ pub const deleteFile = os.unlink;
 pub const deleteFileC = os.unlinkC;
 pub const rename = os.rename;
 pub const renameC = os.renameC;
+pub const renameW = os.renameW;
 pub const changeCurDir = os.chdir;
 pub const changeCurDirC = os.chdirC;
 pub const realpath = os.realpath;
@@ -25,24 +26,24 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE
 /// fit into a UTF-8 encoded array of this length.
 /// path being too long if it is this 0long
 pub const MAX_PATH_BYTES = switch (builtin.os) {
-    .linux, .macosx, .ios, .freebsd, .netbsd => posix.PATH_MAX,
+    .linux, .macosx, .ios, .freebsd, .netbsd => os.PATH_MAX,
     // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
     // If it would require 4 UTF-8 bytes, then there would be a surrogate
     // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
     // +1 for the null byte at the end, which can be encoded in 1 byte.
-    .windows => posix.PATH_MAX_WIDE * 3 + 1,
+    .windows => os.windows.PATH_MAX_WIDE * 3 + 1,
     else => @compileError("Unsupported OS"),
 };
 
 /// The result is a slice of `out_buffer`, from index `0`.
 pub fn getCwd(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
-    return posix.getcwd(out_buffer);
+    return os.getcwd(out_buffer);
 }
 
 /// Caller must free the returned memory.
 pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
     var buf: [MAX_PATH_BYTES]u8 = undefined;
-    return mem.dupe(allocator, u8, try posix.getcwd(&buf));
+    return mem.dupe(allocator, u8, try os.getcwd(&buf));
 }
 
 test "getCwdAlloc" {
@@ -90,7 +91,7 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:
 /// in the same directory as dest_path.
 /// Destination file will have the same mode as the source file.
 pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
-    var in_file = try os.File.openRead(source_path);
+    var in_file = try File.openRead(source_path);
     defer in_file.close();
 
     const mode = try in_file.mode();
@@ -113,7 +114,7 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
 /// merged and readily available,
 /// there is a possibility of power loss or application termination leaving temporary files present
 pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
-    var in_file = try os.File.openRead(source_path);
+    var in_file = try File.openRead(source_path);
     defer in_file.close();
 
     var atomic_file = try AtomicFile.init(dest_path, mode);
@@ -130,12 +131,12 @@ pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.M
 }
 
 pub const AtomicFile = struct {
-    file: os.File,
+    file: File,
     tmp_path_buf: [MAX_PATH_BYTES]u8,
     dest_path: []const u8,
     finished: bool,
 
-    const InitError = os.File.OpenError;
+    const InitError = File.OpenError;
 
     /// dest_path must remain valid for the lifetime of AtomicFile
     /// call finish to atomically replace dest_path with contents
@@ -161,7 +162,7 @@ pub const AtomicFile = struct {
             try getRandomBytes(rand_buf[0..]);
             b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);
 
-            const file = os.File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {
+            const file = File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {
                 error.PathAlreadyExists => continue,
                 // TODO zig should figure out that this error set does not include PathAlreadyExists since
                 // it is handled in the above switch
@@ -190,16 +191,13 @@ pub const AtomicFile = struct {
         assert(!self.finished);
         self.file.close();
         self.finished = true;
-        if (is_posix) {
-            const dest_path_c = try toPosixPath(self.dest_path);
-            return renameC(&self.tmp_path_buf, &dest_path_c);
-        } else if (is_windows) {
-            const dest_path_w = try posix.sliceToPrefixedFileW(self.dest_path);
-            const tmp_path_w = try posix.cStrToPrefixedFileW(&self.tmp_path_buf);
-            return renameW(&tmp_path_w, &dest_path_w);
-        } else {
-            @compileError("Unsupported OS");
+        if (os.windows.is_the_target) {
+            const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
+            const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
+            return os.renameW(&tmp_path_w, &dest_path_w);
         }
+        const dest_path_c = try os.toPosixPath(self.dest_path);
+        return os.renameC(&self.tmp_path_buf, &dest_path_c);
     }
 };
 
@@ -207,17 +205,17 @@ const default_new_dir_mode = 0o755;
 
 /// Create a new directory.
 pub fn makeDir(dir_path: []const u8) !void {
-    return posix.mkdir(dir_path, default_new_dir_mode);
+    return os.mkdir(dir_path, default_new_dir_mode);
 }
 
 /// Same as `makeDir` except the parameter is a null-terminated UTF8-encoded string.
 pub fn makeDirC(dir_path: [*]const u8) !void {
-    return posix.mkdirC(dir_path, default_new_dir_mode);
+    return os.mkdirC(dir_path, default_new_dir_mode);
 }
 
 /// Same as `makeDir` except the parameter is a null-terminated UTF16LE-encoded string.
 pub fn makeDirW(dir_path: [*]const u16) !void {
-    return posix.mkdirW(dir_path, default_new_dir_mode);
+    return os.mkdirW(dir_path, default_new_dir_mode);
 }
 
 /// Calls makeDir recursively to make an entire path. Returns success if the path
@@ -260,17 +258,17 @@ pub fn makePath(allocator: *Allocator, full_path: []const u8) !void {
 /// Returns `error.DirNotEmpty` if the directory is not empty.
 /// To delete a directory recursively, see `deleteTree`.
 pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {
-    return posix.rmdir(dir_path);
+    return os.rmdir(dir_path);
 }
 
 /// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.
 pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {
-    return posix.rmdirC(dir_path);
+    return os.rmdirC(dir_path);
 }
 
 /// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.
 pub fn deleteDirW(dir_path: [*]const u16) DeleteDirError!void {
-    return posix.rmdirW(dir_path);
+    return os.rmdirW(dir_path);
 }
 
 /// Whether ::full_path describes a symlink, file, or directory, this function
@@ -383,22 +381,22 @@ pub const Dir = struct {
     allocator: *Allocator,
 
     pub const Handle = switch (builtin.os) {
-        Os.macosx, Os.ios, Os.freebsd, Os.netbsd => struct {
+        .macosx, .ios, .freebsd, .netbsd => struct {
             fd: i32,
             seek: i64,
             buf: []u8,
             index: usize,
             end_index: usize,
         },
-        Os.linux => struct {
+        .linux => struct {
             fd: i32,
             buf: []u8,
             index: usize,
             end_index: usize,
         },
-        Os.windows => struct {
-            handle: windows.HANDLE,
-            find_file_data: windows.WIN32_FIND_DATAW,
+        .windows => struct {
+            handle: os.windows.HANDLE,
+            find_file_data: os.windows.WIN32_FIND_DATAW,
             first: bool,
             name_data: [256]u8,
         },
@@ -449,9 +447,9 @@ pub const Dir = struct {
         return Dir{
             .allocator = allocator,
             .handle = switch (builtin.os) {
-                Os.windows => blk: {
-                    var find_file_data: windows.WIN32_FIND_DATAW = undefined;
-                    const handle = try windows_util.windowsFindFirstFile(dir_path, &find_file_data);
+                .windows => blk: {
+                    var find_file_data: os.windows.WIN32_FIND_DATAW = undefined;
+                    const handle = try os.windows.FindFirstFile(dir_path, &find_file_data);
                     break :blk Handle{
                         .handle = handle,
                         .find_file_data = find_file_data, // TODO guaranteed copy elision
@@ -459,23 +457,15 @@ pub const Dir = struct {
                         .name_data = undefined,
                     };
                 },
-                Os.macosx, Os.ios, Os.freebsd, Os.netbsd => Handle{
-                    .fd = try posixOpen(
-                        dir_path,
-                        posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
-                        0,
-                    ),
+                .macosx, .ios, .freebsd, .netbsd => Handle{
+                    .fd = try os.open(dir_path, os.O_RDONLY | os.O_NONBLOCK | os.O_DIRECTORY | os.O_CLOEXEC, 0),
                     .seek = 0,
                     .index = 0,
                     .end_index = 0,
                     .buf = []u8{},
                 },
-                Os.linux => Handle{
-                    .fd = try posixOpen(
-                        dir_path,
-                        posix.O_RDONLY | posix.O_DIRECTORY | posix.O_CLOEXEC,
-                        0,
-                    ),
+                .linux => Handle{
+                    .fd = try os.open(dir_path, os.O_RDONLY | os.O_DIRECTORY | os.O_CLOEXEC, 0),
                     .index = 0,
                     .end_index = 0,
                     .buf = []u8{},
@@ -486,27 +476,22 @@ pub const Dir = struct {
     }
 
     pub fn close(self: *Dir) void {
-        switch (builtin.os) {
-            Os.windows => {
-                _ = windows.FindClose(self.handle.handle);
-            },
-            Os.macosx, Os.ios, Os.linux, Os.freebsd, Os.netbsd => {
-                self.allocator.free(self.handle.buf);
-                os.close(self.handle.fd);
-            },
-            else => @compileError("unimplemented"),
+        if (os.windows.is_the_target) {
+            return os.windows.FindClose(self.handle.handle);
         }
+        self.allocator.free(self.handle.buf);
+        os.close(self.handle.fd);
     }
 
     /// Memory such as file names referenced in this returned entry becomes invalid
     /// with subsequent calls to next, as well as when this `Dir` is deinitialized.
     pub fn next(self: *Dir) !?Entry {
         switch (builtin.os) {
-            Os.linux => return self.nextLinux(),
-            Os.macosx, Os.ios => return self.nextDarwin(),
-            Os.windows => return self.nextWindows(),
-            Os.freebsd => return self.nextFreebsd(),
-            Os.netbsd => return self.nextFreebsd(),
+            .linux => return self.nextLinux(),
+            .macosx, .ios => return self.nextDarwin(),
+            .windows => return self.nextWindows(),
+            .freebsd => return self.nextBsd(),
+            .netbsd => return self.nextBsd(),
             else => @compileError("unimplemented"),
         }
     }
@@ -519,18 +504,23 @@ pub const Dir = struct {
                 }
 
                 while (true) {
-                    const result = system.__getdirentries64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);
-                    if (result == 0) return null;
-                    if (result < 0) {
-                        switch (system.getErrno(result)) {
-                            posix.EBADF => unreachable,
-                            posix.EFAULT => unreachable,
-                            posix.ENOTDIR => unreachable,
-                            posix.EINVAL => {
+                    const rc = os.system.__getdirentries64(
+                        self.handle.fd,
+                        self.handle.buf.ptr,
+                        self.handle.buf.len,
+                        &self.handle.seek,
+                    );
+                    if (rc == 0) return null;
+                    if (rc < 0) {
+                        switch (os.errno(rc)) {
+                            os.EBADF => unreachable,
+                            os.EFAULT => unreachable,
+                            os.ENOTDIR => unreachable,
+                            os.EINVAL => {
                                 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
                                 continue;
                             },
-                            else => return unexpectedErrorPosix(err),
+                            else => |err| return os.unexpectedErrno(err),
                         }
                     }
                     self.handle.index = 0;
@@ -538,7 +528,7 @@ pub const Dir = struct {
                     break;
                 }
             }
-            const darwin_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]);
+            const darwin_entry = @ptrCast(*align(1) os.dirent, &self.handle.buf[self.handle.index]);
             const next_index = self.handle.index + darwin_entry.d_reclen;
             self.handle.index = next_index;
 
@@ -549,14 +539,14 @@ pub const Dir = struct {
             }
 
             const entry_kind = switch (darwin_entry.d_type) {
-                posix.DT_BLK => Entry.Kind.BlockDevice,
-                posix.DT_CHR => Entry.Kind.CharacterDevice,
-                posix.DT_DIR => Entry.Kind.Directory,
-                posix.DT_FIFO => Entry.Kind.NamedPipe,
-                posix.DT_LNK => Entry.Kind.SymLink,
-                posix.DT_REG => Entry.Kind.File,
-                posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
-                posix.DT_WHT => Entry.Kind.Whiteout,
+                os.DT_BLK => Entry.Kind.BlockDevice,
+                os.DT_CHR => Entry.Kind.CharacterDevice,
+                os.DT_DIR => Entry.Kind.Directory,
+                os.DT_FIFO => Entry.Kind.NamedPipe,
+                os.DT_LNK => Entry.Kind.SymLink,
+                os.DT_REG => Entry.Kind.File,
+                os.DT_SOCK => Entry.Kind.UnixDomainSocket,
+                os.DT_WHT => Entry.Kind.Whiteout,
                 else => Entry.Kind.Unknown,
             };
             return Entry{
@@ -571,7 +561,7 @@ pub const Dir = struct {
             if (self.handle.first) {
                 self.handle.first = false;
             } else {
-                if (!try posix.FindNextFile(self.handle.handle, &self.handle.find_file_data))
+                if (!try os.windows.FindNextFile(self.handle.handle, &self.handle.find_file_data))
                     return null;
             }
             const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);
@@ -582,9 +572,9 @@ pub const Dir = struct {
             const name_utf8 = self.handle.name_data[0..name_utf8_len];
             const kind = blk: {
                 const attrs = self.handle.find_file_data.dwFileAttributes;
-                if (attrs & windows.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk Entry.Kind.Directory;
-                if (attrs & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk Entry.Kind.SymLink;
-                if (attrs & windows.FILE_ATTRIBUTE_NORMAL != 0) break :blk Entry.Kind.File;
+                if (attrs & os.windows.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk Entry.Kind.Directory;
+                if (attrs & os.windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk Entry.Kind.SymLink;
+                if (attrs & os.windows.FILE_ATTRIBUTE_NORMAL != 0) break :blk Entry.Kind.File;
                 break :blk Entry.Kind.Unknown;
             };
             return Entry{
@@ -602,25 +592,25 @@ pub const Dir = struct {
                 }
 
                 while (true) {
-                    const result = posix.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
-                    const err = posix.getErrno(result);
-                    if (err > 0) {
-                        switch (err) {
-                            posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,
-                            posix.EINVAL => {
-                                self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
-                                continue;
-                            },
-                            else => return unexpectedErrorPosix(err),
-                        }
+                    const rc = os.system.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
+                    switch (os.errno(rc)) {
+                        0 => {},
+                        os.EBADF => unreachable,
+                        os.EFAULT => unreachable,
+                        os.ENOTDIR => unreachable,
+                        os.EINVAL => {
+                            self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
+                            continue;
+                        },
+                        else => |err| return os.unexpectedErrno(err),
                     }
-                    if (result == 0) return null;
+                    if (rc == 0) return null;
                     self.handle.index = 0;
-                    self.handle.end_index = result;
+                    self.handle.end_index = rc;
                     break;
                 }
             }
-            const linux_entry = @ptrCast(*align(1) posix.dirent64, &self.handle.buf[self.handle.index]);
+            const linux_entry = @ptrCast(*align(1) os.dirent64, &self.handle.buf[self.handle.index]);
             const next_index = self.handle.index + linux_entry.d_reclen;
             self.handle.index = next_index;
 
@@ -632,13 +622,13 @@ pub const Dir = struct {
             }
 
             const entry_kind = switch (linux_entry.d_type) {
-                posix.DT_BLK => Entry.Kind.BlockDevice,
-                posix.DT_CHR => Entry.Kind.CharacterDevice,
-                posix.DT_DIR => Entry.Kind.Directory,
-                posix.DT_FIFO => Entry.Kind.NamedPipe,
-                posix.DT_LNK => Entry.Kind.SymLink,
-                posix.DT_REG => Entry.Kind.File,
-                posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
+                os.DT_BLK => Entry.Kind.BlockDevice,
+                os.DT_CHR => Entry.Kind.CharacterDevice,
+                os.DT_DIR => Entry.Kind.Directory,
+                os.DT_FIFO => Entry.Kind.NamedPipe,
+                os.DT_LNK => Entry.Kind.SymLink,
+                os.DT_REG => Entry.Kind.File,
+                os.DT_SOCK => Entry.Kind.UnixDomainSocket,
                 else => Entry.Kind.Unknown,
             };
             return Entry{
@@ -648,7 +638,7 @@ pub const Dir = struct {
         }
     }
 
-    fn nextFreebsd(self: *Dir) !?Entry {
+    fn nextBsd(self: *Dir) !?Entry {
         start_over: while (true) {
             if (self.handle.index >= self.handle.end_index) {
                 if (self.handle.buf.len == 0) {
@@ -656,25 +646,30 @@ pub const Dir = struct {
                 }
 
                 while (true) {
-                    const result = posix.getdirentries(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);
-                    const err = posix.getErrno(result);
-                    if (err > 0) {
-                        switch (err) {
-                            posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,
-                            posix.EINVAL => {
-                                self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
-                                continue;
-                            },
-                            else => return unexpectedErrorPosix(err),
-                        }
+                    const rc = os.system.getdirentries(
+                        self.handle.fd,
+                        self.handle.buf.ptr,
+                        self.handle.buf.len,
+                        &self.handle.seek,
+                    );
+                    switch (os.errno(rc)) {
+                        0 => {},
+                        os.EBADF => unreachable,
+                        os.EFAULT => unreachable,
+                        os.ENOTDIR => unreachable,
+                        os.EINVAL => {
+                            self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
+                            continue;
+                        },
+                        else => |err| return os.unexpectedErrno(err),
                     }
-                    if (result == 0) return null;
+                    if (rc == 0) return null;
                     self.handle.index = 0;
-                    self.handle.end_index = result;
+                    self.handle.end_index = @intCast(usize, rc);
                     break;
                 }
             }
-            const freebsd_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]);
+            const freebsd_entry = @ptrCast(*align(1) os.dirent, &self.handle.buf[self.handle.index]);
             const next_index = self.handle.index + freebsd_entry.d_reclen;
             self.handle.index = next_index;
 
@@ -685,14 +680,14 @@ pub const Dir = struct {
             }
 
             const entry_kind = switch (freebsd_entry.d_type) {
-                posix.DT_BLK => Entry.Kind.BlockDevice,
-                posix.DT_CHR => Entry.Kind.CharacterDevice,
-                posix.DT_DIR => Entry.Kind.Directory,
-                posix.DT_FIFO => Entry.Kind.NamedPipe,
-                posix.DT_LNK => Entry.Kind.SymLink,
-                posix.DT_REG => Entry.Kind.File,
-                posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
-                posix.DT_WHT => Entry.Kind.Whiteout,
+                os.DT_BLK => Entry.Kind.BlockDevice,
+                os.DT_CHR => Entry.Kind.CharacterDevice,
+                os.DT_DIR => Entry.Kind.Directory,
+                os.DT_FIFO => Entry.Kind.NamedPipe,
+                os.DT_LNK => Entry.Kind.SymLink,
+                os.DT_REG => Entry.Kind.File,
+                os.DT_SOCK => Entry.Kind.UnixDomainSocket,
+                os.DT_WHT => Entry.Kind.Whiteout,
                 else => Entry.Kind.Unknown,
             };
             return Entry{
@@ -705,52 +700,40 @@ pub const Dir = struct {
 
 /// Read value of a symbolic link.
 /// The return value is a slice of buffer, from index `0`.
-pub fn readLink(buffer: *[posix.PATH_MAX]u8, pathname: []const u8) ![]u8 {
-    return posix.readlink(pathname, buffer);
+pub fn readLink(pathname: []const u8, buffer: *[os.PATH_MAX]u8) ![]u8 {
+    return os.readlink(pathname, buffer);
 }
 
 /// Same as `readLink`, except the `pathname` parameter is null-terminated.
-pub fn readLinkC(buffer: *[posix.PATH_MAX]u8, pathname: [*]const u8) ![]u8 {
-    return posix.readlinkC(pathname, buffer);
+pub fn readLinkC(pathname: [*]const u8, buffer: *[os.PATH_MAX]u8) ![]u8 {
+    return os.readlinkC(pathname, buffer);
 }
 
-pub fn openSelfExe() !os.File {
-    switch (builtin.os) {
-        Os.linux => return os.File.openReadC(c"/proc/self/exe"),
-        Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
-            var buf: [MAX_PATH_BYTES]u8 = undefined;
-            const self_exe_path = try selfExePath(&buf);
-            buf[self_exe_path.len] = 0;
-            return os.File.openReadC(self_exe_path.ptr);
-        },
-        Os.windows => {
-            var buf: [posix.PATH_MAX_WIDE]u16 = undefined;
-            const wide_slice = try selfExePathW(&buf);
-            return os.File.openReadW(wide_slice.ptr);
-        },
-        else => @compileError("Unsupported OS"),
+pub const OpenSelfExeError = error{};
+
+pub fn openSelfExe() OpenSelfExeError!File {
+    if (os.linux.is_the_target) {
+        return File.openReadC(c"/proc/self/exe");
+    }
+    if (os.windows.is_the_target) {
+        var buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
+        const wide_slice = try selfExePathW(&buf);
+        return File.openReadW(wide_slice.ptr);
     }
+    var buf: [MAX_PATH_BYTES]u8 = undefined;
+    const self_exe_path = try selfExePath(&buf);
+    buf[self_exe_path.len] = 0;
+    return File.openReadC(self_exe_path.ptr);
 }
 
 test "openSelfExe" {
     switch (builtin.os) {
-        Os.linux, Os.macosx, Os.ios, Os.windows, Os.freebsd => (try openSelfExe()).close(),
+        .linux, .macosx, .ios, .windows, .freebsd => (try openSelfExe()).close(),
         else => return error.SkipZigTest, // Unsupported OS.
     }
 }
 
-pub fn selfExePathW(out_buffer: *[posix.PATH_MAX_WIDE]u16) ![]u16 {
-    const casted_len = @intCast(windows.DWORD, out_buffer.len); // TODO shouldn't need this cast
-    const rc = windows.GetModuleFileNameW(null, out_buffer, casted_len);
-    assert(rc <= out_buffer.len);
-    if (rc == 0) {
-        const err = windows.GetLastError();
-        switch (err) {
-            else => return windows.unexpectedError(err),
-        }
-    }
-    return out_buffer[0..rc];
-}
+pub const SelfExePathError = os.ReadLinkError || os.SysCtlError;
 
 /// Get the path to the current executable.
 /// If you only need the directory, use selfExeDirPath.
@@ -763,39 +746,44 @@ pub fn selfExePathW(out_buffer: *[posix.PATH_MAX_WIDE]u16) ![]u16 {
 /// been deleted, the file path looks something like `/a/b/c/exe (deleted)`.
 /// TODO make the return type of this a null terminated pointer
 pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
+    if (os.darwin.is_the_target) {
+        var u32_len: u32 = out_buffer.len;
+        const rc = c._NSGetExecutablePath(out_buffer, &u32_len);
+        if (rc != 0) return error.NameTooLong;
+        return mem.toSlice(u8, out_buffer);
+    }
     switch (builtin.os) {
-        Os.linux => return readLink(out_buffer, "/proc/self/exe"),
-        Os.freebsd => {
-            var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC, posix.KERN_PROC_PATHNAME, -1 };
+        .linux => return os.readlinkC(c"/proc/self/exe", out_buffer),
+        .freebsd => {
+            var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };
             var out_len: usize = out_buffer.len;
-            try posix.sysctl(&mib, out_buffer, &out_len, null, 0);
+            try os.sysctl(&mib, out_buffer, &out_len, null, 0);
             // TODO could this slice from 0 to out_len instead?
             return mem.toSlice(u8, out_buffer);
         },
-        Os.netbsd => {
-            var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC_ARGS, -1, posix.KERN_PROC_PATHNAME };
+        .netbsd => {
+            var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC_ARGS, -1, os.KERN_PROC_PATHNAME };
             var out_len: usize = out_buffer.len;
-            try posix.sysctl(&mib, out_buffer, &out_len, null, 0);
+            try os.sysctl(&mib, out_buffer, &out_len, null, 0);
             // TODO could this slice from 0 to out_len instead?
             return mem.toSlice(u8, out_buffer);
         },
-        Os.windows => {
-            var utf16le_buf: [posix.PATH_MAX_WIDE]u16 = undefined;
+        .windows => {
+            var utf16le_buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
             const utf16le_slice = try selfExePathW(&utf16le_buf);
             // Trust that Windows gives us valid UTF-16LE.
             const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable;
             return out_buffer[0..end_index];
         },
-        Os.macosx, Os.ios => {
-            var u32_len: u32 = @intCast(u32, out_buffer.len); // TODO shouldn't need this cast
-            const rc = c._NSGetExecutablePath(out_buffer, &u32_len);
-            if (rc != 0) return error.NameTooLong;
-            return mem.toSlice(u8, out_buffer);
-        },
-        else => @compileError("Unsupported OS"),
+        else => @compileError("std.fs.selfExePath not supported for this target"),
     }
 }
 
+/// Same as `selfExePath` except the result is UTF16LE-encoded.
+pub fn selfExePathW(out_buffer: *[os.windows.PATH_MAX_WIDE]u16) ![]u16 {
+    return os.windows.GetModuleFileNameW(null, out_buffer, out_buffer.len);
+}
+
 /// `selfExeDirPath` except allocates the result on the heap.
 /// Caller owns returned memory.
 pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
@@ -806,31 +794,26 @@ pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
 /// Get the directory path that contains the current executable.
 /// Returned value is a slice of out_buffer.
 pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {
-    switch (builtin.os) {
-        Os.linux => {
-            // If the currently executing binary has been deleted,
-            // the file path looks something like `/a/b/c/exe (deleted)`
-            // This path cannot be opened, but it's valid for determining the directory
-            // the executable was in when it was run.
-            const full_exe_path = try readLinkC(out_buffer, c"/proc/self/exe");
-            // Assume that /proc/self/exe has an absolute path, and therefore dirname
-            // will not return null.
-            return path.dirname(full_exe_path).?;
-        },
-        Os.windows, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
-            const self_exe_path = try selfExePath(out_buffer);
-            // Assume that the OS APIs return absolute paths, and therefore dirname
-            // will not return null.
-            return path.dirname(self_exe_path).?;
-        },
-        else => @compileError("Unsupported OS"),
+    if (os.linux.is_the_target) {
+        // If the currently executing binary has been deleted,
+        // the file path looks something like `/a/b/c/exe (deleted)`
+        // This path cannot be opened, but it's valid for determining the directory
+        // the executable was in when it was run.
+        const full_exe_path = try os.readlinkC(c"/proc/self/exe", out_buffer);
+        // Assume that /proc/self/exe has an absolute path, and therefore dirname
+        // will not return null.
+        return path.dirname(full_exe_path).?;
     }
+    const self_exe_path = try selfExePath(out_buffer);
+    // Assume that the OS APIs return absolute paths, and therefore dirname
+    // will not return null.
+    return path.dirname(self_exe_path).?;
 }
 
 /// `realpath`, except caller must free the returned memory.
-pub fn realAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
+pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
     var buf: [MAX_PATH_BYTES]u8 = undefined;
-    return mem.dupe(allocator, u8, try realpath(pathname, &buf));
+    return mem.dupe(allocator, u8, try os.realpath(pathname, &buf));
 }
 
 test "" {
std/io.zig
@@ -12,7 +12,7 @@ const meta = std.meta;
 const trait = meta.trait;
 const Buffer = std.Buffer;
 const fmt = std.fmt;
-const File = std.os.File;
+const File = std.fs.File;
 const testing = std.testing;
 
 const is_posix = builtin.os != builtin.Os.windows;
@@ -963,8 +963,8 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
 
 pub const BufferedAtomicFile = struct {
     atomic_file: os.AtomicFile,
-    file_stream: os.File.OutStream,
-    buffered_stream: BufferedOutStream(os.File.WriteError),
+    file_stream: File.OutStream,
+    buffered_stream: BufferedOutStream(File.WriteError),
     allocator: *mem.Allocator,
 
     pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
@@ -978,11 +978,11 @@ pub const BufferedAtomicFile = struct {
         };
         errdefer allocator.destroy(self);
 
-        self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);
+        self.atomic_file = try os.AtomicFile.init(dest_path, File.default_mode);
         errdefer self.atomic_file.deinit();
 
         self.file_stream = self.atomic_file.file.outStream();
-        self.buffered_stream = BufferedOutStream(os.File.WriteError).init(&self.file_stream.stream);
+        self.buffered_stream = BufferedOutStream(File.WriteError).init(&self.file_stream.stream);
         return self;
     }
 
@@ -997,7 +997,7 @@ pub const BufferedAtomicFile = struct {
         try self.atomic_file.finish();
     }
 
-    pub fn stream(self: *BufferedAtomicFile) *OutStream(os.File.WriteError) {
+    pub fn stream(self: *BufferedAtomicFile) *OutStream(File.WriteError) {
         return &self.buffered_stream.stream;
     }
 };
std/os.zig
@@ -16,6 +16,7 @@
 
 const std = @import("std.zig");
 const builtin = @import("builtin");
+const math = std.math;
 const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
 
 comptime {
@@ -114,7 +115,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
     const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
     defer close(fd);
 
-    const stream = &os.File.openHandle(fd).inStream().stream;
+    const stream = &std.fs.File.openHandle(fd).inStream().stream;
     stream.readNoEof(buf) catch return error.Unexpected;
 }
 
@@ -177,6 +178,21 @@ pub fn raise(sig: u8) RaiseError!void {
     }
 }
 
+pub const KillError = error{
+    PermissionDenied,
+    Unexpected,
+};
+
+pub fn kill(pid: pid_t, sig: u8) KillError!void {
+    switch (errno(system.kill(pid, sig))) {
+        0 => return,
+        EINVAL => unreachable, // invalid signal
+        EPERM => return error.PermissionDenied,
+        ESRCH => unreachable, // always a race condition
+        else => |err| return unexpectedErrno(err),
+    }
+}
+
 /// Exits the program cleanly with the specified status code.
 pub fn exit(status: u8) noreturn {
     if (builtin.link_libc) {
@@ -885,8 +901,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
     if (windows.is_the_target and !builtin.link_libc) {
         const old_path_w = try windows.sliceToPrefixedFileW(old_path);
         const new_path_w = try windows.sliceToPrefixedFileW(new_path);
-        const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
-        return windows.MoveFileExW(&old_path_w, &new_path_w, flags);
+        return renameW(&old_path_w, &new_path_w);
     } else {
         const old_path_c = try toPosixPath(old_path);
         const new_path_c = try toPosixPath(new_path);
@@ -899,8 +914,7 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
     if (windows.is_the_target and !builtin.link_libc) {
         const old_path_w = try windows.cStrToPrefixedFileW(old_path);
         const new_path_w = try windows.cStrToPrefixedFileW(new_path);
-        const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
-        return windows.MoveFileExW(&old_path_w, &new_path_w, flags);
+        return renameW(&old_path_w, &new_path_w);
     }
     switch (errno(system.rename(old_path, new_path))) {
         0 => return,
@@ -926,6 +940,13 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
     }
 }
 
+/// Same as `rename` except the parameters are null-terminated UTF16LE encoded byte arrays.
+/// 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);
+}
+
 pub const MakeDirError = error{
     AccessDenied,
     DiskQuota,
@@ -1684,10 +1705,10 @@ pub fn getsockoptError(sockfd: i32) ConnectError!void {
     }
 }
 
-pub fn waitpid(pid: i32) i32 {
+pub fn waitpid(pid: i32, flags: u32) i32 {
     var status: i32 = undefined;
     while (true) {
-        switch (errno(system.waitpid(pid, &status, 0))) {
+        switch (errno(system.waitpid(pid, &status, flags))) {
             0 => return status,
             EINTR => continue,
             ECHILD => unreachable, // The process specified does not exist. It would be a race condition to handle this error.
@@ -1988,9 +2009,10 @@ pub const PipeError = error{
 };
 
 /// Creates a unidirectional data channel that can be used for interprocess communication.
-pub fn pipe(fds: *[2]fd_t) PipeError!void {
-    switch (errno(system.pipe(fds))) {
-        0 => return,
+pub fn pipe() PipeError![2]fd_t {
+    var fds: [2]i32 = undefined;
+    switch (errno(system.pipe(&fds))) {
+        0 => return fds,
         EINVAL => unreachable, // Invalid parameters to pipe()
         EFAULT => unreachable, // Invalid fds pointer
         ENFILE => return error.SystemFdQuotaExceeded,
@@ -1999,9 +2021,10 @@ pub fn pipe(fds: *[2]fd_t) PipeError!void {
     }
 }
 
-pub fn pipe2(fds: *[2]fd_t, flags: u32) PipeError!void {
-    switch (errno(system.pipe2(fds, flags))) {
-        0 => return,
+pub fn pipe2(flags: u32) PipeError![2]fd_t {
+    var fds: [2]i32 = undefined;
+    switch (errno(system.pipe2(&fds, flags))) {
+        0 => return fds,
         EINVAL => unreachable, // Invalid flags
         EFAULT => unreachable, // Invalid fds pointer
         ENFILE => return error.SystemFdQuotaExceeded,
@@ -2281,6 +2304,67 @@ pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPa
     return out_buffer[0..end_index];
 }
 
+/// Spurious wakeups are possible and no precision of timing is guaranteed.
+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 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);
+        windows.kernel32.Sleep(ms);
+        return;
+    }
+    var req = timespec{
+        .tv_sec = math.cast(isize, seconds) catch math.maxInt(isize),
+        .tv_nsec = math.cast(isize, nanoseconds) catch math.maxInt(isize),
+    };
+    var rem: timespec = undefined;
+    while (true) {
+        switch (errno(system.nanosleep(&req, &rem))) {
+            EFAULT => unreachable,
+            EINVAL => {
+                // Sometimes Darwin returns EINVAL for no reason.
+                // We treat it as a spurious wakeup.
+                return;
+            },
+            EINTR => {
+                req = rem;
+                continue;
+            },
+            // This prong handles success as well as unexpected errors.
+            else => return,
+        }
+    }
+}
+
+pub const ClockGetTimeError = error{
+    UnsupportedClock,
+    Unexpected,
+};
+
+pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
+    switch (errno(system.clock_gettime(clk_id, tp))) {
+        0 => return,
+        EFAULT => unreachable,
+        EINVAL => return error.UnsupportedClock,
+        else => |err| return unexpectedErrno(err),
+    }
+}
+
+pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
+    switch (errno(system.clock_getres(clk_id, tp))) {
+        0 => return,
+        EFAULT => unreachable,
+        EINVAL => return error.UnsupportedClock,
+        else => |err| return unexpectedErrno(err),
+    }
+}
+
 /// Used to convert a slice to a null terminated slice on the stack.
 /// TODO https://github.com/ziglang/zig/issues/287
 pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {
std/pdb.zig
@@ -6,6 +6,7 @@ const mem = std.mem;
 const os = std.os;
 const warn = std.debug.warn;
 const coff = std.coff;
+const File = std.fs.File;
 
 const ArrayList = std.ArrayList;
 
@@ -459,7 +460,7 @@ pub const PDBStringTableHeader = packed struct {
 };
 
 pub const Pdb = struct {
-    in_file: os.File,
+    in_file: File,
     allocator: *mem.Allocator,
     coff: *coff.Coff,
     string_table: *MsfStream,
@@ -468,7 +469,7 @@ pub const Pdb = struct {
     msf: Msf,
 
     pub fn openFile(self: *Pdb, coff_ptr: *coff.Coff, file_name: []u8) !void {
-        self.in_file = try os.File.openRead(file_name);
+        self.in_file = try File.openRead(file_name);
         self.allocator = coff_ptr.allocator;
         self.coff = coff_ptr;
 
@@ -492,7 +493,7 @@ const Msf = struct {
     directory: MsfStream,
     streams: []MsfStream,
 
-    fn openFile(self: *Msf, allocator: *mem.Allocator, file: os.File) !void {
+    fn openFile(self: *Msf, allocator: *mem.Allocator, file: File) !void {
         var file_stream = file.inStream();
         const in = &file_stream.stream;
 
@@ -587,7 +588,7 @@ const SuperBlock = packed struct {
 };
 
 const MsfStream = struct {
-    in_file: os.File,
+    in_file: File,
     pos: u64,
     blocks: []u32,
     block_size: u32,
@@ -598,7 +599,7 @@ const MsfStream = struct {
     pub const Error = @typeOf(read).ReturnType.ErrorSet;
     pub const Stream = io.InStream(Error);
 
-    fn init(block_size: u32, block_count: u32, pos: u64, file: os.File, allocator: *mem.Allocator) !MsfStream {
+    fn init(block_size: u32, block_count: u32, pos: u64, file: File, allocator: *mem.Allocator) !MsfStream {
         var stream = MsfStream{
             .in_file = file,
             .pos = 0,
std/time.zig
@@ -1,116 +1,61 @@
-const std = @import("../std.zig");
 const builtin = @import("builtin");
-const Os = builtin.Os;
-const debug = std.debug;
+const std = @import("std.zig");
+const assert = std.debug.assert;
 const testing = std.testing;
-const math = std.math;
-
-const windows = std.os.windows;
-const linux = std.os.linux;
-const darwin = std.os.darwin;
-const wasi = std.os.wasi;
-const posix = std.os.posix;
+const os = std.os;
 
 pub const epoch = @import("epoch.zig");
 
 /// Spurious wakeups are possible and no precision of timing is guaranteed.
 pub fn sleep(nanoseconds: u64) void {
-    switch (builtin.os) {
-        Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
-            const s = nanoseconds / ns_per_s;
-            const ns = nanoseconds % ns_per_s;
-            posixSleep(s, ns);
-        },
-        Os.windows => {
-            const ns_per_ms = ns_per_s / ms_per_s;
-            const milliseconds = nanoseconds / ns_per_ms;
-            const ms_that_will_fit = std.math.cast(windows.DWORD, milliseconds) catch std.math.maxInt(windows.DWORD);
-            windows.Sleep(ms_that_will_fit);
-        },
-        else => @compileError("Unsupported OS"),
-    }
-}
-
-/// Spurious wakeups are possible and no precision of timing is guaranteed.
-pub fn posixSleep(seconds: u64, nanoseconds: u64) void {
-    var req = posix.timespec{
-        .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize),
-        .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize),
-    };
-    var rem: posix.timespec = undefined;
-    while (true) {
-        const ret_val = posix.nanosleep(&req, &rem);
-        const err = posix.getErrno(ret_val);
-        switch (err) {
-            posix.EFAULT => unreachable,
-            posix.EINVAL => {
-                // Sometimes Darwin returns EINVAL for no reason.
-                // We treat it as a spurious wakeup.
-                return;
-            },
-            posix.EINTR => {
-                req = rem;
-                continue;
-            },
-            // This prong handles success as well as unexpected errors.
-            else => return,
-        }
-    }
+    const s = nanoseconds / ns_per_s;
+    const ns = nanoseconds % ns_per_s;
+    std.os.nanosleep(s, ns);
 }
 
 /// Get the posix timestamp, UTC, in seconds
+/// TODO audit this function. is it possible to return an error?
 pub fn timestamp() u64 {
     return @divFloor(milliTimestamp(), ms_per_s);
 }
 
 /// Get the posix timestamp, UTC, in milliseconds
-pub const milliTimestamp = switch (builtin.os) {
-    Os.windows => milliTimestampWindows,
-    Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix,
-    Os.macosx, Os.ios => milliTimestampDarwin,
-    Os.wasi => milliTimestampWasi,
-    else => @compileError("Unsupported OS"),
-};
-
-fn milliTimestampWasi() u64 {
-    var ns: wasi.timestamp_t = undefined;
-
-    // TODO: Verify that precision is ignored
-    const err = wasi.clock_time_get(wasi.CLOCK_REALTIME, 1, &ns);
-    debug.assert(err == wasi.ESUCCESS);
-
-    const ns_per_ms = 1000;
-    return @divFloor(ns, ns_per_ms);
-}
-
-fn milliTimestampWindows() u64 {
-    //FileTime has a granularity of 100 nanoseconds
-    //  and uses the NTFS/Windows epoch
-    var ft: windows.FILETIME = undefined;
-    windows.GetSystemTimeAsFileTime(&ft);
-    const hns_per_ms = (ns_per_s / 100) / ms_per_s;
-    const epoch_adj = epoch.windows * ms_per_s;
-
-    const ft64 = (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
-    return @divFloor(ft64, hns_per_ms) - -epoch_adj;
-}
+/// TODO audit this function. is it possible to return an error?
+pub fn milliTimestamp() u64 {
+    if (os.windows.is_the_target and !builtin.link_libc) {
+        //FileTime has a granularity of 100 nanoseconds
+        //  and uses the NTFS/Windows epoch
+        var ft: os.windows.FILETIME = undefined;
+        os.windows.kernel32.GetSystemTimeAsFileTime(&ft);
+        const hns_per_ms = (ns_per_s / 100) / ms_per_s;
+        const epoch_adj = epoch.windows * ms_per_s;
+
+        const ft64 = (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+        return @divFloor(ft64, hns_per_ms) - -epoch_adj;
+    }
+    if (os.wasi.is_the_target and !builtin.link_libc) {
+        var ns: os.wasi.timestamp_t = undefined;
 
-fn milliTimestampDarwin() u64 {
-    var tv: darwin.timeval = undefined;
-    var err = darwin.gettimeofday(&tv, null);
-    debug.assert(err == 0);
-    const sec_ms = tv.tv_sec * ms_per_s;
-    const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
-    return @intCast(u64, sec_ms + usec_ms);
-}
+        // TODO: Verify that precision is ignored
+        const err = os.wasi.clock_time_get(os.wasi.CLOCK_REALTIME, 1, &ns);
+        assert(err == os.wasi.ESUCCESS);
 
-fn milliTimestampPosix() u64 {
+        const ns_per_ms = 1000;
+        return @divFloor(ns, ns_per_ms);
+    }
+    if (os.darwin.is_the_target) {
+        var tv: os.darwin.timeval = undefined;
+        var err = os.darwin.gettimeofday(&tv, null);
+        assert(err == 0);
+        const sec_ms = tv.tv_sec * ms_per_s;
+        const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
+        return @intCast(u64, sec_ms + usec_ms);
+    }
+    var ts: os.timespec = undefined;
     //From what I can tell there's no reason clock_gettime
     //  should ever fail for us with CLOCK_REALTIME,
     //  seccomp aside.
-    var ts: posix.timespec = undefined;
-    const err = posix.clock_gettime(posix.CLOCK_REALTIME, &ts);
-    debug.assert(err == 0);
+    os.clock_gettime(os.CLOCK_REALTIME, &ts) catch unreachable;
     const sec_ms = @intCast(u64, ts.tv_sec) * ms_per_s;
     const nsec_ms = @divFloor(@intCast(u64, ts.tv_nsec), ns_per_s / ms_per_s);
     return sec_ms + nsec_ms;
@@ -145,27 +90,23 @@ pub const s_per_week = s_per_day * 7;
 ///   depends on the OS. On Windows and Darwin it is a hardware counter
 ///   value that requires calculation to convert to a meaninful unit.
 pub const Timer = struct {
-
-    //if we used resolution's value when performing the
-    //  performance counter calc on windows/darwin, it would
-    //  be less precise
+    ///if we used resolution's value when performing the
+    ///  performance counter calc on windows/darwin, it would
+    ///  be less precise
     frequency: switch (builtin.os) {
-        Os.windows => u64,
-        Os.macosx, Os.ios => darwin.mach_timebase_info_data,
+        .windows => u64,
+        .macosx, .ios, .tvos, .watchos => darwin.mach_timebase_info_data,
         else => void,
     },
     resolution: u64,
     start_time: u64,
 
-    //At some point we may change our minds on RAW, but for now we're
-    //  sticking with posix standard MONOTONIC. For more information, see:
-    //  https://github.com/ziglang/zig/pull/933
-    //
-    //const monotonic_clock_id = switch(builtin.os) {
-    //    Os.linux => linux.CLOCK_MONOTONIC_RAW,
-    //    else => posix.CLOCK_MONOTONIC,
-    //};
-    const monotonic_clock_id = posix.CLOCK_MONOTONIC;
+    const Error = error{TimerUnsupported};
+
+    ///At some point we may change our minds on RAW, but for now we're
+    ///  sticking with posix standard MONOTONIC. For more information, see:
+    ///  https://github.com/ziglang/zig/pull/933
+    const monotonic_clock_id = os.CLOCK_MONOTONIC;
     /// Initialize the timer structure.
     //This gives us an opportunity to grab the counter frequency in windows.
     //On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000.
@@ -174,66 +115,51 @@ pub const Timer = struct {
     //  impossible here barring cosmic rays or other such occurrences of
     //  incredibly bad luck.
     //On Darwin: This cannot fail, as far as I am able to tell.
-    const TimerError = error{
-        TimerUnsupported,
-        Unexpected,
-    };
-    pub fn start() TimerError!Timer {
+    pub fn start() Error!Timer {
         var self: Timer = undefined;
 
-        switch (builtin.os) {
-            Os.windows => {
-                var freq: i64 = undefined;
-                var err = windows.QueryPerformanceFrequency(&freq);
-                if (err == windows.FALSE) return error.TimerUnsupported;
-                self.frequency = @intCast(u64, freq);
-                self.resolution = @divFloor(ns_per_s, self.frequency);
-
-                var start_time: i64 = undefined;
-                err = windows.QueryPerformanceCounter(&start_time);
-                debug.assert(err != windows.FALSE);
-                self.start_time = @intCast(u64, start_time);
-            },
-            Os.linux, Os.freebsd, Os.netbsd => {
-                //On Linux, seccomp can do arbitrary things to our ability to call
-                //  syscalls, including return any errno value it wants and
-                //  inconsistently throwing errors. Since we can't account for
-                //  abuses of seccomp in a reasonable way, we'll assume that if
-                //  seccomp is going to block us it will at least do so consistently
-                var ts: posix.timespec = undefined;
-                var result = posix.clock_getres(monotonic_clock_id, &ts);
-                var errno = posix.getErrno(result);
-                switch (errno) {
-                    0 => {},
-                    posix.EINVAL => return error.TimerUnsupported,
-                    else => return std.os.unexpectedErrorPosix(errno),
-                }
-                self.resolution = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
-
-                result = posix.clock_gettime(monotonic_clock_id, &ts);
-                errno = posix.getErrno(result);
-                if (errno != 0) return std.os.unexpectedErrorPosix(errno);
-                self.start_time = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
-            },
-            Os.macosx, Os.ios => {
-                darwin.mach_timebase_info(&self.frequency);
-                self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
-                self.start_time = darwin.mach_absolute_time();
-            },
-            else => @compileError("Unsupported OS"),
+        if (os.windows.is_the_target) {
+            var freq: i64 = undefined;
+            var err = windows.QueryPerformanceFrequency(&freq);
+            if (err == windows.FALSE) return error.TimerUnsupported;
+            self.frequency = @intCast(u64, freq);
+            self.resolution = @divFloor(ns_per_s, self.frequency);
+
+            var start_time: i64 = undefined;
+            err = windows.QueryPerformanceCounter(&start_time);
+            assert(err != windows.FALSE);
+            self.start_time = @intCast(u64, start_time);
+        } else if (os.darwin.is_the_target) {
+            darwin.mach_timebase_info(&self.frequency);
+            self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
+            self.start_time = darwin.mach_absolute_time();
+        } else {
+            //On Linux, seccomp can do arbitrary things to our ability to call
+            //  syscalls, including return any errno value it wants and
+            //  inconsistently throwing errors. Since we can't account for
+            //  abuses of seccomp in a reasonable way, we'll assume that if
+            //  seccomp is going to block us it will at least do so consistently
+            var ts: os.timespec = undefined;
+            os.clock_getres(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
+            self.resolution = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
+
+            os.clock_gettime(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
+            self.start_time = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
         }
+
         return self;
     }
 
     /// Reads the timer value since start or the last reset in nanoseconds
     pub fn read(self: *Timer) u64 {
         var clock = clockNative() - self.start_time;
-        return switch (builtin.os) {
-            Os.windows => @divFloor(clock * ns_per_s, self.frequency),
-            Os.linux, Os.freebsd, Os.netbsd => clock,
-            Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),
-            else => @compileError("Unsupported OS"),
-        };
+        if (os.windows.is_the_target) {
+            return @divFloor(clock * ns_per_s, self.frequency);
+        }
+        if (os.darwin.is_the_target) {
+            return @divFloor(clock * self.frequency.numer, self.frequency.denom);
+        }
+        return clock;
     }
 
     /// Resets the timer value to 0/now.
@@ -249,37 +175,27 @@ pub const Timer = struct {
         return lap_time;
     }
 
-    const clockNative = switch (builtin.os) {
-        Os.windows => clockWindows,
-        Os.linux, Os.freebsd, Os.netbsd => clockLinux,
-        Os.macosx, Os.ios => clockDarwin,
-        else => @compileError("Unsupported OS"),
-    };
-
-    fn clockWindows() u64 {
-        var result: i64 = undefined;
-        var err = windows.QueryPerformanceCounter(&result);
-        debug.assert(err != windows.FALSE);
-        return @intCast(u64, result);
-    }
-
-    fn clockDarwin() u64 {
-        return darwin.mach_absolute_time();
-    }
-
-    fn clockLinux() u64 {
-        var ts: posix.timespec = undefined;
-        var result = posix.clock_gettime(monotonic_clock_id, &ts);
-        debug.assert(posix.getErrno(result) == 0);
+    fn clockNative() u64 {
+        if (os.windows.is_the_target) {
+            var result: i64 = undefined;
+            var err = windows.QueryPerformanceCounter(&result);
+            assert(err != windows.FALSE);
+            return @intCast(u64, result);
+        }
+        if (os.darwin.is_the_target) {
+            return darwin.mach_absolute_time();
+        }
+        var ts: os.timespec = undefined;
+        os.clock_gettime(monotonic_clock_id, &ts) catch unreachable;
         return @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
     }
 };
 
-test "os.time.sleep" {
+test "sleep" {
     sleep(1);
 }
 
-test "os.time.timestamp" {
+test "timestamp" {
     const ns_per_ms = (ns_per_s / ms_per_s);
     const margin = 50;
 
@@ -290,7 +206,7 @@ test "os.time.timestamp" {
     testing.expect(interval > 0 and interval < margin);
 }
 
-test "os.time.Timer" {
+test "Timer" {
     const ns_per_ms = (ns_per_s / ms_per_s);
     const margin = ns_per_ms * 150;