authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-25 13:07:44-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-26 18:32:44-04:00
log7cb6279ac0cec065234347bda5944be64fe8b3da
tree0eb4befe9a7eb24f5a393559e0621e92e26a4c59
parentca6debcaf4a4f85b7aff94c7b5fe821530b0f195
signaturelock-open Commit is signed but in an unrecognized format.

clean up references to posix


28 files changed, 1390 insertions(+), 1392 deletions(-)

CMakeLists.txt-1
...@@ -620,7 +620,6 @@ set(ZIG_STD_FILES...@@ -620,7 +620,6 @@ set(ZIG_STD_FILES
620 "os/freebsd.zig"620 "os/freebsd.zig"
621 "os/linux.zig"621 "os/linux.zig"
622 "os/linux/arm64.zig"622 "os/linux/arm64.zig"
623 "os/linux/sys.zig"
624 "os/linux/tls.zig"623 "os/linux/tls.zig"
625 "os/linux/vdso.zig"624 "os/linux/vdso.zig"
626 "os/linux/x86_64.zig"625 "os/linux/x86_64.zig"
std/atomic/queue.zig+4-4
...@@ -186,13 +186,13 @@ test "std.atomic.Queue" {...@@ -186,13 +186,13 @@ test "std.atomic.Queue" {
186 }186 }
187 }187 }
188 } else {188 } else {
189 var putters: [put_thread_count]*std.os.Thread = undefined;189 var putters: [put_thread_count]*std.Thread = undefined;
190 for (putters) |*t| {190 for (putters) |*t| {
191 t.* = try std.os.spawnThread(&context, startPuts);191 t.* = try std.Thread.spawn(&context, startPuts);
192 }192 }
193 var getters: [put_thread_count]*std.os.Thread = undefined;193 var getters: [put_thread_count]*std.Thread = undefined;
194 for (getters) |*t| {194 for (getters) |*t| {
195 t.* = try std.os.spawnThread(&context, startGets);195 t.* = try std.Thread.spawn(&context, startGets);
196 }196 }
197197
198 for (putters) |t|198 for (putters) |t|
std/atomic/stack.zig+4-4
...@@ -120,13 +120,13 @@ test "std.atomic.stack" {...@@ -120,13 +120,13 @@ test "std.atomic.stack" {
120 }120 }
121 }121 }
122 } else {122 } else {
123 var putters: [put_thread_count]*std.os.Thread = undefined;123 var putters: [put_thread_count]*std.Thread = undefined;
124 for (putters) |*t| {124 for (putters) |*t| {
125 t.* = try std.os.spawnThread(&context, startPuts);125 t.* = try std.Thread.spawn(&context, startPuts);
126 }126 }
127 var getters: [put_thread_count]*std.os.Thread = undefined;127 var getters: [put_thread_count]*std.Thread = undefined;
128 for (getters) |*t| {128 for (getters) |*t| {
129 t.* = try std.os.spawnThread(&context, startGets);129 t.* = try std.Thread.spawn(&context, startGets);
130 }130 }
131131
132 for (putters) |t|132 for (putters) |t|
std/c/darwin.zig+1-1
...@@ -3,7 +3,7 @@ const assert = std.debug.assert;...@@ -3,7 +3,7 @@ const assert = std.debug.assert;
3const builtin = @import("builtin");3const builtin = @import("builtin");
4const macho = std.macho;4const macho = std.macho;
55
6use @import("posix/darwin.zig");6use @import("../os/bits.zig");
77
8extern "c" fn __error() *c_int;8extern "c" fn __error() *c_int;
9pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;9pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;
std/c/linux.zig+1
...@@ -2,6 +2,7 @@ const std = @import("../std.zig");...@@ -2,6 +2,7 @@ const std = @import("../std.zig");
2use std.c;2use std.c;
33
4pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;4pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;
5pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
5extern "c" fn __errno_location() *c_int;6extern "c" fn __errno_location() *c_int;
6pub const _errno = __errno_location;7pub const _errno = __errno_location;
78
std/child_process.zig+9-9
...@@ -351,22 +351,22 @@ pub const ChildProcess = struct {...@@ -351,22 +351,22 @@ pub const ChildProcess = struct {
351 const err_pipe = try os.pipe();351 const err_pipe = try os.pipe();
352 errdefer destroyPipe(err_pipe);352 errdefer destroyPipe(err_pipe);
353353
354 const pid_result = try posix.fork();354 const pid_result = try os.fork();
355 if (pid_result == 0) {355 if (pid_result == 0) {
356 // we are the child356 // we are the child
357 setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);357 setUpChildIo(self.stdin_behavior, stdin_pipe[0], os.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
358 setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);358 setUpChildIo(self.stdout_behavior, stdout_pipe[1], os.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
359 setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);359 setUpChildIo(self.stderr_behavior, stderr_pipe[1], os.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
360360
361 if (self.stdin_behavior == StdIo.Pipe) {361 if (self.stdin_behavior == .Pipe) {
362 os.close(stdin_pipe[0]);362 os.close(stdin_pipe[0]);
363 os.close(stdin_pipe[1]);363 os.close(stdin_pipe[1]);
364 }364 }
365 if (self.stdout_behavior == StdIo.Pipe) {365 if (self.stdout_behavior == .Pipe) {
366 os.close(stdout_pipe[0]);366 os.close(stdout_pipe[0]);
367 os.close(stdout_pipe[1]);367 os.close(stdout_pipe[1]);
368 }368 }
369 if (self.stderr_behavior == StdIo.Pipe) {369 if (self.stderr_behavior == .Pipe) {
370 os.close(stderr_pipe[0]);370 os.close(stderr_pipe[0]);
371 os.close(stderr_pipe[1]);371 os.close(stderr_pipe[1]);
372 }372 }
...@@ -383,7 +383,7 @@ pub const ChildProcess = struct {...@@ -383,7 +383,7 @@ pub const ChildProcess = struct {
383 os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err);383 os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err);
384 }384 }
385385
386 os.posix.execve(self.allocator, self.argv, env_map) catch |err| forkChildErrReport(err_pipe[1], err);386 os.execve(self.allocator, self.argv, env_map) catch |err| forkChildErrReport(err_pipe[1], err);
387 }387 }
388388
389 // we are the parent389 // we are the parent
...@@ -736,7 +736,7 @@ fn destroyPipe(pipe: [2]i32) void {...@@ -736,7 +736,7 @@ fn destroyPipe(pipe: [2]i32) void {
736// Then the child exits.736// Then the child exits.
737fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {737fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
738 writeIntFd(fd, ErrInt(@errorToInt(err))) catch {};738 writeIntFd(fd, ErrInt(@errorToInt(err))) catch {};
739 posix.exit(1);739 os.exit(1);
740}740}
741741
742const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);742const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
std/crypto.zig+1-1
...@@ -33,7 +33,7 @@ pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;...@@ -33,7 +33,7 @@ pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
33pub const X25519 = @import("crypto/x25519.zig").X25519;33pub const X25519 = @import("crypto/x25519.zig").X25519;
3434
35const std = @import("std.zig");35const std = @import("std.zig");
36pub const randomBytes = std.posix.getrandom;36pub const randomBytes = std.os.getrandom;
3737
38test "crypto" {38test "crypto" {
39 _ = @import("crypto/blake2.zig");39 _ = @import("crypto/blake2.zig");
std/debug.zig+4-5
...@@ -1012,16 +1012,15 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {...@@ -1012,16 +1012,15 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
1012 errdefer S.self_exe_file.close();1012 errdefer S.self_exe_file.close();
10131013
1014 const self_exe_mmap_len = try S.self_exe_file.getEndPos();1014 const self_exe_mmap_len = try S.self_exe_file.getEndPos();
1015 const self_exe_mmap = os.posix.mmap(1015 const self_exe_mmap = try os.mmap(
1016 null,1016 null,
1017 self_exe_mmap_len,1017 self_exe_mmap_len,
1018 os.posix.PROT_READ,1018 os.PROT_READ,
1019 os.posix.MAP_SHARED,1019 os.MAP_SHARED,
1020 S.self_exe_file.handle,1020 S.self_exe_file.handle,
1021 0,1021 0,
1022 );1022 );
1023 if (self_exe_mmap == os.posix.MAP_FAILED) return error.OutOfMemory;1023 errdefer os.munmap(self_exe_mmap, self_exe_mmap_len);
1024 errdefer assert(os.posix.munmap(self_exe_mmap, self_exe_mmap_len) == 0);
10251024
1026 const file_mmap_slice = @intToPtr([*]const u8, self_exe_mmap)[0..self_exe_mmap_len];1025 const file_mmap_slice = @intToPtr([*]const u8, self_exe_mmap)[0..self_exe_mmap_len];
1027 S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(file_mmap_slice);1026 S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(file_mmap_slice);
std/event/fs.zig+17-21
...@@ -5,10 +5,9 @@ const assert = std.debug.assert;...@@ -5,10 +5,9 @@ const assert = std.debug.assert;
5const testing = std.testing;5const testing = std.testing;
6const os = std.os;6const os = std.os;
7const mem = std.mem;7const mem = std.mem;
8const posix = os.posix;
9const windows = os.windows;8const windows = os.windows;
10const Loop = event.Loop;9const Loop = event.Loop;
11const fd_t = posix.fd_t;10const fd_t = os.fd_t;
12const File = std.fs.File;11const File = std.fs.File;
1312
14pub const RequestNode = std.atomic.Queue(Request).Node;13pub const RequestNode = std.atomic.Queue(Request).Node;
...@@ -33,7 +32,7 @@ pub const Request = struct {...@@ -33,7 +32,7 @@ pub const Request = struct {
3332
34 pub const PWriteV = struct {33 pub const PWriteV = struct {
35 fd: fd_t,34 fd: fd_t,
36 iov: []const os.posix.iovec_const,35 iov: []const os.iovec_const,
37 offset: usize,36 offset: usize,
38 result: Error!void,37 result: Error!void,
3938
...@@ -42,7 +41,7 @@ pub const Request = struct {...@@ -42,7 +41,7 @@ pub const Request = struct {
4241
43 pub const PReadV = struct {42 pub const PReadV = struct {
44 fd: fd_t,43 fd: fd_t,
45 iov: []const os.posix.iovec,44 iov: []const os.iovec,
46 offset: usize,45 offset: usize,
47 result: Error!usize,46 result: Error!usize,
4847
...@@ -89,11 +88,11 @@ pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: us...@@ -89,11 +88,11 @@ pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: us
89 builtin.Os.freebsd,88 builtin.Os.freebsd,
90 builtin.Os.netbsd,89 builtin.Os.netbsd,
91 => {90 => {
92 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);91 const iovecs = try loop.allocator.alloc(os.iovec_const, data.len);
93 defer loop.allocator.free(iovecs);92 defer loop.allocator.free(iovecs);
9493
95 for (data) |buf, i| {94 for (data) |buf, i| {
96 iovecs[i] = os.posix.iovec_const{95 iovecs[i] = os.iovec_const{
97 .iov_base = buf.ptr,96 .iov_base = buf.ptr,
98 .iov_len = buf.len,97 .iov_len = buf.len,
99 };98 };
...@@ -171,7 +170,7 @@ pub async fn pwriteWindows(loop: *Loop, fd: fd_t, data: []const u8, offset: u64)...@@ -171,7 +170,7 @@ pub async fn pwriteWindows(loop: *Loop, fd: fd_t, data: []const u8, offset: u64)
171pub async fn pwritevPosix(170pub async fn pwritevPosix(
172 loop: *Loop,171 loop: *Loop,
173 fd: fd_t,172 fd: fd_t,
174 iovecs: []const posix.iovec_const,173 iovecs: []const os.iovec_const,
175 offset: usize,174 offset: usize,
176) os.PosixWriteError!void {175) os.PosixWriteError!void {
177 // workaround for https://github.com/ziglang/zig/issues/1194176 // workaround for https://github.com/ziglang/zig/issues/1194
...@@ -226,11 +225,11 @@ pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PR...@@ -226,11 +225,11 @@ pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PR
226 builtin.Os.freebsd,225 builtin.Os.freebsd,
227 builtin.Os.netbsd,226 builtin.Os.netbsd,
228 => {227 => {
229 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);228 const iovecs = try loop.allocator.alloc(os.iovec, data.len);
230 defer loop.allocator.free(iovecs);229 defer loop.allocator.free(iovecs);
231230
232 for (data) |buf, i| {231 for (data) |buf, i| {
233 iovecs[i] = os.posix.iovec{232 iovecs[i] = os.iovec{
234 .iov_base = buf.ptr,233 .iov_base = buf.ptr,
235 .iov_len = buf.len,234 .iov_len = buf.len,
236 };235 };
...@@ -319,7 +318,7 @@ pub async fn preadWindows(loop: *Loop, fd: fd_t, data: []u8, offset: u64) !usize...@@ -319,7 +318,7 @@ pub async fn preadWindows(loop: *Loop, fd: fd_t, data: []u8, offset: u64) !usize
319pub async fn preadvPosix(318pub async fn preadvPosix(
320 loop: *Loop,319 loop: *Loop,
321 fd: fd_t,320 fd: fd_t,
322 iovecs: []const posix.iovec,321 iovecs: []const os.iovec,
323 offset: usize,322 offset: usize,
324) os.PosixReadError!usize {323) os.PosixReadError!usize {
325 // workaround for https://github.com/ziglang/zig/issues/1194324 // workaround for https://github.com/ziglang/zig/issues/1194
...@@ -405,7 +404,7 @@ pub async fn openPosix(...@@ -405,7 +404,7 @@ pub async fn openPosix(
405pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t {404pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t {
406 switch (builtin.os) {405 switch (builtin.os) {
407 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {406 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
408 const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;407 const flags = os.O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC;
409 return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);408 return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
410 },409 },
411410
...@@ -435,7 +434,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File....@@ -435,7 +434,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File.
435 builtin.Os.freebsd,434 builtin.Os.freebsd,
436 builtin.Os.netbsd,435 builtin.Os.netbsd,
437 => {436 => {
438 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;437 const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC;
439 return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);438 return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
440 },439 },
441 builtin.Os.windows => return os.windowsOpen(440 builtin.Os.windows => return os.windowsOpen(
...@@ -457,7 +456,7 @@ pub async fn openReadWrite(...@@ -457,7 +456,7 @@ pub async fn openReadWrite(
457) File.OpenError!fd_t {456) File.OpenError!fd_t {
458 switch (builtin.os) {457 switch (builtin.os) {
459 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {458 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
460 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;459 const flags = os.O_LARGEFILE | os.O_RDWR | os.O_CREAT | os.O_CLOEXEC;
461 return await (async openPosix(loop, path, flags, mode) catch unreachable);460 return await (async openPosix(loop, path, flags, mode) catch unreachable);
462 },461 },
463462
...@@ -888,10 +887,7 @@ pub fn Watch(comptime V: type) type {...@@ -888,10 +887,7 @@ pub fn Watch(comptime V: type) type {
888 var close_op_consumed = false;887 var close_op_consumed = false;
889 defer if (!close_op_consumed) close_op.finish();888 defer if (!close_op_consumed) close_op.finish();
890889
891 const flags = switch (builtin.os) {890 const flags = if (os.darwin.is_the_target) os.O_SYMLINK | os.O_EVTONLY else 0;
892 builtin.Os.macosx => posix.O_SYMLINK | posix.O_EVTONLY,
893 else => 0,
894 };
895 const mode = 0;891 const mode = 0;
896 const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable);892 const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable);
897 close_op.setHandle(fd);893 close_op.setHandle(fd);
...@@ -943,16 +939,16 @@ pub fn Watch(comptime V: type) type {...@@ -943,16 +939,16 @@ pub fn Watch(comptime V: type) type {
943 while (true) {939 while (true) {
944 if (await (async self.channel.loop.bsdWaitKev(940 if (await (async self.channel.loop.bsdWaitKev(
945 @intCast(usize, close_op.getHandle()),941 @intCast(usize, close_op.getHandle()),
946 posix.EVFILT_VNODE,942 os.EVFILT_VNODE,
947 posix.NOTE_WRITE | posix.NOTE_DELETE,943 os.NOTE_WRITE | os.NOTE_DELETE,
948 ) catch unreachable)) |kev| {944 ) catch unreachable)) |kev| {
949 // TODO handle EV_ERROR945 // TODO handle EV_ERROR
950 if (kev.fflags & posix.NOTE_DELETE != 0) {946 if (kev.fflags & os.NOTE_DELETE != 0) {
951 await (async self.channel.put(Self.Event{947 await (async self.channel.put(Self.Event{
952 .id = Event.Id.Delete,948 .id = Event.Id.Delete,
953 .data = value_copy,949 .data = value_copy,
954 }) catch unreachable);950 }) catch unreachable);
955 } else if (kev.fflags & posix.NOTE_WRITE != 0) {951 } else if (kev.fflags & os.NOTE_WRITE != 0) {
956 await (async self.channel.put(Self.Event{952 await (async self.channel.put(Self.Event{
957 .id = Event.Id.CloseWrite,953 .id = Event.Id.CloseWrite,
958 .data = value_copy,954 .data = value_copy,
std/event/loop.zig+71-71
...@@ -7,9 +7,9 @@ const AtomicRmwOp = builtin.AtomicRmwOp;...@@ -7,9 +7,9 @@ const AtomicRmwOp = builtin.AtomicRmwOp;
7const AtomicOrder = builtin.AtomicOrder;7const AtomicOrder = builtin.AtomicOrder;
8const fs = std.event.fs;8const fs = std.event.fs;
9const os = std.os;9const os = std.os;
10const posix = os.posix;
11const windows = os.windows;10const windows = os.windows;
12const maxInt = std.math.maxInt;11const maxInt = std.math.maxInt;
12const Thread = std.Thread;
1313
14pub const Loop = struct {14pub const Loop = struct {
15 allocator: *mem.Allocator,15 allocator: *mem.Allocator,
...@@ -17,7 +17,7 @@ pub const Loop = struct {...@@ -17,7 +17,7 @@ pub const Loop = struct {
17 os_data: OsData,17 os_data: OsData,
18 final_resume_node: ResumeNode,18 final_resume_node: ResumeNode,
19 pending_event_count: usize,19 pending_event_count: usize,
20 extra_threads: []*os.Thread,20 extra_threads: []*Thread,
2121
22 // pre-allocated eventfds. all permanently active.22 // pre-allocated eventfds. all permanently active.
23 // this is how we send promises to be resumed on other threads.23 // this is how we send promises to be resumed on other threads.
...@@ -65,7 +65,7 @@ pub const Loop = struct {...@@ -65,7 +65,7 @@ pub const Loop = struct {
6565
66 const KEventFd = struct {66 const KEventFd = struct {
67 base: ResumeNode,67 base: ResumeNode,
68 kevent: posix.Kevent,68 kevent: os.Kevent,
69 };69 };
7070
71 pub const Basic = switch (builtin.os) {71 pub const Basic = switch (builtin.os) {
...@@ -81,7 +81,7 @@ pub const Loop = struct {...@@ -81,7 +81,7 @@ pub const Loop = struct {
8181
82 const KEventBasic = struct {82 const KEventBasic = struct {
83 base: ResumeNode,83 base: ResumeNode,
84 kev: posix.Kevent,84 kev: os.Kevent,
85 };85 };
86 };86 };
8787
...@@ -127,7 +127,7 @@ pub const Loop = struct {...@@ -127,7 +127,7 @@ pub const Loop = struct {
127 );127 );
128 errdefer self.allocator.free(self.eventfd_resume_nodes);128 errdefer self.allocator.free(self.eventfd_resume_nodes);
129129
130 self.extra_threads = try self.allocator.alloc(*os.Thread, extra_thread_count);130 self.extra_threads = try self.allocator.alloc(*Thread, extra_thread_count);
131 errdefer self.allocator.free(self.extra_threads);131 errdefer self.allocator.free(self.extra_threads);
132132
133 try self.initOsData(extra_thread_count);133 try self.initOsData(extra_thread_count);
...@@ -172,32 +172,32 @@ pub const Loop = struct {...@@ -172,32 +172,32 @@ pub const Loop = struct {
172 .handle = undefined,172 .handle = undefined,
173 .overlapped = ResumeNode.overlapped_init,173 .overlapped = ResumeNode.overlapped_init,
174 },174 },
175 .eventfd = try os.linuxEventFd(1, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK),175 .eventfd = try os.linuxEventFd(1, os.EFD_CLOEXEC | os.EFD_NONBLOCK),
176 .epoll_op = posix.EPOLL_CTL_ADD,176 .epoll_op = os.EPOLL_CTL_ADD,
177 },177 },
178 .next = undefined,178 .next = undefined,
179 };179 };
180 self.available_eventfd_resume_nodes.push(eventfd_node);180 self.available_eventfd_resume_nodes.push(eventfd_node);
181 }181 }
182182
183 self.os_data.epollfd = try os.linuxEpollCreate(posix.EPOLL_CLOEXEC);183 self.os_data.epollfd = try os.linuxEpollCreate(os.EPOLL_CLOEXEC);
184 errdefer os.close(self.os_data.epollfd);184 errdefer os.close(self.os_data.epollfd);
185185
186 self.os_data.final_eventfd = try os.linuxEventFd(0, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK);186 self.os_data.final_eventfd = try os.linuxEventFd(0, os.EFD_CLOEXEC | os.EFD_NONBLOCK);
187 errdefer os.close(self.os_data.final_eventfd);187 errdefer os.close(self.os_data.final_eventfd);
188188
189 self.os_data.final_eventfd_event = posix.epoll_event{189 self.os_data.final_eventfd_event = os.epoll_event{
190 .events = posix.EPOLLIN,190 .events = os.EPOLLIN,
191 .data = posix.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) },191 .data = os.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) },
192 };192 };
193 try os.linuxEpollCtl(193 try os.linuxEpollCtl(
194 self.os_data.epollfd,194 self.os_data.epollfd,
195 posix.EPOLL_CTL_ADD,195 os.EPOLL_CTL_ADD,
196 self.os_data.final_eventfd,196 self.os_data.final_eventfd,
197 &self.os_data.final_eventfd_event,197 &self.os_data.final_eventfd_event,
198 );198 );
199199
200 self.os_data.fs_thread = try os.spawnThread(self, posixFsRun);200 self.os_data.fs_thread = try Thread.spawn(self, posixFsRun);
201 errdefer {201 errdefer {
202 self.posixFsRequest(&self.os_data.fs_end_request);202 self.posixFsRequest(&self.os_data.fs_end_request);
203 self.os_data.fs_thread.wait();203 self.os_data.fs_thread.wait();
...@@ -218,7 +218,7 @@ pub const Loop = struct {...@@ -218,7 +218,7 @@ pub const Loop = struct {
218 }218 }
219 }219 }
220 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {220 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
221 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);221 self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
222 }222 }
223 },223 },
224 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {224 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
...@@ -240,7 +240,7 @@ pub const Loop = struct {...@@ -240,7 +240,7 @@ pub const Loop = struct {
240 },240 },
241 };241 };
242242
243 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];243 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
244244
245 for (self.eventfd_resume_nodes) |*eventfd_node, i| {245 for (self.eventfd_resume_nodes) |*eventfd_node, i| {
246 eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{246 eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{
...@@ -251,10 +251,10 @@ pub const Loop = struct {...@@ -251,10 +251,10 @@ pub const Loop = struct {
251 .overlapped = ResumeNode.overlapped_init,251 .overlapped = ResumeNode.overlapped_init,
252 },252 },
253 // this one is for sending events253 // this one is for sending events
254 .kevent = posix.Kevent{254 .kevent = os.Kevent{
255 .ident = i,255 .ident = i,
256 .filter = posix.EVFILT_USER,256 .filter = os.EVFILT_USER,
257 .flags = posix.EV_CLEAR | posix.EV_ADD | posix.EV_DISABLE,257 .flags = os.EV_CLEAR | os.EV_ADD | os.EV_DISABLE,
258 .fflags = 0,258 .fflags = 0,
259 .data = 0,259 .data = 0,
260 .udata = @ptrToInt(&eventfd_node.data.base),260 .udata = @ptrToInt(&eventfd_node.data.base),
...@@ -263,46 +263,46 @@ pub const Loop = struct {...@@ -263,46 +263,46 @@ pub const Loop = struct {
263 .next = undefined,263 .next = undefined,
264 };264 };
265 self.available_eventfd_resume_nodes.push(eventfd_node);265 self.available_eventfd_resume_nodes.push(eventfd_node);
266 const kevent_array = (*const [1]posix.Kevent)(&eventfd_node.data.kevent);266 const kevent_array = (*const [1]os.Kevent)(&eventfd_node.data.kevent);
267 _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null);267 _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null);
268 eventfd_node.data.kevent.flags = posix.EV_CLEAR | posix.EV_ENABLE;268 eventfd_node.data.kevent.flags = os.EV_CLEAR | os.EV_ENABLE;
269 eventfd_node.data.kevent.fflags = posix.NOTE_TRIGGER;269 eventfd_node.data.kevent.fflags = os.NOTE_TRIGGER;
270 }270 }
271271
272 // Pre-add so that we cannot get error.SystemResources272 // Pre-add so that we cannot get error.SystemResources
273 // later when we try to activate it.273 // later when we try to activate it.
274 self.os_data.final_kevent = posix.Kevent{274 self.os_data.final_kevent = os.Kevent{
275 .ident = extra_thread_count,275 .ident = extra_thread_count,
276 .filter = posix.EVFILT_USER,276 .filter = os.EVFILT_USER,
277 .flags = posix.EV_ADD | posix.EV_DISABLE,277 .flags = os.EV_ADD | os.EV_DISABLE,
278 .fflags = 0,278 .fflags = 0,
279 .data = 0,279 .data = 0,
280 .udata = @ptrToInt(&self.final_resume_node),280 .udata = @ptrToInt(&self.final_resume_node),
281 };281 };
282 const final_kev_arr = (*const [1]posix.Kevent)(&self.os_data.final_kevent);282 const final_kev_arr = (*const [1]os.Kevent)(&self.os_data.final_kevent);
283 _ = try os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null);283 _ = try os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null);
284 self.os_data.final_kevent.flags = posix.EV_ENABLE;284 self.os_data.final_kevent.flags = os.EV_ENABLE;
285 self.os_data.final_kevent.fflags = posix.NOTE_TRIGGER;285 self.os_data.final_kevent.fflags = os.NOTE_TRIGGER;
286286
287 self.os_data.fs_kevent_wake = posix.Kevent{287 self.os_data.fs_kevent_wake = os.Kevent{
288 .ident = 0,288 .ident = 0,
289 .filter = posix.EVFILT_USER,289 .filter = os.EVFILT_USER,
290 .flags = posix.EV_ADD | posix.EV_ENABLE,290 .flags = os.EV_ADD | os.EV_ENABLE,
291 .fflags = posix.NOTE_TRIGGER,291 .fflags = os.NOTE_TRIGGER,
292 .data = 0,292 .data = 0,
293 .udata = undefined,293 .udata = undefined,
294 };294 };
295295
296 self.os_data.fs_kevent_wait = posix.Kevent{296 self.os_data.fs_kevent_wait = os.Kevent{
297 .ident = 0,297 .ident = 0,
298 .filter = posix.EVFILT_USER,298 .filter = os.EVFILT_USER,
299 .flags = posix.EV_ADD | posix.EV_CLEAR,299 .flags = os.EV_ADD | os.EV_CLEAR,
300 .fflags = 0,300 .fflags = 0,
301 .data = 0,301 .data = 0,
302 .udata = undefined,302 .udata = undefined,
303 };303 };
304304
305 self.os_data.fs_thread = try os.spawnThread(self, posixFsRun);305 self.os_data.fs_thread = try Thread.spawn(self, posixFsRun);
306 errdefer {306 errdefer {
307 self.posixFsRequest(&self.os_data.fs_end_request);307 self.posixFsRequest(&self.os_data.fs_end_request);
308 self.os_data.fs_thread.wait();308 self.os_data.fs_thread.wait();
...@@ -322,7 +322,7 @@ pub const Loop = struct {...@@ -322,7 +322,7 @@ pub const Loop = struct {
322 }322 }
323 }323 }
324 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {324 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
325 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);325 self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
326 }326 }
327 },327 },
328 builtin.Os.windows => {328 builtin.Os.windows => {
...@@ -371,7 +371,7 @@ pub const Loop = struct {...@@ -371,7 +371,7 @@ pub const Loop = struct {
371 }371 }
372 }372 }
373 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {373 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
374 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);374 self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
375 }375 }
376 },376 },
377 else => {},377 else => {},
...@@ -400,19 +400,19 @@ pub const Loop = struct {...@@ -400,19 +400,19 @@ pub const Loop = struct {
400 /// resume_node must live longer than the promise that it holds a reference to.400 /// resume_node must live longer than the promise that it holds a reference to.
401 /// flags must contain EPOLLET401 /// flags must contain EPOLLET
402 pub fn linuxAddFd(self: *Loop, fd: i32, resume_node: *ResumeNode, flags: u32) !void {402 pub fn linuxAddFd(self: *Loop, fd: i32, resume_node: *ResumeNode, flags: u32) !void {
403 assert(flags & posix.EPOLLET == posix.EPOLLET);403 assert(flags & os.EPOLLET == os.EPOLLET);
404 self.beginOneEvent();404 self.beginOneEvent();
405 errdefer self.finishOneEvent();405 errdefer self.finishOneEvent();
406 try self.linuxModFd(406 try self.linuxModFd(
407 fd,407 fd,
408 posix.EPOLL_CTL_ADD,408 os.EPOLL_CTL_ADD,
409 flags,409 flags,
410 resume_node,410 resume_node,
411 );411 );
412 }412 }
413413
414 pub fn linuxModFd(self: *Loop, fd: i32, op: u32, flags: u32, resume_node: *ResumeNode) !void {414 pub fn linuxModFd(self: *Loop, fd: i32, op: u32, flags: u32, resume_node: *ResumeNode) !void {
415 assert(flags & posix.EPOLLET == posix.EPOLLET);415 assert(flags & os.EPOLLET == os.EPOLLET);
416 var ev = os.linux.epoll_event{416 var ev = os.linux.epoll_event{
417 .events = flags,417 .events = flags,
418 .data = os.linux.epoll_data{ .ptr = @ptrToInt(resume_node) },418 .data = os.linux.epoll_data{ .ptr = @ptrToInt(resume_node) },
...@@ -440,7 +440,7 @@ pub const Loop = struct {...@@ -440,7 +440,7 @@ pub const Loop = struct {
440 }440 }
441 }441 }
442442
443 pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !posix.Kevent {443 pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !os.Kevent {
444 // TODO #1194444 // TODO #1194
445 suspend {445 suspend {
446 resume @handle();446 resume @handle();
...@@ -464,30 +464,30 @@ pub const Loop = struct {...@@ -464,30 +464,30 @@ pub const Loop = struct {
464 pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void {464 pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void {
465 self.beginOneEvent();465 self.beginOneEvent();
466 errdefer self.finishOneEvent();466 errdefer self.finishOneEvent();
467 var kev = posix.Kevent{467 var kev = os.Kevent{
468 .ident = ident,468 .ident = ident,
469 .filter = filter,469 .filter = filter,
470 .flags = posix.EV_ADD | posix.EV_ENABLE | posix.EV_CLEAR,470 .flags = os.EV_ADD | os.EV_ENABLE | os.EV_CLEAR,
471 .fflags = fflags,471 .fflags = fflags,
472 .data = 0,472 .data = 0,
473 .udata = @ptrToInt(&resume_node.base),473 .udata = @ptrToInt(&resume_node.base),
474 };474 };
475 const kevent_array = (*const [1]posix.Kevent)(&kev);475 const kevent_array = (*const [1]os.Kevent)(&kev);
476 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];476 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
477 _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null);477 _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null);
478 }478 }
479479
480 pub fn bsdRemoveKev(self: *Loop, ident: usize, filter: i16) void {480 pub fn bsdRemoveKev(self: *Loop, ident: usize, filter: i16) void {
481 var kev = posix.Kevent{481 var kev = os.Kevent{
482 .ident = ident,482 .ident = ident,
483 .filter = filter,483 .filter = filter,
484 .flags = posix.EV_DELETE,484 .flags = os.EV_DELETE,
485 .fflags = 0,485 .fflags = 0,
486 .data = 0,486 .data = 0,
487 .udata = 0,487 .udata = 0,
488 };488 };
489 const kevent_array = (*const [1]posix.Kevent)(&kev);489 const kevent_array = (*const [1]os.Kevent)(&kev);
490 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];490 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
491 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch undefined;491 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch undefined;
492 self.finishOneEvent();492 self.finishOneEvent();
493 }493 }
...@@ -502,8 +502,8 @@ pub const Loop = struct {...@@ -502,8 +502,8 @@ pub const Loop = struct {
502 eventfd_node.base.handle = next_tick_node.data;502 eventfd_node.base.handle = next_tick_node.data;
503 switch (builtin.os) {503 switch (builtin.os) {
504 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {504 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
505 const kevent_array = (*const [1]posix.Kevent)(&eventfd_node.kevent);505 const kevent_array = (*const [1]os.Kevent)(&eventfd_node.kevent);
506 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];506 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
507 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {507 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
508 self.next_tick_queue.unget(next_tick_node);508 self.next_tick_queue.unget(next_tick_node);
509 self.available_eventfd_resume_nodes.push(resume_stack_node);509 self.available_eventfd_resume_nodes.push(resume_stack_node);
...@@ -512,7 +512,7 @@ pub const Loop = struct {...@@ -512,7 +512,7 @@ pub const Loop = struct {
512 },512 },
513 builtin.Os.linux => {513 builtin.Os.linux => {
514 // the pending count is already accounted for514 // the pending count is already accounted for
515 const epoll_events = posix.EPOLLONESHOT | os.linux.EPOLLIN | os.linux.EPOLLOUT |515 const epoll_events = os.EPOLLONESHOT | os.linux.EPOLLIN | os.linux.EPOLLOUT |
516 os.linux.EPOLLET;516 os.linux.EPOLLET;
517 self.linuxModFd(517 self.linuxModFd(
518 eventfd_node.eventfd,518 eventfd_node.eventfd,
...@@ -631,8 +631,8 @@ pub const Loop = struct {...@@ -631,8 +631,8 @@ pub const Loop = struct {
631 },631 },
632 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {632 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
633 self.posixFsRequest(&self.os_data.fs_end_request);633 self.posixFsRequest(&self.os_data.fs_end_request);
634 const final_kevent = (*const [1]posix.Kevent)(&self.os_data.final_kevent);634 const final_kevent = (*const [1]os.Kevent)(&self.os_data.final_kevent);
635 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];635 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
636 // cannot fail because we already added it and this just enables it636 // cannot fail because we already added it and this just enables it
637 _ = os.bsdKEvent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable;637 _ = os.bsdKEvent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable;
638 return;638 return;
...@@ -676,7 +676,7 @@ pub const Loop = struct {...@@ -676,7 +676,7 @@ pub const Loop = struct {
676 ResumeNode.Id.Stop => return,676 ResumeNode.Id.Stop => return,
677 ResumeNode.Id.EventFd => {677 ResumeNode.Id.EventFd => {
678 const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node);678 const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node);
679 event_fd_node.epoll_op = posix.EPOLL_CTL_MOD;679 event_fd_node.epoll_op = os.EPOLL_CTL_MOD;
680 const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node);680 const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node);
681 self.available_eventfd_resume_nodes.push(stack_node);681 self.available_eventfd_resume_nodes.push(stack_node);
682 },682 },
...@@ -688,8 +688,8 @@ pub const Loop = struct {...@@ -688,8 +688,8 @@ pub const Loop = struct {
688 }688 }
689 },689 },
690 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {690 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
691 var eventlist: [1]posix.Kevent = undefined;691 var eventlist: [1]os.Kevent = undefined;
692 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];692 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
693 const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;693 const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;
694 for (eventlist[0..count]) |ev| {694 for (eventlist[0..count]) |ev| {
695 const resume_node = @intToPtr(*ResumeNode, ev.udata);695 const resume_node = @intToPtr(*ResumeNode, ev.udata);
...@@ -751,8 +751,8 @@ pub const Loop = struct {...@@ -751,8 +751,8 @@ pub const Loop = struct {
751 self.os_data.fs_queue.put(request_node);751 self.os_data.fs_queue.put(request_node);
752 switch (builtin.os) {752 switch (builtin.os) {
753 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {753 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
754 const fs_kevs = (*const [1]posix.Kevent)(&self.os_data.fs_kevent_wake);754 const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wake);
755 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];755 const empty_kevs = ([*]os.Kevent)(undefined)[0..0];
756 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;756 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
757 },757 },
758 builtin.Os.linux => {758 builtin.Os.linux => {
...@@ -760,7 +760,7 @@ pub const Loop = struct {...@@ -760,7 +760,7 @@ pub const Loop = struct {
760 const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1);760 const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1);
761 switch (os.linux.getErrno(rc)) {761 switch (os.linux.getErrno(rc)) {
762 0 => {},762 0 => {},
763 posix.EINVAL => unreachable,763 os.EINVAL => unreachable,
764 else => unreachable,764 else => unreachable,
765 }765 }
766 },766 },
...@@ -793,8 +793,8 @@ pub const Loop = struct {...@@ -793,8 +793,8 @@ pub const Loop = struct {
793 },793 },
794 @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd),794 @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd),
795 @TagType(fs.Request.Msg).WriteFile => |*msg| blk: {795 @TagType(fs.Request.Msg).WriteFile => |*msg| blk: {
796 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT |796 const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT |
797 posix.O_CLOEXEC | posix.O_TRUNC;797 os.O_CLOEXEC | os.O_TRUNC;
798 const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| {798 const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| {
799 msg.result = err;799 msg.result = err;
800 break :blk;800 break :blk;
...@@ -816,13 +816,13 @@ pub const Loop = struct {...@@ -816,13 +816,13 @@ pub const Loop = struct {
816 builtin.Os.linux => {816 builtin.Os.linux => {
817 const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null);817 const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null);
818 switch (os.linux.getErrno(rc)) {818 switch (os.linux.getErrno(rc)) {
819 0, posix.EINTR, posix.EAGAIN => continue,819 0, os.EINTR, os.EAGAIN => continue,
820 else => unreachable,820 else => unreachable,
821 }821 }
822 },822 },
823 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {823 builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
824 const fs_kevs = (*const [1]posix.Kevent)(&self.os_data.fs_kevent_wait);824 const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wait);
825 var out_kevs: [1]posix.Kevent = undefined;825 var out_kevs: [1]os.Kevent = undefined;
826 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;826 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
827 },827 },
828 else => @compileError("Unsupported OS"),828 else => @compileError("Unsupported OS"),
...@@ -842,10 +842,10 @@ pub const Loop = struct {...@@ -842,10 +842,10 @@ pub const Loop = struct {
842842
843 const KEventData = struct {843 const KEventData = struct {
844 kqfd: i32,844 kqfd: i32,
845 final_kevent: posix.Kevent,845 final_kevent: os.Kevent,
846 fs_kevent_wake: posix.Kevent,846 fs_kevent_wake: os.Kevent,
847 fs_kevent_wait: posix.Kevent,847 fs_kevent_wait: os.Kevent,
848 fs_thread: *os.Thread,848 fs_thread: *Thread,
849 fs_kqfd: i32,849 fs_kqfd: i32,
850 fs_queue: std.atomic.Queue(fs.Request),850 fs_queue: std.atomic.Queue(fs.Request),
851 fs_end_request: fs.RequestNode,851 fs_end_request: fs.RequestNode,
...@@ -855,7 +855,7 @@ pub const Loop = struct {...@@ -855,7 +855,7 @@ pub const Loop = struct {
855 epollfd: i32,855 epollfd: i32,
856 final_eventfd: i32,856 final_eventfd: i32,
857 final_eventfd_event: os.linux.epoll_event,857 final_eventfd_event: os.linux.epoll_event,
858 fs_thread: *os.Thread,858 fs_thread: *Thread,
859 fs_queue_item: i32,859 fs_queue_item: i32,
860 fs_queue: std.atomic.Queue(fs.Request),860 fs_queue: std.atomic.Queue(fs.Request),
861 fs_end_request: fs.RequestNode,861 fs_end_request: fs.RequestNode,
std/event/net.zig+54-59
...@@ -4,11 +4,9 @@ const testing = std.testing;...@@ -4,11 +4,9 @@ const testing = std.testing;
4const event = std.event;4const event = std.event;
5const mem = std.mem;5const mem = std.mem;
6const os = std.os;6const os = std.os;
7const posix = os.posix;
8const Loop = std.event.Loop;7const Loop = std.event.Loop;
9const File = std.fs.File;8const File = std.fs.File;
109const fd_t = os.fd_t;
11const fd_t = posix.fd_t;
1210
13pub const Server = struct {11pub const Server = struct {
14 handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void,12 handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void,
...@@ -47,19 +45,19 @@ pub const Server = struct {...@@ -47,19 +45,19 @@ pub const Server = struct {
47 ) !void {45 ) !void {
48 self.handleRequestFn = handleRequestFn;46 self.handleRequestFn = handleRequestFn;
4947
50 const sockfd = try os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);48 const sockfd = try os.posixSocket(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, os.PROTO_tcp);
51 errdefer os.close(sockfd);49 errdefer os.close(sockfd);
52 self.sockfd = sockfd;50 self.sockfd = sockfd;
5351
54 try os.posixBind(sockfd, &address.os_addr);52 try os.posixBind(sockfd, &address.os_addr);
55 try os.posixListen(sockfd, posix.SOMAXCONN);53 try os.posixListen(sockfd, os.SOMAXCONN);
56 self.listen_address = std.net.Address.initPosix(try os.posixGetSockName(sockfd));54 self.listen_address = std.net.Address.initPosix(try os.posixGetSockName(sockfd));
5755
58 self.accept_coro = try async<self.loop.allocator> Server.handler(self);56 self.accept_coro = try async<self.loop.allocator> Server.handler(self);
59 errdefer cancel self.accept_coro.?;57 errdefer cancel self.accept_coro.?;
6058
61 self.listen_resume_node.handle = self.accept_coro.?;59 self.listen_resume_node.handle = self.accept_coro.?;
62 try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);60 try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
63 errdefer self.loop.removeFd(sockfd);61 errdefer self.loop.removeFd(sockfd);
64 }62 }
6563
...@@ -78,7 +76,7 @@ pub const Server = struct {...@@ -78,7 +76,7 @@ pub const Server = struct {
78 while (true) {76 while (true) {
79 var accepted_addr: std.net.Address = undefined;77 var accepted_addr: std.net.Address = undefined;
80 // TODO just inline the following function here and don't expose it as posixAsyncAccept78 // TODO just inline the following function here and don't expose it as posixAsyncAccept
81 if (os.posixAsyncAccept(self.sockfd.?, &accepted_addr.os_addr, posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| {79 if (os.posixAsyncAccept(self.sockfd.?, &accepted_addr.os_addr, os.SOCK_NONBLOCK | os.SOCK_CLOEXEC)) |accepted_fd| {
82 if (accepted_fd == -1) {80 if (accepted_fd == -1) {
83 // would block81 // would block
84 suspend; // we will get resumed by epoll_wait in the event loop82 suspend; // we will get resumed by epoll_wait in the event loop
...@@ -108,22 +106,22 @@ pub const Server = struct {...@@ -108,22 +106,22 @@ pub const Server = struct {
108106
109pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 {107pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 {
110 const sockfd = try os.posixSocket(108 const sockfd = try os.posixSocket(
111 posix.AF_UNIX,109 os.AF_UNIX,
112 posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK,110 os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK,
113 0,111 0,
114 );112 );
115 errdefer os.close(sockfd);113 errdefer os.close(sockfd);
116114
117 var sock_addr = posix.sockaddr_un{115 var sock_addr = os.sockaddr_un{
118 .family = posix.AF_UNIX,116 .family = os.AF_UNIX,
119 .path = undefined,117 .path = undefined,
120 };118 };
121119
122 if (path.len > @typeOf(sock_addr.path).len) return error.NameTooLong;120 if (path.len > @typeOf(sock_addr.path).len) return error.NameTooLong;
123 mem.copy(u8, sock_addr.path[0..], path);121 mem.copy(u8, sock_addr.path[0..], path);
124 const size = @intCast(u32, @sizeOf(posix.sa_family_t) + path.len);122 const size = @intCast(u32, @sizeOf(os.sa_family_t) + path.len);
125 try os.posixConnectAsync(sockfd, &sock_addr, size);123 try os.posixConnectAsync(sockfd, &sock_addr, size);
126 try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);124 try await try async loop.linuxWaitFd(sockfd, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
127 try os.posixGetSockOptConnectError(sockfd);125 try os.posixGetSockOptConnectError(sockfd);
128126
129 return sockfd;127 return sockfd;
...@@ -143,50 +141,48 @@ pub const ReadError = error{...@@ -143,50 +141,48 @@ pub const ReadError = error{
143141
144/// returns number of bytes read. 0 means EOF.142/// returns number of bytes read. 0 means EOF.
145pub async fn read(loop: *std.event.Loop, fd: fd_t, buffer: []u8) ReadError!usize {143pub async fn read(loop: *std.event.Loop, fd: fd_t, buffer: []u8) ReadError!usize {
146 const iov = posix.iovec{144 const iov = os.iovec{
147 .iov_base = buffer.ptr,145 .iov_base = buffer.ptr,
148 .iov_len = buffer.len,146 .iov_len = buffer.len,
149 };147 };
150 const iovs: *const [1]posix.iovec = &iov;148 const iovs: *const [1]os.iovec = &iov;
151 return await (async readvPosix(loop, fd, iovs, 1) catch unreachable);149 return await (async readvPosix(loop, fd, iovs, 1) catch unreachable);
152}150}
153151
154pub const WriteError = error{};152pub const WriteError = error{};
155153
156pub async fn write(loop: *std.event.Loop, fd: fd_t, buffer: []const u8) WriteError!void {154pub async fn write(loop: *std.event.Loop, fd: fd_t, buffer: []const u8) WriteError!void {
157 const iov = posix.iovec_const{155 const iov = os.iovec_const{
158 .iov_base = buffer.ptr,156 .iov_base = buffer.ptr,
159 .iov_len = buffer.len,157 .iov_len = buffer.len,
160 };158 };
161 const iovs: *const [1]posix.iovec_const = &iov;159 const iovs: *const [1]os.iovec_const = &iov;
162 return await (async writevPosix(loop, fd, iovs, 1) catch unreachable);160 return await (async writevPosix(loop, fd, iovs, 1) catch unreachable);
163}161}
164162
165pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const, count: usize) !void {163pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const os.iovec_const, count: usize) !void {
166 while (true) {164 while (true) {
167 switch (builtin.os) {165 switch (builtin.os) {
168 builtin.Os.macosx, builtin.Os.linux => {166 .macosx, .linux => {
169 const rc = posix.writev(fd, iov, count);167 switch (os.errno(os.system.writev(fd, iov, count))) {
170 const err = posix.getErrno(rc);
171 switch (err) {
172 0 => return,168 0 => return,
173 posix.EINTR => continue,169 os.EINTR => continue,
174 posix.ESPIPE => unreachable,170 os.ESPIPE => unreachable,
175 posix.EINVAL => unreachable,171 os.EINVAL => unreachable,
176 posix.EFAULT => unreachable,172 os.EFAULT => unreachable,
177 posix.EAGAIN => {173 os.EAGAIN => {
178 try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLOUT) catch unreachable);174 try await (async loop.linuxWaitFd(fd, os.EPOLLET | os.EPOLLOUT) catch unreachable);
179 continue;175 continue;
180 },176 },
181 posix.EBADF => unreachable, // always a race condition177 os.EBADF => unreachable, // always a race condition
182 posix.EDESTADDRREQ => unreachable, // connect was never called178 os.EDESTADDRREQ => unreachable, // connect was never called
183 posix.EDQUOT => unreachable,179 os.EDQUOT => unreachable,
184 posix.EFBIG => unreachable,180 os.EFBIG => unreachable,
185 posix.EIO => return error.InputOutput,181 os.EIO => return error.InputOutput,
186 posix.ENOSPC => unreachable,182 os.ENOSPC => unreachable,
187 posix.EPERM => return error.AccessDenied,183 os.EPERM => return error.AccessDenied,
188 posix.EPIPE => unreachable,184 os.EPIPE => unreachable,
189 else => return os.unexpectedErrorPosix(err),185 else => |err| return os.unexpectedErrno(err),
190 }186 }
191 },187 },
192 else => @compileError("Unsupported OS"),188 else => @compileError("Unsupported OS"),
...@@ -195,27 +191,26 @@ pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const,...@@ -195,27 +191,26 @@ pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const,
195}191}
196192
197/// returns number of bytes read. 0 means EOF.193/// returns number of bytes read. 0 means EOF.
198pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, count: usize) !usize {194pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]os.iovec, count: usize) !usize {
199 while (true) {195 while (true) {
200 switch (builtin.os) {196 switch (builtin.os) {
201 builtin.Os.linux, builtin.Os.freebsd, builtin.Os.macosx => {197 builtin.Os.linux, builtin.Os.freebsd, builtin.Os.macosx => {
202 const rc = posix.readv(fd, iov, count);198 const rc = os.system.readv(fd, iov, count);
203 const err = posix.getErrno(rc);199 switch (os.errno(rc)) {
204 switch (err) {
205 0 => return rc,200 0 => return rc,
206 posix.EINTR => continue,201 os.EINTR => continue,
207 posix.EINVAL => unreachable,202 os.EINVAL => unreachable,
208 posix.EFAULT => unreachable,203 os.EFAULT => unreachable,
209 posix.EAGAIN => {204 os.EAGAIN => {
210 try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLIN) catch unreachable);205 try await (async loop.linuxWaitFd(fd, os.EPOLLET | os.EPOLLIN) catch unreachable);
211 continue;206 continue;
212 },207 },
213 posix.EBADF => unreachable, // always a race condition208 os.EBADF => unreachable, // always a race condition
214 posix.EIO => return error.InputOutput,209 os.EIO => return error.InputOutput,
215 posix.EISDIR => unreachable,210 os.EISDIR => unreachable,
216 posix.ENOBUFS => return error.SystemResources,211 os.ENOBUFS => return error.SystemResources,
217 posix.ENOMEM => return error.SystemResources,212 os.ENOMEM => return error.SystemResources,
218 else => return os.unexpectedErrorPosix(err),213 else => |err| return os.unexpectedErrno(err),
219 }214 }
220 },215 },
221 else => @compileError("Unsupported OS"),216 else => @compileError("Unsupported OS"),
...@@ -224,11 +219,11 @@ pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, cou...@@ -224,11 +219,11 @@ pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, cou
224}219}
225220
226pub async fn writev(loop: *Loop, fd: fd_t, data: []const []const u8) !void {221pub async fn writev(loop: *Loop, fd: fd_t, data: []const []const u8) !void {
227 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);222 const iovecs = try loop.allocator.alloc(os.iovec_const, data.len);
228 defer loop.allocator.free(iovecs);223 defer loop.allocator.free(iovecs);
229224
230 for (data) |buf, i| {225 for (data) |buf, i| {
231 iovecs[i] = os.posix.iovec_const{226 iovecs[i] = os.iovec_const{
232 .iov_base = buf.ptr,227 .iov_base = buf.ptr,
233 .iov_len = buf.len,228 .iov_len = buf.len,
234 };229 };
...@@ -238,11 +233,11 @@ pub async fn writev(loop: *Loop, fd: fd_t, data: []const []const u8) !void {...@@ -238,11 +233,11 @@ pub async fn writev(loop: *Loop, fd: fd_t, data: []const []const u8) !void {
238}233}
239234
240pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {235pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {
241 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);236 const iovecs = try loop.allocator.alloc(os.iovec, data.len);
242 defer loop.allocator.free(iovecs);237 defer loop.allocator.free(iovecs);
243238
244 for (data) |buf, i| {239 for (data) |buf, i| {
245 iovecs[i] = os.posix.iovec{240 iovecs[i] = os.iovec{
246 .iov_base = buf.ptr,241 .iov_base = buf.ptr,
247 .iov_len = buf.len,242 .iov_len = buf.len,
248 };243 };
...@@ -254,11 +249,11 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {...@@ -254,11 +249,11 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {
254pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File {249pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File {
255 var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592250 var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592
256251
257 const sockfd = try os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);252 const sockfd = try os.posixSocket(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, os.PROTO_tcp);
258 errdefer os.close(sockfd);253 errdefer os.close(sockfd);
259254
260 try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(posix.sockaddr_in));255 try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(os.sockaddr_in));
261 try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);256 try await try async loop.linuxWaitFd(sockfd, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
262 try os.posixGetSockOptConnectError(sockfd);257 try os.posixGetSockOptConnectError(sockfd);
263258
264 return File.openHandle(sockfd);259 return File.openHandle(sockfd);
std/fs/path.zig+17-20
...@@ -9,24 +9,21 @@ const fmt = std.fmt;...@@ -9,24 +9,21 @@ const fmt = std.fmt;
9const Allocator = mem.Allocator;9const Allocator = mem.Allocator;
10const os = std.os;10const os = std.os;
11const math = std.math;11const math = std.math;
12const posix = os.posix;
13const windows = os.windows;12const windows = os.windows;
14const cstr = std.cstr;13const cstr = std.cstr;
1514
16pub const sep_windows = '\\';15pub const sep_windows = '\\';
17pub const sep_posix = '/';16pub const sep_posix = '/';
18pub const sep = if (is_windows) sep_windows else sep_posix;17pub const sep = if (windows.is_the_target) sep_windows else sep_posix;
1918
20pub const sep_str = [1]u8{sep};19pub const sep_str = [1]u8{sep};
2120
22pub const delimiter_windows = ';';21pub const delimiter_windows = ';';
23pub const delimiter_posix = ':';22pub const delimiter_posix = ':';
24pub const delimiter = if (is_windows) delimiter_windows else delimiter_posix;23pub const delimiter = if (windows.is_the_target) delimiter_windows else delimiter_posix;
25
26const is_windows = builtin.os == builtin.Os.windows;
2724
28pub fn isSep(byte: u8) bool {25pub fn isSep(byte: u8) bool {
29 if (is_windows) {26 if (windows.is_the_target) {
30 return byte == '/' or byte == '\\';27 return byte == '/' or byte == '\\';
31 } else {28 } else {
32 return byte == '/';29 return byte == '/';
...@@ -76,7 +73,7 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u...@@ -76,7 +73,7 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u
76 return buf;73 return buf;
77}74}
7875
79pub const join = if (is_windows) joinWindows else joinPosix;76pub const join = if (windows.is_the_target) joinWindows else joinPosix;
8077
81/// Naively combines a series of paths with the native path seperator.78/// Naively combines a series of paths with the native path seperator.
82/// Allocates memory for the result, which must be freed by the caller.79/// Allocates memory for the result, which must be freed by the caller.
...@@ -133,7 +130,7 @@ test "join" {...@@ -133,7 +130,7 @@ test "join" {
133}130}
134131
135pub fn isAbsolute(path: []const u8) bool {132pub fn isAbsolute(path: []const u8) bool {
136 if (is_windows) {133 if (windows.is_the_target) {
137 return isAbsoluteWindows(path);134 return isAbsoluteWindows(path);
138 } else {135 } else {
139 return isAbsolutePosix(path);136 return isAbsolutePosix(path);
...@@ -312,7 +309,7 @@ test "windowsParsePath" {...@@ -312,7 +309,7 @@ test "windowsParsePath" {
312}309}
313310
314pub fn diskDesignator(path: []const u8) []const u8 {311pub fn diskDesignator(path: []const u8) []const u8 {
315 if (is_windows) {312 if (windows.is_the_target) {
316 return diskDesignatorWindows(path);313 return diskDesignatorWindows(path);
317 } else {314 } else {
318 return "";315 return "";
...@@ -377,7 +374,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {...@@ -377,7 +374,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {
377374
378/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.375/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
379pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {376pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
380 if (is_windows) {377 if (windows.is_the_target) {
381 return resolveWindows(allocator, paths);378 return resolveWindows(allocator, paths);
382 } else {379 } else {
383 return resolvePosix(allocator, paths);380 return resolvePosix(allocator, paths);
...@@ -394,7 +391,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -394,7 +391,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
394/// Without performing actual syscalls, resolving `..` could be incorrect.391/// Without performing actual syscalls, resolving `..` could be incorrect.
395pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {392pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
396 if (paths.len == 0) {393 if (paths.len == 0) {
397 assert(is_windows); // resolveWindows called on non windows can't use getCwd394 assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
398 return os.getCwdAlloc(allocator);395 return os.getCwdAlloc(allocator);
399 }396 }
400397
...@@ -489,7 +486,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -489,7 +486,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
489 result_disk_designator = result[0..result_index];486 result_disk_designator = result[0..result_index];
490 },487 },
491 WindowsPath.Kind.None => {488 WindowsPath.Kind.None => {
492 assert(is_windows); // resolveWindows called on non windows can't use getCwd489 assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
493 const cwd = try os.getCwdAlloc(allocator);490 const cwd = try os.getCwdAlloc(allocator);
494 defer allocator.free(cwd);491 defer allocator.free(cwd);
495 const parsed_cwd = windowsParsePath(cwd);492 const parsed_cwd = windowsParsePath(cwd);
...@@ -504,7 +501,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -504,7 +501,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
504 },501 },
505 }502 }
506 } else {503 } else {
507 assert(is_windows); // resolveWindows called on non windows can't use getCwd504 assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
508 // TODO call get cwd for the result_disk_designator instead of the global one505 // TODO call get cwd for the result_disk_designator instead of the global one
509 const cwd = try os.getCwdAlloc(allocator);506 const cwd = try os.getCwdAlloc(allocator);
510 defer allocator.free(cwd);507 defer allocator.free(cwd);
...@@ -575,7 +572,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -575,7 +572,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
575/// Without performing actual syscalls, resolving `..` could be incorrect.572/// Without performing actual syscalls, resolving `..` could be incorrect.
576pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {573pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
577 if (paths.len == 0) {574 if (paths.len == 0) {
578 assert(!is_windows); // resolvePosix called on windows can't use getCwd575 assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd
579 return os.getCwdAlloc(allocator);576 return os.getCwdAlloc(allocator);
580 }577 }
581578
...@@ -597,7 +594,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -597,7 +594,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
597 if (have_abs) {594 if (have_abs) {
598 result = try allocator.alloc(u8, max_size);595 result = try allocator.alloc(u8, max_size);
599 } else {596 } else {
600 assert(!is_windows); // resolvePosix called on windows can't use getCwd597 assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd
601 const cwd = try os.getCwdAlloc(allocator);598 const cwd = try os.getCwdAlloc(allocator);
602 defer allocator.free(cwd);599 defer allocator.free(cwd);
603 result = try allocator.alloc(u8, max_size + cwd.len + 1);600 result = try allocator.alloc(u8, max_size + cwd.len + 1);
...@@ -638,7 +635,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -638,7 +635,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
638635
639test "resolve" {636test "resolve" {
640 const cwd = try os.getCwdAlloc(debug.global_allocator);637 const cwd = try os.getCwdAlloc(debug.global_allocator);
641 if (is_windows) {638 if (windows.is_the_target) {
642 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {639 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
643 cwd[0] = asciiUpper(cwd[0]);640 cwd[0] = asciiUpper(cwd[0]);
644 }641 }
...@@ -650,7 +647,7 @@ test "resolve" {...@@ -650,7 +647,7 @@ test "resolve" {
650}647}
651648
652test "resolveWindows" {649test "resolveWindows" {
653 if (is_windows) {650 if (windows.is_the_target) {
654 const cwd = try os.getCwdAlloc(debug.global_allocator);651 const cwd = try os.getCwdAlloc(debug.global_allocator);
655 const parsed_cwd = windowsParsePath(cwd);652 const parsed_cwd = windowsParsePath(cwd);
656 {653 {
...@@ -716,7 +713,7 @@ fn testResolvePosix(paths: []const []const u8) []u8 {...@@ -716,7 +713,7 @@ fn testResolvePosix(paths: []const []const u8) []u8 {
716/// If the path is a file in the current directory (no directory component)713/// If the path is a file in the current directory (no directory component)
717/// then returns null714/// then returns null
718pub fn dirname(path: []const u8) ?[]const u8 {715pub fn dirname(path: []const u8) ?[]const u8 {
719 if (is_windows) {716 if (windows.is_the_target) {
720 return dirnameWindows(path);717 return dirnameWindows(path);
721 } else {718 } else {
722 return dirnamePosix(path);719 return dirnamePosix(path);
...@@ -848,7 +845,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {...@@ -848,7 +845,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {
848}845}
849846
850pub fn basename(path: []const u8) []const u8 {847pub fn basename(path: []const u8) []const u8 {
851 if (is_windows) {848 if (windows.is_the_target) {
852 return basenameWindows(path);849 return basenameWindows(path);
853 } else {850 } else {
854 return basenamePosix(path);851 return basenamePosix(path);
...@@ -964,7 +961,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {...@@ -964,7 +961,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {
964/// string is returned.961/// string is returned.
965/// On Windows this canonicalizes the drive to a capital letter and paths to `\\`.962/// On Windows this canonicalizes the drive to a capital letter and paths to `\\`.
966pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {963pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {
967 if (is_windows) {964 if (windows.is_the_target) {
968 return relativeWindows(allocator, from, to);965 return relativeWindows(allocator, from, to);
969 } else {966 } else {
970 return relativePosix(allocator, from, to);967 return relativePosix(allocator, from, to);
std/heap.zig+156-168
...@@ -5,7 +5,6 @@ const testing = std.testing;...@@ -5,7 +5,6 @@ const testing = std.testing;
5const mem = std.mem;5const mem = std.mem;
6const os = std.os;6const os = std.os;
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const Os = builtin.Os;
9const c = std.c;8const c = std.c;
10const maxInt = std.math.maxInt;9const maxInt = std.math.maxInt;
1110
...@@ -51,201 +50,190 @@ pub const DirectAllocator = struct {...@@ -51,201 +50,190 @@ pub const DirectAllocator = struct {
51 if (n == 0)50 if (n == 0)
52 return (([*]u8)(undefined))[0..0];51 return (([*]u8)(undefined))[0..0];
5352
54 switch (builtin.os) {53 if (os.windows.is_the_target) {
55 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {54 const w = os.windows;
56 const p = os.posix;55
57 const alloc_size = if (alignment <= os.page_size) n else n + alignment;56 // Although officially it's at least aligned to page boundary,
58 const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0);57 // Windows is known to reserve pages on a 64K boundary. It's
59 if (addr == p.MAP_FAILED) return error.OutOfMemory;58 // even more likely that the requested alignment is <= 64K than
60 if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];59 // 4K, so we're just allocating blindly and hoping for the best.
6160 // see https://devblogs.microsoft.com/oldnewthing/?p=42223
62 const aligned_addr = mem.alignForward(addr, alignment);61 const addr = w.VirtualAlloc(
6362 null,
64 // Unmap the extra bytes that were only requested in order to guarantee63 n,
65 // that the range of memory we were provided had a proper alignment in64 w.MEM_COMMIT | w.MEM_RESERVE,
66 // it somewhere. The extra bytes could be at the beginning, or end, or both.65 w.PAGE_READWRITE,
67 const unused_start_len = aligned_addr - addr;66 ) catch return error.OutOfMemory;
68 if (unused_start_len != 0) {67
69 const err = p.munmap(addr, unused_start_len);68 // If the allocation is sufficiently aligned, use it.
70 assert(p.getErrno(err) == 0);69 if (@ptrToInt(addr) & (alignment - 1) == 0) {
71 }70 return @ptrCast([*]u8, addr)[0..n];
72 const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size);71 }
73 const unused_end_len = addr + alloc_size - aligned_end_addr;
74 if (unused_end_len != 0) {
75 const err = p.munmap(aligned_end_addr, unused_end_len);
76 assert(p.getErrno(err) == 0);
77 }
7872
79 return @intToPtr([*]u8, aligned_addr)[0..n];73 // If it wasn't, actually do an explicitely aligned allocation.
80 },74 w.VirtualFree(addr, 0, w.MEM_RELEASE);
81 .windows => {75 const alloc_size = n + alignment;
82 const w = os.windows;76
8377 const final_addr = while (true) {
84 // Although officially it's at least aligned to page boundary,78 // Reserve a range of memory large enough to find a sufficiently
85 // Windows is known to reserve pages on a 64K boundary. It's79 // aligned address.
86 // even more likely that the requested alignment is <= 64K than80 const reserved_addr = w.VirtualAlloc(
87 // 4K, so we're just allocating blindly and hoping for the best.
88 // see https://devblogs.microsoft.com/oldnewthing/?p=42223
89 const addr = w.VirtualAlloc(
90 null,81 null,
82 alloc_size,
83 w.MEM_RESERVE,
84 w.PAGE_NOACCESS,
85 ) catch return error.OutOfMemory;
86 const aligned_addr = mem.alignForward(@ptrToInt(reserved_addr), alignment);
87
88 // Release the reserved pages (not actually used).
89 w.VirtualFree(reserved_addr, 0, w.MEM_RELEASE);
90
91 // At this point, it is possible that another thread has
92 // obtained some memory space that will cause the next
93 // VirtualAlloc call to fail. To handle this, we will retry
94 // until it succeeds.
95 return w.VirtualAlloc(
96 @intToPtr(*c_void, aligned_addr),
91 n,97 n,
92 w.MEM_COMMIT | w.MEM_RESERVE,98 w.MEM_COMMIT | w.MEM_RESERVE,
93 w.PAGE_READWRITE,99 w.PAGE_READWRITE,
94 ) orelse return error.OutOfMemory;100 ) catch continue;
101 };
95102
96 // If the allocation is sufficiently aligned, use it.103 return @ptrCast([*]u8, final_addr)[0..n];
97 if (@ptrToInt(addr) & (alignment - 1) == 0) {104 }
98 return @ptrCast([*]u8, addr)[0..n];
99 }
100105
101 // If it wasn't, actually do an explicitely aligned allocation.106 const alloc_size = if (alignment <= os.page_size) n else n + alignment;
102 if (w.VirtualFree(addr, 0, w.MEM_RELEASE) == 0) unreachable;107 const addr = os.mmap(
103 const alloc_size = n + alignment;108 null,
104109 alloc_size,
105 const final_addr = while (true) {110 os.PROT_READ | os.PROT_WRITE,
106 // Reserve a range of memory large enough to find a sufficiently111 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
107 // aligned address.112 -1,
108 const reserved_addr = w.VirtualAlloc(113 0,
109 null,114 ) catch return error.OutOfMemory;
110 alloc_size,115 if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];
111 w.MEM_RESERVE,116
112 w.PAGE_NOACCESS,117 const aligned_addr = mem.alignForward(addr, alignment);
113 ) orelse return error.OutOfMemory;118
114 const aligned_addr = mem.alignForward(@ptrToInt(reserved_addr), alignment);119 // Unmap the extra bytes that were only requested in order to guarantee
115120 // that the range of memory we were provided had a proper alignment in
116 // Release the reserved pages (not actually used).121 // it somewhere. The extra bytes could be at the beginning, or end, or both.
117 if (w.VirtualFree(reserved_addr, 0, w.MEM_RELEASE) == 0) unreachable;122 const unused_start_len = aligned_addr - addr;
118123 if (unused_start_len != 0) {
119 // At this point, it is possible that another thread has124 os.munmap(addr, unused_start_len);
120 // obtained some memory space that will cause the next125 }
121 // VirtualAlloc call to fail. To handle this, we will retry126 const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size);
122 // until it succeeds.127 const unused_end_len = addr + alloc_size - aligned_end_addr;
123 if (w.VirtualAlloc(128 if (unused_end_len != 0) {
124 @intToPtr(*c_void, aligned_addr),129 os.munmap(aligned_end_addr, unused_end_len);
125 n,
126 w.MEM_COMMIT | w.MEM_RESERVE,
127 w.PAGE_READWRITE,
128 )) |ptr| break ptr;
129 } else unreachable; // TODO else unreachable should not be necessary
130
131 return @ptrCast([*]u8, final_addr)[0..n];
132 },
133 else => @compileError("Unsupported OS"),
134 }130 }
131
132 return @intToPtr([*]u8, aligned_addr)[0..n];
135 }133 }
136134
137 fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {135 fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
138 switch (builtin.os) {136 if (os.windows.is_the_target) {
139 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {137 const w = os.windows;
138 if (new_size == 0) {
139 // From the docs:
140 // "If the dwFreeType parameter is MEM_RELEASE, this parameter
141 // must be 0 (zero). The function frees the entire region that
142 // is reserved in the initial allocation call to VirtualAlloc."
143 // So we can only use MEM_RELEASE when actually releasing the
144 // whole allocation.
145 w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE);
146 } else {
140 const base_addr = @ptrToInt(old_mem.ptr);147 const base_addr = @ptrToInt(old_mem.ptr);
141 const old_addr_end = base_addr + old_mem.len;148 const old_addr_end = base_addr + old_mem.len;
142 const new_addr_end = base_addr + new_size;149 const new_addr_end = base_addr + new_size;
143 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);150 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
144 if (old_addr_end > new_addr_end_rounded) {151 if (old_addr_end > new_addr_end_rounded) {
145 _ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);152 // For shrinking that is not releasing, we will only
146 }153 // decommit the pages not needed anymore.
147 return old_mem[0..new_size];154 w.VirtualFree(
148 },155 @intToPtr(*c_void, new_addr_end_rounded),
149 .windows => {156 old_addr_end - new_addr_end_rounded,
150 const w = os.windows;157 w.MEM_DECOMMIT,
151 if (new_size == 0) {158 );
152 // From the docs:
153 // "If the dwFreeType parameter is MEM_RELEASE, this parameter
154 // must be 0 (zero). The function frees the entire region that
155 // is reserved in the initial allocation call to VirtualAlloc."
156 // So we can only use MEM_RELEASE when actually releasing the
157 // whole allocation.
158 if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
159 } else {
160 const base_addr = @ptrToInt(old_mem.ptr);
161 const old_addr_end = base_addr + old_mem.len;
162 const new_addr_end = base_addr + new_size;
163 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
164 if (old_addr_end > new_addr_end_rounded) {
165 // For shrinking that is not releasing, we will only
166 // decommit the pages not needed anymore.
167 if (w.VirtualFree(
168 @intToPtr(*c_void, new_addr_end_rounded),
169 old_addr_end - new_addr_end_rounded,
170 w.MEM_DECOMMIT,
171 ) == 0) unreachable;
172 }
173 }159 }
174 return old_mem[0..new_size];160 }
175 },161 return old_mem[0..new_size];
176 else => @compileError("Unsupported OS"),
177 }162 }
163 const base_addr = @ptrToInt(old_mem.ptr);
164 const old_addr_end = base_addr + old_mem.len;
165 const new_addr_end = base_addr + new_size;
166 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
167 if (old_addr_end > new_addr_end_rounded) {
168 os.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);
169 }
170 return old_mem[0..new_size];
178 }171 }
179172
180 fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {173 fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
181 switch (builtin.os) {174 if (os.windows.is_the_target) {
182 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {175 if (old_mem.len == 0) {
183 if (new_size <= old_mem.len and new_align <= old_align) {176 return alloc(allocator, new_size, new_align);
184 return shrink(allocator, old_mem, old_align, new_size, new_align);177 }
185 }
186 const result = try alloc(allocator, new_size, new_align);
187 if (old_mem.len != 0) {
188 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
189 _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
190 }
191 return result;
192 },
193 .windows => {
194 if (old_mem.len == 0) {
195 return alloc(allocator, new_size, new_align);
196 }
197
198 if (new_size <= old_mem.len and new_align <= old_align) {
199 return shrink(allocator, old_mem, old_align, new_size, new_align);
200 }
201
202 const w = os.windows;
203 const base_addr = @ptrToInt(old_mem.ptr);
204178
205 if (new_align > old_align and base_addr & (new_align - 1) != 0) {179 if (new_size <= old_mem.len and new_align <= old_align) {
206 // Current allocation doesn't satisfy the new alignment.180 return shrink(allocator, old_mem, old_align, new_size, new_align);
207 // For now we'll do a new one no matter what, but maybe181 }
208 // there is something smarter to do instead.
209 const result = try alloc(allocator, new_size, new_align);
210 assert(old_mem.len != 0);
211 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
212 if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
213182
214 return result;183 const w = os.windows;
215 }184 const base_addr = @ptrToInt(old_mem.ptr);
216185
217 const old_addr_end = base_addr + old_mem.len;186 if (new_align > old_align and base_addr & (new_align - 1) != 0) {
218 const old_addr_end_rounded = mem.alignForward(old_addr_end, os.page_size);187 // Current allocation doesn't satisfy the new alignment.
219 const new_addr_end = base_addr + new_size;188 // For now we'll do a new one no matter what, but maybe
220 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);189 // there is something smarter to do instead.
221 if (new_addr_end_rounded == old_addr_end_rounded) {190 const result = try alloc(allocator, new_size, new_align);
222 // The reallocation fits in the already allocated pages.191 assert(old_mem.len != 0);
223 return @ptrCast([*]u8, old_mem.ptr)[0..new_size];192 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
224 }193 w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE);
225 assert(new_addr_end_rounded > old_addr_end_rounded);
226194
227 // We need to commit new pages.195 return result;
228 const additional_size = new_addr_end - old_addr_end_rounded;196 }
229 const realloc_addr = w.VirtualAlloc(
230 @intToPtr(*c_void, old_addr_end_rounded),
231 additional_size,
232 w.MEM_COMMIT | w.MEM_RESERVE,
233 w.PAGE_READWRITE,
234 ) orelse {
235 // Committing new pages at the end of the existing allocation
236 // failed, we need to try a new one.
237 const new_alloc_mem = try alloc(allocator, new_size, new_align);
238 @memcpy(new_alloc_mem.ptr, old_mem.ptr, old_mem.len);
239 if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable;
240
241 return new_alloc_mem;
242 };
243197
244 assert(@ptrToInt(realloc_addr) == old_addr_end_rounded);198 const old_addr_end = base_addr + old_mem.len;
199 const old_addr_end_rounded = mem.alignForward(old_addr_end, os.page_size);
200 const new_addr_end = base_addr + new_size;
201 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
202 if (new_addr_end_rounded == old_addr_end_rounded) {
203 // The reallocation fits in the already allocated pages.
245 return @ptrCast([*]u8, old_mem.ptr)[0..new_size];204 return @ptrCast([*]u8, old_mem.ptr)[0..new_size];
246 },205 }
247 else => @compileError("Unsupported OS"),206 assert(new_addr_end_rounded > old_addr_end_rounded);
207
208 // We need to commit new pages.
209 const additional_size = new_addr_end - old_addr_end_rounded;
210 const realloc_addr = w.kernel32.VirtualAlloc(
211 @intToPtr(*c_void, old_addr_end_rounded),
212 additional_size,
213 w.MEM_COMMIT | w.MEM_RESERVE,
214 w.PAGE_READWRITE,
215 ) orelse {
216 // Committing new pages at the end of the existing allocation
217 // failed, we need to try a new one.
218 const new_alloc_mem = try alloc(allocator, new_size, new_align);
219 @memcpy(new_alloc_mem.ptr, old_mem.ptr, old_mem.len);
220 w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE);
221
222 return new_alloc_mem;
223 };
224
225 assert(@ptrToInt(realloc_addr) == old_addr_end_rounded);
226 return @ptrCast([*]u8, old_mem.ptr)[0..new_size];
227 }
228 if (new_size <= old_mem.len and new_align <= old_align) {
229 return shrink(allocator, old_mem, old_align, new_size, new_align);
248 }230 }
231 const result = try alloc(allocator, new_size, new_align);
232 if (old_mem.len != 0) {
233 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
234 os.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
235 }
236 return result;
249 }237 }
250};238};
251239
std/mem.zig+3-3
...@@ -1466,17 +1466,17 @@ test "std.mem.alignForward" {...@@ -1466,17 +1466,17 @@ test "std.mem.alignForward" {
1466pub fn getBaseAddress() usize {1466pub fn getBaseAddress() usize {
1467 switch (builtin.os) {1467 switch (builtin.os) {
1468 .linux => {1468 .linux => {
1469 const base = std.os.posix.getauxval(std.elf.AT_BASE);1469 const base = std.os.system.getauxval(std.elf.AT_BASE);
1470 if (base != 0) {1470 if (base != 0) {
1471 return base;1471 return base;
1472 }1472 }
1473 const phdr = std.os.posix.getauxval(std.elf.AT_PHDR);1473 const phdr = std.os.system.getauxval(std.elf.AT_PHDR);
1474 return phdr - @sizeOf(std.elf.Ehdr);1474 return phdr - @sizeOf(std.elf.Ehdr);
1475 },1475 },
1476 .macosx, .freebsd, .netbsd => {1476 .macosx, .freebsd, .netbsd => {
1477 return @ptrToInt(&std.c._mh_execute_header);1477 return @ptrToInt(&std.c._mh_execute_header);
1478 },1478 },
1479 .windows => return @ptrToInt(windows.GetModuleHandleW(null)),1479 .windows => return @ptrToInt(windows.kernel32.GetModuleHandleW(null)),
1480 else => @compileError("Unsupported OS"),1480 else => @compileError("Unsupported OS"),
1481 }1481 }
1482}1482}
std/mutex.zig+2-2
...@@ -152,9 +152,9 @@ test "std.Mutex" {...@@ -152,9 +152,9 @@ test "std.Mutex" {
152 testing.expect(context.data == TestContext.incr_count);152 testing.expect(context.data == TestContext.incr_count);
153 } else {153 } else {
154 const thread_count = 10;154 const thread_count = 10;
155 var threads: [thread_count]*std.os.Thread = undefined;155 var threads: [thread_count]*std.Thread = undefined;
156 for (threads) |*t| {156 for (threads) |*t| {
157 t.* = try std.os.spawnThread(&context, worker);157 t.* = try std.Thread.spawn(&context, worker);
158 }158 }
159 for (threads) |t|159 for (threads) |t|
160 t.wait();160 t.wait();
std/net.zig+12-12
...@@ -2,8 +2,8 @@ const std = @import("std.zig");...@@ -2,8 +2,8 @@ const std = @import("std.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const net = @This();4const net = @This();
5const posix = std.os.posix;
6const mem = std.mem;5const mem = std.mem;
6const os = std.os;
77
8pub const TmpWinAddr = struct {8pub const TmpWinAddr = struct {
9 family: u8,9 family: u8,
...@@ -12,7 +12,7 @@ pub const TmpWinAddr = struct {...@@ -12,7 +12,7 @@ pub const TmpWinAddr = struct {
1212
13pub const OsAddress = switch (builtin.os) {13pub const OsAddress = switch (builtin.os) {
14 builtin.Os.windows => TmpWinAddr,14 builtin.Os.windows => TmpWinAddr,
15 else => posix.sockaddr,15 else => os.sockaddr,
16};16};
1717
18pub const Address = struct {18pub const Address = struct {
...@@ -20,9 +20,9 @@ pub const Address = struct {...@@ -20,9 +20,9 @@ pub const Address = struct {
2020
21 pub fn initIp4(ip4: u32, _port: u16) Address {21 pub fn initIp4(ip4: u32, _port: u16) Address {
22 return Address{22 return Address{
23 .os_addr = posix.sockaddr{23 .os_addr = os.sockaddr{
24 .in = posix.sockaddr_in{24 .in = os.sockaddr_in{
25 .family = posix.AF_INET,25 .family = os.AF_INET,
26 .port = mem.nativeToBig(u16, _port),26 .port = mem.nativeToBig(u16, _port),
27 .addr = ip4,27 .addr = ip4,
28 .zero = []u8{0} ** 8,28 .zero = []u8{0} ** 8,
...@@ -33,10 +33,10 @@ pub const Address = struct {...@@ -33,10 +33,10 @@ pub const Address = struct {
3333
34 pub fn initIp6(ip6: *const Ip6Addr, _port: u16) Address {34 pub fn initIp6(ip6: *const Ip6Addr, _port: u16) Address {
35 return Address{35 return Address{
36 .family = posix.AF_INET6,36 .family = os.AF_INET6,
37 .os_addr = posix.sockaddr{37 .os_addr = os.sockaddr{
38 .in6 = posix.sockaddr_in6{38 .in6 = os.sockaddr_in6{
39 .family = posix.AF_INET6,39 .family = os.AF_INET6,
40 .port = mem.nativeToBig(u16, _port),40 .port = mem.nativeToBig(u16, _port),
41 .flowinfo = 0,41 .flowinfo = 0,
42 .addr = ip6.addr,42 .addr = ip6.addr,
...@@ -50,18 +50,18 @@ pub const Address = struct {...@@ -50,18 +50,18 @@ pub const Address = struct {
50 return mem.bigToNative(u16, self.os_addr.in.port);50 return mem.bigToNative(u16, self.os_addr.in.port);
51 }51 }
5252
53 pub fn initPosix(addr: posix.sockaddr) Address {53 pub fn initPosix(addr: os.sockaddr) Address {
54 return Address{ .os_addr = addr };54 return Address{ .os_addr = addr };
55 }55 }
5656
57 pub fn format(self: *const Address, out_stream: var) !void {57 pub fn format(self: *const Address, out_stream: var) !void {
58 switch (self.os_addr.in.family) {58 switch (self.os_addr.in.family) {
59 posix.AF_INET => {59 os.AF_INET => {
60 const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port);60 const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port);
61 const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);61 const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
62 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);62 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
63 },63 },
64 posix.AF_INET6 => {64 os.AF_INET6 => {
65 const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port);65 const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port);
66 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);66 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
67 },67 },
std/os.zig+19-16
...@@ -164,7 +164,7 @@ pub fn raise(sig: u8) RaiseError!void {...@@ -164,7 +164,7 @@ pub fn raise(sig: u8) RaiseError!void {
164 }164 }
165165
166 if (windows.is_the_target) {166 if (windows.is_the_target) {
167 @compileError("TODO implement std.posix.raise for Windows");167 @compileError("TODO implement std.os.raise for Windows");
168 }168 }
169169
170 var set: system.sigset_t = undefined;170 var set: system.sigset_t = undefined;
...@@ -690,20 +690,6 @@ pub fn getenvC(key: [*]const u8) ?[]const u8 {...@@ -690,20 +690,6 @@ pub fn getenvC(key: [*]const u8) ?[]const u8 {
690 return getenv(mem.toSliceConst(u8, key));690 return getenv(mem.toSliceConst(u8, key));
691}691}
692692
693/// See std.elf for the constants.
694pub fn getauxval(index: usize) usize {
695 if (builtin.link_libc) {
696 return usize(system.getauxval(index));
697 } else if (linux.elf_aux_maybe) |auxv| {
698 var i: usize = 0;
699 while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
700 if (auxv[i].a_type == index)
701 return auxv[i].a_un.a_val;
702 }
703 }
704 return 0;
705}
706
707pub const GetCwdError = error{693pub const GetCwdError = error{
708 NameTooLong,694 NameTooLong,
709 CurrentWorkingDirectoryUnlinked,695 CurrentWorkingDirectoryUnlinked,
...@@ -1198,7 +1184,7 @@ pub fn isatty(handle: fd_t) bool {...@@ -1198,7 +1184,7 @@ pub fn isatty(handle: fd_t) bool {
1198 return windows.kernel32.GetConsoleMode(handle, &out) != 0;1184 return windows.kernel32.GetConsoleMode(handle, &out) != 0;
1199 }1185 }
1200 if (wasi.is_the_target) {1186 if (wasi.is_the_target) {
1201 @compileError("TODO implement std.os.posix.isatty for WASI");1187 @compileError("TODO implement std.os.isatty for WASI");
1202 }1188 }
1203 if (linux.is_the_target) {1189 if (linux.is_the_target) {
1204 var wsz: system.winsize = undefined;1190 var wsz: system.winsize = undefined;
...@@ -2365,6 +2351,23 @@ pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {...@@ -2365,6 +2351,23 @@ pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
2365 }2351 }
2366}2352}
23672353
2354pub const SchedGetAffinityError = error{
2355 PermissionDenied,
2356 Unexpected,
2357};
2358
2359pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {
2360 var set: cpu_set_t = undefined;
2361 switch (errno(system.sched_getaffinity(pid, &set))) {
2362 0 => return set,
2363 EFAULT => unreachable,
2364 EINVAL => unreachable,
2365 ESRCH => unreachable,
2366 EPERM => return error.PermissionDenied,
2367 else => |err| return unexpectedErrno(err),
2368 }
2369}
2370
2368/// Used to convert a slice to a null terminated slice on the stack.2371/// Used to convert a slice to a null terminated slice on the stack.
2369/// TODO https://github.com/ziglang/zig/issues/2872372/// TODO https://github.com/ziglang/zig/issues/287
2370pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {2373pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {
std/os/bits/linux.zig+25
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1const std = @import("../../std.zig");
2
1pub use @import("linux/errno.zig");3pub use @import("linux/errno.zig");
2pub use switch (builtin.arch) {4pub use switch (builtin.arch) {
3 .x86_64 => @import("linux/x86_64.zig"),5 .x86_64 => @import("linux/x86_64.zig"),
...@@ -907,3 +909,26 @@ pub const pthread_attr_t = extern struct {...@@ -907,3 +909,26 @@ pub const pthread_attr_t = extern struct {
907 __size: [56]u8,909 __size: [56]u8,
908 __align: c_long,910 __align: c_long,
909};911};
912
913pub const CPU_SETSIZE = 128;
914pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize;
915pub const cpu_count_t = @IntType(false, std.math.log2(CPU_SETSIZE * 8));
916
917pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
918 var sum: cpu_count_t = 0;
919 for (set) |x| {
920 sum += @popCount(usize, x);
921 }
922 return sum;
923}
924
925// TODO port these over
926//#define CPU_SET(i, set) CPU_SET_S(i,sizeof(cpu_set_t),set)
927//#define CPU_CLR(i, set) CPU_CLR_S(i,sizeof(cpu_set_t),set)
928//#define CPU_ISSET(i, set) CPU_ISSET_S(i,sizeof(cpu_set_t),set)
929//#define CPU_AND(d,s1,s2) CPU_AND_S(sizeof(cpu_set_t),d,s1,s2)
930//#define CPU_OR(d,s1,s2) CPU_OR_S(sizeof(cpu_set_t),d,s1,s2)
931//#define CPU_XOR(d,s1,s2) CPU_XOR_S(sizeof(cpu_set_t),d,s1,s2)
932//#define CPU_COUNT(set) CPU_COUNT_S(sizeof(cpu_set_t),set)
933//#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t),set)
934//#define CPU_EQUAL(s1,s2) CPU_EQUAL_S(sizeof(cpu_set_t),s1,s2)
std/os/linux.zig+872-2
...@@ -1,8 +1,878 @@...@@ -1,8 +1,878 @@
1// This file provides the system interface functions for Linux matching those
2// that are provided by libc, whether or not libc is linked. The following
3// abstractions are made:
4// * Work around kernel bugs and limitations. For example, see sendmmsg.
5// * Implement all the syscalls in the same way that libc functions will
6// provide `rename` when only the `renameat` syscall exists.
7// * Does not support POSIX thread cancellation.
1const std = @import("../std.zig");8const std = @import("../std.zig");
2const builtin = @import("builtin");9const builtin = @import("builtin");
10const assert = std.debug.assert;
11const maxInt = std.math.maxInt;
12const elf = std.elf;
13const vdso = @import("linux/vdso.zig");
14const dl = @import("../dynamic_library.zig");
15
3pub const is_the_target = builtin.os == .linux;16pub const is_the_target = builtin.os == .linux;
4pub const sys = @import("linux/sys.zig");17pub use switch (builtin.arch) {
5pub use if (builtin.link_libc) std.c else sys;18 .x86_64 => @import("linux/x86_64.zig"),
19 .aarch64 => @import("linux/arm64.zig"),
20 else => struct {},
21};
22pub use @import("bits.zig");
23
24/// Set by startup code, used by `getauxval`.
25pub var elf_aux_maybe: ?[*]std.elf.Auxv = null;
26
27/// See `std.elf` for the constants.
28pub fn getauxval(index: usize) usize {
29 const auxv = elf_aux_maybe orelse return 0;
30 var i: usize = 0;
31 while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
32 if (auxv[i].a_type == index)
33 return auxv[i].a_un.a_val;
34 }
35 return 0;
36}
37
38/// Get the errno from a syscall return value, or 0 for no error.
39pub fn getErrno(r: usize) u12 {
40 const signed_r = @bitCast(isize, r);
41 return if (signed_r > -4096 and signed_r < 0) @intCast(u12, -signed_r) else 0;
42}
43
44pub fn dup2(old: i32, new: i32) usize {
45 if (@hasDecl(@This(), "SYS_dup2")) {
46 return syscall2(SYS_dup2, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)));
47 } else {
48 if (old == new) {
49 if (std.debug.runtime_safety) {
50 const rc = syscall2(SYS_fcntl, @bitCast(usize, isize(old)), F_GETFD);
51 if (@bitCast(isize, rc) < 0) return rc;
52 }
53 return @intCast(usize, old);
54 } else {
55 return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), 0);
56 }
57 }
58}
59
60pub fn dup3(old: i32, new: i32, flags: u32) usize {
61 return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags);
62}
63
64// TODO https://github.com/ziglang/zig/issues/265
65pub fn chdir(path: [*]const u8) usize {
66 return syscall1(SYS_chdir, @ptrToInt(path));
67}
68
69// TODO https://github.com/ziglang/zig/issues/265
70pub fn chroot(path: [*]const u8) usize {
71 return syscall1(SYS_chroot, @ptrToInt(path));
72}
73
74// TODO https://github.com/ziglang/zig/issues/265
75pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
76 return syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));
77}
78
79pub fn fork() usize {
80 if (@hasDecl(@This(), "SYS_fork")) {
81 return syscall0(SYS_fork);
82 } else {
83 return syscall2(SYS_clone, SIGCHLD, 0);
84 }
85}
86
87/// This must be inline, and inline call the syscall function, because if the
88/// child does a return it will clobber the parent's stack.
89/// It is advised to avoid this function and use clone instead, because
90/// the compiler is not aware of how vfork affects control flow and you may
91/// see different results in optimized builds.
92pub inline fn vfork() usize {
93 return @inlineCall(syscall0, SYS_vfork);
94}
95
96pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize {
97 return syscall4(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val), @ptrToInt(timeout));
98}
99
100pub fn futex_wake(uaddr: *const i32, futex_op: u32, val: i32) usize {
101 return syscall3(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val));
102}
103
104pub fn getcwd(buf: [*]u8, size: usize) usize {
105 return syscall2(SYS_getcwd, @ptrToInt(buf), size);
106}
107
108pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
109 return syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
110}
111
112pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {
113 return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
114}
115
116pub fn inotify_init1(flags: u32) usize {
117 return syscall1(SYS_inotify_init1, flags);
118}
119
120pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize {
121 return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask);
122}
123
124pub fn inotify_rm_watch(fd: i32, wd: i32) usize {
125 return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd)));
126}
127
128// TODO https://github.com/ziglang/zig/issues/265
129pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
130 if (@hasDecl(@This(), "SYS_readlink")) {
131 return syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
132 } else {
133 return syscall4(SYS_readlinkat, AT_FDCWD, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
134 }
135}
136
137// TODO https://github.com/ziglang/zig/issues/265
138pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
139 return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
140}
141
142// TODO https://github.com/ziglang/zig/issues/265
143pub fn mkdir(path: [*]const u8, mode: u32) usize {
144 if (@hasDecl(@This(), "SYS_mkdir")) {
145 return syscall2(SYS_mkdir, @ptrToInt(path), mode);
146 } else {
147 return syscall3(SYS_mkdirat, AT_FDCWD, @ptrToInt(path), mode);
148 }
149}
150
151// TODO https://github.com/ziglang/zig/issues/265
152pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {
153 return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
154}
155
156// TODO https://github.com/ziglang/zig/issues/265
157pub fn mount(special: [*]const u8, dir: [*]const u8, fstype: [*]const u8, flags: u32, data: usize) usize {
158 return syscall5(SYS_mount, @ptrToInt(special), @ptrToInt(dir), @ptrToInt(fstype), flags, data);
159}
160
161// TODO https://github.com/ziglang/zig/issues/265
162pub fn umount(special: [*]const u8) usize {
163 return syscall2(SYS_umount2, @ptrToInt(special), 0);
164}
165
166// TODO https://github.com/ziglang/zig/issues/265
167pub fn umount2(special: [*]const u8, flags: u32) usize {
168 return syscall2(SYS_umount2, @ptrToInt(special), flags);
169}
170
171pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
172 return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
173}
174
175pub fn mprotect(address: usize, length: usize, protection: usize) usize {
176 return syscall3(SYS_mprotect, address, length, protection);
177}
178
179pub fn munmap(address: usize, length: usize) usize {
180 return syscall2(SYS_munmap, address, length);
181}
182
183pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
184 return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
185}
186
187pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
188 return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
189}
190
191pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
192 return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
193}
194
195pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
196 return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
197}
198
199pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {
200 return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
201}
202
203// TODO https://github.com/ziglang/zig/issues/265
204pub fn rmdir(path: [*]const u8) usize {
205 if (@hasDecl(@This(), "SYS_rmdir")) {
206 return syscall1(SYS_rmdir, @ptrToInt(path));
207 } else {
208 return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), AT_REMOVEDIR);
209 }
210}
211
212// TODO https://github.com/ziglang/zig/issues/265
213pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
214 if (@hasDecl(@This(), "SYS_symlink")) {
215 return syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
216 } else {
217 return syscall3(SYS_symlinkat, @ptrToInt(existing), AT_FDCWD, @ptrToInt(new));
218 }
219}
220
221// TODO https://github.com/ziglang/zig/issues/265
222pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
223 return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath));
224}
225
226// TODO https://github.com/ziglang/zig/issues/265
227pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
228 return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
229}
230
231// TODO https://github.com/ziglang/zig/issues/265
232pub fn access(path: [*]const u8, mode: u32) usize {
233 return syscall2(SYS_access, @ptrToInt(path), mode);
234}
235
236// TODO https://github.com/ziglang/zig/issues/265
237pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
238 return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
239}
240
241pub fn pipe(fd: *[2]i32) usize {
242 if (@hasDecl(@This(), "SYS_pipe")) {
243 return syscall1(SYS_pipe, @ptrToInt(fd));
244 } else {
245 return syscall2(SYS_pipe2, @ptrToInt(fd), 0);
246 }
247}
248
249pub fn pipe2(fd: *[2]i32, flags: u32) usize {
250 return syscall2(SYS_pipe2, @ptrToInt(fd), flags);
251}
252
253pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
254 return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
255}
256
257pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
258 return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
259}
260
261// TODO https://github.com/ziglang/zig/issues/265
262pub fn rename(old: [*]const u8, new: [*]const u8) usize {
263 if (@hasDecl(@This(), "SYS_rename")) {
264 return syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
265 } else if (@hasDecl(@This(), "SYS_renameat")) {
266 return syscall4(SYS_renameat, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new));
267 } else {
268 return syscall5(SYS_renameat2, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new), 0);
269 }
270}
271
272pub fn renameat(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
273 if (@hasDecl(@This(), "SYS_renameat")) {
274 return syscall4(
275 SYS_renameat,
276 @bitCast(usize, isize(oldfd)),
277 @ptrToInt(old),
278 @bitCast(usize, isize(newfd)),
279 @ptrToInt(new),
280 );
281 } else {
282 return syscall5(
283 SYS_renameat2,
284 @bitCast(usize, isize(oldfd)),
285 @ptrToInt(old),
286 @bitCast(usize, isize(newfd)),
287 @ptrToInt(new),
288 0,
289 );
290 }
291}
292
293// TODO https://github.com/ziglang/zig/issues/265
294pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {
295 return syscall5(
296 SYS_renameat2,
297 @bitCast(usize, isize(oldfd)),
298 @ptrToInt(oldpath),
299 @bitCast(usize, isize(newfd)),
300 @ptrToInt(newpath),
301 flags,
302 );
303}
304
305// TODO https://github.com/ziglang/zig/issues/265
306pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
307 return syscall3(SYS_open, @ptrToInt(path), flags, perm);
308}
309
310// TODO https://github.com/ziglang/zig/issues/265
311pub fn create(path: [*]const u8, perm: usize) usize {
312 return syscall2(SYS_creat, @ptrToInt(path), perm);
313}
314
315// TODO https://github.com/ziglang/zig/issues/265
316pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {
317 // dirfd could be negative, for example AT_FDCWD is -100
318 return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode);
319}
320
321/// See also `clone` (from the arch-specific include)
322pub fn clone5(flags: usize, child_stack_ptr: usize, parent_tid: *i32, child_tid: *i32, newtls: usize) usize {
323 return syscall5(SYS_clone, flags, child_stack_ptr, @ptrToInt(parent_tid), @ptrToInt(child_tid), newtls);
324}
325
326/// See also `clone` (from the arch-specific include)
327pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
328 return syscall2(SYS_clone, flags, child_stack_ptr);
329}
330
331pub fn close(fd: i32) usize {
332 return syscall1(SYS_close, @bitCast(usize, isize(fd)));
333}
334
335/// Can only be called on 32 bit systems. For 64 bit see `lseek`.
336pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize {
337 return syscall5(
338 SYS__llseek,
339 @bitCast(usize, isize(fd)),
340 @truncate(usize, offset >> 32),
341 @truncate(usize, offset),
342 @ptrToInt(result),
343 whence,
344 );
345}
346
347/// Can only be called on 64 bit systems. For 32 bit see `llseek`.
348pub fn lseek(fd: i32, offset: i64, whence: usize) usize {
349 return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), whence);
350}
351
352pub fn exit(status: i32) noreturn {
353 _ = syscall1(SYS_exit, @bitCast(usize, isize(status)));
354 unreachable;
355}
356
357pub fn exit_group(status: i32) noreturn {
358 _ = syscall1(SYS_exit_group, @bitCast(usize, isize(status)));
359 unreachable;
360}
361
362pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
363 return syscall3(SYS_getrandom, @ptrToInt(buf), count, flags);
364}
365
366pub fn kill(pid: i32, sig: i32) usize {
367 return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
368}
369
370// TODO https://github.com/ziglang/zig/issues/265
371pub fn unlink(path: [*]const u8) usize {
372 if (@hasDecl(@This(), "SYS_unlink")) {
373 return syscall1(SYS_unlink, @ptrToInt(path));
374 } else {
375 return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), 0);
376 }
377}
378
379// TODO https://github.com/ziglang/zig/issues/265
380pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
381 return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags);
382}
383
384pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
385 return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
386}
387
388var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
389
390// We must follow the C calling convention when we call into the VDSO
391const vdso_clock_gettime_ty = extern fn (i32, *timespec) usize;
392
393pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
394 if (VDSO_CGT_SYM.len != 0) {
395 const ptr = @atomicLoad(?*const c_void, &vdso_clock_gettime, .Unordered);
396 if (ptr) |fn_ptr| {
397 const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr);
398 const rc = f(clk_id, tp);
399 switch (rc) {
400 0, @bitCast(usize, isize(-EINVAL)) => return rc,
401 else => {},
402 }
403 }
404 }
405 return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
406}
407
408extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize {
409 const ptr = @intToPtr(?*const c_void, vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM));
410 // Note that we may not have a VDSO at all, update the stub address anyway
411 // so that clock_gettime will fall back on the good old (and slow) syscall
412 _ = @cmpxchgStrong(?*const c_void, &vdso_clock_gettime, &init_vdso_clock_gettime, ptr, .Monotonic, .Monotonic);
413 // Call into the VDSO if available
414 if (ptr) |fn_ptr| {
415 const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr);
416 return f(clk, ts);
417 }
418 return @bitCast(usize, isize(-ENOSYS));
419}
420
421pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
422 return syscall2(SYS_clock_getres, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
423}
424
425pub fn clock_settime(clk_id: i32, tp: *const timespec) usize {
426 return syscall2(SYS_clock_settime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
427}
428
429pub fn gettimeofday(tv: *timeval, tz: *timezone) usize {
430 return syscall2(SYS_gettimeofday, @ptrToInt(tv), @ptrToInt(tz));
431}
432
433pub fn settimeofday(tv: *const timeval, tz: *const timezone) usize {
434 return syscall2(SYS_settimeofday, @ptrToInt(tv), @ptrToInt(tz));
435}
436
437pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
438 return syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));
439}
440
441pub fn setuid(uid: u32) usize {
442 return syscall1(SYS_setuid, uid);
443}
444
445pub fn setgid(gid: u32) usize {
446 return syscall1(SYS_setgid, gid);
447}
448
449pub fn setreuid(ruid: u32, euid: u32) usize {
450 return syscall2(SYS_setreuid, ruid, euid);
451}
452
453pub fn setregid(rgid: u32, egid: u32) usize {
454 return syscall2(SYS_setregid, rgid, egid);
455}
456
457pub fn getuid() u32 {
458 return u32(syscall0(SYS_getuid));
459}
460
461pub fn getgid() u32 {
462 return u32(syscall0(SYS_getgid));
463}
464
465pub fn geteuid() u32 {
466 return u32(syscall0(SYS_geteuid));
467}
468
469pub fn getegid() u32 {
470 return u32(syscall0(SYS_getegid));
471}
472
473pub fn seteuid(euid: u32) usize {
474 return syscall1(SYS_seteuid, euid);
475}
476
477pub fn setegid(egid: u32) usize {
478 return syscall1(SYS_setegid, egid);
479}
480
481pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize {
482 return syscall3(SYS_getresuid, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid));
483}
484
485pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize {
486 return syscall3(SYS_getresgid, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid));
487}
488
489pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize {
490 return syscall3(SYS_setresuid, ruid, euid, suid);
491}
492
493pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize {
494 return syscall3(SYS_setresgid, rgid, egid, sgid);
495}
496
497pub fn getgroups(size: usize, list: *u32) usize {
498 return syscall2(SYS_getgroups, size, @ptrToInt(list));
499}
500
501pub fn setgroups(size: usize, list: *const u32) usize {
502 return syscall2(SYS_setgroups, size, @ptrToInt(list));
503}
504
505pub fn getpid() i32 {
506 return @bitCast(i32, @truncate(u32, syscall0(SYS_getpid)));
507}
508
509pub fn gettid() i32 {
510 return @bitCast(i32, @truncate(u32, syscall0(SYS_gettid)));
511}
512
513pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize {
514 return syscall4(SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8);
515}
516
517pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize {
518 assert(sig >= 1);
519 assert(sig != SIGKILL);
520 assert(sig != SIGSTOP);
521 var ksa = k_sigaction{
522 .handler = act.handler,
523 .flags = act.flags | SA_RESTORER,
524 .mask = undefined,
525 .restorer = @ptrCast(extern fn () void, restore_rt),
526 };
527 var ksa_old: k_sigaction = undefined;
528 @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), 8);
529 const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @sizeOf(@typeOf(ksa.mask)));
530 const err = getErrno(result);
531 if (err != 0) {
532 return result;
533 }
534 if (oact) |old| {
535 old.handler = ksa_old.handler;
536 old.flags = @truncate(u32, ksa_old.flags);
537 @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), @sizeOf(@typeOf(ksa_old.mask)));
538 }
539 return 0;
540}
541
542fn blockAllSignals(set: *sigset_t) void {
543 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG / 8);
544}
545
546fn blockAppSignals(set: *sigset_t) void {
547 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG / 8);
548}
549
550fn restoreSignals(set: *sigset_t) void {
551 _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG / 8);
552}
553
554pub fn sigaddset(set: *sigset_t, sig: u6) void {
555 const s = sig - 1;
556 (set.*)[@intCast(usize, s) / usize.bit_count] |= @intCast(usize, 1) << (s & (usize.bit_count - 1));
557}
558
559pub fn sigismember(set: *const sigset_t, sig: u6) bool {
560 const s = sig - 1;
561 return ((set.*)[@intCast(usize, s) / usize.bit_count] & (@intCast(usize, 1) << (s & (usize.bit_count - 1)))) != 0;
562}
563
564pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
565 return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
566}
567
568pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
569 return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
570}
571
572pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
573 return syscall3(SYS_socket, domain, socket_type, protocol);
574}
575
576pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
577 return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen));
578}
579
580pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
581 return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
582}
583
584pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize {
585 return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
586}
587
588pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize {
589 if (@typeInfo(usize).Int.bits > @typeInfo(@typeOf(mmsghdr(undefined).msg_len)).Int.bits) {
590 // workaround kernel brokenness:
591 // if adding up all iov_len overflows a i32 then split into multiple calls
592 // see https://www.openwall.com/lists/musl/2014/06/07/5
593 const kvlen = if (vlen > IOV_MAX) IOV_MAX else vlen; // matches kernel
594 var next_unsent: usize = 0;
595 for (msgvec[0..kvlen]) |*msg, i| {
596 var size: i32 = 0;
597 const msg_iovlen = @intCast(usize, msg.msg_hdr.msg_iovlen); // kernel side this is treated as unsigned
598 for (msg.msg_hdr.msg_iov[0..msg_iovlen]) |iov, j| {
599 if (iov.iov_len > std.math.maxInt(i32) or @addWithOverflow(i32, size, @intCast(i32, iov.iov_len), &size)) {
600 // batch-send all messages up to the current message
601 if (next_unsent < i) {
602 const batch_size = i - next_unsent;
603 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
604 if (getErrno(r) != 0) return next_unsent;
605 if (r < batch_size) return next_unsent + r;
606 }
607 // send current message as own packet
608 const r = sendmsg(fd, &msg.msg_hdr, flags);
609 if (getErrno(r) != 0) return r;
610 // Linux limits the total bytes sent by sendmsg to INT_MAX, so this cast is safe.
611 msg.msg_len = @intCast(u32, r);
612 next_unsent = i + 1;
613 break;
614 }
615 }
616 }
617 if (next_unsent < kvlen or next_unsent == 0) { // want to make sure at least one syscall occurs (e.g. to trigger MSG_EOR)
618 const batch_size = kvlen - next_unsent;
619 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
620 if (getErrno(r) != 0) return r;
621 return next_unsent + r;
622 }
623 return kvlen;
624 }
625 return syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(msgvec), vlen, flags);
626}
627
628pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
629 return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);
630}
631
632pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
633 return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
634}
635
636pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
637 return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
638}
639
640pub fn shutdown(fd: i32, how: i32) usize {
641 return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how)));
642}
643
644pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
645 return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len));
646}
647
648pub fn listen(fd: i32, backlog: u32) usize {
649 return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog);
650}
651
652pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
653 return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
654}
655
656pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {
657 return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]));
658}
659
660pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
661 return accept4(fd, addr, len, 0);
662}
663
664pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize {
665 return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags);
666}
667
668pub fn fstat(fd: i32, stat_buf: *Stat) usize {
669 return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
670}
671
672// TODO https://github.com/ziglang/zig/issues/265
673pub fn stat(pathname: [*]const u8, statbuf: *Stat) usize {
674 return syscall2(SYS_stat, @ptrToInt(pathname), @ptrToInt(statbuf));
675}
676
677// TODO https://github.com/ziglang/zig/issues/265
678pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
679 return syscall2(SYS_lstat, @ptrToInt(pathname), @ptrToInt(statbuf));
680}
681
682// TODO https://github.com/ziglang/zig/issues/265
683pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {
684 return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
685}
686
687// TODO https://github.com/ziglang/zig/issues/265
688pub fn listxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
689 return syscall3(SYS_listxattr, @ptrToInt(path), @ptrToInt(list), size);
690}
691
692// TODO https://github.com/ziglang/zig/issues/265
693pub fn llistxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
694 return syscall3(SYS_llistxattr, @ptrToInt(path), @ptrToInt(list), size);
695}
696
697pub fn flistxattr(fd: usize, list: [*]u8, size: usize) usize {
698 return syscall3(SYS_flistxattr, fd, @ptrToInt(list), size);
699}
700
701// TODO https://github.com/ziglang/zig/issues/265
702pub fn getxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
703 return syscall4(SYS_getxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
704}
705
706// TODO https://github.com/ziglang/zig/issues/265
707pub fn lgetxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
708 return syscall4(SYS_lgetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
709}
710
711// TODO https://github.com/ziglang/zig/issues/265
712pub fn fgetxattr(fd: usize, name: [*]const u8, value: [*]u8, size: usize) usize {
713 return syscall4(SYS_lgetxattr, fd, @ptrToInt(name), @ptrToInt(value), size);
714}
715
716// TODO https://github.com/ziglang/zig/issues/265
717pub fn setxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
718 return syscall5(SYS_setxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
719}
720
721// TODO https://github.com/ziglang/zig/issues/265
722pub fn lsetxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
723 return syscall5(SYS_lsetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
724}
725
726// TODO https://github.com/ziglang/zig/issues/265
727pub fn fsetxattr(fd: usize, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
728 return syscall5(SYS_fsetxattr, fd, @ptrToInt(name), @ptrToInt(value), size, flags);
729}
730
731// TODO https://github.com/ziglang/zig/issues/265
732pub fn removexattr(path: [*]const u8, name: [*]const u8) usize {
733 return syscall2(SYS_removexattr, @ptrToInt(path), @ptrToInt(name));
734}
735
736// TODO https://github.com/ziglang/zig/issues/265
737pub fn lremovexattr(path: [*]const u8, name: [*]const u8) usize {
738 return syscall2(SYS_lremovexattr, @ptrToInt(path), @ptrToInt(name));
739}
740
741// TODO https://github.com/ziglang/zig/issues/265
742pub fn fremovexattr(fd: usize, name: [*]const u8) usize {
743 return syscall2(SYS_fremovexattr, fd, @ptrToInt(name));
744}
745
746pub fn sched_getaffinity(pid: i32, size: usize, set: *cpu_set_t) usize {
747 const rc = syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), size, @ptrToInt(set));
748 if (@bitCast(isize, rc) < 0) return rc;
749 if (rc < size) @memset(@ptrCast([*]u8, set) + rc, 0, size - rc);
750 return 0;
751}
752
753pub fn epoll_create() usize {
754 return epoll_create1(0);
755}
756
757pub fn epoll_create1(flags: usize) usize {
758 return syscall1(SYS_epoll_create1, flags);
759}
760
761pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
762 return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev));
763}
764
765pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
766 return syscall4(
767 SYS_epoll_wait,
768 @bitCast(usize, isize(epoll_fd)),
769 @ptrToInt(events),
770 maxevents,
771 @bitCast(usize, isize(timeout)),
772 );
773}
774
775pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
776 return syscall6(
777 SYS_epoll_pwait,
778 @bitCast(usize, isize(epoll_fd)),
779 @ptrToInt(events),
780 @intCast(usize, maxevents),
781 @bitCast(usize, isize(timeout)),
782 @ptrToInt(sigmask),
783 @sizeOf(sigset_t),
784 );
785}
786
787pub fn eventfd(count: u32, flags: u32) usize {
788 return syscall2(SYS_eventfd2, count, flags);
789}
790
791pub fn timerfd_create(clockid: i32, flags: u32) usize {
792 return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags);
793}
794
795pub const itimerspec = extern struct {
796 it_interval: timespec,
797 it_value: timespec,
798};
799
800pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
801 return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value));
802}
803
804pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {
805 return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value));
806}
807
808pub fn unshare(flags: usize) usize {
809 return syscall1(SYS_unshare, flags);
810}
811
812pub fn capget(hdrp: *cap_user_header_t, datap: *cap_user_data_t) usize {
813 return syscall2(SYS_capget, @ptrToInt(hdrp), @ptrToInt(datap));
814}
815
816pub fn capset(hdrp: *cap_user_header_t, datap: *const cap_user_data_t) usize {
817 return syscall2(SYS_capset, @ptrToInt(hdrp), @ptrToInt(datap));
818}
819
820// XXX: This should be weak
821extern const __ehdr_start: elf.Ehdr = undefined;
822
823pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
824 if (builtin.link_libc) {
825 return std.c.dl_iterate_phdr(@ptrCast(std.c.dl_iterate_phdr_callback, callback), @ptrCast(?*c_void, data));
826 }
827
828 const elf_base = @ptrToInt(&__ehdr_start);
829 const n_phdr = __ehdr_start.e_phnum;
830 const phdrs = (@intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff))[0..n_phdr];
831
832 var it = dl.linkmap_iterator(phdrs) catch return 0;
833
834 // The executable has no dynamic link segment, create a single entry for
835 // the whole ELF image
836 if (it.end()) {
837 var info = dl_phdr_info{
838 .dlpi_addr = elf_base,
839 .dlpi_name = c"/proc/self/exe",
840 .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
841 .dlpi_phnum = __ehdr_start.e_phnum,
842 };
843
844 return callback(&info, @sizeOf(dl_phdr_info), data);
845 }
846
847 // Last return value from the callback function
848 var last_r: isize = 0;
849 while (it.next()) |entry| {
850 var dlpi_phdr: usize = undefined;
851 var dlpi_phnum: u16 = undefined;
852
853 if (entry.l_addr != 0) {
854 const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
855 dlpi_phdr = entry.l_addr + elf_header.e_phoff;
856 dlpi_phnum = elf_header.e_phnum;
857 } else {
858 // This is the running ELF image
859 dlpi_phdr = elf_base + __ehdr_start.e_phoff;
860 dlpi_phnum = __ehdr_start.e_phnum;
861 }
862
863 var info = dl_phdr_info{
864 .dlpi_addr = entry.l_addr,
865 .dlpi_name = entry.l_name,
866 .dlpi_phdr = @intToPtr([*]elf.Phdr, dlpi_phdr),
867 .dlpi_phnum = dlpi_phnum,
868 };
869
870 last_r = callback(&info, @sizeOf(dl_phdr_info), data);
871 if (last_r != 0) break;
872 }
873
874 return last_r;
875}
6876
7test "" {877test "" {
8 if (is_the_target) {878 if (is_the_target) {
std/os/linux/sys.zig deleted-859
...@@ -1,859 +0,0 @@
1// This file provides the system interface functions for Linux matching those
2// that are provided by libc, whether or not libc is linked. The following
3// abstractions are made:
4// * Work around kernel bugs and limitations. For example, see sendmmsg.
5// * Implement all the syscalls in the same way that libc functions will
6// provide `rename` when only the `renameat` syscall exists.
7// * Does not support POSIX thread cancellation.
8const std = @import("../../std.zig");
9const builtin = @import("builtin");
10const assert = std.debug.assert;
11const maxInt = std.math.maxInt;
12const elf = std.elf;
13const vdso = @import("vdso.zig");
14const dl = @import("../../dynamic_library.zig");
15pub use switch (builtin.arch) {
16 .x86_64 => @import("x86_64.zig"),
17 .aarch64 => @import("arm64.zig"),
18 else => struct {},
19};
20pub use @import("../bits.zig");
21
22/// See `std.os.posix.getauxval`.
23pub var elf_aux_maybe: ?[*]std.elf.Auxv = null;
24
25/// Get the errno from a syscall return value, or 0 for no error.
26pub fn getErrno(r: usize) u12 {
27 const signed_r = @bitCast(isize, r);
28 return if (signed_r > -4096 and signed_r < 0) @intCast(u12, -signed_r) else 0;
29}
30
31pub fn dup2(old: i32, new: i32) usize {
32 if (@hasDecl(@This(), "SYS_dup2")) {
33 return syscall2(SYS_dup2, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)));
34 } else {
35 if (old == new) {
36 if (std.debug.runtime_safety) {
37 const rc = syscall2(SYS_fcntl, @bitCast(usize, isize(old)), F_GETFD);
38 if (@bitCast(isize, rc) < 0) return rc;
39 }
40 return @intCast(usize, old);
41 } else {
42 return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), 0);
43 }
44 }
45}
46
47pub fn dup3(old: i32, new: i32, flags: u32) usize {
48 return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags);
49}
50
51// TODO https://github.com/ziglang/zig/issues/265
52pub fn chdir(path: [*]const u8) usize {
53 return syscall1(SYS_chdir, @ptrToInt(path));
54}
55
56// TODO https://github.com/ziglang/zig/issues/265
57pub fn chroot(path: [*]const u8) usize {
58 return syscall1(SYS_chroot, @ptrToInt(path));
59}
60
61// TODO https://github.com/ziglang/zig/issues/265
62pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
63 return syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));
64}
65
66pub fn fork() usize {
67 if (@hasDecl(@This(), "SYS_fork")) {
68 return syscall0(SYS_fork);
69 } else {
70 return syscall2(SYS_clone, SIGCHLD, 0);
71 }
72}
73
74/// This must be inline, and inline call the syscall function, because if the
75/// child does a return it will clobber the parent's stack.
76/// It is advised to avoid this function and use clone instead, because
77/// the compiler is not aware of how vfork affects control flow and you may
78/// see different results in optimized builds.
79pub inline fn vfork() usize {
80 return @inlineCall(syscall0, SYS_vfork);
81}
82
83pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize {
84 return syscall4(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val), @ptrToInt(timeout));
85}
86
87pub fn futex_wake(uaddr: *const i32, futex_op: u32, val: i32) usize {
88 return syscall3(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val));
89}
90
91pub fn getcwd(buf: [*]u8, size: usize) usize {
92 return syscall2(SYS_getcwd, @ptrToInt(buf), size);
93}
94
95pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
96 return syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
97}
98
99pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {
100 return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
101}
102
103pub fn inotify_init1(flags: u32) usize {
104 return syscall1(SYS_inotify_init1, flags);
105}
106
107pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize {
108 return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask);
109}
110
111pub fn inotify_rm_watch(fd: i32, wd: i32) usize {
112 return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd)));
113}
114
115// TODO https://github.com/ziglang/zig/issues/265
116pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
117 if (@hasDecl(@This(), "SYS_readlink")) {
118 return syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
119 } else {
120 return syscall4(SYS_readlinkat, AT_FDCWD, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
121 }
122}
123
124// TODO https://github.com/ziglang/zig/issues/265
125pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
126 return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
127}
128
129// TODO https://github.com/ziglang/zig/issues/265
130pub fn mkdir(path: [*]const u8, mode: u32) usize {
131 if (@hasDecl(@This(), "SYS_mkdir")) {
132 return syscall2(SYS_mkdir, @ptrToInt(path), mode);
133 } else {
134 return syscall3(SYS_mkdirat, AT_FDCWD, @ptrToInt(path), mode);
135 }
136}
137
138// TODO https://github.com/ziglang/zig/issues/265
139pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {
140 return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
141}
142
143// TODO https://github.com/ziglang/zig/issues/265
144pub fn mount(special: [*]const u8, dir: [*]const u8, fstype: [*]const u8, flags: u32, data: usize) usize {
145 return syscall5(SYS_mount, @ptrToInt(special), @ptrToInt(dir), @ptrToInt(fstype), flags, data);
146}
147
148// TODO https://github.com/ziglang/zig/issues/265
149pub fn umount(special: [*]const u8) usize {
150 return syscall2(SYS_umount2, @ptrToInt(special), 0);
151}
152
153// TODO https://github.com/ziglang/zig/issues/265
154pub fn umount2(special: [*]const u8, flags: u32) usize {
155 return syscall2(SYS_umount2, @ptrToInt(special), flags);
156}
157
158pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
159 return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
160}
161
162pub fn mprotect(address: usize, length: usize, protection: usize) usize {
163 return syscall3(SYS_mprotect, address, length, protection);
164}
165
166pub fn munmap(address: usize, length: usize) usize {
167 return syscall2(SYS_munmap, address, length);
168}
169
170pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
171 return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
172}
173
174pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
175 return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
176}
177
178pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
179 return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
180}
181
182pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
183 return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
184}
185
186pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {
187 return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
188}
189
190// TODO https://github.com/ziglang/zig/issues/265
191pub fn rmdir(path: [*]const u8) usize {
192 if (@hasDecl(@This(), "SYS_rmdir")) {
193 return syscall1(SYS_rmdir, @ptrToInt(path));
194 } else {
195 return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), AT_REMOVEDIR);
196 }
197}
198
199// TODO https://github.com/ziglang/zig/issues/265
200pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
201 if (@hasDecl(@This(), "SYS_symlink")) {
202 return syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
203 } else {
204 return syscall3(SYS_symlinkat, @ptrToInt(existing), AT_FDCWD, @ptrToInt(new));
205 }
206}
207
208// TODO https://github.com/ziglang/zig/issues/265
209pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
210 return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath));
211}
212
213// TODO https://github.com/ziglang/zig/issues/265
214pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
215 return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
216}
217
218// TODO https://github.com/ziglang/zig/issues/265
219pub fn access(path: [*]const u8, mode: u32) usize {
220 return syscall2(SYS_access, @ptrToInt(path), mode);
221}
222
223// TODO https://github.com/ziglang/zig/issues/265
224pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
225 return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
226}
227
228pub fn pipe(fd: *[2]i32) usize {
229 if (@hasDecl(@This(), "SYS_pipe")) {
230 return syscall1(SYS_pipe, @ptrToInt(fd));
231 } else {
232 return syscall2(SYS_pipe2, @ptrToInt(fd), 0);
233 }
234}
235
236pub fn pipe2(fd: *[2]i32, flags: u32) usize {
237 return syscall2(SYS_pipe2, @ptrToInt(fd), flags);
238}
239
240pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
241 return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
242}
243
244pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
245 return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
246}
247
248// TODO https://github.com/ziglang/zig/issues/265
249pub fn rename(old: [*]const u8, new: [*]const u8) usize {
250 if (@hasDecl(@This(), "SYS_rename")) {
251 return syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
252 } else if (@hasDecl(@This(), "SYS_renameat")) {
253 return syscall4(SYS_renameat, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new));
254 } else {
255 return syscall5(SYS_renameat2, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new), 0);
256 }
257}
258
259pub fn renameat(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
260 if (@hasDecl(@This(), "SYS_renameat")) {
261 return syscall4(
262 SYS_renameat,
263 @bitCast(usize, isize(oldfd)),
264 @ptrToInt(old),
265 @bitCast(usize, isize(newfd)),
266 @ptrToInt(new),
267 );
268 } else {
269 return syscall5(
270 SYS_renameat2,
271 @bitCast(usize, isize(oldfd)),
272 @ptrToInt(old),
273 @bitCast(usize, isize(newfd)),
274 @ptrToInt(new),
275 0,
276 );
277 }
278}
279
280// TODO https://github.com/ziglang/zig/issues/265
281pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {
282 return syscall5(
283 SYS_renameat2,
284 @bitCast(usize, isize(oldfd)),
285 @ptrToInt(oldpath),
286 @bitCast(usize, isize(newfd)),
287 @ptrToInt(newpath),
288 flags,
289 );
290}
291
292// TODO https://github.com/ziglang/zig/issues/265
293pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
294 return syscall3(SYS_open, @ptrToInt(path), flags, perm);
295}
296
297// TODO https://github.com/ziglang/zig/issues/265
298pub fn create(path: [*]const u8, perm: usize) usize {
299 return syscall2(SYS_creat, @ptrToInt(path), perm);
300}
301
302// TODO https://github.com/ziglang/zig/issues/265
303pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {
304 // dirfd could be negative, for example AT_FDCWD is -100
305 return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode);
306}
307
308/// See also `clone` (from the arch-specific include)
309pub fn clone5(flags: usize, child_stack_ptr: usize, parent_tid: *i32, child_tid: *i32, newtls: usize) usize {
310 return syscall5(SYS_clone, flags, child_stack_ptr, @ptrToInt(parent_tid), @ptrToInt(child_tid), newtls);
311}
312
313/// See also `clone` (from the arch-specific include)
314pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
315 return syscall2(SYS_clone, flags, child_stack_ptr);
316}
317
318pub fn close(fd: i32) usize {
319 return syscall1(SYS_close, @bitCast(usize, isize(fd)));
320}
321
322/// Can only be called on 32 bit systems. For 64 bit see `lseek`.
323pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize {
324 return syscall5(
325 SYS__llseek,
326 @bitCast(usize, isize(fd)),
327 @truncate(usize, offset >> 32),
328 @truncate(usize, offset),
329 @ptrToInt(result),
330 whence,
331 );
332}
333
334/// Can only be called on 64 bit systems. For 32 bit see `llseek`.
335pub fn lseek(fd: i32, offset: i64, whence: usize) usize {
336 return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), whence);
337}
338
339pub fn exit(status: i32) noreturn {
340 _ = syscall1(SYS_exit, @bitCast(usize, isize(status)));
341 unreachable;
342}
343
344pub fn exit_group(status: i32) noreturn {
345 _ = syscall1(SYS_exit_group, @bitCast(usize, isize(status)));
346 unreachable;
347}
348
349pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
350 return syscall3(SYS_getrandom, @ptrToInt(buf), count, flags);
351}
352
353pub fn kill(pid: i32, sig: i32) usize {
354 return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
355}
356
357// TODO https://github.com/ziglang/zig/issues/265
358pub fn unlink(path: [*]const u8) usize {
359 if (@hasDecl(@This(), "SYS_unlink")) {
360 return syscall1(SYS_unlink, @ptrToInt(path));
361 } else {
362 return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), 0);
363 }
364}
365
366// TODO https://github.com/ziglang/zig/issues/265
367pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
368 return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags);
369}
370
371pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
372 return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
373}
374
375var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
376
377// We must follow the C calling convention when we call into the VDSO
378const vdso_clock_gettime_ty = extern fn (i32, *timespec) usize;
379
380pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
381 if (VDSO_CGT_SYM.len != 0) {
382 const ptr = @atomicLoad(?*const c_void, &vdso_clock_gettime, .Unordered);
383 if (ptr) |fn_ptr| {
384 const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr);
385 const rc = f(clk_id, tp);
386 switch (rc) {
387 0, @bitCast(usize, isize(-EINVAL)) => return rc,
388 else => {},
389 }
390 }
391 }
392 return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
393}
394
395extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize {
396 const ptr = @intToPtr(?*const c_void, vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM));
397 // Note that we may not have a VDSO at all, update the stub address anyway
398 // so that clock_gettime will fall back on the good old (and slow) syscall
399 _ = @cmpxchgStrong(?*const c_void, &vdso_clock_gettime, &init_vdso_clock_gettime, ptr, .Monotonic, .Monotonic);
400 // Call into the VDSO if available
401 if (ptr) |fn_ptr| {
402 const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr);
403 return f(clk, ts);
404 }
405 return @bitCast(usize, isize(-ENOSYS));
406}
407
408pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
409 return syscall2(SYS_clock_getres, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
410}
411
412pub fn clock_settime(clk_id: i32, tp: *const timespec) usize {
413 return syscall2(SYS_clock_settime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
414}
415
416pub fn gettimeofday(tv: *timeval, tz: *timezone) usize {
417 return syscall2(SYS_gettimeofday, @ptrToInt(tv), @ptrToInt(tz));
418}
419
420pub fn settimeofday(tv: *const timeval, tz: *const timezone) usize {
421 return syscall2(SYS_settimeofday, @ptrToInt(tv), @ptrToInt(tz));
422}
423
424pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
425 return syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));
426}
427
428pub fn setuid(uid: u32) usize {
429 return syscall1(SYS_setuid, uid);
430}
431
432pub fn setgid(gid: u32) usize {
433 return syscall1(SYS_setgid, gid);
434}
435
436pub fn setreuid(ruid: u32, euid: u32) usize {
437 return syscall2(SYS_setreuid, ruid, euid);
438}
439
440pub fn setregid(rgid: u32, egid: u32) usize {
441 return syscall2(SYS_setregid, rgid, egid);
442}
443
444pub fn getuid() u32 {
445 return u32(syscall0(SYS_getuid));
446}
447
448pub fn getgid() u32 {
449 return u32(syscall0(SYS_getgid));
450}
451
452pub fn geteuid() u32 {
453 return u32(syscall0(SYS_geteuid));
454}
455
456pub fn getegid() u32 {
457 return u32(syscall0(SYS_getegid));
458}
459
460pub fn seteuid(euid: u32) usize {
461 return syscall1(SYS_seteuid, euid);
462}
463
464pub fn setegid(egid: u32) usize {
465 return syscall1(SYS_setegid, egid);
466}
467
468pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize {
469 return syscall3(SYS_getresuid, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid));
470}
471
472pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize {
473 return syscall3(SYS_getresgid, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid));
474}
475
476pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize {
477 return syscall3(SYS_setresuid, ruid, euid, suid);
478}
479
480pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize {
481 return syscall3(SYS_setresgid, rgid, egid, sgid);
482}
483
484pub fn getgroups(size: usize, list: *u32) usize {
485 return syscall2(SYS_getgroups, size, @ptrToInt(list));
486}
487
488pub fn setgroups(size: usize, list: *const u32) usize {
489 return syscall2(SYS_setgroups, size, @ptrToInt(list));
490}
491
492pub fn getpid() i32 {
493 return @bitCast(i32, @truncate(u32, syscall0(SYS_getpid)));
494}
495
496pub fn gettid() i32 {
497 return @bitCast(i32, @truncate(u32, syscall0(SYS_gettid)));
498}
499
500pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize {
501 return syscall4(SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8);
502}
503
504pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize {
505 assert(sig >= 1);
506 assert(sig != SIGKILL);
507 assert(sig != SIGSTOP);
508 var ksa = k_sigaction{
509 .handler = act.handler,
510 .flags = act.flags | SA_RESTORER,
511 .mask = undefined,
512 .restorer = @ptrCast(extern fn () void, restore_rt),
513 };
514 var ksa_old: k_sigaction = undefined;
515 @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), 8);
516 const result = syscall4(SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @sizeOf(@typeOf(ksa.mask)));
517 const err = getErrno(result);
518 if (err != 0) {
519 return result;
520 }
521 if (oact) |old| {
522 old.handler = ksa_old.handler;
523 old.flags = @truncate(u32, ksa_old.flags);
524 @memcpy(@ptrCast([*]u8, &old.mask), @ptrCast([*]const u8, &ksa_old.mask), @sizeOf(@typeOf(ksa_old.mask)));
525 }
526 return 0;
527}
528
529fn blockAllSignals(set: *sigset_t) void {
530 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG / 8);
531}
532
533fn blockAppSignals(set: *sigset_t) void {
534 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG / 8);
535}
536
537fn restoreSignals(set: *sigset_t) void {
538 _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG / 8);
539}
540
541pub fn sigaddset(set: *sigset_t, sig: u6) void {
542 const s = sig - 1;
543 (set.*)[@intCast(usize, s) / usize.bit_count] |= @intCast(usize, 1) << (s & (usize.bit_count - 1));
544}
545
546pub fn sigismember(set: *const sigset_t, sig: u6) bool {
547 const s = sig - 1;
548 return ((set.*)[@intCast(usize, s) / usize.bit_count] & (@intCast(usize, 1) << (s & (usize.bit_count - 1)))) != 0;
549}
550
551pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
552 return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
553}
554
555pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
556 return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
557}
558
559pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
560 return syscall3(SYS_socket, domain, socket_type, protocol);
561}
562
563pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
564 return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen));
565}
566
567pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
568 return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
569}
570
571pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize {
572 return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
573}
574
575pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize {
576 if (@typeInfo(usize).Int.bits > @typeInfo(@typeOf(mmsghdr(undefined).msg_len)).Int.bits) {
577 // workaround kernel brokenness:
578 // if adding up all iov_len overflows a i32 then split into multiple calls
579 // see https://www.openwall.com/lists/musl/2014/06/07/5
580 const kvlen = if (vlen > IOV_MAX) IOV_MAX else vlen; // matches kernel
581 var next_unsent: usize = 0;
582 for (msgvec[0..kvlen]) |*msg, i| {
583 var size: i32 = 0;
584 const msg_iovlen = @intCast(usize, msg.msg_hdr.msg_iovlen); // kernel side this is treated as unsigned
585 for (msg.msg_hdr.msg_iov[0..msg_iovlen]) |iov, j| {
586 if (iov.iov_len > std.math.maxInt(i32) or @addWithOverflow(i32, size, @intCast(i32, iov.iov_len), &size)) {
587 // batch-send all messages up to the current message
588 if (next_unsent < i) {
589 const batch_size = i - next_unsent;
590 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
591 if (getErrno(r) != 0) return next_unsent;
592 if (r < batch_size) return next_unsent + r;
593 }
594 // send current message as own packet
595 const r = sendmsg(fd, &msg.msg_hdr, flags);
596 if (getErrno(r) != 0) return r;
597 // Linux limits the total bytes sent by sendmsg to INT_MAX, so this cast is safe.
598 msg.msg_len = @intCast(u32, r);
599 next_unsent = i + 1;
600 break;
601 }
602 }
603 }
604 if (next_unsent < kvlen or next_unsent == 0) { // want to make sure at least one syscall occurs (e.g. to trigger MSG_EOR)
605 const batch_size = kvlen - next_unsent;
606 const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags);
607 if (getErrno(r) != 0) return r;
608 return next_unsent + r;
609 }
610 return kvlen;
611 }
612 return syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(msgvec), vlen, flags);
613}
614
615pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
616 return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);
617}
618
619pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
620 return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
621}
622
623pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
624 return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
625}
626
627pub fn shutdown(fd: i32, how: i32) usize {
628 return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how)));
629}
630
631pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
632 return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len));
633}
634
635pub fn listen(fd: i32, backlog: u32) usize {
636 return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog);
637}
638
639pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
640 return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
641}
642
643pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {
644 return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]));
645}
646
647pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
648 return accept4(fd, addr, len, 0);
649}
650
651pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize {
652 return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags);
653}
654
655pub fn fstat(fd: i32, stat_buf: *Stat) usize {
656 return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
657}
658
659// TODO https://github.com/ziglang/zig/issues/265
660pub fn stat(pathname: [*]const u8, statbuf: *Stat) usize {
661 return syscall2(SYS_stat, @ptrToInt(pathname), @ptrToInt(statbuf));
662}
663
664// TODO https://github.com/ziglang/zig/issues/265
665pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
666 return syscall2(SYS_lstat, @ptrToInt(pathname), @ptrToInt(statbuf));
667}
668
669// TODO https://github.com/ziglang/zig/issues/265
670pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {
671 return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
672}
673
674// TODO https://github.com/ziglang/zig/issues/265
675pub fn listxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
676 return syscall3(SYS_listxattr, @ptrToInt(path), @ptrToInt(list), size);
677}
678
679// TODO https://github.com/ziglang/zig/issues/265
680pub fn llistxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
681 return syscall3(SYS_llistxattr, @ptrToInt(path), @ptrToInt(list), size);
682}
683
684pub fn flistxattr(fd: usize, list: [*]u8, size: usize) usize {
685 return syscall3(SYS_flistxattr, fd, @ptrToInt(list), size);
686}
687
688// TODO https://github.com/ziglang/zig/issues/265
689pub fn getxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
690 return syscall4(SYS_getxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
691}
692
693// TODO https://github.com/ziglang/zig/issues/265
694pub fn lgetxattr(path: [*]const u8, name: [*]const u8, value: [*]u8, size: usize) usize {
695 return syscall4(SYS_lgetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size);
696}
697
698// TODO https://github.com/ziglang/zig/issues/265
699pub fn fgetxattr(fd: usize, name: [*]const u8, value: [*]u8, size: usize) usize {
700 return syscall4(SYS_lgetxattr, fd, @ptrToInt(name), @ptrToInt(value), size);
701}
702
703// TODO https://github.com/ziglang/zig/issues/265
704pub fn setxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
705 return syscall5(SYS_setxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
706}
707
708// TODO https://github.com/ziglang/zig/issues/265
709pub fn lsetxattr(path: [*]const u8, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
710 return syscall5(SYS_lsetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
711}
712
713// TODO https://github.com/ziglang/zig/issues/265
714pub fn fsetxattr(fd: usize, name: [*]const u8, value: *const void, size: usize, flags: usize) usize {
715 return syscall5(SYS_fsetxattr, fd, @ptrToInt(name), @ptrToInt(value), size, flags);
716}
717
718// TODO https://github.com/ziglang/zig/issues/265
719pub fn removexattr(path: [*]const u8, name: [*]const u8) usize {
720 return syscall2(SYS_removexattr, @ptrToInt(path), @ptrToInt(name));
721}
722
723// TODO https://github.com/ziglang/zig/issues/265
724pub fn lremovexattr(path: [*]const u8, name: [*]const u8) usize {
725 return syscall2(SYS_lremovexattr, @ptrToInt(path), @ptrToInt(name));
726}
727
728// TODO https://github.com/ziglang/zig/issues/265
729pub fn fremovexattr(fd: usize, name: [*]const u8) usize {
730 return syscall2(SYS_fremovexattr, fd, @ptrToInt(name));
731}
732
733pub fn sched_getaffinity(pid: i32, set: []usize) usize {
734 return syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), set.len * @sizeOf(usize), @ptrToInt(set.ptr));
735}
736
737pub fn epoll_create() usize {
738 return epoll_create1(0);
739}
740
741pub fn epoll_create1(flags: usize) usize {
742 return syscall1(SYS_epoll_create1, flags);
743}
744
745pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
746 return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev));
747}
748
749pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
750 return syscall4(
751 SYS_epoll_wait,
752 @bitCast(usize, isize(epoll_fd)),
753 @ptrToInt(events),
754 maxevents,
755 @bitCast(usize, isize(timeout)),
756 );
757}
758
759pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
760 return syscall6(
761 SYS_epoll_pwait,
762 @bitCast(usize, isize(epoll_fd)),
763 @ptrToInt(events),
764 @intCast(usize, maxevents),
765 @bitCast(usize, isize(timeout)),
766 @ptrToInt(sigmask),
767 @sizeOf(sigset_t),
768 );
769}
770
771pub fn eventfd(count: u32, flags: u32) usize {
772 return syscall2(SYS_eventfd2, count, flags);
773}
774
775pub fn timerfd_create(clockid: i32, flags: u32) usize {
776 return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags);
777}
778
779pub const itimerspec = extern struct {
780 it_interval: timespec,
781 it_value: timespec,
782};
783
784pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
785 return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value));
786}
787
788pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {
789 return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value));
790}
791
792pub fn unshare(flags: usize) usize {
793 return syscall1(SYS_unshare, flags);
794}
795
796pub fn capget(hdrp: *cap_user_header_t, datap: *cap_user_data_t) usize {
797 return syscall2(SYS_capget, @ptrToInt(hdrp), @ptrToInt(datap));
798}
799
800pub fn capset(hdrp: *cap_user_header_t, datap: *const cap_user_data_t) usize {
801 return syscall2(SYS_capset, @ptrToInt(hdrp), @ptrToInt(datap));
802}
803
804// XXX: This should be weak
805extern const __ehdr_start: elf.Ehdr = undefined;
806
807pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
808 if (builtin.link_libc) {
809 return std.c.dl_iterate_phdr(@ptrCast(std.c.dl_iterate_phdr_callback, callback), @ptrCast(?*c_void, data));
810 }
811
812 const elf_base = @ptrToInt(&__ehdr_start);
813 const n_phdr = __ehdr_start.e_phnum;
814 const phdrs = (@intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff))[0..n_phdr];
815
816 var it = dl.linkmap_iterator(phdrs) catch return 0;
817
818 // The executable has no dynamic link segment, create a single entry for
819 // the whole ELF image
820 if (it.end()) {
821 var info = dl_phdr_info{
822 .dlpi_addr = elf_base,
823 .dlpi_name = c"/proc/self/exe",
824 .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
825 .dlpi_phnum = __ehdr_start.e_phnum,
826 };
827
828 return callback(&info, @sizeOf(dl_phdr_info), data);
829 }
830
831 // Last return value from the callback function
832 var last_r: isize = 0;
833 while (it.next()) |entry| {
834 var dlpi_phdr: usize = undefined;
835 var dlpi_phnum: u16 = undefined;
836
837 if (entry.l_addr != 0) {
838 const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
839 dlpi_phdr = entry.l_addr + elf_header.e_phoff;
840 dlpi_phnum = elf_header.e_phnum;
841 } else {
842 // This is the running ELF image
843 dlpi_phdr = elf_base + __ehdr_start.e_phoff;
844 dlpi_phnum = __ehdr_start.e_phnum;
845 }
846
847 var info = dl_phdr_info{
848 .dlpi_addr = entry.l_addr,
849 .dlpi_name = entry.l_name,
850 .dlpi_phdr = @intToPtr([*]elf.Phdr, dlpi_phdr),
851 .dlpi_phnum = dlpi_phnum,
852 };
853
854 last_r = callback(&info, @sizeOf(dl_phdr_info), data);
855 if (last_r != 0) break;
856 }
857
858 return last_r;
859}
std/os/linux/tls.zig+9-4
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const os = std.os;
2const mem = std.mem;3const mem = std.mem;
3const posix = std.os.posix;
4const elf = std.elf;4const elf = std.elf;
5const builtin = @import("builtin");5const builtin = @import("builtin");
6const assert = std.debug.assert;6const assert = std.debug.assert;
...@@ -237,9 +237,14 @@ pub fn allocateTLS(size: usize) usize {...@@ -237,9 +237,14 @@ pub fn allocateTLS(size: usize) usize {
237 return @ptrToInt(&main_thread_tls_buffer);237 return @ptrToInt(&main_thread_tls_buffer);
238 }238 }
239239
240 const addr = posix.mmap(null, size, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS, -1, 0);240 const addr = os.mmap(
241241 null,
242 if (posix.getErrno(addr) != 0) @panic("out of memory");242 size,
243 os.PROT_READ | os.PROT_WRITE,
244 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
245 -1,
246 0,
247 ) catch @panic("out of memory");
243248
244 return addr;249 return addr;
245}250}
std/os/linux/x86_64.zig+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1use @import("posix/x86_64.zig");1use @import("../bits.zig");
22
3pub fn syscall0(number: usize) usize {3pub fn syscall0(number: usize) usize {
4 return asm volatile ("syscall"4 return asm volatile ("syscall"
std/os/test.zig+15-14
...@@ -5,6 +5,7 @@ const expect = std.testing.expect;...@@ -5,6 +5,7 @@ const expect = std.testing.expect;
5const io = std.io;5const io = std.io;
6const mem = std.mem;6const mem = std.mem;
7const File = std.fs.File;7const File = std.fs.File;
8const Thread = std.Thread;
89
9const a = std.debug.global_allocator;10const a = std.debug.global_allocator;
1011
...@@ -37,25 +38,25 @@ test "access file" {...@@ -37,25 +38,25 @@ test "access file" {
37 try os.deleteTree(a, "os_test_tmp");38 try os.deleteTree(a, "os_test_tmp");
38}39}
3940
40fn testThreadIdFn(thread_id: *os.Thread.Id) void {41fn testThreadIdFn(thread_id: *Thread.Id) void {
41 thread_id.* = os.Thread.getCurrentId();42 thread_id.* = Thread.getCurrentId();
42}43}
4344
44test "std.os.Thread.getCurrentId" {45test "std.Thread.getCurrentId" {
45 if (builtin.single_threaded) return error.SkipZigTest;46 if (builtin.single_threaded) return error.SkipZigTest;
4647
47 var thread_current_id: os.Thread.Id = undefined;48 var thread_current_id: Thread.Id = undefined;
48 const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);49 const thread = try Thread.spawn(&thread_current_id, testThreadIdFn);
49 const thread_id = thread.handle();50 const thread_id = thread.handle();
50 thread.wait();51 thread.wait();
51 if (os.Thread.use_pthreads) {52 if (Thread.use_pthreads) {
52 expect(thread_current_id == thread_id);53 expect(thread_current_id == thread_id);
53 } else {54 } else {
54 switch (builtin.os) {55 switch (builtin.os) {
55 builtin.Os.windows => expect(os.Thread.getCurrentId() != thread_current_id),56 builtin.Os.windows => expect(Thread.getCurrentId() != thread_current_id),
56 else => {57 else => {
57 // If the thread completes very quickly, then thread_id can be 0. See the58 // If the thread completes very quickly, then thread_id can be 0. See the
58 // documentation comments for `std.os.Thread.handle`.59 // documentation comments for `std.Thread.handle`.
59 expect(thread_id == 0 or thread_current_id == thread_id);60 expect(thread_id == 0 or thread_current_id == thread_id);
60 },61 },
61 }62 }
...@@ -67,10 +68,10 @@ test "spawn threads" {...@@ -67,10 +68,10 @@ test "spawn threads" {
6768
68 var shared_ctx: i32 = 1;69 var shared_ctx: i32 = 1;
6970
70 const thread1 = try std.os.spawnThread({}, start1);71 const thread1 = try Thread.spawn({}, start1);
71 const thread2 = try std.os.spawnThread(&shared_ctx, start2);72 const thread2 = try Thread.spawn(&shared_ctx, start2);
72 const thread3 = try std.os.spawnThread(&shared_ctx, start2);73 const thread3 = try Thread.spawn(&shared_ctx, start2);
73 const thread4 = try std.os.spawnThread(&shared_ctx, start2);74 const thread4 = try Thread.spawn(&shared_ctx, start2);
7475
75 thread1.wait();76 thread1.wait();
76 thread2.wait();77 thread2.wait();
...@@ -116,8 +117,8 @@ test "AtomicFile" {...@@ -116,8 +117,8 @@ test "AtomicFile" {
116117
117test "thread local storage" {118test "thread local storage" {
118 if (builtin.single_threaded) return error.SkipZigTest;119 if (builtin.single_threaded) return error.SkipZigTest;
119 const thread1 = try std.os.spawnThread({}, testTls);120 const thread1 = try Thread.spawn({}, testTls);
120 const thread2 = try std.os.spawnThread({}, testTls);121 const thread2 = try Thread.spawn({}, testTls);
121 testTls({});122 testTls({});
122 thread1.wait();123 thread1.wait();
123 thread2.wait();124 thread2.wait();
std/os/windows.zig+15-1
...@@ -591,7 +591,7 @@ pub fn CreateFileW(...@@ -591,7 +591,7 @@ pub fn CreateFileW(
591 ERROR.ACCESS_DENIED => return error.AccessDenied,591 ERROR.ACCESS_DENIED => return error.AccessDenied,
592 ERROR.PIPE_BUSY => return error.PipeBusy,592 ERROR.PIPE_BUSY => return error.PipeBusy,
593 ERROR.FILENAME_EXCED_RANGE => return error.NameTooLong,593 ERROR.FILENAME_EXCED_RANGE => return error.NameTooLong,
594 else => |err| return unexpectedErrorWindows(err),594 else => |err| return unexpectedError(err),
595 }595 }
596 }596 }
597597
...@@ -1089,6 +1089,20 @@ pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError...@@ -1089,6 +1089,20 @@ pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError
1089 }1089 }
1090}1090}
10911091
1092pub const VirtualAllocError = error{Unexpected};
1093
1094pub fn VirtualAlloc(addr: ?LPVOID, size: usize, alloc_type: DWORD, flProtect: DWORD) VirtualAllocError!LPVOID {
1095 return kernel32.VirtualAlloc(addr, size, alloc_type, flProtect) orelse {
1096 switch (kernel32.GetLastError()) {
1097 else => |err| return unexpectedError(err),
1098 }
1099 };
1100}
1101
1102pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void {
1103 assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0);
1104}
1105
1092pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {1106pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {
1093 return sliceToPrefixedFileW(mem.toSliceConst(u8, s));1107 return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
1094}1108}
std/process.zig+17-17
...@@ -1,13 +1,13 @@...@@ -1,13 +1,13 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const posix = std.os.posix;2const os = std.os;
3const BufMap = std.BufMap;3const BufMap = std.BufMap;
4const mem = std.mem;4const mem = std.mem;
5const Allocator = mem.Allocator;5const Allocator = mem.Allocator;
6const assert = std.debug.assert;6const assert = std.debug.assert;
7const testing = std.testing;7const testing = std.testing;
88
9pub const abort = posix.abort;9pub const abort = os.abort;
10pub const exit = posix.exit;10pub const exit = os.exit;
1111
12/// Caller must free result when done.12/// Caller must free result when done.
13/// TODO make this go through libc when we have it13/// TODO make this go through libc when we have it
...@@ -42,13 +42,13 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -42,13 +42,13 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
4242
43 try result.setMove(key, value);43 try result.setMove(key, value);
44 }44 }
45 } else if (builtin.os == Os.wasi) {45 } else if (builtin.os == .wasi) {
46 var environ_count: usize = undefined;46 var environ_count: usize = undefined;
47 var environ_buf_size: usize = undefined;47 var environ_buf_size: usize = undefined;
4848
49 const environ_sizes_get_ret = std.os.wasi.environ_sizes_get(&environ_count, &environ_buf_size);49 const environ_sizes_get_ret = os.wasi.environ_sizes_get(&environ_count, &environ_buf_size);
50 if (environ_sizes_get_ret != os.wasi.ESUCCESS) {50 if (environ_sizes_get_ret != os.wasi.ESUCCESS) {
51 return unexpectedErrorPosix(environ_sizes_get_ret);51 return os.unexpectedErrno(environ_sizes_get_ret);
52 }52 }
5353
54 // TODO: Verify that the documentation is incorrect54 // TODO: Verify that the documentation is incorrect
...@@ -58,9 +58,9 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -58,9 +58,9 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
58 var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size);58 var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size);
59 defer allocator.free(environ_buf);59 defer allocator.free(environ_buf);
6060
61 const environ_get_ret = std.os.wasi.environ_get(environ.ptr, environ_buf.ptr);61 const environ_get_ret = os.wasi.environ_get(environ.ptr, environ_buf.ptr);
62 if (environ_get_ret != os.wasi.ESUCCESS) {62 if (environ_get_ret != os.wasi.ESUCCESS) {
63 return unexpectedErrorPosix(environ_get_ret);63 return os.unexpectedErrno(environ_get_ret);
64 }64 }
6565
66 for (environ) |env| {66 for (environ) |env| {
...@@ -74,7 +74,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -74,7 +74,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
74 }74 }
75 return result;75 return result;
76 } else {76 } else {
77 for (posix.environ) |ptr| {77 for (os.environ) |ptr| {
78 var line_i: usize = 0;78 var line_i: usize = 0;
79 while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}79 while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
80 const key = ptr[0..line_i];80 const key = ptr[0..line_i];
...@@ -331,12 +331,12 @@ pub const ArgIteratorWindows = struct {...@@ -331,12 +331,12 @@ pub const ArgIteratorWindows = struct {
331};331};
332332
333pub const ArgIterator = struct {333pub const ArgIterator = struct {
334 const InnerType = if (builtin.os == Os.windows) ArgIteratorWindows else ArgIteratorPosix;334 const InnerType = if (builtin.os == .windows) ArgIteratorWindows else ArgIteratorPosix;
335335
336 inner: InnerType,336 inner: InnerType,
337337
338 pub fn init() ArgIterator {338 pub fn init() ArgIterator {
339 if (builtin.os == Os.wasi) {339 if (builtin.os == .wasi) {
340 // TODO: Figure out a compatible interface accomodating WASI340 // TODO: Figure out a compatible interface accomodating WASI
341 @compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead.");341 @compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead.");
342 }342 }
...@@ -348,7 +348,7 @@ pub const ArgIterator = struct {...@@ -348,7 +348,7 @@ pub const ArgIterator = struct {
348348
349 /// You must free the returned memory when done.349 /// You must free the returned memory when done.
350 pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) {350 pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) {
351 if (builtin.os == Os.windows) {351 if (builtin.os == .windows) {
352 return self.inner.next(allocator);352 return self.inner.next(allocator);
353 } else {353 } else {
354 return mem.dupe(allocator, u8, self.inner.next() orelse return null);354 return mem.dupe(allocator, u8, self.inner.next() orelse return null);
...@@ -373,13 +373,13 @@ pub fn args() ArgIterator {...@@ -373,13 +373,13 @@ pub fn args() ArgIterator {
373373
374/// Caller must call argsFree on result.374/// Caller must call argsFree on result.
375pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {375pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
376 if (builtin.os == Os.wasi) {376 if (builtin.os == .wasi) {
377 var count: usize = undefined;377 var count: usize = undefined;
378 var buf_size: usize = undefined;378 var buf_size: usize = undefined;
379379
380 const args_sizes_get_ret = os.wasi.args_sizes_get(&count, &buf_size);380 const args_sizes_get_ret = os.wasi.args_sizes_get(&count, &buf_size);
381 if (args_sizes_get_ret != os.wasi.ESUCCESS) {381 if (args_sizes_get_ret != os.wasi.ESUCCESS) {
382 return unexpectedErrorPosix(args_sizes_get_ret);382 return os.unexpectedErrno(args_sizes_get_ret);
383 }383 }
384384
385 var argv = try allocator.alloc([*]u8, count);385 var argv = try allocator.alloc([*]u8, count);
...@@ -388,7 +388,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {...@@ -388,7 +388,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
388 var argv_buf = try allocator.alloc(u8, buf_size);388 var argv_buf = try allocator.alloc(u8, buf_size);
389 const args_get_ret = os.wasi.args_get(argv.ptr, argv_buf.ptr);389 const args_get_ret = os.wasi.args_get(argv.ptr, argv_buf.ptr);
390 if (args_get_ret != os.wasi.ESUCCESS) {390 if (args_get_ret != os.wasi.ESUCCESS) {
391 return unexpectedErrorPosix(args_get_ret);391 return os.unexpectedErrno(args_get_ret);
392 }392 }
393393
394 var result_slice = try allocator.alloc([]u8, count);394 var result_slice = try allocator.alloc([]u8, count);
...@@ -438,7 +438,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {...@@ -438,7 +438,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
438}438}
439439
440pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {440pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
441 if (builtin.os == Os.wasi) {441 if (builtin.os == .wasi) {
442 const last_item = args_alloc[args_alloc.len - 1];442 const last_item = args_alloc[args_alloc.len - 1];
443 const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated443 const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated
444 const first_item_ptr = args_alloc[0].ptr;444 const first_item_ptr = args_alloc[0].ptr;
...@@ -491,7 +491,7 @@ pub const UserInfo = struct {...@@ -491,7 +491,7 @@ pub const UserInfo = struct {
491/// POSIX function which gets a uid from username.491/// POSIX function which gets a uid from username.
492pub fn getUserInfo(name: []const u8) !UserInfo {492pub fn getUserInfo(name: []const u8) !UserInfo {
493 return switch (builtin.os) {493 return switch (builtin.os) {
494 .linux, .macosx, .ios, .freebsd, .netbsd => posixGetUserInfo(name),494 .linux, .macosx, .watchos, .tvos, .ios, .freebsd, .netbsd => posixGetUserInfo(name),
495 else => @compileError("Unsupported OS"),495 else => @compileError("Unsupported OS"),
496 };496 };
497}497}
std/special/bootstrap.zig+2-2
...@@ -92,14 +92,14 @@ fn posixCallMainAndExit() noreturn {...@@ -92,14 +92,14 @@ fn posixCallMainAndExit() noreturn {
92 }92 }
93 }93 }
9494
95 std.os.posix.exit(callMainWithArgs(argc, argv, envp));95 std.os.exit(callMainWithArgs(argc, argv, envp));
96}96}
9797
98// This is marked inline because for some reason LLVM in release mode fails to inline it,98// This is marked inline because for some reason LLVM in release mode fails to inline it,
99// and we want fewer call frames in stack traces.99// and we want fewer call frames in stack traces.
100inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {100inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
101 std.os.ArgIteratorPosix.raw = argv[0..argc];101 std.os.ArgIteratorPosix.raw = argv[0..argc];
102 std.os.posix.environ = envp;102 std.os.environ = envp;
103 return callMain();103 return callMain();
104}104}
105105
std/statically_initialized_mutex.zig+2-2
...@@ -96,9 +96,9 @@ test "std.StaticallyInitializedMutex" {...@@ -96,9 +96,9 @@ test "std.StaticallyInitializedMutex" {
96 expect(context.data == TestContext.incr_count);96 expect(context.data == TestContext.incr_count);
97 } else {97 } else {
98 const thread_count = 10;98 const thread_count = 10;
99 var threads: [thread_count]*std.os.Thread = undefined;99 var threads: [thread_count]*std.Thread = undefined;
100 for (threads) |*t| {100 for (threads) |*t| {
101 t.* = try std.os.spawnThread(&context, TestContext.worker);101 t.* = try std.Thread.spawn(&context, TestContext.worker);
102 }102 }
103 for (threads) |t|103 for (threads) |t|
104 t.wait();104 t.wait();
std/thread.zig+57-93
...@@ -1,6 +1,8 @@...@@ -1,6 +1,8 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std.zig");2const std = @import("std.zig");
3const os = std.os;
3const windows = std.os.windows;4const windows = std.os.windows;
5const c = std.c;
46
5pub const Thread = struct {7pub const Thread = struct {
6 data: Data,8 data: Data,
...@@ -13,8 +15,8 @@ pub const Thread = struct {...@@ -13,8 +15,8 @@ pub const Thread = struct {
13 pub const Handle = if (use_pthreads)15 pub const Handle = if (use_pthreads)
14 c.pthread_t16 c.pthread_t
15 else switch (builtin.os) {17 else switch (builtin.os) {
16 builtin.Os.linux => i32,18 .linux => i32,
17 builtin.Os.windows => windows.HANDLE,19 .windows => windows.HANDLE,
18 else => @compileError("Unsupported OS"),20 else => @compileError("Unsupported OS"),
19 };21 };
2022
...@@ -22,7 +24,7 @@ pub const Thread = struct {...@@ -22,7 +24,7 @@ pub const Thread = struct {
22 /// May be an integer or pointer depending on the platform.24 /// May be an integer or pointer depending on the platform.
23 /// On Linux and POSIX, this is the same as Handle.25 /// On Linux and POSIX, this is the same as Handle.
24 pub const Id = switch (builtin.os) {26 pub const Id = switch (builtin.os) {
25 builtin.Os.windows => windows.DWORD,27 .windows => windows.DWORD,
26 else => Handle,28 else => Handle,
27 };29 };
2830
...@@ -33,12 +35,12 @@ pub const Thread = struct {...@@ -33,12 +35,12 @@ pub const Thread = struct {
33 mmap_len: usize,35 mmap_len: usize,
34 }36 }
35 else switch (builtin.os) {37 else switch (builtin.os) {
36 builtin.Os.linux => struct {38 .linux => struct {
37 handle: Thread.Handle,39 handle: Thread.Handle,
38 mmap_addr: usize,40 mmap_addr: usize,
39 mmap_len: usize,41 mmap_len: usize,
40 },42 },
41 builtin.Os.windows => struct {43 .windows => struct {
42 handle: Thread.Handle,44 handle: Thread.Handle,
43 alloc_start: *c_void,45 alloc_start: *c_void,
44 heap_handle: windows.HANDLE,46 heap_handle: windows.HANDLE,
...@@ -54,8 +56,8 @@ pub const Thread = struct {...@@ -54,8 +56,8 @@ pub const Thread = struct {
54 return c.pthread_self();56 return c.pthread_self();
55 } else57 } else
56 return switch (builtin.os) {58 return switch (builtin.os) {
57 builtin.Os.linux => linux.gettid(),59 .linux => linux.gettid(),
58 builtin.Os.windows => windows.GetCurrentThreadId(),60 .windows => windows.GetCurrentThreadId(),
59 else => @compileError("Unsupported OS"),61 else => @compileError("Unsupported OS"),
60 };62 };
61 }63 }
...@@ -75,28 +77,28 @@ pub const Thread = struct {...@@ -75,28 +77,28 @@ pub const Thread = struct {
75 const err = c.pthread_join(self.data.handle, null);77 const err = c.pthread_join(self.data.handle, null);
76 switch (err) {78 switch (err) {
77 0 => {},79 0 => {},
78 posix.EINVAL => unreachable,80 os.EINVAL => unreachable,
79 posix.ESRCH => unreachable,81 os.ESRCH => unreachable,
80 posix.EDEADLK => unreachable,82 os.EDEADLK => unreachable,
81 else => unreachable,83 else => unreachable,
82 }84 }
83 assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0);85 os.munmap(self.data.mmap_addr, self.data.mmap_len);
84 } else switch (builtin.os) {86 } else switch (builtin.os) {
85 builtin.Os.linux => {87 .linux => {
86 while (true) {88 while (true) {
87 const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst);89 const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst);
88 if (pid_value == 0) break;90 if (pid_value == 0) break;
89 const rc = linux.futex_wait(&self.data.handle, linux.FUTEX_WAIT, pid_value, null);91 const rc = linux.futex_wait(&self.data.handle, linux.FUTEX_WAIT, pid_value, null);
90 switch (linux.getErrno(rc)) {92 switch (linux.getErrno(rc)) {
91 0 => continue,93 0 => continue,
92 posix.EINTR => continue,94 os.EINTR => continue,
93 posix.EAGAIN => continue,95 os.EAGAIN => continue,
94 else => unreachable,96 else => unreachable,
95 }97 }
96 }98 }
97 assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0);99 os.munmap(self.data.mmap_addr, self.data.mmap_len);
98 },100 },
99 builtin.Os.windows => {101 .windows => {
100 assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0);102 assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0);
101 assert(windows.CloseHandle(self.data.handle) != 0);103 assert(windows.CloseHandle(self.data.handle) != 0);
102 assert(windows.HeapFree(self.data.heap_handle, 0, self.data.alloc_start) != 0);104 assert(windows.HeapFree(self.data.heap_handle, 0, self.data.alloc_start) != 0);
...@@ -153,10 +155,10 @@ pub const Thread = struct {...@@ -153,10 +155,10 @@ pub const Thread = struct {
153 extern fn threadMain(raw_arg: windows.LPVOID) windows.DWORD {155 extern fn threadMain(raw_arg: windows.LPVOID) windows.DWORD {
154 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;156 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
155 switch (@typeId(@typeOf(startFn).ReturnType)) {157 switch (@typeId(@typeOf(startFn).ReturnType)) {
156 builtin.TypeId.Int => {158 .Int => {
157 return startFn(arg);159 return startFn(arg);
158 },160 },
159 builtin.TypeId.Void => {161 .Void => {
160 startFn(arg);162 startFn(arg);
161 return 0;163 return 0;
162 },164 },
...@@ -196,10 +198,10 @@ pub const Thread = struct {...@@ -196,10 +198,10 @@ pub const Thread = struct {
196 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;198 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
197199
198 switch (@typeId(@typeOf(startFn).ReturnType)) {200 switch (@typeId(@typeOf(startFn).ReturnType)) {
199 builtin.TypeId.Int => {201 .Int => {
200 return startFn(arg);202 return startFn(arg);
201 },203 },
202 builtin.TypeId.Void => {204 .Void => {
203 startFn(arg);205 startFn(arg);
204 return 0;206 return 0;
205 },207 },
...@@ -217,7 +219,7 @@ pub const Thread = struct {...@@ -217,7 +219,7 @@ pub const Thread = struct {
217 }219 }
218 };220 };
219221
220 const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0;222 const MAP_GROWSDOWN = if (builtin.os == .linux) linux.MAP_GROWSDOWN else 0;
221223
222 var stack_end_offset: usize = undefined;224 var stack_end_offset: usize = undefined;
223 var thread_start_offset: usize = undefined;225 var thread_start_offset: usize = undefined;
...@@ -247,9 +249,8 @@ pub const Thread = struct {...@@ -247,9 +249,8 @@ pub const Thread = struct {
247 }249 }
248 break :blk l;250 break :blk l;
249 };251 };
250 const mmap_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);252 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);
251 if (mmap_addr == posix.MAP_FAILED) return error.OutOfMemory;253 errdefer os.munmap(mmap_addr, mmap_len);
252 errdefer assert(posix.munmap(mmap_addr, mmap_len) == 0);
253254
254 const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));255 const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));
255 thread_ptr.data.mmap_addr = mmap_addr;256 thread_ptr.data.mmap_addr = mmap_addr;
...@@ -273,31 +274,30 @@ pub const Thread = struct {...@@ -273,31 +274,30 @@ pub const Thread = struct {
273 const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));274 const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));
274 switch (err) {275 switch (err) {
275 0 => return thread_ptr,276 0 => return thread_ptr,
276 posix.EAGAIN => return error.SystemResources,277 os.EAGAIN => return error.SystemResources,
277 posix.EPERM => unreachable,278 os.EPERM => unreachable,
278 posix.EINVAL => unreachable,279 os.EINVAL => unreachable,
279 else => return unexpectedErrorPosix(@intCast(usize, err)),280 else => return os.unexpectedErrno(@intCast(usize, err)),
280 }281 }
281 } else if (builtin.os == builtin.Os.linux) {282 } else if (builtin.os == .linux) {
282 var flags: u32 = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND |283 var flags: u32 = os.CLONE_VM | os.CLONE_FS | os.CLONE_FILES | os.CLONE_SIGHAND |
283 posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID |284 os.CLONE_THREAD | os.CLONE_SYSVSEM | os.CLONE_PARENT_SETTID | os.CLONE_CHILD_CLEARTID |
284 posix.CLONE_DETACHED;285 os.CLONE_DETACHED;
285 var newtls: usize = undefined;286 var newtls: usize = undefined;
286 if (linux.tls.tls_image) |tls_img| {287 if (linux.tls.tls_image) |tls_img| {
287 newtls = linux.tls.copyTLS(mmap_addr + tls_start_offset);288 newtls = linux.tls.copyTLS(mmap_addr + tls_start_offset);
288 flags |= posix.CLONE_SETTLS;289 flags |= os.CLONE_SETTLS;
289 }290 }
290 const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);291 const rc = os.linux.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
291 const err = posix.getErrno(rc);292 switch (os.errno(rc)) {
292 switch (err) {
293 0 => return thread_ptr,293 0 => return thread_ptr,
294 posix.EAGAIN => return error.ThreadQuotaExceeded,294 os.EAGAIN => return error.ThreadQuotaExceeded,
295 posix.EINVAL => unreachable,295 os.EINVAL => unreachable,
296 posix.ENOMEM => return error.SystemResources,296 os.ENOMEM => return error.SystemResources,
297 posix.ENOSPC => unreachable,297 os.ENOSPC => unreachable,
298 posix.EPERM => unreachable,298 os.EPERM => unreachable,
299 posix.EUSERS => unreachable,299 os.EUSERS => unreachable,
300 else => return unexpectedErrorPosix(err),300 else => |err| return os.unexpectedErrno(err),
301 }301 }
302 } else {302 } else {
303 @compileError("Unsupported OS");303 @compileError("Unsupported OS");
...@@ -310,56 +310,20 @@ pub const Thread = struct {...@@ -310,56 +310,20 @@ pub const Thread = struct {
310 Unexpected,310 Unexpected,
311 };311 };
312312
313 pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {313 pub fn cpuCount() CpuCountError!usize {
314 switch (builtin.os) {314 if (os.linux.is_the_target) {
315 .macosx, .freebsd, .netbsd => {315 const cpu_set = try os.sched_getaffinity(0);
316 var count: c_int = undefined;316 return os.CPU_COUNT(cpu_set);
317 var count_len: usize = @sizeOf(c_int);317 }
318 const name = switch (builtin.os) {318 if (os.windows.is_the_target) {
319 builtin.Os.macosx => c"hw.logicalcpu",319 var system_info: windows.SYSTEM_INFO = undefined;
320 else => c"hw.ncpu",320 windows.GetSystemInfo(&system_info);
321 };321 return @intCast(usize, system_info.dwNumberOfProcessors);
322 try posix.sysctlbyname(name, @ptrCast(*c_void, &count), &count_len, null, 0);
323 return @intCast(usize, count);
324 },
325 .linux => {
326 const usize_count = 16;
327 const allocator = std.heap.stackFallback(usize_count * @sizeOf(usize), fallback_allocator).get();
328
329 var set = try allocator.alloc(usize, usize_count);
330 defer allocator.free(set);
331
332 while (true) {
333 const rc = posix.sched_getaffinity(0, set);
334 const err = posix.getErrno(rc);
335 switch (err) {
336 0 => {
337 if (rc < set.len * @sizeOf(usize)) {
338 const result = set[0 .. rc / @sizeOf(usize)];
339 var sum: usize = 0;
340 for (result) |x| {
341 sum += @popCount(usize, x);
342 }
343 return sum;
344 } else {
345 set = try allocator.realloc(set, set.len * 2);
346 continue;
347 }
348 },
349 posix.EFAULT => unreachable,
350 posix.EINVAL => unreachable,
351 posix.EPERM => return CpuCountError.PermissionDenied,
352 posix.ESRCH => unreachable,
353 else => return os.unexpectedErrorPosix(err),
354 }
355 }
356 },
357 .windows => {
358 var system_info: windows.SYSTEM_INFO = undefined;
359 windows.GetSystemInfo(&system_info);
360 return @intCast(usize, system_info.dwNumberOfProcessors);
361 },
362 else => @compileError("unsupported OS"),
363 }322 }
323 var count: c_int = undefined;
324 var count_len: usize = @sizeOf(c_int);
325 const name = if (os.darwin.is_the_target) c"hw.logicalcpu" else c"hw.ncpu";
326 try os.sysctlbyname(name, @ptrCast(*c_void, &count), &count_len, null, 0);
327 return @intCast(usize, count);
364 }328 }
365};329};