Commit 0c6ab61b22

Andrew Kelley <andrew@ziglang.org>
2019-05-27 05:35:26
tests passing on linux
1 parent 2b42e91
doc/langref.html.in
@@ -796,8 +796,8 @@ const assert = std.debug.assert;
 threadlocal var x: i32 = 1234;
 
 test "thread local storage" {
-    const thread1 = try std.os.spawnThread({}, testTls);
-    const thread2 = try std.os.spawnThread({}, testTls);
+    const thread1 = try std.Thread.spawn({}, testTls);
+    const thread2 = try std.Thread.spawn({}, testTls);
     testTls({});
     thread1.wait();
     thread2.wait();
example/cat/main.zig
@@ -1,12 +1,13 @@
 const std = @import("std");
 const io = std.io;
+const process = std.process;
+const File = std.fs.File;
 const mem = std.mem;
-const os = std.os;
 const warn = std.debug.warn;
 const allocator = std.debug.global_allocator;
 
 pub fn main() !void {
-    var args_it = os.args();
+    var args_it = process.args();
     const exe = try unwrapArg(args_it.next(allocator).?);
     var catted_anything = false;
     var stdout_file = try io.getStdOut();
@@ -20,7 +21,7 @@ pub fn main() !void {
         } else if (arg[0] == '-') {
             return usage(exe);
         } else {
-            var file = os.File.openRead(arg) catch |err| {
+            var file = File.openRead(arg) catch |err| {
                 warn("Unable to open file: {}\n", @errorName(err));
                 return err;
             };
@@ -41,7 +42,7 @@ fn usage(exe: []const u8) !void {
     return error.Invalid;
 }
 
-fn cat_file(stdout: *os.File, file: *os.File) !void {
+fn cat_file(stdout: *File, file: *File) !void {
     var buf: [1024 * 4]u8 = undefined;
 
     while (true) {
example/guess_number/main.zig
@@ -2,7 +2,6 @@ const builtin = @import("builtin");
 const std = @import("std");
 const io = std.io;
 const fmt = std.fmt;
-const os = std.os;
 
 pub fn main() !void {
     var stdout_file = try io.getStdOut();
@@ -11,7 +10,7 @@ pub fn main() !void {
     try stdout.print("Welcome to the Guess Number Game in Zig.\n");
 
     var seed_bytes: [@sizeOf(u64)]u8 = undefined;
-    os.getRandomBytes(seed_bytes[0..]) catch |err| {
+    std.crypto.randomBytes(seed_bytes[0..]) catch |err| {
         std.debug.warn("unable to seed random number generator: {}", err);
         return err;
     };
example/hello_world/hello_libc.zig
@@ -5,6 +5,6 @@ const c = @cImport({
 });
 
 export fn main(argc: c_int, argv: [*]?[*]u8) c_int {
-    c.fprintf(c.stderr, c"Hello, world!\n");
+    _ = c.fprintf(c.stderr, c"Hello, world!\n");
     return 0;
 }
src-self-hosted/compilation.zig
@@ -301,6 +301,7 @@ pub const Compilation = struct {
         InvalidUtf8,
         BadPathName,
         DeviceBusy,
+        CurrentWorkingDirectoryUnlinked,
     };
 
     pub const Event = union(enum) {
src-self-hosted/libc_installation.zig
@@ -182,7 +182,7 @@ pub const LibCInstallation = struct {
     }
 
     async fn findNativeIncludeDirLinux(self: *LibCInstallation, loop: *event.Loop) !void {
-        const cc_exe = std.process.getEnvPosix("CC") orelse "cc";
+        const cc_exe = std.os.getenv("CC") orelse "cc";
         const argv = []const []const u8{
             cc_exe,
             "-E",
@@ -392,7 +392,7 @@ pub const LibCInstallation = struct {
 
 /// caller owns returned memory
 async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bool) ![]u8 {
-    const cc_exe = std.process.getEnvPosix("CC") orelse "cc";
+    const cc_exe = std.os.getenv("CC") orelse "cc";
     const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file);
     defer loop.allocator.free(arg1);
     const argv = []const []const u8{ cc_exe, arg1 };
@@ -463,7 +463,7 @@ fn fileExists(path: []const u8) !bool {
     if (fs.File.access(path)) |_| {
         return true;
     } else |err| switch (err) {
-        error.FileNotFound, error.PermissionDenied => return false,
+        error.FileNotFound => return false,
         else => return error.FileSystem,
     }
 }
src-self-hosted/main.zig
@@ -702,6 +702,7 @@ const FmtError = error{
     ReadOnlyFileSystem,
     LinkQuotaExceeded,
     FileBusy,
+    CurrentWorkingDirectoryUnlinked,
 } || fs.File.OpenError;
 
 async fn asyncFmtMain(
@@ -851,7 +852,7 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
 }
 
 fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
-    try stdout.print("{}\n", std.cstr.toSliceConst(c.ZIG_VERSION_STRING));
+    try stdout.print("{}\n", std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING));
 }
 
 const args_test_spec = []Flag{Flag.Bool("--help")};
@@ -924,14 +925,14 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
         \\ZIG_DIA_GUIDS_LIB    {}
         \\
     ,
-        std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
-        std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
-        std.cstr.toSliceConst(c.ZIG_LLVM_CONFIG_EXE),
-        std.cstr.toSliceConst(c.ZIG_LLD_INCLUDE_PATH),
-        std.cstr.toSliceConst(c.ZIG_LLD_LIBRARIES),
-        std.cstr.toSliceConst(c.ZIG_STD_FILES),
-        std.cstr.toSliceConst(c.ZIG_C_HEADER_FILES),
-        std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
+        std.mem.toSliceConst(u8, c.ZIG_CMAKE_BINARY_DIR),
+        std.mem.toSliceConst(u8, c.ZIG_CXX_COMPILER),
+        std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE),
+        std.mem.toSliceConst(u8, c.ZIG_LLD_INCLUDE_PATH),
+        std.mem.toSliceConst(u8, c.ZIG_LLD_LIBRARIES),
+        std.mem.toSliceConst(u8, c.ZIG_STD_FILES),
+        std.mem.toSliceConst(u8, c.ZIG_C_HEADER_FILES),
+        std.mem.toSliceConst(u8, c.ZIG_DIA_GUIDS_LIB),
     );
 }
 
std/c/linux.zig
@@ -1,13 +1,27 @@
 const std = @import("../std.zig");
 use std.c;
 
-pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;
-pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
 extern "c" fn __errno_location() *c_int;
 pub const _errno = __errno_location;
 
+pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;
+pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
+pub extern "c" fn eventfd(initval: c_uint, flags: c_uint) c_int;
+pub extern "c" fn epoll_ctl(epfd: fd_t, op: c_uint, fd: fd_t, event: *epoll_event) c_int;
+pub extern "c" fn epoll_create1(flags: c_uint) c_int;
+pub extern "c" fn epoll_wait(epfd: fd_t, events: [*]epoll_event, maxevents: c_uint, timeout: c_int) c_int;
+pub extern "c" fn epoll_pwait(
+    epfd: fd_t,
+    events: [*]epoll_event,
+    maxevents: c_int,
+    timeout: c_int,
+    sigmask: *const sigset_t,
+) c_int;
+pub extern "c" fn inotify_init1(flags: c_uint) c_int;
+pub extern "c" fn inotify_add_watch(fd: fd_t, pathname: [*]const u8, mask: u32) c_int;
+
 /// See std.elf for constants for this
-pub extern fn getauxval(__type: c_ulong) c_ulong;
+pub extern "c" fn getauxval(__type: c_ulong) c_ulong;
 
 pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int;
-pub extern fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
+pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
std/event/fs.zig
@@ -36,7 +36,7 @@ pub const Request = struct {
             offset: usize,
             result: Error!void,
 
-            pub const Error = os.PosixWriteError;
+            pub const Error = os.WriteError;
         };
 
         pub const PReadV = struct {
@@ -45,7 +45,7 @@ pub const Request = struct {
             offset: usize,
             result: Error!usize,
 
-            pub const Error = os.PosixReadError;
+            pub const Error = os.ReadError;
         };
 
         pub const Open = struct {
@@ -172,7 +172,7 @@ pub async fn pwritevPosix(
     fd: fd_t,
     iovecs: []const os.iovec_const,
     offset: usize,
-) os.PosixWriteError!void {
+) os.WriteError!void {
     // workaround for https://github.com/ziglang/zig/issues/1194
     suspend {
         resume @handle();
@@ -320,7 +320,7 @@ pub async fn preadvPosix(
     fd: fd_t,
     iovecs: []const os.iovec,
     offset: usize,
-) os.PosixReadError!usize {
+) os.ReadError!usize {
     // workaround for https://github.com/ziglang/zig/issues/1194
     suspend {
         resume @handle();
@@ -786,7 +786,7 @@ pub fn Watch(comptime V: type) type {
 
             switch (builtin.os) {
                 builtin.Os.linux => {
-                    const inotify_fd = try os.linuxINotifyInit1(os.linux.IN_NONBLOCK | os.linux.IN_CLOEXEC);
+                    const inotify_fd = try os.inotify_init1(os.linux.IN_NONBLOCK | os.linux.IN_CLOEXEC);
                     errdefer os.close(inotify_fd);
 
                     var result: *Self = undefined;
@@ -977,7 +977,7 @@ pub fn Watch(comptime V: type) type {
             var basename_with_null_consumed = false;
             defer if (!basename_with_null_consumed) self.channel.loop.allocator.free(basename_with_null);
 
-            const wd = try os.linuxINotifyAddWatchC(
+            const wd = try os.inotify_add_watchC(
                 self.os_data.inotify_fd,
                 dirname_with_null.ptr,
                 os.linux.IN_CLOSE_WRITE | os.linux.IN_ONLYDIR | os.linux.IN_EXCL_UNLINK,
@@ -1255,7 +1255,7 @@ pub fn Watch(comptime V: type) type {
                             ev = @ptrCast(*os.linux.inotify_event, ptr);
                             if (ev.mask & os.linux.IN_CLOSE_WRITE == os.linux.IN_CLOSE_WRITE) {
                                 const basename_ptr = ptr + @sizeOf(os.linux.inotify_event);
-                                const basename_with_null = basename_ptr[0 .. std.cstr.len(basename_ptr) + 1];
+                                const basename_with_null = basename_ptr[0 .. std.mem.len(u8, basename_ptr) + 1];
                                 const user_value = blk: {
                                     const held = await (async watch.os_data.table_lock.acquire() catch unreachable);
                                     defer held.release();
std/event/loop.zig
@@ -99,7 +99,7 @@ pub const Loop = struct {
     /// have the correct pointer value.
     pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void {
         if (builtin.single_threaded) @compileError("initMultiThreaded unavailable when building in single-threaded mode");
-        const core_count = try os.cpuCount(allocator);
+        const core_count = try Thread.cpuCount();
         return self.initInternal(allocator, core_count);
     }
 
@@ -139,9 +139,9 @@ pub const Loop = struct {
         self.allocator.free(self.extra_threads);
     }
 
-    const InitOsDataError = os.LinuxEpollCreateError || mem.Allocator.Error || os.LinuxEventFdError ||
-        os.SpawnThreadError || os.LinuxEpollCtlError || os.BsdKEventError ||
-        os.WindowsCreateIoCompletionPortError;
+    const InitOsDataError = os.EpollCreateError || mem.Allocator.Error || os.EventFdError ||
+        Thread.SpawnError || os.EpollCtlError || os.KEventError ||
+        windows.CreateIoCompletionPortError;
 
     const wakeup_bytes = []u8{0x1} ** 8;
 
@@ -172,7 +172,7 @@ pub const Loop = struct {
                                 .handle = undefined,
                                 .overlapped = ResumeNode.overlapped_init,
                             },
-                            .eventfd = try os.linuxEventFd(1, os.EFD_CLOEXEC | os.EFD_NONBLOCK),
+                            .eventfd = try os.eventfd(1, os.EFD_CLOEXEC | os.EFD_NONBLOCK),
                             .epoll_op = os.EPOLL_CTL_ADD,
                         },
                         .next = undefined,
@@ -180,17 +180,17 @@ pub const Loop = struct {
                     self.available_eventfd_resume_nodes.push(eventfd_node);
                 }
 
-                self.os_data.epollfd = try os.linuxEpollCreate(os.EPOLL_CLOEXEC);
+                self.os_data.epollfd = try os.epoll_create1(os.EPOLL_CLOEXEC);
                 errdefer os.close(self.os_data.epollfd);
 
-                self.os_data.final_eventfd = try os.linuxEventFd(0, os.EFD_CLOEXEC | os.EFD_NONBLOCK);
+                self.os_data.final_eventfd = try os.eventfd(0, os.EFD_CLOEXEC | os.EFD_NONBLOCK);
                 errdefer os.close(self.os_data.final_eventfd);
 
                 self.os_data.final_eventfd_event = os.epoll_event{
                     .events = os.EPOLLIN,
                     .data = os.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) },
                 };
-                try os.linuxEpollCtl(
+                try os.epoll_ctl(
                     self.os_data.epollfd,
                     os.EPOLL_CTL_ADD,
                     self.os_data.final_eventfd,
@@ -211,7 +211,7 @@ pub const Loop = struct {
                 var extra_thread_index: usize = 0;
                 errdefer {
                     // writing 8 bytes to an eventfd cannot fail
-                    os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
+                    os.write(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
                     while (extra_thread_index != 0) {
                         extra_thread_index -= 1;
                         self.extra_threads[extra_thread_index].wait();
@@ -417,11 +417,11 @@ pub const Loop = struct {
             .events = flags,
             .data = os.linux.epoll_data{ .ptr = @ptrToInt(resume_node) },
         };
-        try os.linuxEpollCtl(self.os_data.epollfd, op, fd, &ev);
+        try os.epoll_ctl(self.os_data.epollfd, op, fd, &ev);
     }
 
     pub fn linuxRemoveFd(self: *Loop, fd: i32) void {
-        os.linuxEpollCtl(self.os_data.epollfd, os.linux.EPOLL_CTL_DEL, fd, undefined) catch {};
+        os.epoll_ctl(self.os_data.epollfd, os.linux.EPOLL_CTL_DEL, fd, undefined) catch {};
         self.finishOneEvent();
     }
 
@@ -626,7 +626,7 @@ pub const Loop = struct {
                 builtin.Os.linux => {
                     self.posixFsRequest(&self.os_data.fs_end_request);
                     // writing 8 bytes to an eventfd cannot fail
-                    os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
+                    os.write(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
                     return;
                 },
                 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
@@ -666,7 +666,7 @@ pub const Loop = struct {
                 builtin.Os.linux => {
                     // only process 1 event so we don't steal from other threads
                     var events: [1]os.linux.epoll_event = undefined;
-                    const count = os.linuxEpollWait(self.os_data.epollfd, events[0..], -1);
+                    const count = os.epoll_wait(self.os_data.epollfd, events[0..], -1);
                     for (events[0..count]) |ev| {
                         const resume_node = @intToPtr(*ResumeNode, ev.data.ptr);
                         const handle = resume_node.handle;
@@ -783,10 +783,10 @@ pub const Loop = struct {
                 switch (node.data.msg) {
                     @TagType(fs.Request.Msg).End => return,
                     @TagType(fs.Request.Msg).PWriteV => |*msg| {
-                        msg.result = os.posix_pwritev(msg.fd, msg.iov.ptr, msg.iov.len, msg.offset);
+                        msg.result = os.pwritev(msg.fd, msg.iov, msg.offset);
                     },
                     @TagType(fs.Request.Msg).PReadV => |*msg| {
-                        msg.result = os.posix_preadv(msg.fd, msg.iov.ptr, msg.iov.len, msg.offset);
+                        msg.result = os.preadv(msg.fd, msg.iov, msg.offset);
                     },
                     @TagType(fs.Request.Msg).Open => |*msg| {
                         msg.result = os.openC(msg.path.ptr, msg.flags, msg.mode);
@@ -800,7 +800,7 @@ pub const Loop = struct {
                             break :blk;
                         };
                         defer os.close(fd);
-                        msg.result = os.posixWrite(fd, msg.contents);
+                        msg.result = os.write(fd, msg.contents);
                     },
                 }
                 switch (node.data.finish) {
std/event/net.zig
@@ -45,13 +45,13 @@ pub const Server = struct {
     ) !void {
         self.handleRequestFn = handleRequestFn;
 
-        const sockfd = try os.posixSocket(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, os.PROTO_tcp);
+        const sockfd = try os.socket(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, os.PROTO_tcp);
         errdefer os.close(sockfd);
         self.sockfd = sockfd;
 
-        try os.posixBind(sockfd, &address.os_addr);
-        try os.posixListen(sockfd, os.SOMAXCONN);
-        self.listen_address = std.net.Address.initPosix(try os.posixGetSockName(sockfd));
+        try os.bind(sockfd, &address.os_addr);
+        try os.listen(sockfd, os.SOMAXCONN);
+        self.listen_address = std.net.Address.initPosix(try os.getsockname(sockfd));
 
         self.accept_coro = try async<self.loop.allocator> Server.handler(self);
         errdefer cancel self.accept_coro.?;
@@ -64,7 +64,10 @@ pub const Server = struct {
     /// Stop listening
     pub fn close(self: *Server) void {
         self.loop.linuxRemoveFd(self.sockfd.?);
-        os.close(self.sockfd.?);
+        if (self.sockfd) |fd| {
+            os.close(fd);
+            self.sockfd = null;
+        }
     }
 
     pub fn deinit(self: *Server) void {
@@ -76,7 +79,7 @@ pub const Server = struct {
         while (true) {
             var accepted_addr: std.net.Address = undefined;
             // TODO just inline the following function here and don't expose it as posixAsyncAccept
-            if (os.posixAsyncAccept(self.sockfd.?, &accepted_addr.os_addr, os.SOCK_NONBLOCK | os.SOCK_CLOEXEC)) |accepted_fd| {
+            if (os.accept4_async(self.sockfd.?, &accepted_addr.os_addr, os.SOCK_NONBLOCK | os.SOCK_CLOEXEC)) |accepted_fd| {
                 if (accepted_fd == -1) {
                     // would block
                     suspend; // we will get resumed by epoll_wait in the event loop
@@ -105,7 +108,7 @@ pub const Server = struct {
 };
 
 pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 {
-    const sockfd = try os.posixSocket(
+    const sockfd = try os.socket(
         os.AF_UNIX,
         os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK,
         0,
@@ -120,9 +123,9 @@ pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 {
     if (path.len > @typeOf(sock_addr.path).len) return error.NameTooLong;
     mem.copy(u8, sock_addr.path[0..], path);
     const size = @intCast(u32, @sizeOf(os.sa_family_t) + path.len);
-    try os.posixConnectAsync(sockfd, &sock_addr, size);
+    try os.connect_async(sockfd, &sock_addr, size);
     try await try async loop.linuxWaitFd(sockfd, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
-    try os.posixGetSockOptConnectError(sockfd);
+    try os.getsockoptError(sockfd);
 
     return sockfd;
 }
@@ -249,12 +252,12 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {
 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(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, os.PROTO_tcp);
+    const sockfd = try os.socket(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, os.PROTO_tcp);
     errdefer os.close(sockfd);
 
-    try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(os.sockaddr_in));
+    try os.connect_async(sockfd, &address.os_addr, @sizeOf(os.sockaddr_in));
     try await try async loop.linuxWaitFd(sockfd, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
-    try os.posixGetSockOptConnectError(sockfd);
+    try os.getsockoptError(sockfd);
 
     return File.openHandle(sockfd);
 }
std/fs/file.zig
@@ -137,24 +137,27 @@ pub const File = struct {
 
     /// Test for the existence of `path`.
     /// `path` is UTF8-encoded.
-    pub fn exists(path: []const u8) !void {
+    /// In general it is recommended to avoid this function. For example,
+    /// instead of testing if a file exists and then opening it, just
+    /// open it and handle the error for file not found.
+    pub fn access(path: []const u8) !void {
         return os.access(path, os.F_OK);
     }
 
-    /// Same as `exists` except the parameter is null-terminated.
-    pub fn existsC(path: [*]const u8) !void {
+    /// Same as `access` except the parameter is null-terminated.
+    pub fn accessC(path: [*]const u8) !void {
         return os.accessC(path, os.F_OK);
     }
 
-    /// Same as `exists` except the parameter is null-terminated UTF16LE-encoded.
-    pub fn existsW(path: [*]const u16) !void {
+    /// Same as `access` except the parameter is null-terminated UTF16LE-encoded.
+    pub fn accessW(path: [*]const u16) !void {
         return os.accessW(path, os.F_OK);
     }
 
     /// Upon success, the stream is in an uninitialized state. To continue using it,
     /// you must use the open() function.
     pub fn close(self: File) void {
-        os.close(self.handle);
+        return os.close(self.handle);
     }
 
     /// Test whether the file refers to a terminal.
std/fs/path.zig
@@ -9,6 +9,7 @@ const Allocator = mem.Allocator;
 const math = std.math;
 const windows = std.os.windows;
 const fs = std.fs;
+const process = std.process;
 
 pub const sep_windows = '\\';
 pub const sep_posix = '/';
@@ -390,7 +391,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
 pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
     if (paths.len == 0) {
         assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
-        return fs.getCwdAlloc(allocator);
+        return process.getCwdAlloc(allocator);
     }
 
     // determine which disk designator we will result with, if any
@@ -485,7 +486,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
             },
             WindowsPath.Kind.None => {
                 assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
-                const cwd = try fs.getCwdAlloc(allocator);
+                const cwd = try process.getCwdAlloc(allocator);
                 defer allocator.free(cwd);
                 const parsed_cwd = windowsParsePath(cwd);
                 result = try allocator.alloc(u8, max_size + parsed_cwd.disk_designator.len + 1);
@@ -501,7 +502,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
     } else {
         assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
         // TODO call get cwd for the result_disk_designator instead of the global one
-        const cwd = try fs.getCwdAlloc(allocator);
+        const cwd = try process.getCwdAlloc(allocator);
         defer allocator.free(cwd);
 
         result = try allocator.alloc(u8, max_size + cwd.len + 1);
@@ -571,7 +572,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
 pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
     if (paths.len == 0) {
         assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd
-        return fs.getCwdAlloc(allocator);
+        return process.getCwdAlloc(allocator);
     }
 
     var first_index: usize = 0;
@@ -593,7 +594,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
         result = try allocator.alloc(u8, max_size);
     } else {
         assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd
-        const cwd = try fs.getCwdAlloc(allocator);
+        const cwd = try process.getCwdAlloc(allocator);
         defer allocator.free(cwd);
         result = try allocator.alloc(u8, max_size + cwd.len + 1);
         mem.copy(u8, result, cwd);
@@ -632,7 +633,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
 }
 
 test "resolve" {
-    const cwd = try fs.getCwdAlloc(debug.global_allocator);
+    const cwd = try process.getCwdAlloc(debug.global_allocator);
     if (windows.is_the_target) {
         if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
             cwd[0] = asciiUpper(cwd[0]);
@@ -646,7 +647,7 @@ test "resolve" {
 
 test "resolveWindows" {
     if (windows.is_the_target) {
-        const cwd = try fs.getCwdAlloc(debug.global_allocator);
+        const cwd = try process.getCwdAlloc(debug.global_allocator);
         const parsed_cwd = windowsParsePath(cwd);
         {
             const result = testResolveWindows([][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" });
std/io/test.zig
@@ -7,7 +7,7 @@ const DefaultPrng = std.rand.DefaultPrng;
 const expect = std.testing.expect;
 const expectError = std.testing.expectError;
 const mem = std.mem;
-const os = std.os;
+const fs = std.fs;
 const File = std.fs.File;
 
 test "write a file, read it, then delete it" {
@@ -58,7 +58,7 @@ test "write a file, read it, then delete it" {
         expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
         expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
     }
-    try os.deleteFile(tmp_file_name);
+    try fs.deleteFile(tmp_file_name);
 }
 
 test "BufferOutStream" {
@@ -316,7 +316,7 @@ test "BitStreams with File Stream" {
 
         expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1));
     }
-    try os.deleteFile(tmp_file_name);
+    try fs.deleteFile(tmp_file_name);
 }
 
 fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
@@ -596,7 +596,7 @@ test "c out stream" {
 
     const filename = c"tmp_io_test_file.txt";
     const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;
-    defer std.os.deleteFileC(filename) catch {};
+    defer fs.deleteFileC(filename) catch {};
 
     const out_stream = &io.COutStream.init(out_file).stream;
     try out_stream.print("hi: {}\n", i32(123));
std/os/bits/darwin.zig
@@ -219,7 +219,7 @@ pub const MAP_NOCACHE = 0x0400;
 
 /// don't reserve needed swap area
 pub const MAP_NORESERVE = 0x0040;
-pub const MAP_FAILED = maxInt(usize);
+pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize));
 
 /// [XSI] no hang in wait/no child to reap
 pub const WNOHANG = 0x00000001;
@@ -749,26 +749,26 @@ pub const IPPROTO_UDP = 17;
 pub const IPPROTO_IP = 0;
 pub const IPPROTO_IPV6 = 41;
 
-fn wstatus(x: i32) i32 {
+fn wstatus(x: u32) u32 {
     return x & 0o177;
 }
 const wstopped = 0o177;
-pub fn WEXITSTATUS(x: i32) i32 {
+pub fn WEXITSTATUS(x: u32) u32 {
     return x >> 8;
 }
-pub fn WTERMSIG(x: i32) i32 {
+pub fn WTERMSIG(x: u32) u32 {
     return wstatus(x);
 }
-pub fn WSTOPSIG(x: i32) i32 {
+pub fn WSTOPSIG(x: u32) u32 {
     return x >> 8;
 }
-pub fn WIFEXITED(x: i32) bool {
+pub fn WIFEXITED(x: u32) bool {
     return wstatus(x) == 0;
 }
-pub fn WIFSTOPPED(x: i32) bool {
+pub fn WIFSTOPPED(x: u32) bool {
     return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13;
 }
-pub fn WIFSIGNALED(x: i32) bool {
+pub fn WIFSIGNALED(x: u32) bool {
     return wstatus(x) != wstopped and wstatus(x) != 0;
 }
 
std/os/bits/freebsd.zig
@@ -161,7 +161,7 @@ pub const CLOCK_SECOND = 13;
 pub const CLOCK_THREAD_CPUTIME_ID = 14;
 pub const CLOCK_PROCESS_CPUTIME_ID = 15;
 
-pub const MAP_FAILED = maxInt(usize);
+pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize));
 pub const MAP_SHARED = 0x0001;
 pub const MAP_PRIVATE = 0x0002;
 pub const MAP_FIXED = 0x0010;
@@ -644,29 +644,23 @@ pub const TIOCGPKT = 0x80045438;
 pub const TIOCGPTLCK = 0x80045439;
 pub const TIOCGEXCL = 0x80045440;
 
-fn unsigned(s: i32) u32 {
-    return @bitCast(u32, s);
+pub fn WEXITSTATUS(s: u32) u32 {
+    return (s & 0xff00) >> 8;
 }
-fn signed(s: u32) i32 {
-    return @bitCast(i32, s);
+pub fn WTERMSIG(s: u32) u32 {
+    return s & 0x7f;
 }
-pub fn WEXITSTATUS(s: i32) i32 {
-    return signed((unsigned(s) & 0xff00) >> 8);
-}
-pub fn WTERMSIG(s: i32) i32 {
-    return signed(unsigned(s) & 0x7f);
-}
-pub fn WSTOPSIG(s: i32) i32 {
+pub fn WSTOPSIG(s: u32) u32 {
     return WEXITSTATUS(s);
 }
-pub fn WIFEXITED(s: i32) bool {
+pub fn WIFEXITED(s: u32) bool {
     return WTERMSIG(s) == 0;
 }
-pub fn WIFSTOPPED(s: i32) bool {
-    return @intCast(u16, (((unsigned(s) & 0xffff) *% 0x10001) >> 8)) > 0x7f00;
+pub fn WIFSTOPPED(s: u32) bool {
+    return @intCast(u16, (((s & 0xffff) *% 0x10001) >> 8)) > 0x7f00;
 }
-pub fn WIFSIGNALED(s: i32) bool {
-    return (unsigned(s) & 0xffff) -% 1 < 0xff;
+pub fn WIFSIGNALED(s: u32) bool {
+    return (s & 0xffff) -% 1 < 0xff;
 }
 
 pub const winsize = extern struct {
std/os/bits/linux.zig
@@ -1,5 +1,7 @@
+const builtin = @import("builtin");
 const std = @import("../../std.zig");
 const maxInt = std.math.maxInt;
+use @import("../bits.zig");
 
 pub use @import("linux/errno.zig");
 pub use switch (builtin.arch) {
@@ -661,29 +663,23 @@ pub const TFD_CLOEXEC = O_CLOEXEC;
 pub const TFD_TIMER_ABSTIME = 1;
 pub const TFD_TIMER_CANCEL_ON_SET = (1 << 1);
 
-fn unsigned(s: i32) u32 {
-    return @bitCast(u32, s);
+pub fn WEXITSTATUS(s: u32) u32 {
+    return (s & 0xff00) >> 8;
 }
-fn signed(s: u32) i32 {
-    return @bitCast(i32, s);
+pub fn WTERMSIG(s: u32) u32 {
+    return s & 0x7f;
 }
-pub fn WEXITSTATUS(s: i32) i32 {
-    return signed((unsigned(s) & 0xff00) >> 8);
-}
-pub fn WTERMSIG(s: i32) i32 {
-    return signed(unsigned(s) & 0x7f);
-}
-pub fn WSTOPSIG(s: i32) i32 {
+pub fn WSTOPSIG(s: u32) u32 {
     return WEXITSTATUS(s);
 }
-pub fn WIFEXITED(s: i32) bool {
+pub fn WIFEXITED(s: u32) bool {
     return WTERMSIG(s) == 0;
 }
-pub fn WIFSTOPPED(s: i32) bool {
-    return @intCast(u16, ((unsigned(s) & 0xffff) *% 0x10001) >> 8) > 0x7f00;
+pub fn WIFSTOPPED(s: u32) bool {
+    return @intCast(u16, ((s & 0xffff) *% 0x10001) >> 8) > 0x7f00;
 }
-pub fn WIFSIGNALED(s: i32) bool {
-    return (unsigned(s) & 0xffff) -% 1 < 0xff;
+pub fn WIFSIGNALED(s: u32) bool {
+    return (s & 0xffff) -% 1 < 0xff;
 }
 
 pub const winsize = extern struct {
@@ -902,7 +898,7 @@ pub const dirent64 = extern struct {
 pub const dl_phdr_info = extern struct {
     dlpi_addr: usize,
     dlpi_name: ?[*]const u8,
-    dlpi_phdr: [*]elf.Phdr,
+    dlpi_phdr: [*]std.elf.Phdr,
     dlpi_phnum: u16,
 };
 
std/os/bits/netbsd.zig
@@ -152,7 +152,7 @@ pub const CLOCK_MONOTONIC = 3;
 pub const CLOCK_THREAD_CPUTIME_ID = 0x20000000;
 pub const CLOCK_PROCESS_CPUTIME_ID = 0x40000000;
 
-pub const MAP_FAILED = maxInt(usize);
+pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize));
 pub const MAP_SHARED = 0x0001;
 pub const MAP_PRIVATE = 0x0002;
 pub const MAP_REMAPDUP = 0x0004;
@@ -516,34 +516,28 @@ pub const TIOCSWINSZ = 0x80087467;
 pub const TIOCUCNTL = 0x80047466;
 pub const TIOCXMTFRAME = 0x80087444;
 
-fn unsigned(s: i32) u32 {
-    return @bitCast(u32, s);
+pub fn WEXITSTATUS(s: u32) u32 {
+    return (s >> 8) & 0xff;
 }
-fn signed(s: u32) i32 {
-    return @bitCast(i32, s);
+pub fn WTERMSIG(s: u32) u32 {
+    return s & 0x7f;
 }
-pub fn WEXITSTATUS(s: i32) i32 {
-    return signed((unsigned(s) >> 8) & 0xff);
-}
-pub fn WTERMSIG(s: i32) i32 {
-    return signed(unsigned(s) & 0x7f);
-}
-pub fn WSTOPSIG(s: i32) i32 {
+pub fn WSTOPSIG(s: u32) u32 {
     return WEXITSTATUS(s);
 }
-pub fn WIFEXITED(s: i32) bool {
+pub fn WIFEXITED(s: u32) bool {
     return WTERMSIG(s) == 0;
 }
 
-pub fn WIFCONTINUED(s: i32) bool {
+pub fn WIFCONTINUED(s: u32) bool {
     return ((s & 0x7f) == 0xffff);
 }
 
-pub fn WIFSTOPPED(s: i32) bool {
+pub fn WIFSTOPPED(s: u32) bool {
     return ((s & 0x7f != 0x7f) and !WIFCONTINUED(s));
 }
 
-pub fn WIFSIGNALED(s: i32) bool {
+pub fn WIFSIGNALED(s: u32) bool {
     return !WIFSTOPPED(s) and !WIFCONTINUED(s) and !WIFEXITED(s);
 }
 
std/os/linux/test.zig
@@ -11,7 +11,7 @@ test "getpid" {
 
 test "timer" {
     const epoll_fd = linux.epoll_create();
-    var err = linux.getErrno(epoll_fd);
+    var err: usize = linux.getErrno(epoll_fd);
     expect(err == 0);
 
     const timer_fd = linux.timerfd_create(linux.CLOCK_MONOTONIC, 0);
std/os/linux/vdso.zig
@@ -5,7 +5,7 @@ const mem = std.mem;
 const maxInt = std.math.maxInt;
 
 pub fn lookup(vername: []const u8, name: []const u8) usize {
-    const vdso_addr = std.os.linuxGetAuxVal(std.elf.AT_SYSINFO_EHDR);
+    const vdso_addr = std.os.system.getauxval(std.elf.AT_SYSINFO_EHDR);
     if (vdso_addr == 0) return 0;
 
     const eh = @intToPtr(*elf.Ehdr, vdso_addr);
std/os/linux.zig
@@ -382,7 +382,7 @@ pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
     return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags);
 }
 
-pub fn waitpid(pid: i32, status: *i32, flags: u32) usize {
+pub fn waitpid(pid: i32, status: *u32, flags: u32) usize {
     return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), flags, 0);
 }
 
std/os/test.zig
@@ -15,11 +15,11 @@ const AtomicRmwOp = builtin.AtomicRmwOp;
 const AtomicOrder = builtin.AtomicOrder;
 
 test "makePath, put some files in it, deleteTree" {
-    try os.makePath(a, "os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c");
+    try fs.makePath(a, "os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c");
     try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c" ++ fs.path.sep_str ++ "file.txt", "nonsense");
     try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "file2.txt", "blah");
-    try os.deleteTree(a, "os_test_tmp");
-    if (os.Dir.open(a, "os_test_tmp")) |dir| {
+    try fs.deleteTree(a, "os_test_tmp");
+    if (fs.Dir.open(a, "os_test_tmp")) |dir| {
         @panic("expected error");
     } else |err| {
         expect(err == error.FileNotFound);
@@ -27,7 +27,7 @@ test "makePath, put some files in it, deleteTree" {
 }
 
 test "access file" {
-    try os.makePath(a, "os_test_tmp");
+    try fs.makePath(a, "os_test_tmp");
     if (File.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt")) |ok| {
         @panic("expected error");
     } else |err| {
@@ -35,8 +35,8 @@ test "access file" {
     }
 
     try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", "");
-    try File.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt");
-    try os.deleteTree(a, "os_test_tmp");
+    try os.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", os.F_OK);
+    try fs.deleteTree(a, "os_test_tmp");
 }
 
 fn testThreadIdFn(thread_id: *Thread.Id) void {
@@ -52,15 +52,12 @@ test "std.Thread.getCurrentId" {
     thread.wait();
     if (Thread.use_pthreads) {
         expect(thread_current_id == thread_id);
+    } else if (os.windows.is_the_target) {
+        expect(Thread.getCurrentId() != thread_current_id);
     } else {
-        switch (builtin.os) {
-            builtin.Os.windows => expect(Thread.getCurrentId() != thread_current_id),
-            else => {
-                // If the thread completes very quickly, then thread_id can be 0. See the
-                // documentation comments for `std.Thread.handle`.
-                expect(thread_id == 0 or thread_current_id == thread_id);
-            },
-        }
+        // If the thread completes very quickly, then thread_id can be 0. See the
+        // documentation comments for `std.Thread.handle`.
+        expect(thread_id == 0 or thread_current_id == thread_id);
     }
 }
 
@@ -92,7 +89,7 @@ fn start2(ctx: *i32) u8 {
 }
 
 test "cpu count" {
-    const cpu_count = try std.os.cpuCount(a);
+    const cpu_count = try Thread.cpuCount();
     expect(cpu_count >= 1);
 }
 
@@ -105,7 +102,7 @@ test "AtomicFile" {
         \\ this is a test file
     ;
     {
-        var af = try os.AtomicFile.init(test_out_file, File.default_mode);
+        var af = try fs.AtomicFile.init(test_out_file, File.default_mode);
         defer af.deinit();
         try af.file.write(test_content);
         try af.finish();
@@ -113,7 +110,7 @@ test "AtomicFile" {
     const content = try io.readFileAlloc(allocator, test_out_file);
     expect(mem.eql(u8, content, test_content));
 
-    try os.deleteFile(test_out_file);
+    try fs.deleteFile(test_out_file);
 }
 
 test "thread local storage" {
@@ -145,10 +142,10 @@ test "getrandom" {
 test "getcwd" {
     // at least call it so it gets compiled
     var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
-    _ = os.getcwd(&buf) catch {};
+    _ = os.getcwd(&buf) catch undefined;
 }
 
 test "realpath" {
     var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
-    testing.expectError(error.FileNotFound, os.realpath("definitely_bogus_does_not_exist1234", &buf));
+    testing.expectError(error.FileNotFound, fs.realpath("definitely_bogus_does_not_exist1234", &buf));
 }
std/os/windows.zig
@@ -1180,6 +1180,44 @@ pub fn CreateProcessW(
     }
 }
 
+pub const LoadLibraryError = error{
+    FileNotFound,
+    Unexpected,
+};
+
+pub fn LoadLibraryW(lpLibFileName: [*]const u16) LoadLibraryError!HMODULE {
+    return kernel32.LoadLibraryW(lpLibFileName) orelse {
+        switch (kernel32.GetLastError()) {
+            ERROR.FILE_NOT_FOUND => return error.FileNotFound,
+            ERROR.PATH_NOT_FOUND => return error.FileNotFound,
+            ERROR.MOD_NOT_FOUND => return error.FileNotFound,
+            else => |err| return unexpectedError(err),
+        }
+    };
+}
+
+pub fn FreeLibrary(hModule: HMODULE) void {
+    assert(kernel32.FreeLibrary(hModule) != 0);
+}
+
+pub fn QueryPerformanceFrequency() u64 {
+    // "On systems that run Windows XP or later, the function will always succeed"
+    // https://docs.microsoft.com/en-us/windows/desktop/api/profileapi/nf-profileapi-queryperformancefrequency
+    var result: LARGE_INTEGER = undefined;
+    assert(kernel32.QueryPerformanceFrequency(&result) != 0);
+    // The kernel treats this integer as unsigned.
+    return @bitCast(u64, result);
+}
+
+pub fn QueryPerformanceCounter() u64 {
+    // "On systems that run Windows XP or later, the function will always succeed"
+    // https://docs.microsoft.com/en-us/windows/desktop/api/profileapi/nf-profileapi-queryperformancecounter
+    var result: LARGE_INTEGER = undefined;
+    assert(kernel32.QueryPerformanceCounter(&result) != 0);
+    // The kernel treats this integer as unsigned.
+    return @bitCast(u64, result);
+}
+
 pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {
     return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
 }
std/os/zen.zig
@@ -80,7 +80,7 @@ pub const STDOUT_FILENO = 1;
 pub const STDERR_FILENO = 2;
 
 // FIXME: let's borrow Linux's error numbers for now.
-use @import("../bits/linux/errno.zig");
+use @import("bits/linux/errno.zig");
 // Get the errno from a syscall return value, or 0 for no error.
 pub fn getErrno(r: usize) usize {
     const signed_r = @bitCast(isize, r);
std/c.zig
@@ -39,8 +39,8 @@ pub extern "c" fn open(path: [*]const u8, oflag: c_uint, ...) c_int;
 pub extern "c" fn raise(sig: c_int) c_int;
 pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize;
 pub extern "c" fn pread(fd: fd_t, buf: [*]u8, nbyte: usize, offset: u64) isize;
-pub extern "c" fn preadv(fd: c_int, iov: [*]const iovec, iovcnt: c_int, offset: usize) isize;
-pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec, iovcnt: c_int, offset: usize) isize;
+pub extern "c" fn preadv(fd: c_int, iov: [*]const iovec, iovcnt: c_uint, offset: usize) isize;
+pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint, offset: usize) isize;
 pub extern "c" fn stat(noalias path: [*]const u8, noalias buf: *Stat) c_int;
 pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize;
 pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: u64) isize;
@@ -49,7 +49,7 @@ pub extern "c" fn munmap(addr: *align(page_size) c_void, len: usize) c_int;
 pub extern "c" fn mprotect(addr: *align(page_size) c_void, len: usize, prot: c_uint) c_int;
 pub extern "c" fn unlink(path: [*]const u8) c_int;
 pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8;
-pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_int, options: c_int) c_int;
+pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_uint, options: c_uint) c_int;
 pub extern "c" fn fork() c_int;
 pub extern "c" fn access(path: [*]const u8, mode: c_uint) c_int;
 pub extern "c" fn pipe(fds: *[2]fd_t) c_int;
@@ -76,7 +76,12 @@ pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usi
 pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
 
 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 socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int;
+pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;
+pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int;
+pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int;
+pub extern "c" fn accept4(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t, flags: c_uint) c_int;
+pub extern "c" fn getsockopt(sockfd: fd_t, level: c_int, optname: c_int, optval: *c_void, optlen: *socklen_t) 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) isize;
 pub extern "c" fn openat(fd: c_int, path: [*]const u8, flags: c_int) c_int;
std/child_process.zig
@@ -54,10 +54,10 @@ pub const ChildProcess = struct {
         os.ChangeCurDirError || windows.CreateProcessError;
 
     pub const Term = union(enum) {
-        Exited: i32,
-        Signal: i32,
-        Stopped: i32,
-        Unknown: i32,
+        Exited: u32,
+        Signal: u32,
+        Stopped: u32,
+        Unknown: u32,
     };
 
     pub const StdIo = enum {
@@ -155,7 +155,7 @@ pub const ChildProcess = struct {
     }
 
     pub const ExecResult = struct {
-        term: os.ChildProcess.Term,
+        term: Term,
         stdout: []u8,
         stderr: []u8,
     };
@@ -224,7 +224,7 @@ pub const ChildProcess = struct {
             if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) {
                 break :x Term{ .Unknown = 0 };
             } else {
-                break :x Term{ .Exited = @bitCast(i32, exit_code) };
+                break :x Term{ .Exited = exit_code };
             }
         });
 
@@ -240,7 +240,7 @@ pub const ChildProcess = struct {
         self.handleWaitResult(status);
     }
 
-    fn handleWaitResult(self: *ChildProcess, status: i32) void {
+    fn handleWaitResult(self: *ChildProcess, status: u32) void {
         self.term = self.cleanupAfterWait(status);
     }
 
@@ -259,7 +259,7 @@ pub const ChildProcess = struct {
         }
     }
 
-    fn cleanupAfterWait(self: *ChildProcess, status: i32) !Term {
+    fn cleanupAfterWait(self: *ChildProcess, status: u32) !Term {
         defer {
             os.close(self.err_pipe[0]);
             os.close(self.err_pipe[1]);
@@ -281,7 +281,7 @@ pub const ChildProcess = struct {
         return statusToTerm(status);
     }
 
-    fn statusToTerm(status: i32) Term {
+    fn statusToTerm(status: u32) Term {
         return if (os.WIFEXITED(status))
             Term{ .Exited = os.WEXITSTATUS(status) }
         else if (os.WIFSIGNALED(status))
std/cstr.zig
@@ -28,7 +28,7 @@ test "cstr fns" {
 
 fn testCStrFnsImpl() void {
     testing.expect(cmp(c"aoeu", c"aoez") == -1);
-    testing.expect(len(c"123456789") == 9);
+    testing.expect(mem.len(u8, c"123456789") == 9);
 }
 
 /// Returns a mutable slice with 1 more byte of length which is a null byte.
std/dynamic_library.zig
@@ -6,8 +6,7 @@ const os = std.os;
 const assert = std.debug.assert;
 const testing = std.testing;
 const elf = std.elf;
-const windows = os.windows;
-const win_util = @import("os/windows/util.zig");
+const windows = std.os.windows;
 const maxInt = std.math.maxInt;
 
 pub const DynLib = switch (builtin.os) {
@@ -102,17 +101,16 @@ pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
 pub const LinuxDynLib = struct {
     elf_lib: ElfLib,
     fd: i32,
-    map_addr: usize,
-    map_size: usize,
+    memory: []align(mem.page_size) u8,
 
     /// Trusts the file
     pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
         const fd = try os.open(path, 0, os.O_RDONLY | os.O_CLOEXEC);
-        errdefer std.os.close(fd);
+        errdefer os.close(fd);
 
-        const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
+        const size = @intCast(usize, (try os.fstat(fd)).size);
 
-        const addr = os.mmap(
+        const bytes = try os.mmap(
             null,
             size,
             os.PROT_READ | os.PROT_EXEC,
@@ -120,21 +118,18 @@ pub const LinuxDynLib = struct {
             fd,
             0,
         );
-        errdefer os.munmap(addr, size);
-
-        const bytes = @intToPtr([*]align(mem.page_size) u8, addr)[0..size];
+        errdefer os.munmap(bytes);
 
         return DynLib{
             .elf_lib = try ElfLib.init(bytes),
             .fd = fd,
-            .map_addr = addr,
-            .map_size = size,
+            .memory = bytes,
         };
     }
 
     pub fn close(self: *DynLib) void {
-        os.munmap(self.map_addr, self.map_size);
-        std.os.close(self.fd);
+        os.munmap(self.memory);
+        os.close(self.fd);
         self.* = undefined;
     }
 
@@ -253,28 +248,21 @@ pub const WindowsDynLib = struct {
     dll: windows.HMODULE,
 
     pub fn open(allocator: *mem.Allocator, path: []const u8) !WindowsDynLib {
-        const wpath = try win_util.sliceToPrefixedFileW(path);
+        const wpath = try windows.sliceToPrefixedFileW(path);
 
         return WindowsDynLib{
             .allocator = allocator,
-            .dll = windows.LoadLibraryW(&wpath) orelse {
-                switch (windows.GetLastError()) {
-                    windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound,
-                    windows.ERROR.PATH_NOT_FOUND => return error.FileNotFound,
-                    windows.ERROR.MOD_NOT_FOUND => return error.FileNotFound,
-                    else => |err| return windows.unexpectedError(err),
-                }
-            },
+            .dll = try windows.LoadLibraryW(&wpath),
         };
     }
 
     pub fn close(self: *WindowsDynLib) void {
-        assert(windows.FreeLibrary(self.dll) != 0);
+        windows.FreeLibrary(self.dll);
         self.* = undefined;
     }
 
     pub fn lookup(self: *WindowsDynLib, name: []const u8) ?usize {
-        return @ptrToInt(windows.GetProcAddress(self.dll, name.ptr));
+        return @ptrToInt(windows.kernel32.GetProcAddress(self.dll, name.ptr));
     }
 };
 
std/fs.zig
@@ -38,24 +38,6 @@ pub const MAX_PATH_BYTES = switch (builtin.os) {
     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 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 os.getcwd(&buf));
-}
-
-test "getCwdAlloc" {
-    // at least call it so it gets compiled
-    var buf: [1000]u8 = undefined;
-    const allocator = &std.heap.FixedBufferAllocator.init(&buf).allocator;
-    _ = getCwdAlloc(allocator) catch {};
-}
-
 // here we replace the standard +/ with -_ so that it can be used in a file name
 const b64_fs_encoder = base64.Base64Encoder.init("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", base64.standard_pad_char);
 
@@ -260,17 +242,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 {
+pub fn deleteDir(dir_path: []const u8) !void {
     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 {
+pub fn deleteDirC(dir_path: [*]const u8) !void {
     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 {
+pub fn deleteDirW(dir_path: [*]const u16) !void {
     return os.rmdirW(dir_path);
 }
 
@@ -362,7 +344,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!
             };
             defer dir.close();
 
-            var full_entry_buf = ArrayList(u8).init(allocator);
+            var full_entry_buf = std.ArrayList(u8).init(allocator);
             defer full_entry_buf.deinit();
 
             while (try dir.next()) |entry| {
std/heap.zig
@@ -112,7 +112,7 @@ pub const DirectAllocator = struct {
             -1,
             0,
         ) catch return error.OutOfMemory;
-        if (alloc_size == n) return slice;
+        if (alloc_size == n) return slice[0..n];
 
         const aligned_addr = mem.alignForward(@ptrToInt(slice.ptr), alignment);
 
std/os.zig
@@ -284,7 +284,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
 /// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
 /// This function is for blocking file descriptors only. For non-blocking, see
 /// `preadvAsync`.
-pub fn preadv(fd: fd_t, iov: [*]const iovec, count: usize, offset: u64) ReadError!usize {
+pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) ReadError!usize {
     if (darwin.is_the_target) {
         // Darwin does not have preadv but it does have pread.
         var off: usize = 0;
@@ -301,7 +301,7 @@ pub fn preadv(fd: fd_t, iov: [*]const iovec, count: usize, offset: u64) ReadErro
                     if (inner_off == v.iov_len) {
                         iov_i += 1;
                         inner_off = 0;
-                        if (iov_i == count) {
+                        if (iov_i == iov.len) {
                             return off;
                         }
                     }
@@ -323,9 +323,10 @@ pub fn preadv(fd: fd_t, iov: [*]const iovec, count: usize, offset: u64) ReadErro
         }
     }
     while (true) {
-        const rc = system.preadv(fd, iov, count, offset);
+        // TODO handle the case when iov_len is too large and get rid of this @intCast
+        const rc = system.preadv(fd, iov.ptr, @intCast(u32, iov.len), offset);
         switch (errno(rc)) {
-            0 => return rc,
+            0 => return @bitCast(usize, rc),
             EINTR => continue,
             EINVAL => unreachable,
             EFAULT => unreachable,
@@ -407,7 +408,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {
 /// Write multiple buffers to a file descriptor. Keeps trying if it gets interrupted.
 /// This function is for blocking file descriptors only. For non-blocking, see
 /// `pwritevAsync`.
-pub fn pwritev(fd: fd_t, iov: [*]const iovec_const, count: usize, offset: u64) WriteError!void {
+pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) WriteError!void {
     if (darwin.is_the_target) {
         // Darwin does not have pwritev but it does have pwrite.
         var off: usize = 0;
@@ -424,7 +425,7 @@ pub fn pwritev(fd: fd_t, iov: [*]const iovec_const, count: usize, offset: u64) W
                     if (inner_off == v.iov_len) {
                         iov_i += 1;
                         inner_off = 0;
-                        if (iov_i == count) {
+                        if (iov_i == iov.len) {
                             return;
                         }
                     }
@@ -449,7 +450,8 @@ pub fn pwritev(fd: fd_t, iov: [*]const iovec_const, count: usize, offset: u64) W
     }
 
     while (true) {
-        const rc = system.pwritev(fd, iov, count, offset);
+        // TODO handle the case when iov_len is too large and get rid of this @intCast
+        const rc = system.pwritev(fd, iov.ptr, @intCast(u32, iov.len), offset);
         switch (errno(rc)) {
             0 => return,
             EINTR => continue,
@@ -724,7 +726,7 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
         EINVAL => unreachable,
         ENOENT => return error.CurrentWorkingDirectoryUnlinked,
         ERANGE => return error.NameTooLong,
-        else => return unexpectedErrno(err),
+        else => return unexpectedErrno(@intCast(usize, err)),
     }
 }
 
@@ -1121,7 +1123,7 @@ pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
     }
     const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len);
     switch (errno(rc)) {
-        0 => return out_buffer[0..rc],
+        0 => return out_buffer[0..@bitCast(usize, rc)],
         EACCES => return error.AccessDenied,
         EFAULT => unreachable,
         EINVAL => unreachable,
@@ -1307,7 +1309,7 @@ pub const BindError = error{
 
 /// addr is `*const T` where T is one of the sockaddr
 pub fn bind(fd: i32, addr: *const sockaddr) BindError!void {
-    const rc = system.bind(fd, system, @sizeOf(sockaddr));
+    const rc = system.bind(fd, addr, @sizeOf(sockaddr));
     switch (errno(rc)) {
         0 => return,
         EACCES => return error.AccessDenied,
@@ -1521,7 +1523,7 @@ pub fn epoll_wait(epfd: i32, events: []epoll_event, timeout: i32) usize {
         // TODO get rid of the @intCast
         const rc = system.epoll_wait(epfd, events.ptr, @intCast(u32, events.len), timeout);
         switch (errno(rc)) {
-            0 => return rc,
+            0 => return @intCast(usize, rc),
             EINTR => continue,
             EBADF => unreachable,
             EFAULT => unreachable,
@@ -1613,12 +1615,10 @@ pub const ConnectError = error{
 /// Initiate a connection on a socket.
 /// This is for blocking file descriptors only.
 /// For non-blocking, see `connect_async`.
-pub fn connect(sockfd: i32, sockaddr: *const sockaddr) ConnectError!void {
+pub fn connect(sockfd: i32, sock_addr: *sockaddr, len: socklen_t) ConnectError!void {
     while (true) {
-        switch (errno(system.connect(sockfd, sockaddr, @sizeOf(sockaddr)))) {
+        switch (errno(system.connect(sockfd, sock_addr, @sizeOf(sockaddr)))) {
             0 => return,
-            else => |err| return unexpectedErrno(err),
-
             EACCES => return error.PermissionDenied,
             EPERM => return error.PermissionDenied,
             EADDRINUSE => return error.AddressInUse,
@@ -1636,19 +1636,18 @@ pub fn connect(sockfd: i32, sockaddr: *const sockaddr) ConnectError!void {
             ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
             EPROTOTYPE => unreachable, // The socket type does not support the requested communications protocol.
             ETIMEDOUT => return error.ConnectionTimedOut,
+            else => |err| return unexpectedErrno(err),
         }
     }
 }
 
 /// Same as `connect` except it is for blocking socket file descriptors.
 /// It expects to receive EINPROGRESS`.
-pub fn connect_async(sockfd: i32, sockaddr: *const c_void, len: u32) ConnectError!void {
+pub fn connect_async(sockfd: i32, sock_addr: *sockaddr, len: socklen_t) ConnectError!void {
     while (true) {
-        switch (errno(system.connect(sockfd, sockaddr, len))) {
-            0, EINPROGRESS => return,
+        switch (errno(system.connect(sockfd, sock_addr, @sizeOf(sockaddr)))) {
             EINTR => continue,
-            else => |err| return unexpectedErrno(err),
-
+            0, EINPROGRESS => return,
             EACCES => return error.PermissionDenied,
             EPERM => return error.PermissionDenied,
             EADDRINUSE => return error.AddressInUse,
@@ -1664,13 +1663,14 @@ pub fn connect_async(sockfd: i32, sockaddr: *const c_void, len: u32) ConnectErro
             ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
             EPROTOTYPE => unreachable, // The socket type does not support the requested communications protocol.
             ETIMEDOUT => return error.ConnectionTimedOut,
+            else => |err| return unexpectedErrno(err),
         }
     }
 }
 
 pub fn getsockoptError(sockfd: i32) ConnectError!void {
-    var err_code: i32 = undefined;
-    var size: u32 = @sizeOf(i32);
+    var err_code: u32 = undefined;
+    var size: u32 = @sizeOf(u32);
     const rc = system.getsockopt(sockfd, SOL_SOCKET, SO_ERROR, @ptrCast([*]u8, &err_code), &size);
     assert(size == 4);
     switch (errno(rc)) {
@@ -1702,11 +1702,13 @@ pub fn getsockoptError(sockfd: i32) ConnectError!void {
     }
 }
 
-pub fn waitpid(pid: i32, flags: u32) i32 {
-    var status: i32 = undefined;
+pub fn waitpid(pid: i32, flags: u32) u32 {
+    // TODO allow implicit pointer cast from *u32 to *c_uint ?
+    const Status = if (builtin.link_libc) c_uint else u32;
+    var status: Status = undefined;
     while (true) {
         switch (errno(system.waitpid(pid, &status, flags))) {
-            0 => return status,
+            0 => return @bitCast(u32, status),
             EINTR => continue,
             ECHILD => unreachable, // The process specified does not exist. It would be a race condition to handle this error.
             EINVAL => unreachable, // The options argument was invalid
@@ -1892,11 +1894,19 @@ pub fn fork() ForkError!pid_t {
 }
 
 pub const MMapError = error{
+    /// The underlying filesystem of the specified file does not support memory mapping.
+    MemoryMappingNotSupported,
+
+    /// A file descriptor refers to a non-regular file. Or a file mapping was requested,
+    /// but the file descriptor is not open for reading. Or `MAP_SHARED` was requested
+    /// and `PROT_WRITE` is set, but the file descriptor is not open in `O_RDWR` mode.
+    /// Or `PROT_WRITE` is set, but the file is append-only.
     AccessDenied,
+
+    /// The `prot` argument asks for `PROT_EXEC` but the mapped area belongs to a file on
+    /// a filesystem that was mounted no-exec.
     PermissionDenied,
     LockedMemoryLimitExceeded,
-    SystemFdQuotaExceeded,
-    MemoryMappingNotSupported,
     OutOfMemory,
     Unexpected,
 };
@@ -1932,7 +1942,6 @@ pub fn mmap(
         EAGAIN => return error.LockedMemoryLimitExceeded,
         EBADF => unreachable, // Always a race condition.
         EOVERFLOW => unreachable, // The number of pages used for length + offset would overflow.
-        ENFILE => return error.SystemFdQuotaExceeded,
         ENODEV => return error.MemoryMappingNotSupported,
         EINVAL => unreachable, // Invalid parameters to mmap()
         ENOMEM => return error.OutOfMemory,
@@ -2265,7 +2274,7 @@ pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
         ENAMETOOLONG => return error.NameTooLong,
         ELOOP => return error.SymLinkLoop,
         EIO => return error.InputOutput,
-        else => |err| return unexpectedErrno(err),
+        else => |err| return unexpectedErrno(@intCast(usize, err)),
     };
     return mem.toSlice(u8, result_path);
 }
@@ -2349,7 +2358,7 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
 }
 
 pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
-    switch (errno(system.clock_getres(clk_id, tp))) {
+    switch (errno(system.clock_getres(clk_id, res))) {
         0 => return,
         EFAULT => unreachable,
         EINVAL => return error.UnsupportedClock,
@@ -2364,7 +2373,7 @@ pub const SchedGetAffinityError = error{
 
 pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {
     var set: cpu_set_t = undefined;
-    switch (errno(system.sched_getaffinity(pid, &set))) {
+    switch (errno(system.sched_getaffinity(pid, @sizeOf(cpu_set_t), &set))) {
         0 => return set,
         EFAULT => unreachable,
         EINVAL => unreachable,
std/process.zig
@@ -1,7 +1,9 @@
 const builtin = @import("builtin");
 const std = @import("std.zig");
 const os = std.os;
+const fs = std.fs;
 const BufMap = std.BufMap;
+const Buffer = std.Buffer;
 const mem = std.mem;
 const math = std.math;
 const Allocator = mem.Allocator;
@@ -13,6 +15,24 @@ pub const exit = os.exit;
 pub const changeCurDir = os.chdir;
 pub const changeCurDirC = os.chdirC;
 
+/// The result is a slice of `out_buffer`, from index `0`.
+pub fn getCwd(out_buffer: *[fs.MAX_PATH_BYTES]u8) ![]u8 {
+    return os.getcwd(out_buffer);
+}
+
+/// Caller must free the returned memory.
+pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
+    var buf: [fs.MAX_PATH_BYTES]u8 = undefined;
+    return mem.dupe(allocator, u8, try os.getcwd(&buf));
+}
+
+test "getCwdAlloc" {
+    // at least call it so it gets compiled
+    var buf: [1000]u8 = undefined;
+    const allocator = &std.heap.FixedBufferAllocator.init(&buf).allocator;
+    _ = getCwdAlloc(allocator) catch undefined;
+}
+
 /// Caller must free result when done.
 /// TODO make this go through libc when we have it
 pub fn getEnvMap(allocator: *Allocator) !BufMap {
@@ -402,7 +422,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
     var contents = try Buffer.initSize(allocator, 0);
     defer contents.deinit();
 
-    var slice_list = ArrayList(usize).init(allocator);
+    var slice_list = std.ArrayList(usize).init(allocator);
     defer slice_list.deinit();
 
     while (it.next(allocator)) |arg_or_err| {
std/thread.zig
@@ -1,8 +1,10 @@
 const builtin = @import("builtin");
 const std = @import("std.zig");
 const os = std.os;
+const mem = std.mem;
 const windows = std.os.windows;
 const c = std.c;
+const assert = std.debug.assert;
 
 pub const Thread = struct {
     data: Data,
@@ -31,14 +33,12 @@ pub const Thread = struct {
     pub const Data = if (use_pthreads)
         struct {
             handle: Thread.Handle,
-            mmap_addr: usize,
-            mmap_len: usize,
+            memory: []align(mem.page_size) u8,
         }
     else switch (builtin.os) {
         .linux => struct {
             handle: Thread.Handle,
-            mmap_addr: usize,
-            mmap_len: usize,
+            memory: []align(mem.page_size) u8,
         },
         .windows => struct {
             handle: Thread.Handle,
@@ -56,7 +56,7 @@ pub const Thread = struct {
             return c.pthread_self();
         } else
             return switch (builtin.os) {
-            .linux => linux.gettid(),
+            .linux => os.linux.gettid(),
             .windows => windows.GetCurrentThreadId(),
             else => @compileError("Unsupported OS"),
         };
@@ -82,21 +82,21 @@ pub const Thread = struct {
                 os.EDEADLK => unreachable,
                 else => unreachable,
             }
-            os.munmap(self.data.mmap_addr, self.data.mmap_len);
+            os.munmap(self.data.memory);
         } else switch (builtin.os) {
             .linux => {
                 while (true) {
                     const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst);
                     if (pid_value == 0) break;
-                    const rc = linux.futex_wait(&self.data.handle, linux.FUTEX_WAIT, pid_value, null);
-                    switch (linux.getErrno(rc)) {
+                    const rc = os.linux.futex_wait(&self.data.handle, os.linux.FUTEX_WAIT, pid_value, null);
+                    switch (os.linux.getErrno(rc)) {
                         0 => continue,
                         os.EINTR => continue,
                         os.EAGAIN => continue,
                         else => unreachable,
                     }
                 }
-                os.munmap(self.data.mmap_addr, self.data.mmap_len);
+                os.munmap(self.data.memory);
             },
             .windows => {
                 assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0);
@@ -130,6 +130,10 @@ pub const Thread = struct {
         /// Not enough userland memory to spawn the thread.
         OutOfMemory,
 
+        /// `mlockall` is enabled, and the memory needed to spawn the thread
+        /// would exceed the limit.
+        LockedMemoryLimitExceeded,
+
         Unexpected,
     };
 
@@ -219,7 +223,7 @@ pub const Thread = struct {
             }
         };
 
-        const MAP_GROWSDOWN = if (builtin.os == .linux) linux.MAP_GROWSDOWN else 0;
+        const MAP_GROWSDOWN = if (os.linux.is_the_target) os.linux.MAP_GROWSDOWN else 0;
 
         var stack_end_offset: usize = undefined;
         var thread_start_offset: usize = undefined;
@@ -241,7 +245,7 @@ pub const Thread = struct {
             }
             // Finally, the Thread Local Storage, if any.
             if (!Thread.use_pthreads) {
-                if (linux.tls.tls_image) |tls_img| {
+                if (os.linux.tls.tls_image) |tls_img| {
                     l = mem.alignForward(l, @alignOf(usize));
                     tls_start_offset = l;
                     l += tls_img.alloc_size;
@@ -249,12 +253,24 @@ pub const Thread = struct {
             }
             break :blk l;
         };
-        const mmap_addr = try os.mmap(null, mmap_len, os.PROT_READ | os.PROT_WRITE, os.MAP_PRIVATE | os.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
-        errdefer os.munmap(mmap_addr, mmap_len);
+        const mmap_slice = os.mmap(
+            null,
+            mem.alignForward(mmap_len, mem.page_size),
+            os.PROT_READ | os.PROT_WRITE,
+            os.MAP_PRIVATE | os.MAP_ANONYMOUS | MAP_GROWSDOWN,
+            -1,
+            0,
+        ) catch |err| switch (err) {
+            error.MemoryMappingNotSupported => unreachable, // no file descriptor
+            error.AccessDenied => unreachable, // no file descriptor
+            error.PermissionDenied => unreachable, // no file descriptor
+            else => |e| return e,
+        };
+        errdefer os.munmap(mmap_slice);
+        const mmap_addr = @ptrToInt(mmap_slice.ptr);
 
         const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));
-        thread_ptr.data.mmap_addr = mmap_addr;
-        thread_ptr.data.mmap_len = mmap_len;
+        thread_ptr.data.memory = mmap_slice;
 
         var arg: usize = undefined;
         if (@sizeOf(Context) != 0) {
@@ -269,7 +285,7 @@ pub const Thread = struct {
             if (c.pthread_attr_init(&attr) != 0) return error.SystemResources;
             defer assert(c.pthread_attr_destroy(&attr) == 0);
 
-            assert(c.pthread_attr_setstack(&attr, @intToPtr(*c_void, mmap_addr), stack_end_offset) == 0);
+            assert(c.pthread_attr_setstack(&attr, mmap_slice.ptr, stack_end_offset) == 0);
 
             const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));
             switch (err) {
@@ -279,13 +295,13 @@ pub const Thread = struct {
                 os.EINVAL => unreachable,
                 else => return os.unexpectedErrno(@intCast(usize, err)),
             }
-        } else if (builtin.os == .linux) {
+        } else if (os.linux.is_the_target) {
             var flags: u32 = os.CLONE_VM | os.CLONE_FS | os.CLONE_FILES | os.CLONE_SIGHAND |
                 os.CLONE_THREAD | os.CLONE_SYSVSEM | os.CLONE_PARENT_SETTID | os.CLONE_CHILD_CLEARTID |
                 os.CLONE_DETACHED;
             var newtls: usize = undefined;
-            if (linux.tls.tls_image) |tls_img| {
-                newtls = linux.tls.copyTLS(mmap_addr + tls_start_offset);
+            if (os.linux.tls.tls_image) |tls_img| {
+                newtls = os.linux.tls.copyTLS(mmap_addr + tls_start_offset);
                 flags |= os.CLONE_SETTLS;
             }
             const rc = os.linux.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
@@ -313,7 +329,7 @@ pub const Thread = struct {
     pub fn cpuCount() CpuCountError!usize {
         if (os.linux.is_the_target) {
             const cpu_set = try os.sched_getaffinity(0);
-            return os.CPU_COUNT(cpu_set);
+            return usize(os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast
         }
         if (os.windows.is_the_target) {
             var system_info: windows.SYSTEM_INFO = undefined;
std/time.zig
@@ -95,7 +95,7 @@ pub const Timer = struct {
     ///  be less precise
     frequency: switch (builtin.os) {
         .windows => u64,
-        .macosx, .ios, .tvos, .watchos => darwin.mach_timebase_info_data,
+        .macosx, .ios, .tvos, .watchos => os.darwin.mach_timebase_info_data,
         else => void,
     },
     resolution: u64,
@@ -119,20 +119,13 @@ pub const Timer = struct {
         var self: Timer = undefined;
 
         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.frequency = os.windows.QueryPerformanceFrequency();
             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);
+            self.start_time = os.windows.QueryPerformanceCounter();
         } else if (os.darwin.is_the_target) {
-            darwin.mach_timebase_info(&self.frequency);
+            os.darwin.mach_timebase_info(&self.frequency);
             self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
-            self.start_time = darwin.mach_absolute_time();
+            self.start_time = os.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
@@ -177,13 +170,10 @@ pub const Timer = struct {
 
     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);
+            return os.windows.QueryPerformanceCounter();
         }
         if (os.darwin.is_the_target) {
-            return darwin.mach_absolute_time();
+            return os.darwin.mach_absolute_time();
         }
         var ts: os.timespec = undefined;
         os.clock_gettime(monotonic_clock_id, &ts) catch unreachable;
test/standalone/empty_env/main.zig
@@ -1,6 +1,6 @@
 const std = @import("std");
 
 pub fn main() void {
-    const env_map = std.os.getEnvMap(std.debug.global_allocator) catch @panic("unable to get env map");
+    const env_map = std.process.getEnvMap(std.debug.global_allocator) catch @panic("unable to get env map");
     std.testing.expect(env_map.count() == 0);
 }
test/compare_output.zig
@@ -377,7 +377,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         \\    stdout.print("before\n") catch unreachable;
         \\    defer stdout.print("defer1\n") catch unreachable;
         \\    defer stdout.print("defer2\n") catch unreachable;
-        \\    var args_it = @import("std").os.args();
+        \\    var args_it = @import("std").process.args();
         \\    if (args_it.skip() and !args_it.skip()) return;
         \\    defer stdout.print("defer3\n") catch unreachable;
         \\    stdout.print("after\n") catch unreachable;
@@ -444,7 +444,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
             \\const allocator = std.debug.global_allocator;
             \\
             \\pub fn main() !void {
-            \\    var args_it = os.args();
+            \\    var args_it = std.process.args();
             \\    var stdout_file = try io.getStdOut();
             \\    var stdout_adapter = stdout_file.outStream();
             \\    const stdout = &stdout_adapter.stream;
@@ -485,7 +485,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
             \\const allocator = std.debug.global_allocator;
             \\
             \\pub fn main() !void {
-            \\    var args_it = os.args();
+            \\    var args_it = std.process.args();
             \\    var stdout_file = try io.getStdOut();
             \\    var stdout_adapter = stdout_file.outStream();
             \\    const stdout = &stdout_adapter.stream;
test/tests.zig
@@ -393,7 +393,7 @@ pub const CompareOutputContext = struct {
                 debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
             };
 
-            const expected_exit_code: i32 = 126;
+            const expected_exit_code: u32 = 126;
             switch (term) {
                 .Exited => |code| {
                     if (code != expected_exit_code) {
build.zig
@@ -166,10 +166,8 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {
 }
 
 fn fileExists(filename: []const u8) !bool {
-    fs.File.exists(filename) catch |err| switch (err) {
-        error.PermissionDenied,
-        error.FileNotFound,
-        => return false,
+    fs.File.access(filename) catch |err| switch (err) {
+        error.FileNotFound => return false,
         else => return err,
     };
     return true;