| author | |
| committer | |
| log | 7cb6279ac0cec065234347bda5944be64fe8b3da |
| tree | 0eb4befe9a7eb24f5a393559e0621e92e26a4c59 |
| parent | ca6debcaf4a4f85b7aff94c7b5fe821530b0f195 |
| signature |
28 files changed, 1390 insertions(+), 1392 deletions(-)
CMakeLists.txt-1| ... | ... | @@ -620,7 +620,6 @@ set(ZIG_STD_FILES |
| 620 | 620 | "os/freebsd.zig" |
| 621 | 621 | "os/linux.zig" |
| 622 | 622 | "os/linux/arm64.zig" |
| 623 | "os/linux/sys.zig" | |
| 624 | 623 | "os/linux/tls.zig" |
| 625 | 624 | "os/linux/vdso.zig" |
| 626 | 625 | "os/linux/x86_64.zig" |
std/atomic/queue.zig+4-4| ... | ... | @@ -186,13 +186,13 @@ test "std.atomic.Queue" { |
| 186 | 186 | } |
| 187 | 187 | } |
| 188 | 188 | } else { |
| 189 | var putters: [put_thread_count]*std.os.Thread = undefined; | |
| 189 | var putters: [put_thread_count]*std.Thread = undefined; | |
| 190 | 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 | 194 | for (getters) |*t| { |
| 195 | t.* = try std.os.spawnThread(&context, startGets); | |
| 195 | t.* = try std.Thread.spawn(&context, startGets); | |
| 196 | 196 | } |
| 197 | 197 | |
| 198 | 198 | for (putters) |t| |
std/atomic/stack.zig+4-4| ... | ... | @@ -120,13 +120,13 @@ test "std.atomic.stack" { |
| 120 | 120 | } |
| 121 | 121 | } |
| 122 | 122 | } else { |
| 123 | var putters: [put_thread_count]*std.os.Thread = undefined; | |
| 123 | var putters: [put_thread_count]*std.Thread = undefined; | |
| 124 | 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 | 128 | for (getters) |*t| { |
| 129 | t.* = try std.os.spawnThread(&context, startGets); | |
| 129 | t.* = try std.Thread.spawn(&context, startGets); | |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | for (putters) |t| |
std/c/darwin.zig+1-1| ... | ... | @@ -3,7 +3,7 @@ const assert = std.debug.assert; |
| 3 | 3 | const builtin = @import("builtin"); |
| 4 | 4 | const macho = std.macho; |
| 5 | 5 | |
| 6 | use @import("posix/darwin.zig"); | |
| 6 | use @import("../os/bits.zig"); | |
| 7 | 7 | |
| 8 | 8 | extern "c" fn __error() *c_int; |
| 9 | 9 | pub 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 | 2 | use std.c; |
| 3 | 3 | |
| 4 | 4 | pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int; |
| 5 | pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int; | |
| 5 | 6 | extern "c" fn __errno_location() *c_int; |
| 6 | 7 | pub const _errno = __errno_location; |
| 7 | 8 |
std/child_process.zig+9-9| ... | ... | @@ -351,22 +351,22 @@ pub const ChildProcess = struct { |
| 351 | 351 | const err_pipe = try os.pipe(); |
| 352 | 352 | errdefer destroyPipe(err_pipe); |
| 353 | 353 | |
| 354 | const pid_result = try posix.fork(); | |
| 354 | const pid_result = try os.fork(); | |
| 355 | 355 | if (pid_result == 0) { |
| 356 | 356 | // 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); | |
| 358 | setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.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); | |
| 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], os.STDOUT_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); | |
| 360 | 360 | |
| 361 | if (self.stdin_behavior == StdIo.Pipe) { | |
| 361 | if (self.stdin_behavior == .Pipe) { | |
| 362 | 362 | os.close(stdin_pipe[0]); |
| 363 | 363 | os.close(stdin_pipe[1]); |
| 364 | 364 | } |
| 365 | if (self.stdout_behavior == StdIo.Pipe) { | |
| 365 | if (self.stdout_behavior == .Pipe) { | |
| 366 | 366 | os.close(stdout_pipe[0]); |
| 367 | 367 | os.close(stdout_pipe[1]); |
| 368 | 368 | } |
| 369 | if (self.stderr_behavior == StdIo.Pipe) { | |
| 369 | if (self.stderr_behavior == .Pipe) { | |
| 370 | 370 | os.close(stderr_pipe[0]); |
| 371 | 371 | os.close(stderr_pipe[1]); |
| 372 | 372 | } |
| ... | ... | @@ -383,7 +383,7 @@ pub const ChildProcess = struct { |
| 383 | 383 | os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); |
| 384 | 384 | } |
| 385 | 385 | |
| 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 | } |
| 388 | 388 | |
| 389 | 389 | // we are the parent |
| ... | ... | @@ -736,7 +736,7 @@ fn destroyPipe(pipe: [2]i32) void { |
| 736 | 736 | // Then the child exits. |
| 737 | 737 | fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { |
| 738 | 738 | writeIntFd(fd, ErrInt(@errorToInt(err))) catch {}; |
| 739 | posix.exit(1); | |
| 739 | os.exit(1); | |
| 740 | 740 | } |
| 741 | 741 | |
| 742 | 742 | const ErrInt = @IntType(false, @sizeOf(anyerror) * 8); |
std/crypto.zig+1-1| ... | ... | @@ -33,7 +33,7 @@ pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; |
| 33 | 33 | pub const X25519 = @import("crypto/x25519.zig").X25519; |
| 34 | 34 | |
| 35 | 35 | const std = @import("std.zig"); |
| 36 | pub const randomBytes = std.posix.getrandom; | |
| 36 | pub const randomBytes = std.os.getrandom; | |
| 37 | 37 | |
| 38 | 38 | test "crypto" { |
| 39 | 39 | _ = @import("crypto/blake2.zig"); |
std/debug.zig+4-5| ... | ... | @@ -1012,16 +1012,15 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo { |
| 1012 | 1012 | errdefer S.self_exe_file.close(); |
| 1013 | 1013 | |
| 1014 | 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 | 1016 | null, |
| 1017 | 1017 | self_exe_mmap_len, |
| 1018 | os.posix.PROT_READ, | |
| 1019 | os.posix.MAP_SHARED, | |
| 1018 | os.PROT_READ, | |
| 1019 | os.MAP_SHARED, | |
| 1020 | 1020 | S.self_exe_file.handle, |
| 1021 | 1021 | 0, |
| 1022 | 1022 | ); |
| 1023 | if (self_exe_mmap == os.posix.MAP_FAILED) return error.OutOfMemory; | |
| 1024 | errdefer assert(os.posix.munmap(self_exe_mmap, self_exe_mmap_len) == 0); | |
| 1023 | errdefer os.munmap(self_exe_mmap, self_exe_mmap_len); | |
| 1025 | 1024 | |
| 1026 | 1025 | const file_mmap_slice = @intToPtr([*]const u8, self_exe_mmap)[0..self_exe_mmap_len]; |
| 1027 | 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 | 5 | const testing = std.testing; |
| 6 | 6 | const os = std.os; |
| 7 | 7 | const mem = std.mem; |
| 8 | const posix = os.posix; | |
| 9 | 8 | const windows = os.windows; |
| 10 | 9 | const Loop = event.Loop; |
| 11 | const fd_t = posix.fd_t; | |
| 10 | const fd_t = os.fd_t; | |
| 12 | 11 | const File = std.fs.File; |
| 13 | 12 | |
| 14 | 13 | pub const RequestNode = std.atomic.Queue(Request).Node; |
| ... | ... | @@ -33,7 +32,7 @@ pub const Request = struct { |
| 33 | 32 | |
| 34 | 33 | pub const PWriteV = struct { |
| 35 | 34 | fd: fd_t, |
| 36 | iov: []const os.posix.iovec_const, | |
| 35 | iov: []const os.iovec_const, | |
| 37 | 36 | offset: usize, |
| 38 | 37 | result: Error!void, |
| 39 | 38 | |
| ... | ... | @@ -42,7 +41,7 @@ pub const Request = struct { |
| 42 | 41 | |
| 43 | 42 | pub const PReadV = struct { |
| 44 | 43 | fd: fd_t, |
| 45 | iov: []const os.posix.iovec, | |
| 44 | iov: []const os.iovec, | |
| 46 | 45 | offset: usize, |
| 47 | 46 | result: Error!usize, |
| 48 | 47 | |
| ... | ... | @@ -89,11 +88,11 @@ pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: us |
| 89 | 88 | builtin.Os.freebsd, |
| 90 | 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 | 92 | defer loop.allocator.free(iovecs); |
| 94 | 93 | |
| 95 | 94 | for (data) |buf, i| { |
| 96 | iovecs[i] = os.posix.iovec_const{ | |
| 95 | iovecs[i] = os.iovec_const{ | |
| 97 | 96 | .iov_base = buf.ptr, |
| 98 | 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 | 170 | pub async fn pwritevPosix( |
| 172 | 171 | loop: *Loop, |
| 173 | 172 | fd: fd_t, |
| 174 | iovecs: []const posix.iovec_const, | |
| 173 | iovecs: []const os.iovec_const, | |
| 175 | 174 | offset: usize, |
| 176 | 175 | ) os.PosixWriteError!void { |
| 177 | 176 | // 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 | 225 | builtin.Os.freebsd, |
| 227 | 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 | 229 | defer loop.allocator.free(iovecs); |
| 231 | 230 | |
| 232 | 231 | for (data) |buf, i| { |
| 233 | iovecs[i] = os.posix.iovec{ | |
| 232 | iovecs[i] = os.iovec{ | |
| 234 | 233 | .iov_base = buf.ptr, |
| 235 | 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 | 318 | pub async fn preadvPosix( |
| 320 | 319 | loop: *Loop, |
| 321 | 320 | fd: fd_t, |
| 322 | iovecs: []const posix.iovec, | |
| 321 | iovecs: []const os.iovec, | |
| 323 | 322 | offset: usize, |
| 324 | 323 | ) os.PosixReadError!usize { |
| 325 | 324 | // workaround for https://github.com/ziglang/zig/issues/1194 |
| ... | ... | @@ -405,7 +404,7 @@ pub async fn openPosix( |
| 405 | 404 | pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t { |
| 406 | 405 | switch (builtin.os) { |
| 407 | 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 | 408 | return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable); |
| 410 | 409 | }, |
| 411 | 410 | |
| ... | ... | @@ -435,7 +434,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File. |
| 435 | 434 | builtin.Os.freebsd, |
| 436 | 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 | 438 | return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable); |
| 440 | 439 | }, |
| 441 | 440 | builtin.Os.windows => return os.windowsOpen( |
| ... | ... | @@ -457,7 +456,7 @@ pub async fn openReadWrite( |
| 457 | 456 | ) File.OpenError!fd_t { |
| 458 | 457 | switch (builtin.os) { |
| 459 | 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 | 460 | return await (async openPosix(loop, path, flags, mode) catch unreachable); |
| 462 | 461 | }, |
| 463 | 462 | |
| ... | ... | @@ -888,10 +887,7 @@ pub fn Watch(comptime V: type) type { |
| 888 | 887 | var close_op_consumed = false; |
| 889 | 888 | defer if (!close_op_consumed) close_op.finish(); |
| 890 | 889 | |
| 891 | const flags = switch (builtin.os) { | |
| 892 | builtin.Os.macosx => posix.O_SYMLINK | posix.O_EVTONLY, | |
| 893 | else => 0, | |
| 894 | }; | |
| 890 | const flags = if (os.darwin.is_the_target) os.O_SYMLINK | os.O_EVTONLY else 0; | |
| 895 | 891 | const mode = 0; |
| 896 | 892 | const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable); |
| 897 | 893 | close_op.setHandle(fd); |
| ... | ... | @@ -943,16 +939,16 @@ pub fn Watch(comptime V: type) type { |
| 943 | 939 | while (true) { |
| 944 | 940 | if (await (async self.channel.loop.bsdWaitKev( |
| 945 | 941 | @intCast(usize, close_op.getHandle()), |
| 946 | posix.EVFILT_VNODE, | |
| 947 | posix.NOTE_WRITE | posix.NOTE_DELETE, | |
| 942 | os.EVFILT_VNODE, | |
| 943 | os.NOTE_WRITE | os.NOTE_DELETE, | |
| 948 | 944 | ) catch unreachable)) |kev| { |
| 949 | 945 | // TODO handle EV_ERROR |
| 950 | if (kev.fflags & posix.NOTE_DELETE != 0) { | |
| 946 | if (kev.fflags & os.NOTE_DELETE != 0) { | |
| 951 | 947 | await (async self.channel.put(Self.Event{ |
| 952 | 948 | .id = Event.Id.Delete, |
| 953 | 949 | .data = value_copy, |
| 954 | 950 | }) catch unreachable); |
| 955 | } else if (kev.fflags & posix.NOTE_WRITE != 0) { | |
| 951 | } else if (kev.fflags & os.NOTE_WRITE != 0) { | |
| 956 | 952 | await (async self.channel.put(Self.Event{ |
| 957 | 953 | .id = Event.Id.CloseWrite, |
| 958 | 954 | .data = value_copy, |
std/event/loop.zig+71-71| ... | ... | @@ -7,9 +7,9 @@ const AtomicRmwOp = builtin.AtomicRmwOp; |
| 7 | 7 | const AtomicOrder = builtin.AtomicOrder; |
| 8 | 8 | const fs = std.event.fs; |
| 9 | 9 | const os = std.os; |
| 10 | const posix = os.posix; | |
| 11 | 10 | const windows = os.windows; |
| 12 | 11 | const maxInt = std.math.maxInt; |
| 12 | const Thread = std.Thread; | |
| 13 | 13 | |
| 14 | 14 | pub const Loop = struct { |
| 15 | 15 | allocator: *mem.Allocator, |
| ... | ... | @@ -17,7 +17,7 @@ pub const Loop = struct { |
| 17 | 17 | os_data: OsData, |
| 18 | 18 | final_resume_node: ResumeNode, |
| 19 | 19 | pending_event_count: usize, |
| 20 | extra_threads: []*os.Thread, | |
| 20 | extra_threads: []*Thread, | |
| 21 | 21 | |
| 22 | 22 | // pre-allocated eventfds. all permanently active. |
| 23 | 23 | // this is how we send promises to be resumed on other threads. |
| ... | ... | @@ -65,7 +65,7 @@ pub const Loop = struct { |
| 65 | 65 | |
| 66 | 66 | const KEventFd = struct { |
| 67 | 67 | base: ResumeNode, |
| 68 | kevent: posix.Kevent, | |
| 68 | kevent: os.Kevent, | |
| 69 | 69 | }; |
| 70 | 70 | |
| 71 | 71 | pub const Basic = switch (builtin.os) { |
| ... | ... | @@ -81,7 +81,7 @@ pub const Loop = struct { |
| 81 | 81 | |
| 82 | 82 | const KEventBasic = struct { |
| 83 | 83 | base: ResumeNode, |
| 84 | kev: posix.Kevent, | |
| 84 | kev: os.Kevent, | |
| 85 | 85 | }; |
| 86 | 86 | }; |
| 87 | 87 | |
| ... | ... | @@ -127,7 +127,7 @@ pub const Loop = struct { |
| 127 | 127 | ); |
| 128 | 128 | errdefer self.allocator.free(self.eventfd_resume_nodes); |
| 129 | 129 | |
| 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 | 131 | errdefer self.allocator.free(self.extra_threads); |
| 132 | 132 | |
| 133 | 133 | try self.initOsData(extra_thread_count); |
| ... | ... | @@ -172,32 +172,32 @@ pub const Loop = struct { |
| 172 | 172 | .handle = undefined, |
| 173 | 173 | .overlapped = ResumeNode.overlapped_init, |
| 174 | 174 | }, |
| 175 | .eventfd = try os.linuxEventFd(1, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK), | |
| 176 | .epoll_op = posix.EPOLL_CTL_ADD, | |
| 175 | .eventfd = try os.linuxEventFd(1, os.EFD_CLOEXEC | os.EFD_NONBLOCK), | |
| 176 | .epoll_op = os.EPOLL_CTL_ADD, | |
| 177 | 177 | }, |
| 178 | 178 | .next = undefined, |
| 179 | 179 | }; |
| 180 | 180 | self.available_eventfd_resume_nodes.push(eventfd_node); |
| 181 | 181 | } |
| 182 | 182 | |
| 183 | self.os_data.epollfd = try os.linuxEpollCreate(posix.EPOLL_CLOEXEC); | |
| 183 | self.os_data.epollfd = try os.linuxEpollCreate(os.EPOLL_CLOEXEC); | |
| 184 | 184 | errdefer os.close(self.os_data.epollfd); |
| 185 | 185 | |
| 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 | 187 | errdefer os.close(self.os_data.final_eventfd); |
| 188 | 188 | |
| 189 | self.os_data.final_eventfd_event = posix.epoll_event{ | |
| 190 | .events = posix.EPOLLIN, | |
| 191 | .data = posix.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) }, | |
| 189 | self.os_data.final_eventfd_event = os.epoll_event{ | |
| 190 | .events = os.EPOLLIN, | |
| 191 | .data = os.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) }, | |
| 192 | 192 | }; |
| 193 | 193 | try os.linuxEpollCtl( |
| 194 | 194 | self.os_data.epollfd, |
| 195 | posix.EPOLL_CTL_ADD, | |
| 195 | os.EPOLL_CTL_ADD, | |
| 196 | 196 | self.os_data.final_eventfd, |
| 197 | 197 | &self.os_data.final_eventfd_event, |
| 198 | 198 | ); |
| 199 | 199 | |
| 200 | self.os_data.fs_thread = try os.spawnThread(self, posixFsRun); | |
| 200 | self.os_data.fs_thread = try Thread.spawn(self, posixFsRun); | |
| 201 | 201 | errdefer { |
| 202 | 202 | self.posixFsRequest(&self.os_data.fs_end_request); |
| 203 | 203 | self.os_data.fs_thread.wait(); |
| ... | ... | @@ -218,7 +218,7 @@ pub const Loop = struct { |
| 218 | 218 | } |
| 219 | 219 | } |
| 220 | 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 | 224 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| ... | ... | @@ -240,7 +240,7 @@ pub const Loop = struct { |
| 240 | 240 | }, |
| 241 | 241 | }; |
| 242 | 242 | |
| 243 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | |
| 243 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; | |
| 244 | 244 | |
| 245 | 245 | for (self.eventfd_resume_nodes) |*eventfd_node, i| { |
| 246 | 246 | eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{ |
| ... | ... | @@ -251,10 +251,10 @@ pub const Loop = struct { |
| 251 | 251 | .overlapped = ResumeNode.overlapped_init, |
| 252 | 252 | }, |
| 253 | 253 | // this one is for sending events |
| 254 | .kevent = posix.Kevent{ | |
| 254 | .kevent = os.Kevent{ | |
| 255 | 255 | .ident = i, |
| 256 | .filter = posix.EVFILT_USER, | |
| 257 | .flags = posix.EV_CLEAR | posix.EV_ADD | posix.EV_DISABLE, | |
| 256 | .filter = os.EVFILT_USER, | |
| 257 | .flags = os.EV_CLEAR | os.EV_ADD | os.EV_DISABLE, | |
| 258 | 258 | .fflags = 0, |
| 259 | 259 | .data = 0, |
| 260 | 260 | .udata = @ptrToInt(&eventfd_node.data.base), |
| ... | ... | @@ -263,46 +263,46 @@ pub const Loop = struct { |
| 263 | 263 | .next = undefined, |
| 264 | 264 | }; |
| 265 | 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 | 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; | |
| 269 | eventfd_node.data.kevent.fflags = posix.NOTE_TRIGGER; | |
| 268 | eventfd_node.data.kevent.flags = os.EV_CLEAR | os.EV_ENABLE; | |
| 269 | eventfd_node.data.kevent.fflags = os.NOTE_TRIGGER; | |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | 272 | // Pre-add so that we cannot get error.SystemResources |
| 273 | 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 | 275 | .ident = extra_thread_count, |
| 276 | .filter = posix.EVFILT_USER, | |
| 277 | .flags = posix.EV_ADD | posix.EV_DISABLE, | |
| 276 | .filter = os.EVFILT_USER, | |
| 277 | .flags = os.EV_ADD | os.EV_DISABLE, | |
| 278 | 278 | .fflags = 0, |
| 279 | 279 | .data = 0, |
| 280 | 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 | 283 | _ = try os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null); |
| 284 | self.os_data.final_kevent.flags = posix.EV_ENABLE; | |
| 285 | self.os_data.final_kevent.fflags = posix.NOTE_TRIGGER; | |
| 284 | self.os_data.final_kevent.flags = os.EV_ENABLE; | |
| 285 | self.os_data.final_kevent.fflags = os.NOTE_TRIGGER; | |
| 286 | 286 | |
| 287 | self.os_data.fs_kevent_wake = posix.Kevent{ | |
| 287 | self.os_data.fs_kevent_wake = os.Kevent{ | |
| 288 | 288 | .ident = 0, |
| 289 | .filter = posix.EVFILT_USER, | |
| 290 | .flags = posix.EV_ADD | posix.EV_ENABLE, | |
| 291 | .fflags = posix.NOTE_TRIGGER, | |
| 289 | .filter = os.EVFILT_USER, | |
| 290 | .flags = os.EV_ADD | os.EV_ENABLE, | |
| 291 | .fflags = os.NOTE_TRIGGER, | |
| 292 | 292 | .data = 0, |
| 293 | 293 | .udata = undefined, |
| 294 | 294 | }; |
| 295 | 295 | |
| 296 | self.os_data.fs_kevent_wait = posix.Kevent{ | |
| 296 | self.os_data.fs_kevent_wait = os.Kevent{ | |
| 297 | 297 | .ident = 0, |
| 298 | .filter = posix.EVFILT_USER, | |
| 299 | .flags = posix.EV_ADD | posix.EV_CLEAR, | |
| 298 | .filter = os.EVFILT_USER, | |
| 299 | .flags = os.EV_ADD | os.EV_CLEAR, | |
| 300 | 300 | .fflags = 0, |
| 301 | 301 | .data = 0, |
| 302 | 302 | .udata = undefined, |
| 303 | 303 | }; |
| 304 | 304 | |
| 305 | self.os_data.fs_thread = try os.spawnThread(self, posixFsRun); | |
| 305 | self.os_data.fs_thread = try Thread.spawn(self, posixFsRun); | |
| 306 | 306 | errdefer { |
| 307 | 307 | self.posixFsRequest(&self.os_data.fs_end_request); |
| 308 | 308 | self.os_data.fs_thread.wait(); |
| ... | ... | @@ -322,7 +322,7 @@ pub const Loop = struct { |
| 322 | 322 | } |
| 323 | 323 | } |
| 324 | 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 | 328 | builtin.Os.windows => { |
| ... | ... | @@ -371,7 +371,7 @@ pub const Loop = struct { |
| 371 | 371 | } |
| 372 | 372 | } |
| 373 | 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 | 377 | else => {}, |
| ... | ... | @@ -400,19 +400,19 @@ pub const Loop = struct { |
| 400 | 400 | /// resume_node must live longer than the promise that it holds a reference to. |
| 401 | 401 | /// flags must contain EPOLLET |
| 402 | 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 | 404 | self.beginOneEvent(); |
| 405 | 405 | errdefer self.finishOneEvent(); |
| 406 | 406 | try self.linuxModFd( |
| 407 | 407 | fd, |
| 408 | posix.EPOLL_CTL_ADD, | |
| 408 | os.EPOLL_CTL_ADD, | |
| 409 | 409 | flags, |
| 410 | 410 | resume_node, |
| 411 | 411 | ); |
| 412 | 412 | } |
| 413 | 413 | |
| 414 | 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 | 416 | var ev = os.linux.epoll_event{ |
| 417 | 417 | .events = flags, |
| 418 | 418 | .data = os.linux.epoll_data{ .ptr = @ptrToInt(resume_node) }, |
| ... | ... | @@ -440,7 +440,7 @@ pub const Loop = struct { |
| 440 | 440 | } |
| 441 | 441 | } |
| 442 | 442 | |
| 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 | 444 | // TODO #1194 |
| 445 | 445 | suspend { |
| 446 | 446 | resume @handle(); |
| ... | ... | @@ -464,30 +464,30 @@ pub const Loop = struct { |
| 464 | 464 | pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void { |
| 465 | 465 | self.beginOneEvent(); |
| 466 | 466 | errdefer self.finishOneEvent(); |
| 467 | var kev = posix.Kevent{ | |
| 467 | var kev = os.Kevent{ | |
| 468 | 468 | .ident = ident, |
| 469 | 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 | 471 | .fflags = fflags, |
| 472 | 472 | .data = 0, |
| 473 | 473 | .udata = @ptrToInt(&resume_node.base), |
| 474 | 474 | }; |
| 475 | const kevent_array = (*const [1]posix.Kevent)(&kev); | |
| 476 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | |
| 475 | const kevent_array = (*const [1]os.Kevent)(&kev); | |
| 476 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; | |
| 477 | 477 | _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null); |
| 478 | 478 | } |
| 479 | 479 | |
| 480 | 480 | pub fn bsdRemoveKev(self: *Loop, ident: usize, filter: i16) void { |
| 481 | var kev = posix.Kevent{ | |
| 481 | var kev = os.Kevent{ | |
| 482 | 482 | .ident = ident, |
| 483 | 483 | .filter = filter, |
| 484 | .flags = posix.EV_DELETE, | |
| 484 | .flags = os.EV_DELETE, | |
| 485 | 485 | .fflags = 0, |
| 486 | 486 | .data = 0, |
| 487 | 487 | .udata = 0, |
| 488 | 488 | }; |
| 489 | const kevent_array = (*const [1]posix.Kevent)(&kev); | |
| 490 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | |
| 489 | const kevent_array = (*const [1]os.Kevent)(&kev); | |
| 490 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; | |
| 491 | 491 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch undefined; |
| 492 | 492 | self.finishOneEvent(); |
| 493 | 493 | } |
| ... | ... | @@ -502,8 +502,8 @@ pub const Loop = struct { |
| 502 | 502 | eventfd_node.base.handle = next_tick_node.data; |
| 503 | 503 | switch (builtin.os) { |
| 504 | 504 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 505 | const kevent_array = (*const [1]posix.Kevent)(&eventfd_node.kevent); | |
| 506 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | |
| 505 | const kevent_array = (*const [1]os.Kevent)(&eventfd_node.kevent); | |
| 506 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; | |
| 507 | 507 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch { |
| 508 | 508 | self.next_tick_queue.unget(next_tick_node); |
| 509 | 509 | self.available_eventfd_resume_nodes.push(resume_stack_node); |
| ... | ... | @@ -512,7 +512,7 @@ pub const Loop = struct { |
| 512 | 512 | }, |
| 513 | 513 | builtin.Os.linux => { |
| 514 | 514 | // 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 | 516 | os.linux.EPOLLET; |
| 517 | 517 | self.linuxModFd( |
| 518 | 518 | eventfd_node.eventfd, |
| ... | ... | @@ -631,8 +631,8 @@ pub const Loop = struct { |
| 631 | 631 | }, |
| 632 | 632 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 633 | 633 | self.posixFsRequest(&self.os_data.fs_end_request); |
| 634 | const final_kevent = (*const [1]posix.Kevent)(&self.os_data.final_kevent); | |
| 635 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | |
| 634 | const final_kevent = (*const [1]os.Kevent)(&self.os_data.final_kevent); | |
| 635 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; | |
| 636 | 636 | // cannot fail because we already added it and this just enables it |
| 637 | 637 | _ = os.bsdKEvent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable; |
| 638 | 638 | return; |
| ... | ... | @@ -676,7 +676,7 @@ pub const Loop = struct { |
| 676 | 676 | ResumeNode.Id.Stop => return, |
| 677 | 677 | ResumeNode.Id.EventFd => { |
| 678 | 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 | 680 | const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node); |
| 681 | 681 | self.available_eventfd_resume_nodes.push(stack_node); |
| 682 | 682 | }, |
| ... | ... | @@ -688,8 +688,8 @@ pub const Loop = struct { |
| 688 | 688 | } |
| 689 | 689 | }, |
| 690 | 690 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 691 | var eventlist: [1]posix.Kevent = undefined; | |
| 692 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | |
| 691 | var eventlist: [1]os.Kevent = undefined; | |
| 692 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; | |
| 693 | 693 | const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable; |
| 694 | 694 | for (eventlist[0..count]) |ev| { |
| 695 | 695 | const resume_node = @intToPtr(*ResumeNode, ev.udata); |
| ... | ... | @@ -751,8 +751,8 @@ pub const Loop = struct { |
| 751 | 751 | self.os_data.fs_queue.put(request_node); |
| 752 | 752 | switch (builtin.os) { |
| 753 | 753 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 754 | const fs_kevs = (*const [1]posix.Kevent)(&self.os_data.fs_kevent_wake); | |
| 755 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | |
| 754 | const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wake); | |
| 755 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; | |
| 756 | 756 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable; |
| 757 | 757 | }, |
| 758 | 758 | builtin.Os.linux => { |
| ... | ... | @@ -760,7 +760,7 @@ pub const Loop = struct { |
| 760 | 760 | const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1); |
| 761 | 761 | switch (os.linux.getErrno(rc)) { |
| 762 | 762 | 0 => {}, |
| 763 | posix.EINVAL => unreachable, | |
| 763 | os.EINVAL => unreachable, | |
| 764 | 764 | else => unreachable, |
| 765 | 765 | } |
| 766 | 766 | }, |
| ... | ... | @@ -793,8 +793,8 @@ pub const Loop = struct { |
| 793 | 793 | }, |
| 794 | 794 | @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd), |
| 795 | 795 | @TagType(fs.Request.Msg).WriteFile => |*msg| blk: { |
| 796 | const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | | |
| 797 | posix.O_CLOEXEC | posix.O_TRUNC; | |
| 796 | const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | | |
| 797 | os.O_CLOEXEC | os.O_TRUNC; | |
| 798 | 798 | const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| { |
| 799 | 799 | msg.result = err; |
| 800 | 800 | break :blk; |
| ... | ... | @@ -816,13 +816,13 @@ pub const Loop = struct { |
| 816 | 816 | builtin.Os.linux => { |
| 817 | 817 | const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null); |
| 818 | 818 | switch (os.linux.getErrno(rc)) { |
| 819 | 0, posix.EINTR, posix.EAGAIN => continue, | |
| 819 | 0, os.EINTR, os.EAGAIN => continue, | |
| 820 | 820 | else => unreachable, |
| 821 | 821 | } |
| 822 | 822 | }, |
| 823 | 823 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 824 | const fs_kevs = (*const [1]posix.Kevent)(&self.os_data.fs_kevent_wait); | |
| 825 | var out_kevs: [1]posix.Kevent = undefined; | |
| 824 | const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wait); | |
| 825 | var out_kevs: [1]os.Kevent = undefined; | |
| 826 | 826 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable; |
| 827 | 827 | }, |
| 828 | 828 | else => @compileError("Unsupported OS"), |
| ... | ... | @@ -842,10 +842,10 @@ pub const Loop = struct { |
| 842 | 842 | |
| 843 | 843 | const KEventData = struct { |
| 844 | 844 | kqfd: i32, |
| 845 | final_kevent: posix.Kevent, | |
| 846 | fs_kevent_wake: posix.Kevent, | |
| 847 | fs_kevent_wait: posix.Kevent, | |
| 848 | fs_thread: *os.Thread, | |
| 845 | final_kevent: os.Kevent, | |
| 846 | fs_kevent_wake: os.Kevent, | |
| 847 | fs_kevent_wait: os.Kevent, | |
| 848 | fs_thread: *Thread, | |
| 849 | 849 | fs_kqfd: i32, |
| 850 | 850 | fs_queue: std.atomic.Queue(fs.Request), |
| 851 | 851 | fs_end_request: fs.RequestNode, |
| ... | ... | @@ -855,7 +855,7 @@ pub const Loop = struct { |
| 855 | 855 | epollfd: i32, |
| 856 | 856 | final_eventfd: i32, |
| 857 | 857 | final_eventfd_event: os.linux.epoll_event, |
| 858 | fs_thread: *os.Thread, | |
| 858 | fs_thread: *Thread, | |
| 859 | 859 | fs_queue_item: i32, |
| 860 | 860 | fs_queue: std.atomic.Queue(fs.Request), |
| 861 | 861 | fs_end_request: fs.RequestNode, |
std/event/net.zig+54-59| ... | ... | @@ -4,11 +4,9 @@ const testing = std.testing; |
| 4 | 4 | const event = std.event; |
| 5 | 5 | const mem = std.mem; |
| 6 | 6 | const os = std.os; |
| 7 | const posix = os.posix; | |
| 8 | 7 | const Loop = std.event.Loop; |
| 9 | 8 | const File = std.fs.File; |
| 10 | ||
| 11 | const fd_t = posix.fd_t; | |
| 9 | const fd_t = os.fd_t; | |
| 12 | 10 | |
| 13 | 11 | pub const Server = struct { |
| 14 | 12 | handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void, |
| ... | ... | @@ -47,19 +45,19 @@ pub const Server = struct { |
| 47 | 45 | ) !void { |
| 48 | 46 | self.handleRequestFn = handleRequestFn; |
| 49 | 47 | |
| 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 | 49 | errdefer os.close(sockfd); |
| 52 | 50 | self.sockfd = sockfd; |
| 53 | 51 | |
| 54 | 52 | try os.posixBind(sockfd, &address.os_addr); |
| 55 | try os.posixListen(sockfd, posix.SOMAXCONN); | |
| 53 | try os.posixListen(sockfd, os.SOMAXCONN); | |
| 56 | 54 | self.listen_address = std.net.Address.initPosix(try os.posixGetSockName(sockfd)); |
| 57 | 55 | |
| 58 | 56 | self.accept_coro = try async<self.loop.allocator> Server.handler(self); |
| 59 | 57 | errdefer cancel self.accept_coro.?; |
| 60 | 58 | |
| 61 | 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 | 61 | errdefer self.loop.removeFd(sockfd); |
| 64 | 62 | } |
| 65 | 63 | |
| ... | ... | @@ -78,7 +76,7 @@ pub const Server = struct { |
| 78 | 76 | while (true) { |
| 79 | 77 | var accepted_addr: std.net.Address = undefined; |
| 80 | 78 | // 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 | 80 | if (accepted_fd == -1) { |
| 83 | 81 | // would block |
| 84 | 82 | suspend; // we will get resumed by epoll_wait in the event loop |
| ... | ... | @@ -108,22 +106,22 @@ pub const Server = struct { |
| 108 | 106 | |
| 109 | 107 | pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 { |
| 110 | 108 | const sockfd = try os.posixSocket( |
| 111 | posix.AF_UNIX, | |
| 112 | posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, | |
| 109 | os.AF_UNIX, | |
| 110 | os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, | |
| 113 | 111 | 0, |
| 114 | 112 | ); |
| 115 | 113 | errdefer os.close(sockfd); |
| 116 | 114 | |
| 117 | var sock_addr = posix.sockaddr_un{ | |
| 118 | .family = posix.AF_UNIX, | |
| 115 | var sock_addr = os.sockaddr_un{ | |
| 116 | .family = os.AF_UNIX, | |
| 119 | 117 | .path = undefined, |
| 120 | 118 | }; |
| 121 | 119 | |
| 122 | 120 | if (path.len > @typeOf(sock_addr.path).len) return error.NameTooLong; |
| 123 | 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 | 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 | 125 | try os.posixGetSockOptConnectError(sockfd); |
| 128 | 126 | |
| 129 | 127 | return sockfd; |
| ... | ... | @@ -143,50 +141,48 @@ pub const ReadError = error{ |
| 143 | 141 | |
| 144 | 142 | /// returns number of bytes read. 0 means EOF. |
| 145 | 143 | pub 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 | 145 | .iov_base = buffer.ptr, |
| 148 | 146 | .iov_len = buffer.len, |
| 149 | 147 | }; |
| 150 | const iovs: *const [1]posix.iovec = &iov; | |
| 148 | const iovs: *const [1]os.iovec = &iov; | |
| 151 | 149 | return await (async readvPosix(loop, fd, iovs, 1) catch unreachable); |
| 152 | 150 | } |
| 153 | 151 | |
| 154 | 152 | pub const WriteError = error{}; |
| 155 | 153 | |
| 156 | 154 | pub 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 | 156 | .iov_base = buffer.ptr, |
| 159 | 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 | 160 | return await (async writevPosix(loop, fd, iovs, 1) catch unreachable); |
| 163 | 161 | } |
| 164 | 162 | |
| 165 | pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const, count: usize) !void { | |
| 163 | pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const os.iovec_const, count: usize) !void { | |
| 166 | 164 | while (true) { |
| 167 | 165 | switch (builtin.os) { |
| 168 | builtin.Os.macosx, builtin.Os.linux => { | |
| 169 | const rc = posix.writev(fd, iov, count); | |
| 170 | const err = posix.getErrno(rc); | |
| 171 | switch (err) { | |
| 166 | .macosx, .linux => { | |
| 167 | switch (os.errno(os.system.writev(fd, iov, count))) { | |
| 172 | 168 | 0 => return, |
| 173 | posix.EINTR => continue, | |
| 174 | posix.ESPIPE => unreachable, | |
| 175 | posix.EINVAL => unreachable, | |
| 176 | posix.EFAULT => unreachable, | |
| 177 | posix.EAGAIN => { | |
| 178 | try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLOUT) catch unreachable); | |
| 169 | os.EINTR => continue, | |
| 170 | os.ESPIPE => unreachable, | |
| 171 | os.EINVAL => unreachable, | |
| 172 | os.EFAULT => unreachable, | |
| 173 | os.EAGAIN => { | |
| 174 | try await (async loop.linuxWaitFd(fd, os.EPOLLET | os.EPOLLOUT) catch unreachable); | |
| 179 | 175 | continue; |
| 180 | 176 | }, |
| 181 | posix.EBADF => unreachable, // always a race condition | |
| 182 | posix.EDESTADDRREQ => unreachable, // connect was never called | |
| 183 | posix.EDQUOT => unreachable, | |
| 184 | posix.EFBIG => unreachable, | |
| 185 | posix.EIO => return error.InputOutput, | |
| 186 | posix.ENOSPC => unreachable, | |
| 187 | posix.EPERM => return error.AccessDenied, | |
| 188 | posix.EPIPE => unreachable, | |
| 189 | else => return os.unexpectedErrorPosix(err), | |
| 177 | os.EBADF => unreachable, // always a race condition | |
| 178 | os.EDESTADDRREQ => unreachable, // connect was never called | |
| 179 | os.EDQUOT => unreachable, | |
| 180 | os.EFBIG => unreachable, | |
| 181 | os.EIO => return error.InputOutput, | |
| 182 | os.ENOSPC => unreachable, | |
| 183 | os.EPERM => return error.AccessDenied, | |
| 184 | os.EPIPE => unreachable, | |
| 185 | else => |err| return os.unexpectedErrno(err), | |
| 190 | 186 | } |
| 191 | 187 | }, |
| 192 | 188 | else => @compileError("Unsupported OS"), |
| ... | ... | @@ -195,27 +191,26 @@ pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const, |
| 195 | 191 | } |
| 196 | 192 | |
| 197 | 193 | /// returns number of bytes read. 0 means EOF. |
| 198 | pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, count: usize) !usize { | |
| 194 | pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]os.iovec, count: usize) !usize { | |
| 199 | 195 | while (true) { |
| 200 | 196 | switch (builtin.os) { |
| 201 | 197 | builtin.Os.linux, builtin.Os.freebsd, builtin.Os.macosx => { |
| 202 | const rc = posix.readv(fd, iov, count); | |
| 203 | const err = posix.getErrno(rc); | |
| 204 | switch (err) { | |
| 198 | const rc = os.system.readv(fd, iov, count); | |
| 199 | switch (os.errno(rc)) { | |
| 205 | 200 | 0 => return rc, |
| 206 | posix.EINTR => continue, | |
| 207 | posix.EINVAL => unreachable, | |
| 208 | posix.EFAULT => unreachable, | |
| 209 | posix.EAGAIN => { | |
| 210 | try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLIN) catch unreachable); | |
| 201 | os.EINTR => continue, | |
| 202 | os.EINVAL => unreachable, | |
| 203 | os.EFAULT => unreachable, | |
| 204 | os.EAGAIN => { | |
| 205 | try await (async loop.linuxWaitFd(fd, os.EPOLLET | os.EPOLLIN) catch unreachable); | |
| 211 | 206 | continue; |
| 212 | 207 | }, |
| 213 | posix.EBADF => unreachable, // always a race condition | |
| 214 | posix.EIO => return error.InputOutput, | |
| 215 | posix.EISDIR => unreachable, | |
| 216 | posix.ENOBUFS => return error.SystemResources, | |
| 217 | posix.ENOMEM => return error.SystemResources, | |
| 218 | else => return os.unexpectedErrorPosix(err), | |
| 208 | os.EBADF => unreachable, // always a race condition | |
| 209 | os.EIO => return error.InputOutput, | |
| 210 | os.EISDIR => unreachable, | |
| 211 | os.ENOBUFS => return error.SystemResources, | |
| 212 | os.ENOMEM => return error.SystemResources, | |
| 213 | else => |err| return os.unexpectedErrno(err), | |
| 219 | 214 | } |
| 220 | 215 | }, |
| 221 | 216 | else => @compileError("Unsupported OS"), |
| ... | ... | @@ -224,11 +219,11 @@ pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, cou |
| 224 | 219 | } |
| 225 | 220 | |
| 226 | 221 | pub 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 | 223 | defer loop.allocator.free(iovecs); |
| 229 | 224 | |
| 230 | 225 | for (data) |buf, i| { |
| 231 | iovecs[i] = os.posix.iovec_const{ | |
| 226 | iovecs[i] = os.iovec_const{ | |
| 232 | 227 | .iov_base = buf.ptr, |
| 233 | 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 | 233 | } |
| 239 | 234 | |
| 240 | 235 | pub 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 | 237 | defer loop.allocator.free(iovecs); |
| 243 | 238 | |
| 244 | 239 | for (data) |buf, i| { |
| 245 | iovecs[i] = os.posix.iovec{ | |
| 240 | iovecs[i] = os.iovec{ | |
| 246 | 241 | .iov_base = buf.ptr, |
| 247 | 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 | 249 | pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File { |
| 255 | 250 | var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592 |
| 256 | 251 | |
| 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 | 253 | errdefer os.close(sockfd); |
| 259 | 254 | |
| 260 | try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(posix.sockaddr_in)); | |
| 261 | try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET); | |
| 255 | try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(os.sockaddr_in)); | |
| 256 | try await try async loop.linuxWaitFd(sockfd, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET); | |
| 262 | 257 | try os.posixGetSockOptConnectError(sockfd); |
| 263 | 258 | |
| 264 | 259 | return File.openHandle(sockfd); |
std/fs/path.zig+17-20| ... | ... | @@ -9,24 +9,21 @@ const fmt = std.fmt; |
| 9 | 9 | const Allocator = mem.Allocator; |
| 10 | 10 | const os = std.os; |
| 11 | 11 | const math = std.math; |
| 12 | const posix = os.posix; | |
| 13 | 12 | const windows = os.windows; |
| 14 | 13 | const cstr = std.cstr; |
| 15 | 14 | |
| 16 | 15 | pub const sep_windows = '\\'; |
| 17 | 16 | pub const sep_posix = '/'; |
| 18 | pub const sep = if (is_windows) sep_windows else sep_posix; | |
| 17 | pub const sep = if (windows.is_the_target) sep_windows else sep_posix; | |
| 19 | 18 | |
| 20 | 19 | pub const sep_str = [1]u8{sep}; |
| 21 | 20 | |
| 22 | 21 | pub const delimiter_windows = ';'; |
| 23 | 22 | pub const delimiter_posix = ':'; |
| 24 | pub const delimiter = if (is_windows) delimiter_windows else delimiter_posix; | |
| 25 | ||
| 26 | const is_windows = builtin.os == builtin.Os.windows; | |
| 23 | pub const delimiter = if (windows.is_the_target) delimiter_windows else delimiter_posix; | |
| 27 | 24 | |
| 28 | 25 | pub fn isSep(byte: u8) bool { |
| 29 | if (is_windows) { | |
| 26 | if (windows.is_the_target) { | |
| 30 | 27 | return byte == '/' or byte == '\\'; |
| 31 | 28 | } else { |
| 32 | 29 | return byte == '/'; |
| ... | ... | @@ -76,7 +73,7 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u |
| 76 | 73 | return buf; |
| 77 | 74 | } |
| 78 | 75 | |
| 79 | pub const join = if (is_windows) joinWindows else joinPosix; | |
| 76 | pub const join = if (windows.is_the_target) joinWindows else joinPosix; | |
| 80 | 77 | |
| 81 | 78 | /// Naively combines a series of paths with the native path seperator. |
| 82 | 79 | /// Allocates memory for the result, which must be freed by the caller. |
| ... | ... | @@ -133,7 +130,7 @@ test "join" { |
| 133 | 130 | } |
| 134 | 131 | |
| 135 | 132 | pub fn isAbsolute(path: []const u8) bool { |
| 136 | if (is_windows) { | |
| 133 | if (windows.is_the_target) { | |
| 137 | 134 | return isAbsoluteWindows(path); |
| 138 | 135 | } else { |
| 139 | 136 | return isAbsolutePosix(path); |
| ... | ... | @@ -312,7 +309,7 @@ test "windowsParsePath" { |
| 312 | 309 | } |
| 313 | 310 | |
| 314 | 311 | pub fn diskDesignator(path: []const u8) []const u8 { |
| 315 | if (is_windows) { | |
| 312 | if (windows.is_the_target) { | |
| 316 | 313 | return diskDesignatorWindows(path); |
| 317 | 314 | } else { |
| 318 | 315 | return ""; |
| ... | ... | @@ -377,7 +374,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool { |
| 377 | 374 | |
| 378 | 375 | /// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`. |
| 379 | 376 | pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 380 | if (is_windows) { | |
| 377 | if (windows.is_the_target) { | |
| 381 | 378 | return resolveWindows(allocator, paths); |
| 382 | 379 | } else { |
| 383 | 380 | return resolvePosix(allocator, paths); |
| ... | ... | @@ -394,7 +391,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 394 | 391 | /// Without performing actual syscalls, resolving `..` could be incorrect. |
| 395 | 392 | pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 396 | 393 | if (paths.len == 0) { |
| 397 | assert(is_windows); // resolveWindows called on non windows can't use getCwd | |
| 394 | assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd | |
| 398 | 395 | return os.getCwdAlloc(allocator); |
| 399 | 396 | } |
| 400 | 397 | |
| ... | ... | @@ -489,7 +486,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 489 | 486 | result_disk_designator = result[0..result_index]; |
| 490 | 487 | }, |
| 491 | 488 | WindowsPath.Kind.None => { |
| 492 | assert(is_windows); // resolveWindows called on non windows can't use getCwd | |
| 489 | assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd | |
| 493 | 490 | const cwd = try os.getCwdAlloc(allocator); |
| 494 | 491 | defer allocator.free(cwd); |
| 495 | 492 | const parsed_cwd = windowsParsePath(cwd); |
| ... | ... | @@ -504,7 +501,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 504 | 501 | }, |
| 505 | 502 | } |
| 506 | 503 | } else { |
| 507 | assert(is_windows); // resolveWindows called on non windows can't use getCwd | |
| 504 | assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd | |
| 508 | 505 | // TODO call get cwd for the result_disk_designator instead of the global one |
| 509 | 506 | const cwd = try os.getCwdAlloc(allocator); |
| 510 | 507 | defer allocator.free(cwd); |
| ... | ... | @@ -575,7 +572,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 575 | 572 | /// Without performing actual syscalls, resolving `..` could be incorrect. |
| 576 | 573 | pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 577 | 574 | if (paths.len == 0) { |
| 578 | assert(!is_windows); // resolvePosix called on windows can't use getCwd | |
| 575 | assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd | |
| 579 | 576 | return os.getCwdAlloc(allocator); |
| 580 | 577 | } |
| 581 | 578 | |
| ... | ... | @@ -597,7 +594,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 597 | 594 | if (have_abs) { |
| 598 | 595 | result = try allocator.alloc(u8, max_size); |
| 599 | 596 | } else { |
| 600 | assert(!is_windows); // resolvePosix called on windows can't use getCwd | |
| 597 | assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd | |
| 601 | 598 | const cwd = try os.getCwdAlloc(allocator); |
| 602 | 599 | defer allocator.free(cwd); |
| 603 | 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 | 635 | |
| 639 | 636 | test "resolve" { |
| 640 | 637 | const cwd = try os.getCwdAlloc(debug.global_allocator); |
| 641 | if (is_windows) { | |
| 638 | if (windows.is_the_target) { | |
| 642 | 639 | if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) { |
| 643 | 640 | cwd[0] = asciiUpper(cwd[0]); |
| 644 | 641 | } |
| ... | ... | @@ -650,7 +647,7 @@ test "resolve" { |
| 650 | 647 | } |
| 651 | 648 | |
| 652 | 649 | test "resolveWindows" { |
| 653 | if (is_windows) { | |
| 650 | if (windows.is_the_target) { | |
| 654 | 651 | const cwd = try os.getCwdAlloc(debug.global_allocator); |
| 655 | 652 | const parsed_cwd = windowsParsePath(cwd); |
| 656 | 653 | { |
| ... | ... | @@ -716,7 +713,7 @@ fn testResolvePosix(paths: []const []const u8) []u8 { |
| 716 | 713 | /// If the path is a file in the current directory (no directory component) |
| 717 | 714 | /// then returns null |
| 718 | 715 | pub fn dirname(path: []const u8) ?[]const u8 { |
| 719 | if (is_windows) { | |
| 716 | if (windows.is_the_target) { | |
| 720 | 717 | return dirnameWindows(path); |
| 721 | 718 | } else { |
| 722 | 719 | return dirnamePosix(path); |
| ... | ... | @@ -848,7 +845,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void { |
| 848 | 845 | } |
| 849 | 846 | |
| 850 | 847 | pub fn basename(path: []const u8) []const u8 { |
| 851 | if (is_windows) { | |
| 848 | if (windows.is_the_target) { | |
| 852 | 849 | return basenameWindows(path); |
| 853 | 850 | } else { |
| 854 | 851 | return basenamePosix(path); |
| ... | ... | @@ -964,7 +961,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void { |
| 964 | 961 | /// string is returned. |
| 965 | 962 | /// On Windows this canonicalizes the drive to a capital letter and paths to `\\`. |
| 966 | 963 | pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 { |
| 967 | if (is_windows) { | |
| 964 | if (windows.is_the_target) { | |
| 968 | 965 | return relativeWindows(allocator, from, to); |
| 969 | 966 | } else { |
| 970 | 967 | return relativePosix(allocator, from, to); |
std/heap.zig+156-168| ... | ... | @@ -5,7 +5,6 @@ const testing = std.testing; |
| 5 | 5 | const mem = std.mem; |
| 6 | 6 | const os = std.os; |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | const Os = builtin.Os; | |
| 9 | 8 | const c = std.c; |
| 10 | 9 | const maxInt = std.math.maxInt; |
| 11 | 10 | |
| ... | ... | @@ -51,201 +50,190 @@ pub const DirectAllocator = struct { |
| 51 | 50 | if (n == 0) |
| 52 | 51 | return (([*]u8)(undefined))[0..0]; |
| 53 | 52 | |
| 54 | switch (builtin.os) { | |
| 55 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 56 | const p = os.posix; | |
| 57 | const alloc_size = if (alignment <= os.page_size) n else n + alignment; | |
| 58 | const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0); | |
| 59 | if (addr == p.MAP_FAILED) return error.OutOfMemory; | |
| 60 | if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n]; | |
| 61 | ||
| 62 | const aligned_addr = mem.alignForward(addr, alignment); | |
| 63 | ||
| 64 | // Unmap the extra bytes that were only requested in order to guarantee | |
| 65 | // that the range of memory we were provided had a proper alignment in | |
| 66 | // it somewhere. The extra bytes could be at the beginning, or end, or both. | |
| 67 | const unused_start_len = aligned_addr - addr; | |
| 68 | if (unused_start_len != 0) { | |
| 69 | const err = p.munmap(addr, unused_start_len); | |
| 70 | assert(p.getErrno(err) == 0); | |
| 71 | } | |
| 72 | const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size); | |
| 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 | } | |
| 53 | if (os.windows.is_the_target) { | |
| 54 | const w = os.windows; | |
| 55 | ||
| 56 | // Although officially it's at least aligned to page boundary, | |
| 57 | // Windows is known to reserve pages on a 64K boundary. It's | |
| 58 | // even more likely that the requested alignment is <= 64K than | |
| 59 | // 4K, so we're just allocating blindly and hoping for the best. | |
| 60 | // see https://devblogs.microsoft.com/oldnewthing/?p=42223 | |
| 61 | const addr = w.VirtualAlloc( | |
| 62 | null, | |
| 63 | n, | |
| 64 | w.MEM_COMMIT | w.MEM_RESERVE, | |
| 65 | w.PAGE_READWRITE, | |
| 66 | ) catch return error.OutOfMemory; | |
| 67 | ||
| 68 | // If the allocation is sufficiently aligned, use it. | |
| 69 | if (@ptrToInt(addr) & (alignment - 1) == 0) { | |
| 70 | return @ptrCast([*]u8, addr)[0..n]; | |
| 71 | } | |
| 78 | 72 | |
| 79 | return @intToPtr([*]u8, aligned_addr)[0..n]; | |
| 80 | }, | |
| 81 | .windows => { | |
| 82 | const w = os.windows; | |
| 83 | ||
| 84 | // Although officially it's at least aligned to page boundary, | |
| 85 | // Windows is known to reserve pages on a 64K boundary. It's | |
| 86 | // even more likely that the requested alignment is <= 64K than | |
| 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( | |
| 73 | // If it wasn't, actually do an explicitely aligned allocation. | |
| 74 | w.VirtualFree(addr, 0, w.MEM_RELEASE); | |
| 75 | const alloc_size = n + alignment; | |
| 76 | ||
| 77 | const final_addr = while (true) { | |
| 78 | // Reserve a range of memory large enough to find a sufficiently | |
| 79 | // aligned address. | |
| 80 | const reserved_addr = w.VirtualAlloc( | |
| 90 | 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 | 97 | n, |
| 92 | 98 | w.MEM_COMMIT | w.MEM_RESERVE, |
| 93 | 99 | w.PAGE_READWRITE, |
| 94 | ) orelse return error.OutOfMemory; | |
| 100 | ) catch continue; | |
| 101 | }; | |
| 95 | 102 | |
| 96 | // If the allocation is sufficiently aligned, use it. | |
| 97 | if (@ptrToInt(addr) & (alignment - 1) == 0) { | |
| 98 | return @ptrCast([*]u8, addr)[0..n]; | |
| 99 | } | |
| 103 | return @ptrCast([*]u8, final_addr)[0..n]; | |
| 104 | } | |
| 100 | 105 | |
| 101 | // If it wasn't, actually do an explicitely aligned allocation. | |
| 102 | if (w.VirtualFree(addr, 0, w.MEM_RELEASE) == 0) unreachable; | |
| 103 | const alloc_size = n + alignment; | |
| 104 | ||
| 105 | const final_addr = while (true) { | |
| 106 | // Reserve a range of memory large enough to find a sufficiently | |
| 107 | // aligned address. | |
| 108 | const reserved_addr = w.VirtualAlloc( | |
| 109 | null, | |
| 110 | alloc_size, | |
| 111 | w.MEM_RESERVE, | |
| 112 | w.PAGE_NOACCESS, | |
| 113 | ) orelse return error.OutOfMemory; | |
| 114 | const aligned_addr = mem.alignForward(@ptrToInt(reserved_addr), alignment); | |
| 115 | ||
| 116 | // Release the reserved pages (not actually used). | |
| 117 | if (w.VirtualFree(reserved_addr, 0, w.MEM_RELEASE) == 0) unreachable; | |
| 118 | ||
| 119 | // At this point, it is possible that another thread has | |
| 120 | // obtained some memory space that will cause the next | |
| 121 | // VirtualAlloc call to fail. To handle this, we will retry | |
| 122 | // until it succeeds. | |
| 123 | if (w.VirtualAlloc( | |
| 124 | @intToPtr(*c_void, aligned_addr), | |
| 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"), | |
| 106 | const alloc_size = if (alignment <= os.page_size) n else n + alignment; | |
| 107 | const addr = os.mmap( | |
| 108 | null, | |
| 109 | alloc_size, | |
| 110 | os.PROT_READ | os.PROT_WRITE, | |
| 111 | os.MAP_PRIVATE | os.MAP_ANONYMOUS, | |
| 112 | -1, | |
| 113 | 0, | |
| 114 | ) catch return error.OutOfMemory; | |
| 115 | if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n]; | |
| 116 | ||
| 117 | const aligned_addr = mem.alignForward(addr, alignment); | |
| 118 | ||
| 119 | // Unmap the extra bytes that were only requested in order to guarantee | |
| 120 | // that the range of memory we were provided had a proper alignment in | |
| 121 | // it somewhere. The extra bytes could be at the beginning, or end, or both. | |
| 122 | const unused_start_len = aligned_addr - addr; | |
| 123 | if (unused_start_len != 0) { | |
| 124 | os.munmap(addr, unused_start_len); | |
| 125 | } | |
| 126 | const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size); | |
| 127 | const unused_end_len = addr + alloc_size - aligned_end_addr; | |
| 128 | if (unused_end_len != 0) { | |
| 129 | os.munmap(aligned_end_addr, unused_end_len); | |
| 134 | 130 | } |
| 131 | ||
| 132 | return @intToPtr([*]u8, aligned_addr)[0..n]; | |
| 135 | 133 | } |
| 136 | 134 | |
| 137 | 135 | fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { |
| 138 | switch (builtin.os) { | |
| 139 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 136 | if (os.windows.is_the_target) { | |
| 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 | 147 | const base_addr = @ptrToInt(old_mem.ptr); |
| 141 | 148 | const old_addr_end = base_addr + old_mem.len; |
| 142 | 149 | const new_addr_end = base_addr + new_size; |
| 143 | 150 | const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size); |
| 144 | 151 | if (old_addr_end > new_addr_end_rounded) { |
| 145 | _ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded); | |
| 146 | } | |
| 147 | return old_mem[0..new_size]; | |
| 148 | }, | |
| 149 | .windows => { | |
| 150 | const w = os.windows; | |
| 151 | if (new_size == 0) { | |
| 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 | } | |
| 152 | // For shrinking that is not releasing, we will only | |
| 153 | // decommit the pages not needed anymore. | |
| 154 | w.VirtualFree( | |
| 155 | @intToPtr(*c_void, new_addr_end_rounded), | |
| 156 | old_addr_end - new_addr_end_rounded, | |
| 157 | w.MEM_DECOMMIT, | |
| 158 | ); | |
| 173 | 159 | } |
| 174 | return old_mem[0..new_size]; | |
| 175 | }, | |
| 176 | else => @compileError("Unsupported OS"), | |
| 160 | } | |
| 161 | return old_mem[0..new_size]; | |
| 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 | } |
| 179 | 172 | |
| 180 | 173 | fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 { |
| 181 | switch (builtin.os) { | |
| 182 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | |
| 183 | if (new_size <= old_mem.len and new_align <= old_align) { | |
| 184 | return shrink(allocator, old_mem, old_align, new_size, new_align); | |
| 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); | |
| 174 | if (os.windows.is_the_target) { | |
| 175 | if (old_mem.len == 0) { | |
| 176 | return alloc(allocator, new_size, new_align); | |
| 177 | } | |
| 204 | 178 | |
| 205 | if (new_align > old_align and base_addr & (new_align - 1) != 0) { | |
| 206 | // Current allocation doesn't satisfy the new alignment. | |
| 207 | // For now we'll do a new one no matter what, but maybe | |
| 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; | |
| 179 | if (new_size <= old_mem.len and new_align <= old_align) { | |
| 180 | return shrink(allocator, old_mem, old_align, new_size, new_align); | |
| 181 | } | |
| 213 | 182 | |
| 214 | return result; | |
| 215 | } | |
| 183 | const w = os.windows; | |
| 184 | const base_addr = @ptrToInt(old_mem.ptr); | |
| 216 | 185 | |
| 217 | const old_addr_end = base_addr + old_mem.len; | |
| 218 | const old_addr_end_rounded = mem.alignForward(old_addr_end, os.page_size); | |
| 219 | const new_addr_end = base_addr + new_size; | |
| 220 | const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size); | |
| 221 | if (new_addr_end_rounded == old_addr_end_rounded) { | |
| 222 | // The reallocation fits in the already allocated pages. | |
| 223 | return @ptrCast([*]u8, old_mem.ptr)[0..new_size]; | |
| 224 | } | |
| 225 | assert(new_addr_end_rounded > old_addr_end_rounded); | |
| 186 | if (new_align > old_align and base_addr & (new_align - 1) != 0) { | |
| 187 | // Current allocation doesn't satisfy the new alignment. | |
| 188 | // For now we'll do a new one no matter what, but maybe | |
| 189 | // there is something smarter to do instead. | |
| 190 | const result = try alloc(allocator, new_size, new_align); | |
| 191 | assert(old_mem.len != 0); | |
| 192 | @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len)); | |
| 193 | w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE); | |
| 226 | 194 | |
| 227 | // We need to commit new pages. | |
| 228 | const additional_size = new_addr_end - old_addr_end_rounded; | |
| 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 | }; | |
| 195 | return result; | |
| 196 | } | |
| 243 | 197 | |
| 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 | 204 | return @ptrCast([*]u8, old_mem.ptr)[0..new_size]; |
| 246 | }, | |
| 247 | else => @compileError("Unsupported OS"), | |
| 205 | } | |
| 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 | }; |
| 251 | 239 |
std/mem.zig+3-3| ... | ... | @@ -1466,17 +1466,17 @@ test "std.mem.alignForward" { |
| 1466 | 1466 | pub fn getBaseAddress() usize { |
| 1467 | 1467 | switch (builtin.os) { |
| 1468 | 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 | 1470 | if (base != 0) { |
| 1471 | 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 | 1474 | return phdr - @sizeOf(std.elf.Ehdr); |
| 1475 | 1475 | }, |
| 1476 | 1476 | .macosx, .freebsd, .netbsd => { |
| 1477 | 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 | 1480 | else => @compileError("Unsupported OS"), |
| 1481 | 1481 | } |
| 1482 | 1482 | } |
std/mutex.zig+2-2| ... | ... | @@ -152,9 +152,9 @@ test "std.Mutex" { |
| 152 | 152 | testing.expect(context.data == TestContext.incr_count); |
| 153 | 153 | } else { |
| 154 | 154 | const thread_count = 10; |
| 155 | var threads: [thread_count]*std.os.Thread = undefined; | |
| 155 | var threads: [thread_count]*std.Thread = undefined; | |
| 156 | 156 | for (threads) |*t| { |
| 157 | t.* = try std.os.spawnThread(&context, worker); | |
| 157 | t.* = try std.Thread.spawn(&context, worker); | |
| 158 | 158 | } |
| 159 | 159 | for (threads) |t| |
| 160 | 160 | t.wait(); |
std/net.zig+12-12| ... | ... | @@ -2,8 +2,8 @@ const std = @import("std.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | const net = @This(); |
| 5 | const posix = std.os.posix; | |
| 6 | 5 | const mem = std.mem; |
| 6 | const os = std.os; | |
| 7 | 7 | |
| 8 | 8 | pub const TmpWinAddr = struct { |
| 9 | 9 | family: u8, |
| ... | ... | @@ -12,7 +12,7 @@ pub const TmpWinAddr = struct { |
| 12 | 12 | |
| 13 | 13 | pub const OsAddress = switch (builtin.os) { |
| 14 | 14 | builtin.Os.windows => TmpWinAddr, |
| 15 | else => posix.sockaddr, | |
| 15 | else => os.sockaddr, | |
| 16 | 16 | }; |
| 17 | 17 | |
| 18 | 18 | pub const Address = struct { |
| ... | ... | @@ -20,9 +20,9 @@ pub const Address = struct { |
| 20 | 20 | |
| 21 | 21 | pub fn initIp4(ip4: u32, _port: u16) Address { |
| 22 | 22 | return Address{ |
| 23 | .os_addr = posix.sockaddr{ | |
| 24 | .in = posix.sockaddr_in{ | |
| 25 | .family = posix.AF_INET, | |
| 23 | .os_addr = os.sockaddr{ | |
| 24 | .in = os.sockaddr_in{ | |
| 25 | .family = os.AF_INET, | |
| 26 | 26 | .port = mem.nativeToBig(u16, _port), |
| 27 | 27 | .addr = ip4, |
| 28 | 28 | .zero = []u8{0} ** 8, |
| ... | ... | @@ -33,10 +33,10 @@ pub const Address = struct { |
| 33 | 33 | |
| 34 | 34 | pub fn initIp6(ip6: *const Ip6Addr, _port: u16) Address { |
| 35 | 35 | return Address{ |
| 36 | .family = posix.AF_INET6, | |
| 37 | .os_addr = posix.sockaddr{ | |
| 38 | .in6 = posix.sockaddr_in6{ | |
| 39 | .family = posix.AF_INET6, | |
| 36 | .family = os.AF_INET6, | |
| 37 | .os_addr = os.sockaddr{ | |
| 38 | .in6 = os.sockaddr_in6{ | |
| 39 | .family = os.AF_INET6, | |
| 40 | 40 | .port = mem.nativeToBig(u16, _port), |
| 41 | 41 | .flowinfo = 0, |
| 42 | 42 | .addr = ip6.addr, |
| ... | ... | @@ -50,18 +50,18 @@ pub const Address = struct { |
| 50 | 50 | return mem.bigToNative(u16, self.os_addr.in.port); |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | pub fn initPosix(addr: posix.sockaddr) Address { | |
| 53 | pub fn initPosix(addr: os.sockaddr) Address { | |
| 54 | 54 | return Address{ .os_addr = addr }; |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | 57 | pub fn format(self: *const Address, out_stream: var) !void { |
| 58 | 58 | switch (self.os_addr.in.family) { |
| 59 | posix.AF_INET => { | |
| 59 | os.AF_INET => { | |
| 60 | 60 | const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port); |
| 61 | 61 | const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]); |
| 62 | 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 | 65 | const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port); |
| 66 | 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 | 164 | } |
| 165 | 165 | |
| 166 | 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 | } |
| 169 | 169 | |
| 170 | 170 | var set: system.sigset_t = undefined; |
| ... | ... | @@ -690,20 +690,6 @@ pub fn getenvC(key: [*]const u8) ?[]const u8 { |
| 690 | 690 | return getenv(mem.toSliceConst(u8, key)); |
| 691 | 691 | } |
| 692 | 692 | |
| 693 | /// See std.elf for the constants. | |
| 694 | pub 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 | ||
| 707 | 693 | pub const GetCwdError = error{ |
| 708 | 694 | NameTooLong, |
| 709 | 695 | CurrentWorkingDirectoryUnlinked, |
| ... | ... | @@ -1198,7 +1184,7 @@ pub fn isatty(handle: fd_t) bool { |
| 1198 | 1184 | return windows.kernel32.GetConsoleMode(handle, &out) != 0; |
| 1199 | 1185 | } |
| 1200 | 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 | 1189 | if (linux.is_the_target) { |
| 1204 | 1190 | var wsz: system.winsize = undefined; |
| ... | ... | @@ -2365,6 +2351,23 @@ pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void { |
| 2365 | 2351 | } |
| 2366 | 2352 | } |
| 2367 | 2353 | |
| 2354 | pub const SchedGetAffinityError = error{ | |
| 2355 | PermissionDenied, | |
| 2356 | Unexpected, | |
| 2357 | }; | |
| 2358 | ||
| 2359 | pub 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 | 2371 | /// Used to convert a slice to a null terminated slice on the stack. |
| 2369 | 2372 | /// TODO https://github.com/ziglang/zig/issues/287 |
| 2370 | 2373 | pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 { |
std/os/bits/linux.zig+25| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | const std = @import("../../std.zig"); | |
| 2 | ||
| 1 | 3 | pub use @import("linux/errno.zig"); |
| 2 | 4 | pub use switch (builtin.arch) { |
| 3 | 5 | .x86_64 => @import("linux/x86_64.zig"), |
| ... | ... | @@ -907,3 +909,26 @@ pub const pthread_attr_t = extern struct { |
| 907 | 909 | __size: [56]u8, |
| 908 | 910 | __align: c_long, |
| 909 | 911 | }; |
| 912 | ||
| 913 | pub const CPU_SETSIZE = 128; | |
| 914 | pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize; | |
| 915 | pub const cpu_count_t = @IntType(false, std.math.log2(CPU_SETSIZE * 8)); | |
| 916 | ||
| 917 | pub 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 | // 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. | |
| 1 | 8 | const std = @import("../std.zig"); |
| 2 | 9 | const builtin = @import("builtin"); |
| 10 | const assert = std.debug.assert; | |
| 11 | const maxInt = std.math.maxInt; | |
| 12 | const elf = std.elf; | |
| 13 | const vdso = @import("linux/vdso.zig"); | |
| 14 | const dl = @import("../dynamic_library.zig"); | |
| 15 | ||
| 3 | 16 | pub const is_the_target = builtin.os == .linux; |
| 4 | pub const sys = @import("linux/sys.zig"); | |
| 5 | pub use if (builtin.link_libc) std.c else sys; | |
| 17 | pub use switch (builtin.arch) { | |
| 18 | .x86_64 => @import("linux/x86_64.zig"), | |
| 19 | .aarch64 => @import("linux/arm64.zig"), | |
| 20 | else => struct {}, | |
| 21 | }; | |
| 22 | pub use @import("bits.zig"); | |
| 23 | ||
| 24 | /// Set by startup code, used by `getauxval`. | |
| 25 | pub var elf_aux_maybe: ?[*]std.elf.Auxv = null; | |
| 26 | ||
| 27 | /// See `std.elf` for the constants. | |
| 28 | pub 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. | |
| 39 | pub 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 | ||
| 44 | pub 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 | ||
| 60 | pub 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 | |
| 65 | pub fn chdir(path: [*]const u8) usize { | |
| 66 | return syscall1(SYS_chdir, @ptrToInt(path)); | |
| 67 | } | |
| 68 | ||
| 69 | // TODO https://github.com/ziglang/zig/issues/265 | |
| 70 | pub fn chroot(path: [*]const u8) usize { | |
| 71 | return syscall1(SYS_chroot, @ptrToInt(path)); | |
| 72 | } | |
| 73 | ||
| 74 | // TODO https://github.com/ziglang/zig/issues/265 | |
| 75 | pub 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 | ||
| 79 | pub 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. | |
| 92 | pub inline fn vfork() usize { | |
| 93 | return @inlineCall(syscall0, SYS_vfork); | |
| 94 | } | |
| 95 | ||
| 96 | pub 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 | ||
| 100 | pub 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 | ||
| 104 | pub fn getcwd(buf: [*]u8, size: usize) usize { | |
| 105 | return syscall2(SYS_getcwd, @ptrToInt(buf), size); | |
| 106 | } | |
| 107 | ||
| 108 | pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize { | |
| 109 | return syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count); | |
| 110 | } | |
| 111 | ||
| 112 | pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize { | |
| 113 | return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count); | |
| 114 | } | |
| 115 | ||
| 116 | pub fn inotify_init1(flags: u32) usize { | |
| 117 | return syscall1(SYS_inotify_init1, flags); | |
| 118 | } | |
| 119 | ||
| 120 | pub 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 | ||
| 124 | pub 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 | |
| 129 | pub 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 | |
| 138 | pub 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 | |
| 143 | pub 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 | |
| 152 | pub 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 | |
| 157 | pub 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 | |
| 162 | pub 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 | |
| 167 | pub fn umount2(special: [*]const u8, flags: u32) usize { | |
| 168 | return syscall2(SYS_umount2, @ptrToInt(special), flags); | |
| 169 | } | |
| 170 | ||
| 171 | pub 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 | ||
| 175 | pub fn mprotect(address: usize, length: usize, protection: usize) usize { | |
| 176 | return syscall3(SYS_mprotect, address, length, protection); | |
| 177 | } | |
| 178 | ||
| 179 | pub fn munmap(address: usize, length: usize) usize { | |
| 180 | return syscall2(SYS_munmap, address, length); | |
| 181 | } | |
| 182 | ||
| 183 | pub fn read(fd: i32, buf: [*]u8, count: usize) usize { | |
| 184 | return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); | |
| 185 | } | |
| 186 | ||
| 187 | pub 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 | ||
| 191 | pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { | |
| 192 | return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); | |
| 193 | } | |
| 194 | ||
| 195 | pub 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 | ||
| 199 | pub 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 | |
| 204 | pub 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 | |
| 213 | pub 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 | |
| 222 | pub 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 | |
| 227 | pub 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 | |
| 232 | pub 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 | |
| 237 | pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize { | |
| 238 | return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode); | |
| 239 | } | |
| 240 | ||
| 241 | pub 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 | ||
| 249 | pub fn pipe2(fd: *[2]i32, flags: u32) usize { | |
| 250 | return syscall2(SYS_pipe2, @ptrToInt(fd), flags); | |
| 251 | } | |
| 252 | ||
| 253 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | |
| 254 | return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); | |
| 255 | } | |
| 256 | ||
| 257 | pub 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 | |
| 262 | pub 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 | ||
| 272 | pub 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 | |
| 294 | pub 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 | |
| 306 | pub 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 | |
| 311 | pub 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 | |
| 316 | pub 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) | |
| 322 | pub 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) | |
| 327 | pub fn clone2(flags: u32, child_stack_ptr: usize) usize { | |
| 328 | return syscall2(SYS_clone, flags, child_stack_ptr); | |
| 329 | } | |
| 330 | ||
| 331 | pub 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`. | |
| 336 | pub 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`. | |
| 348 | pub fn lseek(fd: i32, offset: i64, whence: usize) usize { | |
| 349 | return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), whence); | |
| 350 | } | |
| 351 | ||
| 352 | pub fn exit(status: i32) noreturn { | |
| 353 | _ = syscall1(SYS_exit, @bitCast(usize, isize(status))); | |
| 354 | unreachable; | |
| 355 | } | |
| 356 | ||
| 357 | pub fn exit_group(status: i32) noreturn { | |
| 358 | _ = syscall1(SYS_exit_group, @bitCast(usize, isize(status))); | |
| 359 | unreachable; | |
| 360 | } | |
| 361 | ||
| 362 | pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { | |
| 363 | return syscall3(SYS_getrandom, @ptrToInt(buf), count, flags); | |
| 364 | } | |
| 365 | ||
| 366 | pub 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 | |
| 371 | pub 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 | |
| 380 | pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize { | |
| 381 | return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags); | |
| 382 | } | |
| 383 | ||
| 384 | pub 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 | ||
| 388 | var 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 | |
| 391 | const vdso_clock_gettime_ty = extern fn (i32, *timespec) usize; | |
| 392 | ||
| 393 | pub 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 | ||
| 408 | extern 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 | ||
| 421 | pub fn clock_getres(clk_id: i32, tp: *timespec) usize { | |
| 422 | return syscall2(SYS_clock_getres, @bitCast(usize, isize(clk_id)), @ptrToInt(tp)); | |
| 423 | } | |
| 424 | ||
| 425 | pub 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 | ||
| 429 | pub fn gettimeofday(tv: *timeval, tz: *timezone) usize { | |
| 430 | return syscall2(SYS_gettimeofday, @ptrToInt(tv), @ptrToInt(tz)); | |
| 431 | } | |
| 432 | ||
| 433 | pub fn settimeofday(tv: *const timeval, tz: *const timezone) usize { | |
| 434 | return syscall2(SYS_settimeofday, @ptrToInt(tv), @ptrToInt(tz)); | |
| 435 | } | |
| 436 | ||
| 437 | pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { | |
| 438 | return syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem)); | |
| 439 | } | |
| 440 | ||
| 441 | pub fn setuid(uid: u32) usize { | |
| 442 | return syscall1(SYS_setuid, uid); | |
| 443 | } | |
| 444 | ||
| 445 | pub fn setgid(gid: u32) usize { | |
| 446 | return syscall1(SYS_setgid, gid); | |
| 447 | } | |
| 448 | ||
| 449 | pub fn setreuid(ruid: u32, euid: u32) usize { | |
| 450 | return syscall2(SYS_setreuid, ruid, euid); | |
| 451 | } | |
| 452 | ||
| 453 | pub fn setregid(rgid: u32, egid: u32) usize { | |
| 454 | return syscall2(SYS_setregid, rgid, egid); | |
| 455 | } | |
| 456 | ||
| 457 | pub fn getuid() u32 { | |
| 458 | return u32(syscall0(SYS_getuid)); | |
| 459 | } | |
| 460 | ||
| 461 | pub fn getgid() u32 { | |
| 462 | return u32(syscall0(SYS_getgid)); | |
| 463 | } | |
| 464 | ||
| 465 | pub fn geteuid() u32 { | |
| 466 | return u32(syscall0(SYS_geteuid)); | |
| 467 | } | |
| 468 | ||
| 469 | pub fn getegid() u32 { | |
| 470 | return u32(syscall0(SYS_getegid)); | |
| 471 | } | |
| 472 | ||
| 473 | pub fn seteuid(euid: u32) usize { | |
| 474 | return syscall1(SYS_seteuid, euid); | |
| 475 | } | |
| 476 | ||
| 477 | pub fn setegid(egid: u32) usize { | |
| 478 | return syscall1(SYS_setegid, egid); | |
| 479 | } | |
| 480 | ||
| 481 | pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize { | |
| 482 | return syscall3(SYS_getresuid, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid)); | |
| 483 | } | |
| 484 | ||
| 485 | pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize { | |
| 486 | return syscall3(SYS_getresgid, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid)); | |
| 487 | } | |
| 488 | ||
| 489 | pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize { | |
| 490 | return syscall3(SYS_setresuid, ruid, euid, suid); | |
| 491 | } | |
| 492 | ||
| 493 | pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize { | |
| 494 | return syscall3(SYS_setresgid, rgid, egid, sgid); | |
| 495 | } | |
| 496 | ||
| 497 | pub fn getgroups(size: usize, list: *u32) usize { | |
| 498 | return syscall2(SYS_getgroups, size, @ptrToInt(list)); | |
| 499 | } | |
| 500 | ||
| 501 | pub fn setgroups(size: usize, list: *const u32) usize { | |
| 502 | return syscall2(SYS_setgroups, size, @ptrToInt(list)); | |
| 503 | } | |
| 504 | ||
| 505 | pub fn getpid() i32 { | |
| 506 | return @bitCast(i32, @truncate(u32, syscall0(SYS_getpid))); | |
| 507 | } | |
| 508 | ||
| 509 | pub fn gettid() i32 { | |
| 510 | return @bitCast(i32, @truncate(u32, syscall0(SYS_gettid))); | |
| 511 | } | |
| 512 | ||
| 513 | pub 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 | ||
| 517 | pub 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 | ||
| 542 | fn blockAllSignals(set: *sigset_t) void { | |
| 543 | _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG / 8); | |
| 544 | } | |
| 545 | ||
| 546 | fn blockAppSignals(set: *sigset_t) void { | |
| 547 | _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG / 8); | |
| 548 | } | |
| 549 | ||
| 550 | fn restoreSignals(set: *sigset_t) void { | |
| 551 | _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG / 8); | |
| 552 | } | |
| 553 | ||
| 554 | pub 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 | ||
| 559 | pub 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 | ||
| 564 | pub 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 | ||
| 568 | pub 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 | ||
| 572 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { | |
| 573 | return syscall3(SYS_socket, domain, socket_type, protocol); | |
| 574 | } | |
| 575 | ||
| 576 | pub 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 | ||
| 580 | pub 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 | ||
| 584 | pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize { | |
| 585 | return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); | |
| 586 | } | |
| 587 | ||
| 588 | pub 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 | ||
| 628 | pub 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 | ||
| 632 | pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { | |
| 633 | return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); | |
| 634 | } | |
| 635 | ||
| 636 | pub 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 | ||
| 640 | pub fn shutdown(fd: i32, how: i32) usize { | |
| 641 | return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how))); | |
| 642 | } | |
| 643 | ||
| 644 | pub 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 | ||
| 648 | pub fn listen(fd: i32, backlog: u32) usize { | |
| 649 | return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog); | |
| 650 | } | |
| 651 | ||
| 652 | pub 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 | ||
| 656 | pub 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 | ||
| 660 | pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { | |
| 661 | return accept4(fd, addr, len, 0); | |
| 662 | } | |
| 663 | ||
| 664 | pub 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 | ||
| 668 | pub 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 | |
| 673 | pub 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 | |
| 678 | pub 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 | |
| 683 | pub 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 | |
| 688 | pub 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 | |
| 693 | pub fn llistxattr(path: [*]const u8, list: [*]u8, size: usize) usize { | |
| 694 | return syscall3(SYS_llistxattr, @ptrToInt(path), @ptrToInt(list), size); | |
| 695 | } | |
| 696 | ||
| 697 | pub 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 | |
| 702 | pub 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 | |
| 707 | pub 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 | |
| 712 | pub 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 | |
| 717 | pub 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 | |
| 722 | pub 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 | |
| 727 | pub 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 | |
| 732 | pub 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 | |
| 737 | pub 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 | |
| 742 | pub fn fremovexattr(fd: usize, name: [*]const u8) usize { | |
| 743 | return syscall2(SYS_fremovexattr, fd, @ptrToInt(name)); | |
| 744 | } | |
| 745 | ||
| 746 | pub 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 | ||
| 753 | pub fn epoll_create() usize { | |
| 754 | return epoll_create1(0); | |
| 755 | } | |
| 756 | ||
| 757 | pub fn epoll_create1(flags: usize) usize { | |
| 758 | return syscall1(SYS_epoll_create1, flags); | |
| 759 | } | |
| 760 | ||
| 761 | pub 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 | ||
| 765 | pub 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 | ||
| 775 | pub 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 | ||
| 787 | pub fn eventfd(count: u32, flags: u32) usize { | |
| 788 | return syscall2(SYS_eventfd2, count, flags); | |
| 789 | } | |
| 790 | ||
| 791 | pub fn timerfd_create(clockid: i32, flags: u32) usize { | |
| 792 | return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags); | |
| 793 | } | |
| 794 | ||
| 795 | pub const itimerspec = extern struct { | |
| 796 | it_interval: timespec, | |
| 797 | it_value: timespec, | |
| 798 | }; | |
| 799 | ||
| 800 | pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize { | |
| 801 | return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value)); | |
| 802 | } | |
| 803 | ||
| 804 | pub 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 | ||
| 808 | pub fn unshare(flags: usize) usize { | |
| 809 | return syscall1(SYS_unshare, flags); | |
| 810 | } | |
| 811 | ||
| 812 | pub fn capget(hdrp: *cap_user_header_t, datap: *cap_user_data_t) usize { | |
| 813 | return syscall2(SYS_capget, @ptrToInt(hdrp), @ptrToInt(datap)); | |
| 814 | } | |
| 815 | ||
| 816 | pub 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 | |
| 821 | extern const __ehdr_start: elf.Ehdr = undefined; | |
| 822 | ||
| 823 | pub 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 | } | |
| 6 | 876 | |
| 7 | 877 | test "" { |
| 8 | 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. | |
| 8 | const std = @import("../../std.zig"); | |
| 9 | const builtin = @import("builtin"); | |
| 10 | const assert = std.debug.assert; | |
| 11 | const maxInt = std.math.maxInt; | |
| 12 | const elf = std.elf; | |
| 13 | const vdso = @import("vdso.zig"); | |
| 14 | const dl = @import("../../dynamic_library.zig"); | |
| 15 | pub use switch (builtin.arch) { | |
| 16 | .x86_64 => @import("x86_64.zig"), | |
| 17 | .aarch64 => @import("arm64.zig"), | |
| 18 | else => struct {}, | |
| 19 | }; | |
| 20 | pub use @import("../bits.zig"); | |
| 21 | ||
| 22 | /// See `std.os.posix.getauxval`. | |
| 23 | pub var elf_aux_maybe: ?[*]std.elf.Auxv = null; | |
| 24 | ||
| 25 | /// Get the errno from a syscall return value, or 0 for no error. | |
| 26 | pub 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 | ||
| 31 | pub 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 | ||
| 47 | pub 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 | |
| 52 | pub fn chdir(path: [*]const u8) usize { | |
| 53 | return syscall1(SYS_chdir, @ptrToInt(path)); | |
| 54 | } | |
| 55 | ||
| 56 | // TODO https://github.com/ziglang/zig/issues/265 | |
| 57 | pub fn chroot(path: [*]const u8) usize { | |
| 58 | return syscall1(SYS_chroot, @ptrToInt(path)); | |
| 59 | } | |
| 60 | ||
| 61 | // TODO https://github.com/ziglang/zig/issues/265 | |
| 62 | pub 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 | ||
| 66 | pub 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. | |
| 79 | pub inline fn vfork() usize { | |
| 80 | return @inlineCall(syscall0, SYS_vfork); | |
| 81 | } | |
| 82 | ||
| 83 | pub 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 | ||
| 87 | pub 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 | ||
| 91 | pub fn getcwd(buf: [*]u8, size: usize) usize { | |
| 92 | return syscall2(SYS_getcwd, @ptrToInt(buf), size); | |
| 93 | } | |
| 94 | ||
| 95 | pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize { | |
| 96 | return syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count); | |
| 97 | } | |
| 98 | ||
| 99 | pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize { | |
| 100 | return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count); | |
| 101 | } | |
| 102 | ||
| 103 | pub fn inotify_init1(flags: u32) usize { | |
| 104 | return syscall1(SYS_inotify_init1, flags); | |
| 105 | } | |
| 106 | ||
| 107 | pub 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 | ||
| 111 | pub 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 | |
| 116 | pub 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 | |
| 125 | pub 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 | |
| 130 | pub 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 | |
| 139 | pub 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 | |
| 144 | pub 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 | |
| 149 | pub 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 | |
| 154 | pub fn umount2(special: [*]const u8, flags: u32) usize { | |
| 155 | return syscall2(SYS_umount2, @ptrToInt(special), flags); | |
| 156 | } | |
| 157 | ||
| 158 | pub 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 | ||
| 162 | pub fn mprotect(address: usize, length: usize, protection: usize) usize { | |
| 163 | return syscall3(SYS_mprotect, address, length, protection); | |
| 164 | } | |
| 165 | ||
| 166 | pub fn munmap(address: usize, length: usize) usize { | |
| 167 | return syscall2(SYS_munmap, address, length); | |
| 168 | } | |
| 169 | ||
| 170 | pub fn read(fd: i32, buf: [*]u8, count: usize) usize { | |
| 171 | return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); | |
| 172 | } | |
| 173 | ||
| 174 | pub 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 | ||
| 178 | pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { | |
| 179 | return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); | |
| 180 | } | |
| 181 | ||
| 182 | pub 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 | ||
| 186 | pub 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 | |
| 191 | pub 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 | |
| 200 | pub 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 | |
| 209 | pub 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 | |
| 214 | pub 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 | |
| 219 | pub 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 | |
| 224 | pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize { | |
| 225 | return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode); | |
| 226 | } | |
| 227 | ||
| 228 | pub 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 | ||
| 236 | pub fn pipe2(fd: *[2]i32, flags: u32) usize { | |
| 237 | return syscall2(SYS_pipe2, @ptrToInt(fd), flags); | |
| 238 | } | |
| 239 | ||
| 240 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | |
| 241 | return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); | |
| 242 | } | |
| 243 | ||
| 244 | pub 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 | |
| 249 | pub 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 | ||
| 259 | pub 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 | |
| 281 | pub 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 | |
| 293 | pub 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 | |
| 298 | pub 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 | |
| 303 | pub 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) | |
| 309 | pub 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) | |
| 314 | pub fn clone2(flags: u32, child_stack_ptr: usize) usize { | |
| 315 | return syscall2(SYS_clone, flags, child_stack_ptr); | |
| 316 | } | |
| 317 | ||
| 318 | pub 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`. | |
| 323 | pub 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`. | |
| 335 | pub fn lseek(fd: i32, offset: i64, whence: usize) usize { | |
| 336 | return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), whence); | |
| 337 | } | |
| 338 | ||
| 339 | pub fn exit(status: i32) noreturn { | |
| 340 | _ = syscall1(SYS_exit, @bitCast(usize, isize(status))); | |
| 341 | unreachable; | |
| 342 | } | |
| 343 | ||
| 344 | pub fn exit_group(status: i32) noreturn { | |
| 345 | _ = syscall1(SYS_exit_group, @bitCast(usize, isize(status))); | |
| 346 | unreachable; | |
| 347 | } | |
| 348 | ||
| 349 | pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { | |
| 350 | return syscall3(SYS_getrandom, @ptrToInt(buf), count, flags); | |
| 351 | } | |
| 352 | ||
| 353 | pub 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 | |
| 358 | pub 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 | |
| 367 | pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize { | |
| 368 | return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags); | |
| 369 | } | |
| 370 | ||
| 371 | pub 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 | ||
| 375 | var 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 | |
| 378 | const vdso_clock_gettime_ty = extern fn (i32, *timespec) usize; | |
| 379 | ||
| 380 | pub 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 | ||
| 395 | extern 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 | ||
| 408 | pub fn clock_getres(clk_id: i32, tp: *timespec) usize { | |
| 409 | return syscall2(SYS_clock_getres, @bitCast(usize, isize(clk_id)), @ptrToInt(tp)); | |
| 410 | } | |
| 411 | ||
| 412 | pub 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 | ||
| 416 | pub fn gettimeofday(tv: *timeval, tz: *timezone) usize { | |
| 417 | return syscall2(SYS_gettimeofday, @ptrToInt(tv), @ptrToInt(tz)); | |
| 418 | } | |
| 419 | ||
| 420 | pub fn settimeofday(tv: *const timeval, tz: *const timezone) usize { | |
| 421 | return syscall2(SYS_settimeofday, @ptrToInt(tv), @ptrToInt(tz)); | |
| 422 | } | |
| 423 | ||
| 424 | pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { | |
| 425 | return syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem)); | |
| 426 | } | |
| 427 | ||
| 428 | pub fn setuid(uid: u32) usize { | |
| 429 | return syscall1(SYS_setuid, uid); | |
| 430 | } | |
| 431 | ||
| 432 | pub fn setgid(gid: u32) usize { | |
| 433 | return syscall1(SYS_setgid, gid); | |
| 434 | } | |
| 435 | ||
| 436 | pub fn setreuid(ruid: u32, euid: u32) usize { | |
| 437 | return syscall2(SYS_setreuid, ruid, euid); | |
| 438 | } | |
| 439 | ||
| 440 | pub fn setregid(rgid: u32, egid: u32) usize { | |
| 441 | return syscall2(SYS_setregid, rgid, egid); | |
| 442 | } | |
| 443 | ||
| 444 | pub fn getuid() u32 { | |
| 445 | return u32(syscall0(SYS_getuid)); | |
| 446 | } | |
| 447 | ||
| 448 | pub fn getgid() u32 { | |
| 449 | return u32(syscall0(SYS_getgid)); | |
| 450 | } | |
| 451 | ||
| 452 | pub fn geteuid() u32 { | |
| 453 | return u32(syscall0(SYS_geteuid)); | |
| 454 | } | |
| 455 | ||
| 456 | pub fn getegid() u32 { | |
| 457 | return u32(syscall0(SYS_getegid)); | |
| 458 | } | |
| 459 | ||
| 460 | pub fn seteuid(euid: u32) usize { | |
| 461 | return syscall1(SYS_seteuid, euid); | |
| 462 | } | |
| 463 | ||
| 464 | pub fn setegid(egid: u32) usize { | |
| 465 | return syscall1(SYS_setegid, egid); | |
| 466 | } | |
| 467 | ||
| 468 | pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize { | |
| 469 | return syscall3(SYS_getresuid, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid)); | |
| 470 | } | |
| 471 | ||
| 472 | pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize { | |
| 473 | return syscall3(SYS_getresgid, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid)); | |
| 474 | } | |
| 475 | ||
| 476 | pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize { | |
| 477 | return syscall3(SYS_setresuid, ruid, euid, suid); | |
| 478 | } | |
| 479 | ||
| 480 | pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize { | |
| 481 | return syscall3(SYS_setresgid, rgid, egid, sgid); | |
| 482 | } | |
| 483 | ||
| 484 | pub fn getgroups(size: usize, list: *u32) usize { | |
| 485 | return syscall2(SYS_getgroups, size, @ptrToInt(list)); | |
| 486 | } | |
| 487 | ||
| 488 | pub fn setgroups(size: usize, list: *const u32) usize { | |
| 489 | return syscall2(SYS_setgroups, size, @ptrToInt(list)); | |
| 490 | } | |
| 491 | ||
| 492 | pub fn getpid() i32 { | |
| 493 | return @bitCast(i32, @truncate(u32, syscall0(SYS_getpid))); | |
| 494 | } | |
| 495 | ||
| 496 | pub fn gettid() i32 { | |
| 497 | return @bitCast(i32, @truncate(u32, syscall0(SYS_gettid))); | |
| 498 | } | |
| 499 | ||
| 500 | pub 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 | ||
| 504 | pub 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 | ||
| 529 | fn blockAllSignals(set: *sigset_t) void { | |
| 530 | _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG / 8); | |
| 531 | } | |
| 532 | ||
| 533 | fn blockAppSignals(set: *sigset_t) void { | |
| 534 | _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG / 8); | |
| 535 | } | |
| 536 | ||
| 537 | fn restoreSignals(set: *sigset_t) void { | |
| 538 | _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG / 8); | |
| 539 | } | |
| 540 | ||
| 541 | pub 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 | ||
| 546 | pub 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 | ||
| 551 | pub 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 | ||
| 555 | pub 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 | ||
| 559 | pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { | |
| 560 | return syscall3(SYS_socket, domain, socket_type, protocol); | |
| 561 | } | |
| 562 | ||
| 563 | pub 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 | ||
| 567 | pub 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 | ||
| 571 | pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize { | |
| 572 | return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); | |
| 573 | } | |
| 574 | ||
| 575 | pub 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 | ||
| 615 | pub 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 | ||
| 619 | pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { | |
| 620 | return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); | |
| 621 | } | |
| 622 | ||
| 623 | pub 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 | ||
| 627 | pub fn shutdown(fd: i32, how: i32) usize { | |
| 628 | return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how))); | |
| 629 | } | |
| 630 | ||
| 631 | pub 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 | ||
| 635 | pub fn listen(fd: i32, backlog: u32) usize { | |
| 636 | return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog); | |
| 637 | } | |
| 638 | ||
| 639 | pub 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 | ||
| 643 | pub 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 | ||
| 647 | pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { | |
| 648 | return accept4(fd, addr, len, 0); | |
| 649 | } | |
| 650 | ||
| 651 | pub 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 | ||
| 655 | pub 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 | |
| 660 | pub 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 | |
| 665 | pub 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 | |
| 670 | pub 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 | |
| 675 | pub 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 | |
| 680 | pub fn llistxattr(path: [*]const u8, list: [*]u8, size: usize) usize { | |
| 681 | return syscall3(SYS_llistxattr, @ptrToInt(path), @ptrToInt(list), size); | |
| 682 | } | |
| 683 | ||
| 684 | pub 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 | |
| 689 | pub 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 | |
| 694 | pub 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 | |
| 699 | pub 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 | |
| 704 | pub 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 | |
| 709 | pub 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 | |
| 714 | pub 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 | |
| 719 | pub 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 | |
| 724 | pub 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 | |
| 729 | pub fn fremovexattr(fd: usize, name: [*]const u8) usize { | |
| 730 | return syscall2(SYS_fremovexattr, fd, @ptrToInt(name)); | |
| 731 | } | |
| 732 | ||
| 733 | pub 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 | ||
| 737 | pub fn epoll_create() usize { | |
| 738 | return epoll_create1(0); | |
| 739 | } | |
| 740 | ||
| 741 | pub fn epoll_create1(flags: usize) usize { | |
| 742 | return syscall1(SYS_epoll_create1, flags); | |
| 743 | } | |
| 744 | ||
| 745 | pub 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 | ||
| 749 | pub 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 | ||
| 759 | pub 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 | ||
| 771 | pub fn eventfd(count: u32, flags: u32) usize { | |
| 772 | return syscall2(SYS_eventfd2, count, flags); | |
| 773 | } | |
| 774 | ||
| 775 | pub fn timerfd_create(clockid: i32, flags: u32) usize { | |
| 776 | return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags); | |
| 777 | } | |
| 778 | ||
| 779 | pub const itimerspec = extern struct { | |
| 780 | it_interval: timespec, | |
| 781 | it_value: timespec, | |
| 782 | }; | |
| 783 | ||
| 784 | pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize { | |
| 785 | return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value)); | |
| 786 | } | |
| 787 | ||
| 788 | pub 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 | ||
| 792 | pub fn unshare(flags: usize) usize { | |
| 793 | return syscall1(SYS_unshare, flags); | |
| 794 | } | |
| 795 | ||
| 796 | pub fn capget(hdrp: *cap_user_header_t, datap: *cap_user_data_t) usize { | |
| 797 | return syscall2(SYS_capget, @ptrToInt(hdrp), @ptrToInt(datap)); | |
| 798 | } | |
| 799 | ||
| 800 | pub 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 | |
| 805 | extern const __ehdr_start: elf.Ehdr = undefined; | |
| 806 | ||
| 807 | pub 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 | 1 | const std = @import("std"); |
| 2 | const os = std.os; | |
| 2 | 3 | const mem = std.mem; |
| 3 | const posix = std.os.posix; | |
| 4 | 4 | const elf = std.elf; |
| 5 | 5 | const builtin = @import("builtin"); |
| 6 | 6 | const assert = std.debug.assert; |
| ... | ... | @@ -237,9 +237,14 @@ pub fn allocateTLS(size: usize) usize { |
| 237 | 237 | return @ptrToInt(&main_thread_tls_buffer); |
| 238 | 238 | } |
| 239 | 239 | |
| 240 | const addr = posix.mmap(null, size, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS, -1, 0); | |
| 241 | ||
| 242 | if (posix.getErrno(addr) != 0) @panic("out of memory"); | |
| 240 | const addr = os.mmap( | |
| 241 | null, | |
| 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"); | |
| 243 | 248 | |
| 244 | 249 | return addr; |
| 245 | 250 | } |
std/os/linux/x86_64.zig+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | use @import("posix/x86_64.zig"); | |
| 1 | use @import("../bits.zig"); | |
| 2 | 2 | |
| 3 | 3 | pub fn syscall0(number: usize) usize { |
| 4 | 4 | return asm volatile ("syscall" |
std/os/test.zig+15-14| ... | ... | @@ -5,6 +5,7 @@ const expect = std.testing.expect; |
| 5 | 5 | const io = std.io; |
| 6 | 6 | const mem = std.mem; |
| 7 | 7 | const File = std.fs.File; |
| 8 | const Thread = std.Thread; | |
| 8 | 9 | |
| 9 | 10 | const a = std.debug.global_allocator; |
| 10 | 11 | |
| ... | ... | @@ -37,25 +38,25 @@ test "access file" { |
| 37 | 38 | try os.deleteTree(a, "os_test_tmp"); |
| 38 | 39 | } |
| 39 | 40 | |
| 40 | fn testThreadIdFn(thread_id: *os.Thread.Id) void { | |
| 41 | thread_id.* = os.Thread.getCurrentId(); | |
| 41 | fn testThreadIdFn(thread_id: *Thread.Id) void { | |
| 42 | thread_id.* = Thread.getCurrentId(); | |
| 42 | 43 | } |
| 43 | 44 | |
| 44 | test "std.os.Thread.getCurrentId" { | |
| 45 | test "std.Thread.getCurrentId" { | |
| 45 | 46 | if (builtin.single_threaded) return error.SkipZigTest; |
| 46 | 47 | |
| 47 | var thread_current_id: os.Thread.Id = undefined; | |
| 48 | const thread = try os.spawnThread(&thread_current_id, testThreadIdFn); | |
| 48 | var thread_current_id: Thread.Id = undefined; | |
| 49 | const thread = try Thread.spawn(&thread_current_id, testThreadIdFn); | |
| 49 | 50 | const thread_id = thread.handle(); |
| 50 | 51 | thread.wait(); |
| 51 | if (os.Thread.use_pthreads) { | |
| 52 | if (Thread.use_pthreads) { | |
| 52 | 53 | expect(thread_current_id == thread_id); |
| 53 | 54 | } else { |
| 54 | 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 | 57 | else => { |
| 57 | 58 | // 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 | 60 | expect(thread_id == 0 or thread_current_id == thread_id); |
| 60 | 61 | }, |
| 61 | 62 | } |
| ... | ... | @@ -67,10 +68,10 @@ test "spawn threads" { |
| 67 | 68 | |
| 68 | 69 | var shared_ctx: i32 = 1; |
| 69 | 70 | |
| 70 | const thread1 = try std.os.spawnThread({}, start1); | |
| 71 | const thread2 = try std.os.spawnThread(&shared_ctx, start2); | |
| 72 | const thread3 = try std.os.spawnThread(&shared_ctx, start2); | |
| 73 | const thread4 = try std.os.spawnThread(&shared_ctx, start2); | |
| 71 | const thread1 = try Thread.spawn({}, start1); | |
| 72 | const thread2 = try Thread.spawn(&shared_ctx, start2); | |
| 73 | const thread3 = try Thread.spawn(&shared_ctx, start2); | |
| 74 | const thread4 = try Thread.spawn(&shared_ctx, start2); | |
| 74 | 75 | |
| 75 | 76 | thread1.wait(); |
| 76 | 77 | thread2.wait(); |
| ... | ... | @@ -116,8 +117,8 @@ test "AtomicFile" { |
| 116 | 117 | |
| 117 | 118 | test "thread local storage" { |
| 118 | 119 | if (builtin.single_threaded) return error.SkipZigTest; |
| 119 | const thread1 = try std.os.spawnThread({}, testTls); | |
| 120 | const thread2 = try std.os.spawnThread({}, testTls); | |
| 120 | const thread1 = try Thread.spawn({}, testTls); | |
| 121 | const thread2 = try Thread.spawn({}, testTls); | |
| 121 | 122 | testTls({}); |
| 122 | 123 | thread1.wait(); |
| 123 | 124 | thread2.wait(); |
std/os/windows.zig+15-1| ... | ... | @@ -591,7 +591,7 @@ pub fn CreateFileW( |
| 591 | 591 | ERROR.ACCESS_DENIED => return error.AccessDenied, |
| 592 | 592 | ERROR.PIPE_BUSY => return error.PipeBusy, |
| 593 | 593 | ERROR.FILENAME_EXCED_RANGE => return error.NameTooLong, |
| 594 | else => |err| return unexpectedErrorWindows(err), | |
| 594 | else => |err| return unexpectedError(err), | |
| 595 | 595 | } |
| 596 | 596 | } |
| 597 | 597 | |
| ... | ... | @@ -1089,6 +1089,20 @@ pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError |
| 1089 | 1089 | } |
| 1090 | 1090 | } |
| 1091 | 1091 | |
| 1092 | pub const VirtualAllocError = error{Unexpected}; | |
| 1093 | ||
| 1094 | pub 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 | ||
| 1102 | pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void { | |
| 1103 | assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0); | |
| 1104 | } | |
| 1105 | ||
| 1092 | 1106 | pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 { |
| 1093 | 1107 | return sliceToPrefixedFileW(mem.toSliceConst(u8, s)); |
| 1094 | 1108 | } |
std/process.zig+17-17| ... | ... | @@ -1,13 +1,13 @@ |
| 1 | 1 | const std = @import("std.zig"); |
| 2 | const posix = std.os.posix; | |
| 2 | const os = std.os; | |
| 3 | 3 | const BufMap = std.BufMap; |
| 4 | 4 | const mem = std.mem; |
| 5 | 5 | const Allocator = mem.Allocator; |
| 6 | 6 | const assert = std.debug.assert; |
| 7 | 7 | const testing = std.testing; |
| 8 | 8 | |
| 9 | pub const abort = posix.abort; | |
| 10 | pub const exit = posix.exit; | |
| 9 | pub const abort = os.abort; | |
| 10 | pub const exit = os.exit; | |
| 11 | 11 | |
| 12 | 12 | /// Caller must free result when done. |
| 13 | 13 | /// TODO make this go through libc when we have it |
| ... | ... | @@ -42,13 +42,13 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 42 | 42 | |
| 43 | 43 | try result.setMove(key, value); |
| 44 | 44 | } |
| 45 | } else if (builtin.os == Os.wasi) { | |
| 45 | } else if (builtin.os == .wasi) { | |
| 46 | 46 | var environ_count: usize = undefined; |
| 47 | 47 | var environ_buf_size: usize = undefined; |
| 48 | 48 | |
| 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 | 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 | } |
| 53 | 53 | |
| 54 | 54 | // TODO: Verify that the documentation is incorrect |
| ... | ... | @@ -58,9 +58,9 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 58 | 58 | var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size); |
| 59 | 59 | defer allocator.free(environ_buf); |
| 60 | 60 | |
| 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 | 62 | if (environ_get_ret != os.wasi.ESUCCESS) { |
| 63 | return unexpectedErrorPosix(environ_get_ret); | |
| 63 | return os.unexpectedErrno(environ_get_ret); | |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | 66 | for (environ) |env| { |
| ... | ... | @@ -74,7 +74,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 74 | 74 | } |
| 75 | 75 | return result; |
| 76 | 76 | } else { |
| 77 | for (posix.environ) |ptr| { | |
| 77 | for (os.environ) |ptr| { | |
| 78 | 78 | var line_i: usize = 0; |
| 79 | 79 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} |
| 80 | 80 | const key = ptr[0..line_i]; |
| ... | ... | @@ -331,12 +331,12 @@ pub const ArgIteratorWindows = struct { |
| 331 | 331 | }; |
| 332 | 332 | |
| 333 | 333 | pub const ArgIterator = struct { |
| 334 | const InnerType = if (builtin.os == Os.windows) ArgIteratorWindows else ArgIteratorPosix; | |
| 334 | const InnerType = if (builtin.os == .windows) ArgIteratorWindows else ArgIteratorPosix; | |
| 335 | 335 | |
| 336 | 336 | inner: InnerType, |
| 337 | 337 | |
| 338 | 338 | pub fn init() ArgIterator { |
| 339 | if (builtin.os == Os.wasi) { | |
| 339 | if (builtin.os == .wasi) { | |
| 340 | 340 | // TODO: Figure out a compatible interface accomodating WASI |
| 341 | 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 | 348 | |
| 349 | 349 | /// You must free the returned memory when done. |
| 350 | 350 | pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) { |
| 351 | if (builtin.os == Os.windows) { | |
| 351 | if (builtin.os == .windows) { | |
| 352 | 352 | return self.inner.next(allocator); |
| 353 | 353 | } else { |
| 354 | 354 | return mem.dupe(allocator, u8, self.inner.next() orelse return null); |
| ... | ... | @@ -373,13 +373,13 @@ pub fn args() ArgIterator { |
| 373 | 373 | |
| 374 | 374 | /// Caller must call argsFree on result. |
| 375 | 375 | pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { |
| 376 | if (builtin.os == Os.wasi) { | |
| 376 | if (builtin.os == .wasi) { | |
| 377 | 377 | var count: usize = undefined; |
| 378 | 378 | var buf_size: usize = undefined; |
| 379 | 379 | |
| 380 | 380 | const args_sizes_get_ret = os.wasi.args_sizes_get(&count, &buf_size); |
| 381 | 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 | } |
| 384 | 384 | |
| 385 | 385 | var argv = try allocator.alloc([*]u8, count); |
| ... | ... | @@ -388,7 +388,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { |
| 388 | 388 | var argv_buf = try allocator.alloc(u8, buf_size); |
| 389 | 389 | const args_get_ret = os.wasi.args_get(argv.ptr, argv_buf.ptr); |
| 390 | 390 | if (args_get_ret != os.wasi.ESUCCESS) { |
| 391 | return unexpectedErrorPosix(args_get_ret); | |
| 391 | return os.unexpectedErrno(args_get_ret); | |
| 392 | 392 | } |
| 393 | 393 | |
| 394 | 394 | var result_slice = try allocator.alloc([]u8, count); |
| ... | ... | @@ -438,7 +438,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { |
| 438 | 438 | } |
| 439 | 439 | |
| 440 | 440 | pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void { |
| 441 | if (builtin.os == Os.wasi) { | |
| 441 | if (builtin.os == .wasi) { | |
| 442 | 442 | const last_item = args_alloc[args_alloc.len - 1]; |
| 443 | 443 | const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated |
| 444 | 444 | const first_item_ptr = args_alloc[0].ptr; |
| ... | ... | @@ -491,7 +491,7 @@ pub const UserInfo = struct { |
| 491 | 491 | /// POSIX function which gets a uid from username. |
| 492 | 492 | pub fn getUserInfo(name: []const u8) !UserInfo { |
| 493 | 493 | return switch (builtin.os) { |
| 494 | .linux, .macosx, .ios, .freebsd, .netbsd => posixGetUserInfo(name), | |
| 494 | .linux, .macosx, .watchos, .tvos, .ios, .freebsd, .netbsd => posixGetUserInfo(name), | |
| 495 | 495 | else => @compileError("Unsupported OS"), |
| 496 | 496 | }; |
| 497 | 497 | } |
std/special/bootstrap.zig+2-2| ... | ... | @@ -92,14 +92,14 @@ fn posixCallMainAndExit() noreturn { |
| 92 | 92 | } |
| 93 | 93 | } |
| 94 | 94 | |
| 95 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); | |
| 95 | std.os.exit(callMainWithArgs(argc, argv, envp)); | |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | 98 | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 99 | 99 | // and we want fewer call frames in stack traces. |
| 100 | 100 | inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 { |
| 101 | 101 | std.os.ArgIteratorPosix.raw = argv[0..argc]; |
| 102 | std.os.posix.environ = envp; | |
| 102 | std.os.environ = envp; | |
| 103 | 103 | return callMain(); |
| 104 | 104 | } |
| 105 | 105 |
std/statically_initialized_mutex.zig+2-2| ... | ... | @@ -96,9 +96,9 @@ test "std.StaticallyInitializedMutex" { |
| 96 | 96 | expect(context.data == TestContext.incr_count); |
| 97 | 97 | } else { |
| 98 | 98 | const thread_count = 10; |
| 99 | var threads: [thread_count]*std.os.Thread = undefined; | |
| 99 | var threads: [thread_count]*std.Thread = undefined; | |
| 100 | 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 | 103 | for (threads) |t| |
| 104 | 104 | t.wait(); |
std/thread.zig+57-93| ... | ... | @@ -1,6 +1,8 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | 2 | const std = @import("std.zig"); |
| 3 | const os = std.os; | |
| 3 | 4 | const windows = std.os.windows; |
| 5 | const c = std.c; | |
| 4 | 6 | |
| 5 | 7 | pub const Thread = struct { |
| 6 | 8 | data: Data, |
| ... | ... | @@ -13,8 +15,8 @@ pub const Thread = struct { |
| 13 | 15 | pub const Handle = if (use_pthreads) |
| 14 | 16 | c.pthread_t |
| 15 | 17 | else switch (builtin.os) { |
| 16 | builtin.Os.linux => i32, | |
| 17 | builtin.Os.windows => windows.HANDLE, | |
| 18 | .linux => i32, | |
| 19 | .windows => windows.HANDLE, | |
| 18 | 20 | else => @compileError("Unsupported OS"), |
| 19 | 21 | }; |
| 20 | 22 | |
| ... | ... | @@ -22,7 +24,7 @@ pub const Thread = struct { |
| 22 | 24 | /// May be an integer or pointer depending on the platform. |
| 23 | 25 | /// On Linux and POSIX, this is the same as Handle. |
| 24 | 26 | pub const Id = switch (builtin.os) { |
| 25 | builtin.Os.windows => windows.DWORD, | |
| 27 | .windows => windows.DWORD, | |
| 26 | 28 | else => Handle, |
| 27 | 29 | }; |
| 28 | 30 | |
| ... | ... | @@ -33,12 +35,12 @@ pub const Thread = struct { |
| 33 | 35 | mmap_len: usize, |
| 34 | 36 | } |
| 35 | 37 | else switch (builtin.os) { |
| 36 | builtin.Os.linux => struct { | |
| 38 | .linux => struct { | |
| 37 | 39 | handle: Thread.Handle, |
| 38 | 40 | mmap_addr: usize, |
| 39 | 41 | mmap_len: usize, |
| 40 | 42 | }, |
| 41 | builtin.Os.windows => struct { | |
| 43 | .windows => struct { | |
| 42 | 44 | handle: Thread.Handle, |
| 43 | 45 | alloc_start: *c_void, |
| 44 | 46 | heap_handle: windows.HANDLE, |
| ... | ... | @@ -54,8 +56,8 @@ pub const Thread = struct { |
| 54 | 56 | return c.pthread_self(); |
| 55 | 57 | } else |
| 56 | 58 | return switch (builtin.os) { |
| 57 | builtin.Os.linux => linux.gettid(), | |
| 58 | builtin.Os.windows => windows.GetCurrentThreadId(), | |
| 59 | .linux => linux.gettid(), | |
| 60 | .windows => windows.GetCurrentThreadId(), | |
| 59 | 61 | else => @compileError("Unsupported OS"), |
| 60 | 62 | }; |
| 61 | 63 | } |
| ... | ... | @@ -75,28 +77,28 @@ pub const Thread = struct { |
| 75 | 77 | const err = c.pthread_join(self.data.handle, null); |
| 76 | 78 | switch (err) { |
| 77 | 79 | 0 => {}, |
| 78 | posix.EINVAL => unreachable, | |
| 79 | posix.ESRCH => unreachable, | |
| 80 | posix.EDEADLK => unreachable, | |
| 80 | os.EINVAL => unreachable, | |
| 81 | os.ESRCH => unreachable, | |
| 82 | os.EDEADLK => unreachable, | |
| 81 | 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 | 86 | } else switch (builtin.os) { |
| 85 | builtin.Os.linux => { | |
| 87 | .linux => { | |
| 86 | 88 | while (true) { |
| 87 | 89 | const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst); |
| 88 | 90 | if (pid_value == 0) break; |
| 89 | 91 | const rc = linux.futex_wait(&self.data.handle, linux.FUTEX_WAIT, pid_value, null); |
| 90 | 92 | switch (linux.getErrno(rc)) { |
| 91 | 93 | 0 => continue, |
| 92 | posix.EINTR => continue, | |
| 93 | posix.EAGAIN => continue, | |
| 94 | os.EINTR => continue, | |
| 95 | os.EAGAIN => continue, | |
| 94 | 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 | 102 | assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0); |
| 101 | 103 | assert(windows.CloseHandle(self.data.handle) != 0); |
| 102 | 104 | assert(windows.HeapFree(self.data.heap_handle, 0, self.data.alloc_start) != 0); |
| ... | ... | @@ -153,10 +155,10 @@ pub const Thread = struct { |
| 153 | 155 | extern fn threadMain(raw_arg: windows.LPVOID) windows.DWORD { |
| 154 | 156 | const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*; |
| 155 | 157 | switch (@typeId(@typeOf(startFn).ReturnType)) { |
| 156 | builtin.TypeId.Int => { | |
| 158 | .Int => { | |
| 157 | 159 | return startFn(arg); |
| 158 | 160 | }, |
| 159 | builtin.TypeId.Void => { | |
| 161 | .Void => { | |
| 160 | 162 | startFn(arg); |
| 161 | 163 | return 0; |
| 162 | 164 | }, |
| ... | ... | @@ -196,10 +198,10 @@ pub const Thread = struct { |
| 196 | 198 | const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*; |
| 197 | 199 | |
| 198 | 200 | switch (@typeId(@typeOf(startFn).ReturnType)) { |
| 199 | builtin.TypeId.Int => { | |
| 201 | .Int => { | |
| 200 | 202 | return startFn(arg); |
| 201 | 203 | }, |
| 202 | builtin.TypeId.Void => { | |
| 204 | .Void => { | |
| 203 | 205 | startFn(arg); |
| 204 | 206 | return 0; |
| 205 | 207 | }, |
| ... | ... | @@ -217,7 +219,7 @@ pub const Thread = struct { |
| 217 | 219 | } |
| 218 | 220 | }; |
| 219 | 221 | |
| 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; | |
| 221 | 223 | |
| 222 | 224 | var stack_end_offset: usize = undefined; |
| 223 | 225 | var thread_start_offset: usize = undefined; |
| ... | ... | @@ -247,9 +249,8 @@ pub const Thread = struct { |
| 247 | 249 | } |
| 248 | 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); | |
| 251 | if (mmap_addr == posix.MAP_FAILED) return error.OutOfMemory; | |
| 252 | errdefer assert(posix.munmap(mmap_addr, mmap_len) == 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); | |
| 253 | errdefer os.munmap(mmap_addr, mmap_len); | |
| 253 | 254 | |
| 254 | 255 | const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset)); |
| 255 | 256 | thread_ptr.data.mmap_addr = mmap_addr; |
| ... | ... | @@ -273,31 +274,30 @@ pub const Thread = struct { |
| 273 | 274 | const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg)); |
| 274 | 275 | switch (err) { |
| 275 | 276 | 0 => return thread_ptr, |
| 276 | posix.EAGAIN => return error.SystemResources, | |
| 277 | posix.EPERM => unreachable, | |
| 278 | posix.EINVAL => unreachable, | |
| 279 | else => return unexpectedErrorPosix(@intCast(usize, err)), | |
| 277 | os.EAGAIN => return error.SystemResources, | |
| 278 | os.EPERM => unreachable, | |
| 279 | os.EINVAL => unreachable, | |
| 280 | else => return os.unexpectedErrno(@intCast(usize, err)), | |
| 280 | 281 | } |
| 281 | } else if (builtin.os == builtin.Os.linux) { | |
| 282 | var flags: u32 = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | | |
| 283 | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | | |
| 284 | posix.CLONE_DETACHED; | |
| 282 | } else if (builtin.os == .linux) { | |
| 283 | var flags: u32 = os.CLONE_VM | os.CLONE_FS | os.CLONE_FILES | os.CLONE_SIGHAND | | |
| 284 | os.CLONE_THREAD | os.CLONE_SYSVSEM | os.CLONE_PARENT_SETTID | os.CLONE_CHILD_CLEARTID | | |
| 285 | os.CLONE_DETACHED; | |
| 285 | 286 | var newtls: usize = undefined; |
| 286 | 287 | if (linux.tls.tls_image) |tls_img| { |
| 287 | 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 err = posix.getErrno(rc); | |
| 292 | switch (err) { | |
| 291 | const rc = os.linux.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle); | |
| 292 | switch (os.errno(rc)) { | |
| 293 | 293 | 0 => return thread_ptr, |
| 294 | posix.EAGAIN => return error.ThreadQuotaExceeded, | |
| 295 | posix.EINVAL => unreachable, | |
| 296 | posix.ENOMEM => return error.SystemResources, | |
| 297 | posix.ENOSPC => unreachable, | |
| 298 | posix.EPERM => unreachable, | |
| 299 | posix.EUSERS => unreachable, | |
| 300 | else => return unexpectedErrorPosix(err), | |
| 294 | os.EAGAIN => return error.ThreadQuotaExceeded, | |
| 295 | os.EINVAL => unreachable, | |
| 296 | os.ENOMEM => return error.SystemResources, | |
| 297 | os.ENOSPC => unreachable, | |
| 298 | os.EPERM => unreachable, | |
| 299 | os.EUSERS => unreachable, | |
| 300 | else => |err| return os.unexpectedErrno(err), | |
| 301 | 301 | } |
| 302 | 302 | } else { |
| 303 | 303 | @compileError("Unsupported OS"); |
| ... | ... | @@ -310,56 +310,20 @@ pub const Thread = struct { |
| 310 | 310 | Unexpected, |
| 311 | 311 | }; |
| 312 | 312 | |
| 313 | pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize { | |
| 314 | switch (builtin.os) { | |
| 315 | .macosx, .freebsd, .netbsd => { | |
| 316 | var count: c_int = undefined; | |
| 317 | var count_len: usize = @sizeOf(c_int); | |
| 318 | const name = switch (builtin.os) { | |
| 319 | builtin.Os.macosx => c"hw.logicalcpu", | |
| 320 | else => c"hw.ncpu", | |
| 321 | }; | |
| 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"), | |
| 313 | pub fn cpuCount() CpuCountError!usize { | |
| 314 | if (os.linux.is_the_target) { | |
| 315 | const cpu_set = try os.sched_getaffinity(0); | |
| 316 | return os.CPU_COUNT(cpu_set); | |
| 317 | } | |
| 318 | if (os.windows.is_the_target) { | |
| 319 | var system_info: windows.SYSTEM_INFO = undefined; | |
| 320 | windows.GetSystemInfo(&system_info); | |
| 321 | return @intCast(usize, system_info.dwNumberOfProcessors); | |
| 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 | }; |