| author | |
| committer | |
| log | 7cb6279ac0cec065234347bda5944be64fe8b3da |
| tree | 0eb4befe9a7eb24f5a393559e0621e92e26a4c59 |
| parent | ca6debcaf4a4f85b7aff94c7b5fe821530b0f195 |
| signature | Commit is signed but in an unrecognized format. |
28 files changed, 1390 insertions(+), 1392 deletions(-)
CMakeLists.txt-1| ... | @@ -620,7 +620,6 @@ set(ZIG_STD_FILES | ... | @@ -620,7 +620,6 @@ set(ZIG_STD_FILES |
| 620 | "os/freebsd.zig" | 620 | "os/freebsd.zig" |
| 621 | "os/linux.zig" | 621 | "os/linux.zig" |
| 622 | "os/linux/arm64.zig" | 622 | "os/linux/arm64.zig" |
| 623 | "os/linux/sys.zig" | ||
| 624 | "os/linux/tls.zig" | 623 | "os/linux/tls.zig" |
| 625 | "os/linux/vdso.zig" | 624 | "os/linux/vdso.zig" |
| 626 | "os/linux/x86_64.zig" | 625 | "os/linux/x86_64.zig" |
std/atomic/queue.zig+4-4| ... | @@ -186,13 +186,13 @@ test "std.atomic.Queue" { | ... | @@ -186,13 +186,13 @@ test "std.atomic.Queue" { |
| 186 | } | 186 | } |
| 187 | } | 187 | } |
| 188 | } else { | 188 | } else { |
| 189 | var putters: [put_thread_count]*std.os.Thread = undefined; | 189 | var putters: [put_thread_count]*std.Thread = undefined; |
| 190 | for (putters) |*t| { | 190 | for (putters) |*t| { |
| 191 | t.* = try std.os.spawnThread(&context, startPuts); | 191 | t.* = try std.Thread.spawn(&context, startPuts); |
| 192 | } | 192 | } |
| 193 | var getters: [put_thread_count]*std.os.Thread = undefined; | 193 | var getters: [put_thread_count]*std.Thread = undefined; |
| 194 | for (getters) |*t| { | 194 | for (getters) |*t| { |
| 195 | t.* = try std.os.spawnThread(&context, startGets); | 195 | t.* = try std.Thread.spawn(&context, startGets); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | for (putters) |t| | 198 | for (putters) |t| |
std/atomic/stack.zig+4-4| ... | @@ -120,13 +120,13 @@ test "std.atomic.stack" { | ... | @@ -120,13 +120,13 @@ test "std.atomic.stack" { |
| 120 | } | 120 | } |
| 121 | } | 121 | } |
| 122 | } else { | 122 | } else { |
| 123 | var putters: [put_thread_count]*std.os.Thread = undefined; | 123 | var putters: [put_thread_count]*std.Thread = undefined; |
| 124 | for (putters) |*t| { | 124 | for (putters) |*t| { |
| 125 | t.* = try std.os.spawnThread(&context, startPuts); | 125 | t.* = try std.Thread.spawn(&context, startPuts); |
| 126 | } | 126 | } |
| 127 | var getters: [put_thread_count]*std.os.Thread = undefined; | 127 | var getters: [put_thread_count]*std.Thread = undefined; |
| 128 | for (getters) |*t| { | 128 | for (getters) |*t| { |
| 129 | t.* = try std.os.spawnThread(&context, startGets); | 129 | t.* = try std.Thread.spawn(&context, startGets); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | for (putters) |t| | 132 | for (putters) |t| |
std/c/darwin.zig+1-1| ... | @@ -3,7 +3,7 @@ const assert = std.debug.assert; | ... | @@ -3,7 +3,7 @@ const assert = std.debug.assert; |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | const macho = std.macho; | 4 | const macho = std.macho; |
| 5 | 5 | ||
| 6 | use @import("posix/darwin.zig"); | 6 | use @import("../os/bits.zig"); |
| 7 | 7 | ||
| 8 | extern "c" fn __error() *c_int; | 8 | extern "c" fn __error() *c_int; |
| 9 | pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int; | 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,6 +2,7 @@ const std = @import("../std.zig"); |
| 2 | use std.c; | 2 | use std.c; |
| 3 | 3 | ||
| 4 | pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int; | 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 | extern "c" fn __errno_location() *c_int; | 6 | extern "c" fn __errno_location() *c_int; |
| 6 | pub const _errno = __errno_location; | 7 | pub const _errno = __errno_location; |
| 7 | 8 |
std/child_process.zig+9-9| ... | @@ -351,22 +351,22 @@ pub const ChildProcess = struct { | ... | @@ -351,22 +351,22 @@ pub const ChildProcess = struct { |
| 351 | const err_pipe = try os.pipe(); | 351 | const err_pipe = try os.pipe(); |
| 352 | errdefer destroyPipe(err_pipe); | 352 | errdefer destroyPipe(err_pipe); |
| 353 | 353 | ||
| 354 | const pid_result = try posix.fork(); | 354 | const pid_result = try os.fork(); |
| 355 | if (pid_result == 0) { | 355 | if (pid_result == 0) { |
| 356 | // we are the child | 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); | 357 | setUpChildIo(self.stdin_behavior, stdin_pipe[0], os.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 358 | setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); | 358 | setUpChildIo(self.stdout_behavior, stdout_pipe[1], os.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 359 | setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); | 359 | setUpChildIo(self.stderr_behavior, stderr_pipe[1], os.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err); |
| 360 | 360 | ||
| 361 | if (self.stdin_behavior == StdIo.Pipe) { | 361 | if (self.stdin_behavior == .Pipe) { |
| 362 | os.close(stdin_pipe[0]); | 362 | os.close(stdin_pipe[0]); |
| 363 | os.close(stdin_pipe[1]); | 363 | os.close(stdin_pipe[1]); |
| 364 | } | 364 | } |
| 365 | if (self.stdout_behavior == StdIo.Pipe) { | 365 | if (self.stdout_behavior == .Pipe) { |
| 366 | os.close(stdout_pipe[0]); | 366 | os.close(stdout_pipe[0]); |
| 367 | os.close(stdout_pipe[1]); | 367 | os.close(stdout_pipe[1]); |
| 368 | } | 368 | } |
| 369 | if (self.stderr_behavior == StdIo.Pipe) { | 369 | if (self.stderr_behavior == .Pipe) { |
| 370 | os.close(stderr_pipe[0]); | 370 | os.close(stderr_pipe[0]); |
| 371 | os.close(stderr_pipe[1]); | 371 | os.close(stderr_pipe[1]); |
| 372 | } | 372 | } |
| ... | @@ -383,7 +383,7 @@ pub const ChildProcess = struct { | ... | @@ -383,7 +383,7 @@ pub const ChildProcess = struct { |
| 383 | os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); | 383 | os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); |
| 384 | } | 384 | } |
| 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 | // we are the parent | 389 | // we are the parent |
| ... | @@ -736,7 +736,7 @@ fn destroyPipe(pipe: [2]i32) void { | ... | @@ -736,7 +736,7 @@ fn destroyPipe(pipe: [2]i32) void { |
| 736 | // Then the child exits. | 736 | // Then the child exits. |
| 737 | fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { | 737 | fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { |
| 738 | writeIntFd(fd, ErrInt(@errorToInt(err))) catch {}; | 738 | writeIntFd(fd, ErrInt(@errorToInt(err))) catch {}; |
| 739 | posix.exit(1); | 739 | os.exit(1); |
| 740 | } | 740 | } |
| 741 | 741 | ||
| 742 | const ErrInt = @IntType(false, @sizeOf(anyerror) * 8); | 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,7 +33,7 @@ pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; |
| 33 | pub const X25519 = @import("crypto/x25519.zig").X25519; | 33 | pub const X25519 = @import("crypto/x25519.zig").X25519; |
| 34 | 34 | ||
| 35 | const std = @import("std.zig"); | 35 | const std = @import("std.zig"); |
| 36 | pub const randomBytes = std.posix.getrandom; | 36 | pub const randomBytes = std.os.getrandom; |
| 37 | 37 | ||
| 38 | test "crypto" { | 38 | test "crypto" { |
| 39 | _ = @import("crypto/blake2.zig"); | 39 | _ = @import("crypto/blake2.zig"); |
std/debug.zig+4-5| ... | @@ -1012,16 +1012,15 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo { | ... | @@ -1012,16 +1012,15 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo { |
| 1012 | errdefer S.self_exe_file.close(); | 1012 | errdefer S.self_exe_file.close(); |
| 1013 | 1013 | ||
| 1014 | const self_exe_mmap_len = try S.self_exe_file.getEndPos(); | 1014 | const self_exe_mmap_len = try S.self_exe_file.getEndPos(); |
| 1015 | const self_exe_mmap = os.posix.mmap( | 1015 | const self_exe_mmap = try os.mmap( |
| 1016 | null, | 1016 | null, |
| 1017 | self_exe_mmap_len, | 1017 | self_exe_mmap_len, |
| 1018 | os.posix.PROT_READ, | 1018 | os.PROT_READ, |
| 1019 | os.posix.MAP_SHARED, | 1019 | os.MAP_SHARED, |
| 1020 | S.self_exe_file.handle, | 1020 | S.self_exe_file.handle, |
| 1021 | 0, | 1021 | 0, |
| 1022 | ); | 1022 | ); |
| 1023 | if (self_exe_mmap == os.posix.MAP_FAILED) return error.OutOfMemory; | 1023 | errdefer os.munmap(self_exe_mmap, self_exe_mmap_len); |
| 1024 | errdefer assert(os.posix.munmap(self_exe_mmap, self_exe_mmap_len) == 0); | ||
| 1025 | 1024 | ||
| 1026 | const file_mmap_slice = @intToPtr([*]const u8, self_exe_mmap)[0..self_exe_mmap_len]; | 1025 | const file_mmap_slice = @intToPtr([*]const u8, self_exe_mmap)[0..self_exe_mmap_len]; |
| 1027 | S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(file_mmap_slice); | 1026 | S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(file_mmap_slice); |
std/event/fs.zig+17-21| ... | @@ -5,10 +5,9 @@ const assert = std.debug.assert; | ... | @@ -5,10 +5,9 @@ const assert = std.debug.assert; |
| 5 | const testing = std.testing; | 5 | const testing = std.testing; |
| 6 | const os = std.os; | 6 | const os = std.os; |
| 7 | const mem = std.mem; | 7 | const mem = std.mem; |
| 8 | const posix = os.posix; | ||
| 9 | const windows = os.windows; | 8 | const windows = os.windows; |
| 10 | const Loop = event.Loop; | 9 | const Loop = event.Loop; |
| 11 | const fd_t = posix.fd_t; | 10 | const fd_t = os.fd_t; |
| 12 | const File = std.fs.File; | 11 | const File = std.fs.File; |
| 13 | 12 | ||
| 14 | pub const RequestNode = std.atomic.Queue(Request).Node; | 13 | pub const RequestNode = std.atomic.Queue(Request).Node; |
| ... | @@ -33,7 +32,7 @@ pub const Request = struct { | ... | @@ -33,7 +32,7 @@ pub const Request = struct { |
| 33 | 32 | ||
| 34 | pub const PWriteV = struct { | 33 | pub const PWriteV = struct { |
| 35 | fd: fd_t, | 34 | fd: fd_t, |
| 36 | iov: []const os.posix.iovec_const, | 35 | iov: []const os.iovec_const, |
| 37 | offset: usize, | 36 | offset: usize, |
| 38 | result: Error!void, | 37 | result: Error!void, |
| 39 | 38 | ||
| ... | @@ -42,7 +41,7 @@ pub const Request = struct { | ... | @@ -42,7 +41,7 @@ pub const Request = struct { |
| 42 | 41 | ||
| 43 | pub const PReadV = struct { | 42 | pub const PReadV = struct { |
| 44 | fd: fd_t, | 43 | fd: fd_t, |
| 45 | iov: []const os.posix.iovec, | 44 | iov: []const os.iovec, |
| 46 | offset: usize, | 45 | offset: usize, |
| 47 | result: Error!usize, | 46 | result: Error!usize, |
| 48 | 47 | ||
| ... | @@ -89,11 +88,11 @@ pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: us | ... | @@ -89,11 +88,11 @@ pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: us |
| 89 | builtin.Os.freebsd, | 88 | builtin.Os.freebsd, |
| 90 | builtin.Os.netbsd, | 89 | builtin.Os.netbsd, |
| 91 | => { | 90 | => { |
| 92 | const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len); | 91 | const iovecs = try loop.allocator.alloc(os.iovec_const, data.len); |
| 93 | defer loop.allocator.free(iovecs); | 92 | defer loop.allocator.free(iovecs); |
| 94 | 93 | ||
| 95 | for (data) |buf, i| { | 94 | for (data) |buf, i| { |
| 96 | iovecs[i] = os.posix.iovec_const{ | 95 | iovecs[i] = os.iovec_const{ |
| 97 | .iov_base = buf.ptr, | 96 | .iov_base = buf.ptr, |
| 98 | .iov_len = buf.len, | 97 | .iov_len = buf.len, |
| 99 | }; | 98 | }; |
| ... | @@ -171,7 +170,7 @@ pub async fn pwriteWindows(loop: *Loop, fd: fd_t, data: []const u8, offset: u64) | ... | @@ -171,7 +170,7 @@ pub async fn pwriteWindows(loop: *Loop, fd: fd_t, data: []const u8, offset: u64) |
| 171 | pub async fn pwritevPosix( | 170 | pub async fn pwritevPosix( |
| 172 | loop: *Loop, | 171 | loop: *Loop, |
| 173 | fd: fd_t, | 172 | fd: fd_t, |
| 174 | iovecs: []const posix.iovec_const, | 173 | iovecs: []const os.iovec_const, |
| 175 | offset: usize, | 174 | offset: usize, |
| 176 | ) os.PosixWriteError!void { | 175 | ) os.PosixWriteError!void { |
| 177 | // workaround for https://github.com/ziglang/zig/issues/1194 | 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,11 +225,11 @@ pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PR |
| 226 | builtin.Os.freebsd, | 225 | builtin.Os.freebsd, |
| 227 | builtin.Os.netbsd, | 226 | builtin.Os.netbsd, |
| 228 | => { | 227 | => { |
| 229 | const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len); | 228 | const iovecs = try loop.allocator.alloc(os.iovec, data.len); |
| 230 | defer loop.allocator.free(iovecs); | 229 | defer loop.allocator.free(iovecs); |
| 231 | 230 | ||
| 232 | for (data) |buf, i| { | 231 | for (data) |buf, i| { |
| 233 | iovecs[i] = os.posix.iovec{ | 232 | iovecs[i] = os.iovec{ |
| 234 | .iov_base = buf.ptr, | 233 | .iov_base = buf.ptr, |
| 235 | .iov_len = buf.len, | 234 | .iov_len = buf.len, |
| 236 | }; | 235 | }; |
| ... | @@ -319,7 +318,7 @@ pub async fn preadWindows(loop: *Loop, fd: fd_t, data: []u8, offset: u64) !usize | ... | @@ -319,7 +318,7 @@ pub async fn preadWindows(loop: *Loop, fd: fd_t, data: []u8, offset: u64) !usize |
| 319 | pub async fn preadvPosix( | 318 | pub async fn preadvPosix( |
| 320 | loop: *Loop, | 319 | loop: *Loop, |
| 321 | fd: fd_t, | 320 | fd: fd_t, |
| 322 | iovecs: []const posix.iovec, | 321 | iovecs: []const os.iovec, |
| 323 | offset: usize, | 322 | offset: usize, |
| 324 | ) os.PosixReadError!usize { | 323 | ) os.PosixReadError!usize { |
| 325 | // workaround for https://github.com/ziglang/zig/issues/1194 | 324 | // workaround for https://github.com/ziglang/zig/issues/1194 |
| ... | @@ -405,7 +404,7 @@ pub async fn openPosix( | ... | @@ -405,7 +404,7 @@ pub async fn openPosix( |
| 405 | pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t { | 404 | pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t { |
| 406 | switch (builtin.os) { | 405 | switch (builtin.os) { |
| 407 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => { | 406 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 408 | const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC; | 407 | const flags = os.O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC; |
| 409 | return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable); | 408 | return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable); |
| 410 | }, | 409 | }, |
| 411 | 410 | ||
| ... | @@ -435,7 +434,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File. | ... | @@ -435,7 +434,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File. |
| 435 | builtin.Os.freebsd, | 434 | builtin.Os.freebsd, |
| 436 | builtin.Os.netbsd, | 435 | builtin.Os.netbsd, |
| 437 | => { | 436 | => { |
| 438 | const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC; | 437 | const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC; |
| 439 | return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable); | 438 | return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable); |
| 440 | }, | 439 | }, |
| 441 | builtin.Os.windows => return os.windowsOpen( | 440 | builtin.Os.windows => return os.windowsOpen( |
| ... | @@ -457,7 +456,7 @@ pub async fn openReadWrite( | ... | @@ -457,7 +456,7 @@ pub async fn openReadWrite( |
| 457 | ) File.OpenError!fd_t { | 456 | ) File.OpenError!fd_t { |
| 458 | switch (builtin.os) { | 457 | switch (builtin.os) { |
| 459 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => { | 458 | builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 460 | const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC; | 459 | const flags = os.O_LARGEFILE | os.O_RDWR | os.O_CREAT | os.O_CLOEXEC; |
| 461 | return await (async openPosix(loop, path, flags, mode) catch unreachable); | 460 | return await (async openPosix(loop, path, flags, mode) catch unreachable); |
| 462 | }, | 461 | }, |
| 463 | 462 | ||
| ... | @@ -888,10 +887,7 @@ pub fn Watch(comptime V: type) type { | ... | @@ -888,10 +887,7 @@ pub fn Watch(comptime V: type) type { |
| 888 | var close_op_consumed = false; | 887 | var close_op_consumed = false; |
| 889 | defer if (!close_op_consumed) close_op.finish(); | 888 | defer if (!close_op_consumed) close_op.finish(); |
| 890 | 889 | ||
| 891 | const flags = switch (builtin.os) { | 890 | const flags = if (os.darwin.is_the_target) os.O_SYMLINK | os.O_EVTONLY else 0; |
| 892 | builtin.Os.macosx => posix.O_SYMLINK | posix.O_EVTONLY, | ||
| 893 | else => 0, | ||
| 894 | }; | ||
| 895 | const mode = 0; | 891 | const mode = 0; |
| 896 | const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable); | 892 | const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable); |
| 897 | close_op.setHandle(fd); | 893 | close_op.setHandle(fd); |
| ... | @@ -943,16 +939,16 @@ pub fn Watch(comptime V: type) type { | ... | @@ -943,16 +939,16 @@ pub fn Watch(comptime V: type) type { |
| 943 | while (true) { | 939 | while (true) { |
| 944 | if (await (async self.channel.loop.bsdWaitKev( | 940 | if (await (async self.channel.loop.bsdWaitKev( |
| 945 | @intCast(usize, close_op.getHandle()), | 941 | @intCast(usize, close_op.getHandle()), |
| 946 | posix.EVFILT_VNODE, | 942 | os.EVFILT_VNODE, |
| 947 | posix.NOTE_WRITE | posix.NOTE_DELETE, | 943 | os.NOTE_WRITE | os.NOTE_DELETE, |
| 948 | ) catch unreachable)) |kev| { | 944 | ) catch unreachable)) |kev| { |
| 949 | // TODO handle EV_ERROR | 945 | // TODO handle EV_ERROR |
| 950 | if (kev.fflags & posix.NOTE_DELETE != 0) { | 946 | if (kev.fflags & os.NOTE_DELETE != 0) { |
| 951 | await (async self.channel.put(Self.Event{ | 947 | await (async self.channel.put(Self.Event{ |
| 952 | .id = Event.Id.Delete, | 948 | .id = Event.Id.Delete, |
| 953 | .data = value_copy, | 949 | .data = value_copy, |
| 954 | }) catch unreachable); | 950 | }) catch unreachable); |
| 955 | } else if (kev.fflags & posix.NOTE_WRITE != 0) { | 951 | } else if (kev.fflags & os.NOTE_WRITE != 0) { |
| 956 | await (async self.channel.put(Self.Event{ | 952 | await (async self.channel.put(Self.Event{ |
| 957 | .id = Event.Id.CloseWrite, | 953 | .id = Event.Id.CloseWrite, |
| 958 | .data = value_copy, | 954 | .data = value_copy, |
std/event/loop.zig+71-71| ... | @@ -7,9 +7,9 @@ const AtomicRmwOp = builtin.AtomicRmwOp; | ... | @@ -7,9 +7,9 @@ const AtomicRmwOp = builtin.AtomicRmwOp; |
| 7 | const AtomicOrder = builtin.AtomicOrder; | 7 | const AtomicOrder = builtin.AtomicOrder; |
| 8 | const fs = std.event.fs; | 8 | const fs = std.event.fs; |
| 9 | const os = std.os; | 9 | const os = std.os; |
| 10 | const posix = os.posix; | ||
| 11 | const windows = os.windows; | 10 | const windows = os.windows; |
| 12 | const maxInt = std.math.maxInt; | 11 | const maxInt = std.math.maxInt; |
| 12 | const Thread = std.Thread; | ||
| 13 | 13 | ||
| 14 | pub const Loop = struct { | 14 | pub const Loop = struct { |
| 15 | allocator: *mem.Allocator, | 15 | allocator: *mem.Allocator, |
| ... | @@ -17,7 +17,7 @@ pub const Loop = struct { | ... | @@ -17,7 +17,7 @@ pub const Loop = struct { |
| 17 | os_data: OsData, | 17 | os_data: OsData, |
| 18 | final_resume_node: ResumeNode, | 18 | final_resume_node: ResumeNode, |
| 19 | pending_event_count: usize, | 19 | pending_event_count: usize, |
| 20 | extra_threads: []*os.Thread, | 20 | extra_threads: []*Thread, |
| 21 | 21 | ||
| 22 | // pre-allocated eventfds. all permanently active. | 22 | // pre-allocated eventfds. all permanently active. |
| 23 | // this is how we send promises to be resumed on other threads. | 23 | // this is how we send promises to be resumed on other threads. |
| ... | @@ -65,7 +65,7 @@ pub const Loop = struct { | ... | @@ -65,7 +65,7 @@ pub const Loop = struct { |
| 65 | 65 | ||
| 66 | const KEventFd = struct { | 66 | const KEventFd = struct { |
| 67 | base: ResumeNode, | 67 | base: ResumeNode, |
| 68 | kevent: posix.Kevent, | 68 | kevent: os.Kevent, |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | pub const Basic = switch (builtin.os) { | 71 | pub const Basic = switch (builtin.os) { |
| ... | @@ -81,7 +81,7 @@ pub const Loop = struct { | ... | @@ -81,7 +81,7 @@ pub const Loop = struct { |
| 81 | 81 | ||
| 82 | const KEventBasic = struct { | 82 | const KEventBasic = struct { |
| 83 | base: ResumeNode, | 83 | base: ResumeNode, |
| 84 | kev: posix.Kevent, | 84 | kev: os.Kevent, |
| 85 | }; | 85 | }; |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| ... | @@ -127,7 +127,7 @@ pub const Loop = struct { | ... | @@ -127,7 +127,7 @@ pub const Loop = struct { |
| 127 | ); | 127 | ); |
| 128 | errdefer self.allocator.free(self.eventfd_resume_nodes); | 128 | errdefer self.allocator.free(self.eventfd_resume_nodes); |
| 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 | errdefer self.allocator.free(self.extra_threads); | 131 | errdefer self.allocator.free(self.extra_threads); |
| 132 | 132 | ||
| 133 | try self.initOsData(extra_thread_count); | 133 | try self.initOsData(extra_thread_count); |
| ... | @@ -172,32 +172,32 @@ pub const Loop = struct { | ... | @@ -172,32 +172,32 @@ pub const Loop = struct { |
| 172 | .handle = undefined, | 172 | .handle = undefined, |
| 173 | .overlapped = ResumeNode.overlapped_init, | 173 | .overlapped = ResumeNode.overlapped_init, |
| 174 | }, | 174 | }, |
| 175 | .eventfd = try os.linuxEventFd(1, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK), | 175 | .eventfd = try os.linuxEventFd(1, os.EFD_CLOEXEC | os.EFD_NONBLOCK), |
| 176 | .epoll_op = posix.EPOLL_CTL_ADD, | 176 | .epoll_op = os.EPOLL_CTL_ADD, |
| 177 | }, | 177 | }, |
| 178 | .next = undefined, | 178 | .next = undefined, |
| 179 | }; | 179 | }; |
| 180 | self.available_eventfd_resume_nodes.push(eventfd_node); | 180 | self.available_eventfd_resume_nodes.push(eventfd_node); |
| 181 | } | 181 | } |
| 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 | errdefer os.close(self.os_data.epollfd); | 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 | errdefer os.close(self.os_data.final_eventfd); | 187 | errdefer os.close(self.os_data.final_eventfd); |
| 188 | 188 | ||
| 189 | self.os_data.final_eventfd_event = posix.epoll_event{ | 189 | self.os_data.final_eventfd_event = os.epoll_event{ |
| 190 | .events = posix.EPOLLIN, | 190 | .events = os.EPOLLIN, |
| 191 | .data = posix.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) }, | 191 | .data = os.epoll_data{ .ptr = @ptrToInt(&self.final_resume_node) }, |
| 192 | }; | 192 | }; |
| 193 | try os.linuxEpollCtl( | 193 | try os.linuxEpollCtl( |
| 194 | self.os_data.epollfd, | 194 | self.os_data.epollfd, |
| 195 | posix.EPOLL_CTL_ADD, | 195 | os.EPOLL_CTL_ADD, |
| 196 | self.os_data.final_eventfd, | 196 | self.os_data.final_eventfd, |
| 197 | &self.os_data.final_eventfd_event, | 197 | &self.os_data.final_eventfd_event, |
| 198 | ); | 198 | ); |
| 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 | errdefer { | 201 | errdefer { |
| 202 | self.posixFsRequest(&self.os_data.fs_end_request); | 202 | self.posixFsRequest(&self.os_data.fs_end_request); |
| 203 | self.os_data.fs_thread.wait(); | 203 | self.os_data.fs_thread.wait(); |
| ... | @@ -218,7 +218,7 @@ pub const Loop = struct { | ... | @@ -218,7 +218,7 @@ pub const Loop = struct { |
| 218 | } | 218 | } |
| 219 | } | 219 | } |
| 220 | while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { | 220 | while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { |
| 221 | self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun); | 221 | self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun); |
| 222 | } | 222 | } |
| 223 | }, | 223 | }, |
| 224 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | 224 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| ... | @@ -240,7 +240,7 @@ pub const Loop = struct { | ... | @@ -240,7 +240,7 @@ pub const Loop = struct { |
| 240 | }, | 240 | }, |
| 241 | }; | 241 | }; |
| 242 | 242 | ||
| 243 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 243 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; |
| 244 | 244 | ||
| 245 | for (self.eventfd_resume_nodes) |*eventfd_node, i| { | 245 | for (self.eventfd_resume_nodes) |*eventfd_node, i| { |
| 246 | eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{ | 246 | eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{ |
| ... | @@ -251,10 +251,10 @@ pub const Loop = struct { | ... | @@ -251,10 +251,10 @@ pub const Loop = struct { |
| 251 | .overlapped = ResumeNode.overlapped_init, | 251 | .overlapped = ResumeNode.overlapped_init, |
| 252 | }, | 252 | }, |
| 253 | // this one is for sending events | 253 | // this one is for sending events |
| 254 | .kevent = posix.Kevent{ | 254 | .kevent = os.Kevent{ |
| 255 | .ident = i, | 255 | .ident = i, |
| 256 | .filter = posix.EVFILT_USER, | 256 | .filter = os.EVFILT_USER, |
| 257 | .flags = posix.EV_CLEAR | posix.EV_ADD | posix.EV_DISABLE, | 257 | .flags = os.EV_CLEAR | os.EV_ADD | os.EV_DISABLE, |
| 258 | .fflags = 0, | 258 | .fflags = 0, |
| 259 | .data = 0, | 259 | .data = 0, |
| 260 | .udata = @ptrToInt(&eventfd_node.data.base), | 260 | .udata = @ptrToInt(&eventfd_node.data.base), |
| ... | @@ -263,46 +263,46 @@ pub const Loop = struct { | ... | @@ -263,46 +263,46 @@ pub const Loop = struct { |
| 263 | .next = undefined, | 263 | .next = undefined, |
| 264 | }; | 264 | }; |
| 265 | self.available_eventfd_resume_nodes.push(eventfd_node); | 265 | self.available_eventfd_resume_nodes.push(eventfd_node); |
| 266 | const kevent_array = (*const [1]posix.Kevent)(&eventfd_node.data.kevent); | 266 | const kevent_array = (*const [1]os.Kevent)(&eventfd_node.data.kevent); |
| 267 | _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null); | 267 | _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null); |
| 268 | eventfd_node.data.kevent.flags = posix.EV_CLEAR | posix.EV_ENABLE; | 268 | eventfd_node.data.kevent.flags = os.EV_CLEAR | os.EV_ENABLE; |
| 269 | eventfd_node.data.kevent.fflags = posix.NOTE_TRIGGER; | 269 | eventfd_node.data.kevent.fflags = os.NOTE_TRIGGER; |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | // Pre-add so that we cannot get error.SystemResources | 272 | // Pre-add so that we cannot get error.SystemResources |
| 273 | // later when we try to activate it. | 273 | // later when we try to activate it. |
| 274 | self.os_data.final_kevent = posix.Kevent{ | 274 | self.os_data.final_kevent = os.Kevent{ |
| 275 | .ident = extra_thread_count, | 275 | .ident = extra_thread_count, |
| 276 | .filter = posix.EVFILT_USER, | 276 | .filter = os.EVFILT_USER, |
| 277 | .flags = posix.EV_ADD | posix.EV_DISABLE, | 277 | .flags = os.EV_ADD | os.EV_DISABLE, |
| 278 | .fflags = 0, | 278 | .fflags = 0, |
| 279 | .data = 0, | 279 | .data = 0, |
| 280 | .udata = @ptrToInt(&self.final_resume_node), | 280 | .udata = @ptrToInt(&self.final_resume_node), |
| 281 | }; | 281 | }; |
| 282 | const final_kev_arr = (*const [1]posix.Kevent)(&self.os_data.final_kevent); | 282 | const final_kev_arr = (*const [1]os.Kevent)(&self.os_data.final_kevent); |
| 283 | _ = try os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null); | 283 | _ = try os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null); |
| 284 | self.os_data.final_kevent.flags = posix.EV_ENABLE; | 284 | self.os_data.final_kevent.flags = os.EV_ENABLE; |
| 285 | self.os_data.final_kevent.fflags = posix.NOTE_TRIGGER; | 285 | self.os_data.final_kevent.fflags = os.NOTE_TRIGGER; |
| 286 | 286 | ||
| 287 | self.os_data.fs_kevent_wake = posix.Kevent{ | 287 | self.os_data.fs_kevent_wake = os.Kevent{ |
| 288 | .ident = 0, | 288 | .ident = 0, |
| 289 | .filter = posix.EVFILT_USER, | 289 | .filter = os.EVFILT_USER, |
| 290 | .flags = posix.EV_ADD | posix.EV_ENABLE, | 290 | .flags = os.EV_ADD | os.EV_ENABLE, |
| 291 | .fflags = posix.NOTE_TRIGGER, | 291 | .fflags = os.NOTE_TRIGGER, |
| 292 | .data = 0, | 292 | .data = 0, |
| 293 | .udata = undefined, | 293 | .udata = undefined, |
| 294 | }; | 294 | }; |
| 295 | 295 | ||
| 296 | self.os_data.fs_kevent_wait = posix.Kevent{ | 296 | self.os_data.fs_kevent_wait = os.Kevent{ |
| 297 | .ident = 0, | 297 | .ident = 0, |
| 298 | .filter = posix.EVFILT_USER, | 298 | .filter = os.EVFILT_USER, |
| 299 | .flags = posix.EV_ADD | posix.EV_CLEAR, | 299 | .flags = os.EV_ADD | os.EV_CLEAR, |
| 300 | .fflags = 0, | 300 | .fflags = 0, |
| 301 | .data = 0, | 301 | .data = 0, |
| 302 | .udata = undefined, | 302 | .udata = undefined, |
| 303 | }; | 303 | }; |
| 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 | errdefer { | 306 | errdefer { |
| 307 | self.posixFsRequest(&self.os_data.fs_end_request); | 307 | self.posixFsRequest(&self.os_data.fs_end_request); |
| 308 | self.os_data.fs_thread.wait(); | 308 | self.os_data.fs_thread.wait(); |
| ... | @@ -322,7 +322,7 @@ pub const Loop = struct { | ... | @@ -322,7 +322,7 @@ pub const Loop = struct { |
| 322 | } | 322 | } |
| 323 | } | 323 | } |
| 324 | while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { | 324 | while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { |
| 325 | self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun); | 325 | self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun); |
| 326 | } | 326 | } |
| 327 | }, | 327 | }, |
| 328 | builtin.Os.windows => { | 328 | builtin.Os.windows => { |
| ... | @@ -371,7 +371,7 @@ pub const Loop = struct { | ... | @@ -371,7 +371,7 @@ pub const Loop = struct { |
| 371 | } | 371 | } |
| 372 | } | 372 | } |
| 373 | while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { | 373 | while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { |
| 374 | self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun); | 374 | self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun); |
| 375 | } | 375 | } |
| 376 | }, | 376 | }, |
| 377 | else => {}, | 377 | else => {}, |
| ... | @@ -400,19 +400,19 @@ pub const Loop = struct { | ... | @@ -400,19 +400,19 @@ pub const Loop = struct { |
| 400 | /// resume_node must live longer than the promise that it holds a reference to. | 400 | /// resume_node must live longer than the promise that it holds a reference to. |
| 401 | /// flags must contain EPOLLET | 401 | /// flags must contain EPOLLET |
| 402 | pub fn linuxAddFd(self: *Loop, fd: i32, resume_node: *ResumeNode, flags: u32) !void { | 402 | pub fn linuxAddFd(self: *Loop, fd: i32, resume_node: *ResumeNode, flags: u32) !void { |
| 403 | assert(flags & posix.EPOLLET == posix.EPOLLET); | 403 | assert(flags & os.EPOLLET == os.EPOLLET); |
| 404 | self.beginOneEvent(); | 404 | self.beginOneEvent(); |
| 405 | errdefer self.finishOneEvent(); | 405 | errdefer self.finishOneEvent(); |
| 406 | try self.linuxModFd( | 406 | try self.linuxModFd( |
| 407 | fd, | 407 | fd, |
| 408 | posix.EPOLL_CTL_ADD, | 408 | os.EPOLL_CTL_ADD, |
| 409 | flags, | 409 | flags, |
| 410 | resume_node, | 410 | resume_node, |
| 411 | ); | 411 | ); |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | pub fn linuxModFd(self: *Loop, fd: i32, op: u32, flags: u32, resume_node: *ResumeNode) !void { | 414 | pub fn linuxModFd(self: *Loop, fd: i32, op: u32, flags: u32, resume_node: *ResumeNode) !void { |
| 415 | assert(flags & posix.EPOLLET == posix.EPOLLET); | 415 | assert(flags & os.EPOLLET == os.EPOLLET); |
| 416 | var ev = os.linux.epoll_event{ | 416 | var ev = os.linux.epoll_event{ |
| 417 | .events = flags, | 417 | .events = flags, |
| 418 | .data = os.linux.epoll_data{ .ptr = @ptrToInt(resume_node) }, | 418 | .data = os.linux.epoll_data{ .ptr = @ptrToInt(resume_node) }, |
| ... | @@ -440,7 +440,7 @@ pub const Loop = struct { | ... | @@ -440,7 +440,7 @@ pub const Loop = struct { |
| 440 | } | 440 | } |
| 441 | } | 441 | } |
| 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 | // TODO #1194 | 444 | // TODO #1194 |
| 445 | suspend { | 445 | suspend { |
| 446 | resume @handle(); | 446 | resume @handle(); |
| ... | @@ -464,30 +464,30 @@ pub const Loop = struct { | ... | @@ -464,30 +464,30 @@ pub const Loop = struct { |
| 464 | pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void { | 464 | pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void { |
| 465 | self.beginOneEvent(); | 465 | self.beginOneEvent(); |
| 466 | errdefer self.finishOneEvent(); | 466 | errdefer self.finishOneEvent(); |
| 467 | var kev = posix.Kevent{ | 467 | var kev = os.Kevent{ |
| 468 | .ident = ident, | 468 | .ident = ident, |
| 469 | .filter = filter, | 469 | .filter = filter, |
| 470 | .flags = posix.EV_ADD | posix.EV_ENABLE | posix.EV_CLEAR, | 470 | .flags = os.EV_ADD | os.EV_ENABLE | os.EV_CLEAR, |
| 471 | .fflags = fflags, | 471 | .fflags = fflags, |
| 472 | .data = 0, | 472 | .data = 0, |
| 473 | .udata = @ptrToInt(&resume_node.base), | 473 | .udata = @ptrToInt(&resume_node.base), |
| 474 | }; | 474 | }; |
| 475 | const kevent_array = (*const [1]posix.Kevent)(&kev); | 475 | const kevent_array = (*const [1]os.Kevent)(&kev); |
| 476 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 476 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; |
| 477 | _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null); | 477 | _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null); |
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | pub fn bsdRemoveKev(self: *Loop, ident: usize, filter: i16) void { | 480 | pub fn bsdRemoveKev(self: *Loop, ident: usize, filter: i16) void { |
| 481 | var kev = posix.Kevent{ | 481 | var kev = os.Kevent{ |
| 482 | .ident = ident, | 482 | .ident = ident, |
| 483 | .filter = filter, | 483 | .filter = filter, |
| 484 | .flags = posix.EV_DELETE, | 484 | .flags = os.EV_DELETE, |
| 485 | .fflags = 0, | 485 | .fflags = 0, |
| 486 | .data = 0, | 486 | .data = 0, |
| 487 | .udata = 0, | 487 | .udata = 0, |
| 488 | }; | 488 | }; |
| 489 | const kevent_array = (*const [1]posix.Kevent)(&kev); | 489 | const kevent_array = (*const [1]os.Kevent)(&kev); |
| 490 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 490 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; |
| 491 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch undefined; | 491 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch undefined; |
| 492 | self.finishOneEvent(); | 492 | self.finishOneEvent(); |
| 493 | } | 493 | } |
| ... | @@ -502,8 +502,8 @@ pub const Loop = struct { | ... | @@ -502,8 +502,8 @@ pub const Loop = struct { |
| 502 | eventfd_node.base.handle = next_tick_node.data; | 502 | eventfd_node.base.handle = next_tick_node.data; |
| 503 | switch (builtin.os) { | 503 | switch (builtin.os) { |
| 504 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | 504 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 505 | const kevent_array = (*const [1]posix.Kevent)(&eventfd_node.kevent); | 505 | const kevent_array = (*const [1]os.Kevent)(&eventfd_node.kevent); |
| 506 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 506 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; |
| 507 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch { | 507 | _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch { |
| 508 | self.next_tick_queue.unget(next_tick_node); | 508 | self.next_tick_queue.unget(next_tick_node); |
| 509 | self.available_eventfd_resume_nodes.push(resume_stack_node); | 509 | self.available_eventfd_resume_nodes.push(resume_stack_node); |
| ... | @@ -512,7 +512,7 @@ pub const Loop = struct { | ... | @@ -512,7 +512,7 @@ pub const Loop = struct { |
| 512 | }, | 512 | }, |
| 513 | builtin.Os.linux => { | 513 | builtin.Os.linux => { |
| 514 | // the pending count is already accounted for | 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 | os.linux.EPOLLET; | 516 | os.linux.EPOLLET; |
| 517 | self.linuxModFd( | 517 | self.linuxModFd( |
| 518 | eventfd_node.eventfd, | 518 | eventfd_node.eventfd, |
| ... | @@ -631,8 +631,8 @@ pub const Loop = struct { | ... | @@ -631,8 +631,8 @@ pub const Loop = struct { |
| 631 | }, | 631 | }, |
| 632 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | 632 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 633 | self.posixFsRequest(&self.os_data.fs_end_request); | 633 | self.posixFsRequest(&self.os_data.fs_end_request); |
| 634 | const final_kevent = (*const [1]posix.Kevent)(&self.os_data.final_kevent); | 634 | const final_kevent = (*const [1]os.Kevent)(&self.os_data.final_kevent); |
| 635 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 635 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; |
| 636 | // cannot fail because we already added it and this just enables it | 636 | // cannot fail because we already added it and this just enables it |
| 637 | _ = os.bsdKEvent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable; | 637 | _ = os.bsdKEvent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable; |
| 638 | return; | 638 | return; |
| ... | @@ -676,7 +676,7 @@ pub const Loop = struct { | ... | @@ -676,7 +676,7 @@ pub const Loop = struct { |
| 676 | ResumeNode.Id.Stop => return, | 676 | ResumeNode.Id.Stop => return, |
| 677 | ResumeNode.Id.EventFd => { | 677 | ResumeNode.Id.EventFd => { |
| 678 | const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node); | 678 | const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node); |
| 679 | event_fd_node.epoll_op = posix.EPOLL_CTL_MOD; | 679 | event_fd_node.epoll_op = os.EPOLL_CTL_MOD; |
| 680 | const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node); | 680 | const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node); |
| 681 | self.available_eventfd_resume_nodes.push(stack_node); | 681 | self.available_eventfd_resume_nodes.push(stack_node); |
| 682 | }, | 682 | }, |
| ... | @@ -688,8 +688,8 @@ pub const Loop = struct { | ... | @@ -688,8 +688,8 @@ pub const Loop = struct { |
| 688 | } | 688 | } |
| 689 | }, | 689 | }, |
| 690 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | 690 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 691 | var eventlist: [1]posix.Kevent = undefined; | 691 | var eventlist: [1]os.Kevent = undefined; |
| 692 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 692 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; |
| 693 | const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable; | 693 | const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable; |
| 694 | for (eventlist[0..count]) |ev| { | 694 | for (eventlist[0..count]) |ev| { |
| 695 | const resume_node = @intToPtr(*ResumeNode, ev.udata); | 695 | const resume_node = @intToPtr(*ResumeNode, ev.udata); |
| ... | @@ -751,8 +751,8 @@ pub const Loop = struct { | ... | @@ -751,8 +751,8 @@ pub const Loop = struct { |
| 751 | self.os_data.fs_queue.put(request_node); | 751 | self.os_data.fs_queue.put(request_node); |
| 752 | switch (builtin.os) { | 752 | switch (builtin.os) { |
| 753 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | 753 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 754 | const fs_kevs = (*const [1]posix.Kevent)(&self.os_data.fs_kevent_wake); | 754 | const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wake); |
| 755 | const empty_kevs = ([*]posix.Kevent)(undefined)[0..0]; | 755 | const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; |
| 756 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable; | 756 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable; |
| 757 | }, | 757 | }, |
| 758 | builtin.Os.linux => { | 758 | builtin.Os.linux => { |
| ... | @@ -760,7 +760,7 @@ pub const Loop = struct { | ... | @@ -760,7 +760,7 @@ pub const Loop = struct { |
| 760 | const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1); | 760 | const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1); |
| 761 | switch (os.linux.getErrno(rc)) { | 761 | switch (os.linux.getErrno(rc)) { |
| 762 | 0 => {}, | 762 | 0 => {}, |
| 763 | posix.EINVAL => unreachable, | 763 | os.EINVAL => unreachable, |
| 764 | else => unreachable, | 764 | else => unreachable, |
| 765 | } | 765 | } |
| 766 | }, | 766 | }, |
| ... | @@ -793,8 +793,8 @@ pub const Loop = struct { | ... | @@ -793,8 +793,8 @@ pub const Loop = struct { |
| 793 | }, | 793 | }, |
| 794 | @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd), | 794 | @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd), |
| 795 | @TagType(fs.Request.Msg).WriteFile => |*msg| blk: { | 795 | @TagType(fs.Request.Msg).WriteFile => |*msg| blk: { |
| 796 | const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | | 796 | const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | |
| 797 | posix.O_CLOEXEC | posix.O_TRUNC; | 797 | os.O_CLOEXEC | os.O_TRUNC; |
| 798 | const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| { | 798 | const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| { |
| 799 | msg.result = err; | 799 | msg.result = err; |
| 800 | break :blk; | 800 | break :blk; |
| ... | @@ -816,13 +816,13 @@ pub const Loop = struct { | ... | @@ -816,13 +816,13 @@ pub const Loop = struct { |
| 816 | builtin.Os.linux => { | 816 | builtin.Os.linux => { |
| 817 | const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null); | 817 | const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null); |
| 818 | switch (os.linux.getErrno(rc)) { | 818 | switch (os.linux.getErrno(rc)) { |
| 819 | 0, posix.EINTR, posix.EAGAIN => continue, | 819 | 0, os.EINTR, os.EAGAIN => continue, |
| 820 | else => unreachable, | 820 | else => unreachable, |
| 821 | } | 821 | } |
| 822 | }, | 822 | }, |
| 823 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { | 823 | builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { |
| 824 | const fs_kevs = (*const [1]posix.Kevent)(&self.os_data.fs_kevent_wait); | 824 | const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wait); |
| 825 | var out_kevs: [1]posix.Kevent = undefined; | 825 | var out_kevs: [1]os.Kevent = undefined; |
| 826 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable; | 826 | _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable; |
| 827 | }, | 827 | }, |
| 828 | else => @compileError("Unsupported OS"), | 828 | else => @compileError("Unsupported OS"), |
| ... | @@ -842,10 +842,10 @@ pub const Loop = struct { | ... | @@ -842,10 +842,10 @@ pub const Loop = struct { |
| 842 | 842 | ||
| 843 | const KEventData = struct { | 843 | const KEventData = struct { |
| 844 | kqfd: i32, | 844 | kqfd: i32, |
| 845 | final_kevent: posix.Kevent, | 845 | final_kevent: os.Kevent, |
| 846 | fs_kevent_wake: posix.Kevent, | 846 | fs_kevent_wake: os.Kevent, |
| 847 | fs_kevent_wait: posix.Kevent, | 847 | fs_kevent_wait: os.Kevent, |
| 848 | fs_thread: *os.Thread, | 848 | fs_thread: *Thread, |
| 849 | fs_kqfd: i32, | 849 | fs_kqfd: i32, |
| 850 | fs_queue: std.atomic.Queue(fs.Request), | 850 | fs_queue: std.atomic.Queue(fs.Request), |
| 851 | fs_end_request: fs.RequestNode, | 851 | fs_end_request: fs.RequestNode, |
| ... | @@ -855,7 +855,7 @@ pub const Loop = struct { | ... | @@ -855,7 +855,7 @@ pub const Loop = struct { |
| 855 | epollfd: i32, | 855 | epollfd: i32, |
| 856 | final_eventfd: i32, | 856 | final_eventfd: i32, |
| 857 | final_eventfd_event: os.linux.epoll_event, | 857 | final_eventfd_event: os.linux.epoll_event, |
| 858 | fs_thread: *os.Thread, | 858 | fs_thread: *Thread, |
| 859 | fs_queue_item: i32, | 859 | fs_queue_item: i32, |
| 860 | fs_queue: std.atomic.Queue(fs.Request), | 860 | fs_queue: std.atomic.Queue(fs.Request), |
| 861 | fs_end_request: fs.RequestNode, | 861 | fs_end_request: fs.RequestNode, |
std/event/net.zig+54-59| ... | @@ -4,11 +4,9 @@ const testing = std.testing; | ... | @@ -4,11 +4,9 @@ const testing = std.testing; |
| 4 | const event = std.event; | 4 | const event = std.event; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const os = std.os; | 6 | const os = std.os; |
| 7 | const posix = os.posix; | ||
| 8 | const Loop = std.event.Loop; | 7 | const Loop = std.event.Loop; |
| 9 | const File = std.fs.File; | 8 | const File = std.fs.File; |
| 10 | 9 | const fd_t = os.fd_t; | |
| 11 | const fd_t = posix.fd_t; | ||
| 12 | 10 | ||
| 13 | pub const Server = struct { | 11 | pub const Server = struct { |
| 14 | handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void, | 12 | handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void, |
| ... | @@ -47,19 +45,19 @@ pub const Server = struct { | ... | @@ -47,19 +45,19 @@ pub const Server = struct { |
| 47 | ) !void { | 45 | ) !void { |
| 48 | self.handleRequestFn = handleRequestFn; | 46 | self.handleRequestFn = handleRequestFn; |
| 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 | errdefer os.close(sockfd); | 49 | errdefer os.close(sockfd); |
| 52 | self.sockfd = sockfd; | 50 | self.sockfd = sockfd; |
| 53 | 51 | ||
| 54 | try os.posixBind(sockfd, &address.os_addr); | 52 | try os.posixBind(sockfd, &address.os_addr); |
| 55 | try os.posixListen(sockfd, posix.SOMAXCONN); | 53 | try os.posixListen(sockfd, os.SOMAXCONN); |
| 56 | self.listen_address = std.net.Address.initPosix(try os.posixGetSockName(sockfd)); | 54 | self.listen_address = std.net.Address.initPosix(try os.posixGetSockName(sockfd)); |
| 57 | 55 | ||
| 58 | self.accept_coro = try async<self.loop.allocator> Server.handler(self); | 56 | self.accept_coro = try async<self.loop.allocator> Server.handler(self); |
| 59 | errdefer cancel self.accept_coro.?; | 57 | errdefer cancel self.accept_coro.?; |
| 60 | 58 | ||
| 61 | self.listen_resume_node.handle = self.accept_coro.?; | 59 | self.listen_resume_node.handle = self.accept_coro.?; |
| 62 | try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET); | 60 | try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET); |
| 63 | errdefer self.loop.removeFd(sockfd); | 61 | errdefer self.loop.removeFd(sockfd); |
| 64 | } | 62 | } |
| 65 | 63 | ||
| ... | @@ -78,7 +76,7 @@ pub const Server = struct { | ... | @@ -78,7 +76,7 @@ pub const Server = struct { |
| 78 | while (true) { | 76 | while (true) { |
| 79 | var accepted_addr: std.net.Address = undefined; | 77 | var accepted_addr: std.net.Address = undefined; |
| 80 | // TODO just inline the following function here and don't expose it as posixAsyncAccept | 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 | if (accepted_fd == -1) { | 80 | if (accepted_fd == -1) { |
| 83 | // would block | 81 | // would block |
| 84 | suspend; // we will get resumed by epoll_wait in the event loop | 82 | suspend; // we will get resumed by epoll_wait in the event loop |
| ... | @@ -108,22 +106,22 @@ pub const Server = struct { | ... | @@ -108,22 +106,22 @@ pub const Server = struct { |
| 108 | 106 | ||
| 109 | pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 { | 107 | pub async fn connectUnixSocket(loop: *Loop, path: []const u8) !i32 { |
| 110 | const sockfd = try os.posixSocket( | 108 | const sockfd = try os.posixSocket( |
| 111 | posix.AF_UNIX, | 109 | os.AF_UNIX, |
| 112 | posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, | 110 | os.SOCK_STREAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK, |
| 113 | 0, | 111 | 0, |
| 114 | ); | 112 | ); |
| 115 | errdefer os.close(sockfd); | 113 | errdefer os.close(sockfd); |
| 116 | 114 | ||
| 117 | var sock_addr = posix.sockaddr_un{ | 115 | var sock_addr = os.sockaddr_un{ |
| 118 | .family = posix.AF_UNIX, | 116 | .family = os.AF_UNIX, |
| 119 | .path = undefined, | 117 | .path = undefined, |
| 120 | }; | 118 | }; |
| 121 | 119 | ||
| 122 | if (path.len > @typeOf(sock_addr.path).len) return error.NameTooLong; | 120 | if (path.len > @typeOf(sock_addr.path).len) return error.NameTooLong; |
| 123 | mem.copy(u8, sock_addr.path[0..], path); | 121 | mem.copy(u8, sock_addr.path[0..], path); |
| 124 | const size = @intCast(u32, @sizeOf(posix.sa_family_t) + path.len); | 122 | const size = @intCast(u32, @sizeOf(os.sa_family_t) + path.len); |
| 125 | try os.posixConnectAsync(sockfd, &sock_addr, size); | 123 | try os.posixConnectAsync(sockfd, &sock_addr, size); |
| 126 | try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET); | 124 | try await try async loop.linuxWaitFd(sockfd, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET); |
| 127 | try os.posixGetSockOptConnectError(sockfd); | 125 | try os.posixGetSockOptConnectError(sockfd); |
| 128 | 126 | ||
| 129 | return sockfd; | 127 | return sockfd; |
| ... | @@ -143,50 +141,48 @@ pub const ReadError = error{ | ... | @@ -143,50 +141,48 @@ pub const ReadError = error{ |
| 143 | 141 | ||
| 144 | /// returns number of bytes read. 0 means EOF. | 142 | /// returns number of bytes read. 0 means EOF. |
| 145 | pub async fn read(loop: *std.event.Loop, fd: fd_t, buffer: []u8) ReadError!usize { | 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 | .iov_base = buffer.ptr, | 145 | .iov_base = buffer.ptr, |
| 148 | .iov_len = buffer.len, | 146 | .iov_len = buffer.len, |
| 149 | }; | 147 | }; |
| 150 | const iovs: *const [1]posix.iovec = &iov; | 148 | const iovs: *const [1]os.iovec = &iov; |
| 151 | return await (async readvPosix(loop, fd, iovs, 1) catch unreachable); | 149 | return await (async readvPosix(loop, fd, iovs, 1) catch unreachable); |
| 152 | } | 150 | } |
| 153 | 151 | ||
| 154 | pub const WriteError = error{}; | 152 | pub const WriteError = error{}; |
| 155 | 153 | ||
| 156 | pub async fn write(loop: *std.event.Loop, fd: fd_t, buffer: []const u8) WriteError!void { | 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 | .iov_base = buffer.ptr, | 156 | .iov_base = buffer.ptr, |
| 159 | .iov_len = buffer.len, | 157 | .iov_len = buffer.len, |
| 160 | }; | 158 | }; |
| 161 | const iovs: *const [1]posix.iovec_const = &iov; | 159 | const iovs: *const [1]os.iovec_const = &iov; |
| 162 | return await (async writevPosix(loop, fd, iovs, 1) catch unreachable); | 160 | return await (async writevPosix(loop, fd, iovs, 1) catch unreachable); |
| 163 | } | 161 | } |
| 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 | while (true) { | 164 | while (true) { |
| 167 | switch (builtin.os) { | 165 | switch (builtin.os) { |
| 168 | builtin.Os.macosx, builtin.Os.linux => { | 166 | .macosx, .linux => { |
| 169 | const rc = posix.writev(fd, iov, count); | 167 | switch (os.errno(os.system.writev(fd, iov, count))) { |
| 170 | const err = posix.getErrno(rc); | ||
| 171 | switch (err) { | ||
| 172 | 0 => return, | 168 | 0 => return, |
| 173 | posix.EINTR => continue, | 169 | os.EINTR => continue, |
| 174 | posix.ESPIPE => unreachable, | 170 | os.ESPIPE => unreachable, |
| 175 | posix.EINVAL => unreachable, | 171 | os.EINVAL => unreachable, |
| 176 | posix.EFAULT => unreachable, | 172 | os.EFAULT => unreachable, |
| 177 | posix.EAGAIN => { | 173 | os.EAGAIN => { |
| 178 | try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLOUT) catch unreachable); | 174 | try await (async loop.linuxWaitFd(fd, os.EPOLLET | os.EPOLLOUT) catch unreachable); |
| 179 | continue; | 175 | continue; |
| 180 | }, | 176 | }, |
| 181 | posix.EBADF => unreachable, // always a race condition | 177 | os.EBADF => unreachable, // always a race condition |
| 182 | posix.EDESTADDRREQ => unreachable, // connect was never called | 178 | os.EDESTADDRREQ => unreachable, // connect was never called |
| 183 | posix.EDQUOT => unreachable, | 179 | os.EDQUOT => unreachable, |
| 184 | posix.EFBIG => unreachable, | 180 | os.EFBIG => unreachable, |
| 185 | posix.EIO => return error.InputOutput, | 181 | os.EIO => return error.InputOutput, |
| 186 | posix.ENOSPC => unreachable, | 182 | os.ENOSPC => unreachable, |
| 187 | posix.EPERM => return error.AccessDenied, | 183 | os.EPERM => return error.AccessDenied, |
| 188 | posix.EPIPE => unreachable, | 184 | os.EPIPE => unreachable, |
| 189 | else => return os.unexpectedErrorPosix(err), | 185 | else => |err| return os.unexpectedErrno(err), |
| 190 | } | 186 | } |
| 191 | }, | 187 | }, |
| 192 | else => @compileError("Unsupported OS"), | 188 | else => @compileError("Unsupported OS"), |
| ... | @@ -195,27 +191,26 @@ pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const, | ... | @@ -195,27 +191,26 @@ pub async fn writevPosix(loop: *Loop, fd: i32, iov: [*]const posix.iovec_const, |
| 195 | } | 191 | } |
| 196 | 192 | ||
| 197 | /// returns number of bytes read. 0 means EOF. | 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 | while (true) { | 195 | while (true) { |
| 200 | switch (builtin.os) { | 196 | switch (builtin.os) { |
| 201 | builtin.Os.linux, builtin.Os.freebsd, builtin.Os.macosx => { | 197 | builtin.Os.linux, builtin.Os.freebsd, builtin.Os.macosx => { |
| 202 | const rc = posix.readv(fd, iov, count); | 198 | const rc = os.system.readv(fd, iov, count); |
| 203 | const err = posix.getErrno(rc); | 199 | switch (os.errno(rc)) { |
| 204 | switch (err) { | ||
| 205 | 0 => return rc, | 200 | 0 => return rc, |
| 206 | posix.EINTR => continue, | 201 | os.EINTR => continue, |
| 207 | posix.EINVAL => unreachable, | 202 | os.EINVAL => unreachable, |
| 208 | posix.EFAULT => unreachable, | 203 | os.EFAULT => unreachable, |
| 209 | posix.EAGAIN => { | 204 | os.EAGAIN => { |
| 210 | try await (async loop.linuxWaitFd(fd, posix.EPOLLET | posix.EPOLLIN) catch unreachable); | 205 | try await (async loop.linuxWaitFd(fd, os.EPOLLET | os.EPOLLIN) catch unreachable); |
| 211 | continue; | 206 | continue; |
| 212 | }, | 207 | }, |
| 213 | posix.EBADF => unreachable, // always a race condition | 208 | os.EBADF => unreachable, // always a race condition |
| 214 | posix.EIO => return error.InputOutput, | 209 | os.EIO => return error.InputOutput, |
| 215 | posix.EISDIR => unreachable, | 210 | os.EISDIR => unreachable, |
| 216 | posix.ENOBUFS => return error.SystemResources, | 211 | os.ENOBUFS => return error.SystemResources, |
| 217 | posix.ENOMEM => return error.SystemResources, | 212 | os.ENOMEM => return error.SystemResources, |
| 218 | else => return os.unexpectedErrorPosix(err), | 213 | else => |err| return os.unexpectedErrno(err), |
| 219 | } | 214 | } |
| 220 | }, | 215 | }, |
| 221 | else => @compileError("Unsupported OS"), | 216 | else => @compileError("Unsupported OS"), |
| ... | @@ -224,11 +219,11 @@ pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, cou | ... | @@ -224,11 +219,11 @@ pub async fn readvPosix(loop: *std.event.Loop, fd: i32, iov: [*]posix.iovec, cou |
| 224 | } | 219 | } |
| 225 | 220 | ||
| 226 | pub async fn writev(loop: *Loop, fd: fd_t, data: []const []const u8) !void { | 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 | defer loop.allocator.free(iovecs); | 223 | defer loop.allocator.free(iovecs); |
| 229 | 224 | ||
| 230 | for (data) |buf, i| { | 225 | for (data) |buf, i| { |
| 231 | iovecs[i] = os.posix.iovec_const{ | 226 | iovecs[i] = os.iovec_const{ |
| 232 | .iov_base = buf.ptr, | 227 | .iov_base = buf.ptr, |
| 233 | .iov_len = buf.len, | 228 | .iov_len = buf.len, |
| 234 | }; | 229 | }; |
| ... | @@ -238,11 +233,11 @@ pub async fn writev(loop: *Loop, fd: fd_t, data: []const []const u8) !void { | ... | @@ -238,11 +233,11 @@ pub async fn writev(loop: *Loop, fd: fd_t, data: []const []const u8) !void { |
| 238 | } | 233 | } |
| 239 | 234 | ||
| 240 | pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize { | 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 | defer loop.allocator.free(iovecs); | 237 | defer loop.allocator.free(iovecs); |
| 243 | 238 | ||
| 244 | for (data) |buf, i| { | 239 | for (data) |buf, i| { |
| 245 | iovecs[i] = os.posix.iovec{ | 240 | iovecs[i] = os.iovec{ |
| 246 | .iov_base = buf.ptr, | 241 | .iov_base = buf.ptr, |
| 247 | .iov_len = buf.len, | 242 | .iov_len = buf.len, |
| 248 | }; | 243 | }; |
| ... | @@ -254,11 +249,11 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize { | ... | @@ -254,11 +249,11 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize { |
| 254 | pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File { | 249 | pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File { |
| 255 | var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592 | 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 | errdefer os.close(sockfd); | 253 | errdefer os.close(sockfd); |
| 259 | 254 | ||
| 260 | try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(posix.sockaddr_in)); | 255 | try os.posixConnectAsync(sockfd, &address.os_addr, @sizeOf(os.sockaddr_in)); |
| 261 | try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET); | 256 | try await try async loop.linuxWaitFd(sockfd, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET); |
| 262 | try os.posixGetSockOptConnectError(sockfd); | 257 | try os.posixGetSockOptConnectError(sockfd); |
| 263 | 258 | ||
| 264 | return File.openHandle(sockfd); | 259 | return File.openHandle(sockfd); |
std/fs/path.zig+17-20| ... | @@ -9,24 +9,21 @@ const fmt = std.fmt; | ... | @@ -9,24 +9,21 @@ const fmt = std.fmt; |
| 9 | const Allocator = mem.Allocator; | 9 | const Allocator = mem.Allocator; |
| 10 | const os = std.os; | 10 | const os = std.os; |
| 11 | const math = std.math; | 11 | const math = std.math; |
| 12 | const posix = os.posix; | ||
| 13 | const windows = os.windows; | 12 | const windows = os.windows; |
| 14 | const cstr = std.cstr; | 13 | const cstr = std.cstr; |
| 15 | 14 | ||
| 16 | pub const sep_windows = '\\'; | 15 | pub const sep_windows = '\\'; |
| 17 | pub const sep_posix = '/'; | 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 | pub const sep_str = [1]u8{sep}; | 19 | pub const sep_str = [1]u8{sep}; |
| 21 | 20 | ||
| 22 | pub const delimiter_windows = ';'; | 21 | pub const delimiter_windows = ';'; |
| 23 | pub const delimiter_posix = ':'; | 22 | pub const delimiter_posix = ':'; |
| 24 | pub const delimiter = if (is_windows) delimiter_windows else delimiter_posix; | 23 | pub const delimiter = if (windows.is_the_target) delimiter_windows else delimiter_posix; |
| 25 | |||
| 26 | const is_windows = builtin.os == builtin.Os.windows; | ||
| 27 | 24 | ||
| 28 | pub fn isSep(byte: u8) bool { | 25 | pub fn isSep(byte: u8) bool { |
| 29 | if (is_windows) { | 26 | if (windows.is_the_target) { |
| 30 | return byte == '/' or byte == '\\'; | 27 | return byte == '/' or byte == '\\'; |
| 31 | } else { | 28 | } else { |
| 32 | return byte == '/'; | 29 | return byte == '/'; |
| ... | @@ -76,7 +73,7 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u | ... | @@ -76,7 +73,7 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u |
| 76 | return buf; | 73 | return buf; |
| 77 | } | 74 | } |
| 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 | /// Naively combines a series of paths with the native path seperator. | 78 | /// Naively combines a series of paths with the native path seperator. |
| 82 | /// Allocates memory for the result, which must be freed by the caller. | 79 | /// Allocates memory for the result, which must be freed by the caller. |
| ... | @@ -133,7 +130,7 @@ test "join" { | ... | @@ -133,7 +130,7 @@ test "join" { |
| 133 | } | 130 | } |
| 134 | 131 | ||
| 135 | pub fn isAbsolute(path: []const u8) bool { | 132 | pub fn isAbsolute(path: []const u8) bool { |
| 136 | if (is_windows) { | 133 | if (windows.is_the_target) { |
| 137 | return isAbsoluteWindows(path); | 134 | return isAbsoluteWindows(path); |
| 138 | } else { | 135 | } else { |
| 139 | return isAbsolutePosix(path); | 136 | return isAbsolutePosix(path); |
| ... | @@ -312,7 +309,7 @@ test "windowsParsePath" { | ... | @@ -312,7 +309,7 @@ test "windowsParsePath" { |
| 312 | } | 309 | } |
| 313 | 310 | ||
| 314 | pub fn diskDesignator(path: []const u8) []const u8 { | 311 | pub fn diskDesignator(path: []const u8) []const u8 { |
| 315 | if (is_windows) { | 312 | if (windows.is_the_target) { |
| 316 | return diskDesignatorWindows(path); | 313 | return diskDesignatorWindows(path); |
| 317 | } else { | 314 | } else { |
| 318 | return ""; | 315 | return ""; |
| ... | @@ -377,7 +374,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool { | ... | @@ -377,7 +374,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool { |
| 377 | 374 | ||
| 378 | /// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`. | 375 | /// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`. |
| 379 | pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 { | 376 | pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 380 | if (is_windows) { | 377 | if (windows.is_the_target) { |
| 381 | return resolveWindows(allocator, paths); | 378 | return resolveWindows(allocator, paths); |
| 382 | } else { | 379 | } else { |
| 383 | return resolvePosix(allocator, paths); | 380 | return resolvePosix(allocator, paths); |
| ... | @@ -394,7 +391,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -394,7 +391,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 394 | /// Without performing actual syscalls, resolving `..` could be incorrect. | 391 | /// Without performing actual syscalls, resolving `..` could be incorrect. |
| 395 | pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { | 392 | pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 396 | if (paths.len == 0) { | 393 | if (paths.len == 0) { |
| 397 | assert(is_windows); // resolveWindows called on non windows can't use getCwd | 394 | assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd |
| 398 | return os.getCwdAlloc(allocator); | 395 | return os.getCwdAlloc(allocator); |
| 399 | } | 396 | } |
| 400 | 397 | ||
| ... | @@ -489,7 +486,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -489,7 +486,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 489 | result_disk_designator = result[0..result_index]; | 486 | result_disk_designator = result[0..result_index]; |
| 490 | }, | 487 | }, |
| 491 | WindowsPath.Kind.None => { | 488 | WindowsPath.Kind.None => { |
| 492 | assert(is_windows); // resolveWindows called on non windows can't use getCwd | 489 | assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd |
| 493 | const cwd = try os.getCwdAlloc(allocator); | 490 | const cwd = try os.getCwdAlloc(allocator); |
| 494 | defer allocator.free(cwd); | 491 | defer allocator.free(cwd); |
| 495 | const parsed_cwd = windowsParsePath(cwd); | 492 | const parsed_cwd = windowsParsePath(cwd); |
| ... | @@ -504,7 +501,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -504,7 +501,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 504 | }, | 501 | }, |
| 505 | } | 502 | } |
| 506 | } else { | 503 | } else { |
| 507 | assert(is_windows); // resolveWindows called on non windows can't use getCwd | 504 | assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd |
| 508 | // TODO call get cwd for the result_disk_designator instead of the global one | 505 | // TODO call get cwd for the result_disk_designator instead of the global one |
| 509 | const cwd = try os.getCwdAlloc(allocator); | 506 | const cwd = try os.getCwdAlloc(allocator); |
| 510 | defer allocator.free(cwd); | 507 | defer allocator.free(cwd); |
| ... | @@ -575,7 +572,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -575,7 +572,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 575 | /// Without performing actual syscalls, resolving `..` could be incorrect. | 572 | /// Without performing actual syscalls, resolving `..` could be incorrect. |
| 576 | pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { | 573 | pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 577 | if (paths.len == 0) { | 574 | if (paths.len == 0) { |
| 578 | assert(!is_windows); // resolvePosix called on windows can't use getCwd | 575 | assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd |
| 579 | return os.getCwdAlloc(allocator); | 576 | return os.getCwdAlloc(allocator); |
| 580 | } | 577 | } |
| 581 | 578 | ||
| ... | @@ -597,7 +594,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -597,7 +594,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 597 | if (have_abs) { | 594 | if (have_abs) { |
| 598 | result = try allocator.alloc(u8, max_size); | 595 | result = try allocator.alloc(u8, max_size); |
| 599 | } else { | 596 | } else { |
| 600 | assert(!is_windows); // resolvePosix called on windows can't use getCwd | 597 | assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd |
| 601 | const cwd = try os.getCwdAlloc(allocator); | 598 | const cwd = try os.getCwdAlloc(allocator); |
| 602 | defer allocator.free(cwd); | 599 | defer allocator.free(cwd); |
| 603 | result = try allocator.alloc(u8, max_size + cwd.len + 1); | 600 | result = try allocator.alloc(u8, max_size + cwd.len + 1); |
| ... | @@ -638,7 +635,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { | ... | @@ -638,7 +635,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { |
| 638 | 635 | ||
| 639 | test "resolve" { | 636 | test "resolve" { |
| 640 | const cwd = try os.getCwdAlloc(debug.global_allocator); | 637 | const cwd = try os.getCwdAlloc(debug.global_allocator); |
| 641 | if (is_windows) { | 638 | if (windows.is_the_target) { |
| 642 | if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) { | 639 | if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) { |
| 643 | cwd[0] = asciiUpper(cwd[0]); | 640 | cwd[0] = asciiUpper(cwd[0]); |
| 644 | } | 641 | } |
| ... | @@ -650,7 +647,7 @@ test "resolve" { | ... | @@ -650,7 +647,7 @@ test "resolve" { |
| 650 | } | 647 | } |
| 651 | 648 | ||
| 652 | test "resolveWindows" { | 649 | test "resolveWindows" { |
| 653 | if (is_windows) { | 650 | if (windows.is_the_target) { |
| 654 | const cwd = try os.getCwdAlloc(debug.global_allocator); | 651 | const cwd = try os.getCwdAlloc(debug.global_allocator); |
| 655 | const parsed_cwd = windowsParsePath(cwd); | 652 | const parsed_cwd = windowsParsePath(cwd); |
| 656 | { | 653 | { |
| ... | @@ -716,7 +713,7 @@ fn testResolvePosix(paths: []const []const u8) []u8 { | ... | @@ -716,7 +713,7 @@ fn testResolvePosix(paths: []const []const u8) []u8 { |
| 716 | /// If the path is a file in the current directory (no directory component) | 713 | /// If the path is a file in the current directory (no directory component) |
| 717 | /// then returns null | 714 | /// then returns null |
| 718 | pub fn dirname(path: []const u8) ?[]const u8 { | 715 | pub fn dirname(path: []const u8) ?[]const u8 { |
| 719 | if (is_windows) { | 716 | if (windows.is_the_target) { |
| 720 | return dirnameWindows(path); | 717 | return dirnameWindows(path); |
| 721 | } else { | 718 | } else { |
| 722 | return dirnamePosix(path); | 719 | return dirnamePosix(path); |
| ... | @@ -848,7 +845,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void { | ... | @@ -848,7 +845,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void { |
| 848 | } | 845 | } |
| 849 | 846 | ||
| 850 | pub fn basename(path: []const u8) []const u8 { | 847 | pub fn basename(path: []const u8) []const u8 { |
| 851 | if (is_windows) { | 848 | if (windows.is_the_target) { |
| 852 | return basenameWindows(path); | 849 | return basenameWindows(path); |
| 853 | } else { | 850 | } else { |
| 854 | return basenamePosix(path); | 851 | return basenamePosix(path); |
| ... | @@ -964,7 +961,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void { | ... | @@ -964,7 +961,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void { |
| 964 | /// string is returned. | 961 | /// string is returned. |
| 965 | /// On Windows this canonicalizes the drive to a capital letter and paths to `\\`. | 962 | /// On Windows this canonicalizes the drive to a capital letter and paths to `\\`. |
| 966 | pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 { | 963 | pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 { |
| 967 | if (is_windows) { | 964 | if (windows.is_the_target) { |
| 968 | return relativeWindows(allocator, from, to); | 965 | return relativeWindows(allocator, from, to); |
| 969 | } else { | 966 | } else { |
| 970 | return relativePosix(allocator, from, to); | 967 | return relativePosix(allocator, from, to); |
std/heap.zig+156-168| ... | @@ -5,7 +5,6 @@ const testing = std.testing; | ... | @@ -5,7 +5,6 @@ const testing = std.testing; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const os = std.os; | 6 | const os = std.os; |
| 7 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 8 | const Os = builtin.Os; | ||
| 9 | const c = std.c; | 8 | const c = std.c; |
| 10 | const maxInt = std.math.maxInt; | 9 | const maxInt = std.math.maxInt; |
| 11 | 10 | ||
| ... | @@ -51,201 +50,190 @@ pub const DirectAllocator = struct { | ... | @@ -51,201 +50,190 @@ pub const DirectAllocator = struct { |
| 51 | if (n == 0) | 50 | if (n == 0) |
| 52 | return (([*]u8)(undefined))[0..0]; | 51 | return (([*]u8)(undefined))[0..0]; |
| 53 | 52 | ||
| 54 | switch (builtin.os) { | 53 | if (os.windows.is_the_target) { |
| 55 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | 54 | const w = os.windows; |
| 56 | const p = os.posix; | 55 | |
| 57 | const alloc_size = if (alignment <= os.page_size) n else n + alignment; | 56 | // Although officially it's at least aligned to page boundary, |
| 58 | const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0); | 57 | // Windows is known to reserve pages on a 64K boundary. It's |
| 59 | if (addr == p.MAP_FAILED) return error.OutOfMemory; | 58 | // even more likely that the requested alignment is <= 64K than |
| 60 | if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n]; | 59 | // 4K, so we're just allocating blindly and hoping for the best. |
| 61 | 60 | // see https://devblogs.microsoft.com/oldnewthing/?p=42223 | |
| 62 | const aligned_addr = mem.alignForward(addr, alignment); | 61 | const addr = w.VirtualAlloc( |
| 63 | 62 | null, | |
| 64 | // Unmap the extra bytes that were only requested in order to guarantee | 63 | n, |
| 65 | // that the range of memory we were provided had a proper alignment in | 64 | w.MEM_COMMIT | w.MEM_RESERVE, |
| 66 | // it somewhere. The extra bytes could be at the beginning, or end, or both. | 65 | w.PAGE_READWRITE, |
| 67 | const unused_start_len = aligned_addr - addr; | 66 | ) catch return error.OutOfMemory; |
| 68 | if (unused_start_len != 0) { | 67 | |
| 69 | const err = p.munmap(addr, unused_start_len); | 68 | // If the allocation is sufficiently aligned, use it. |
| 70 | assert(p.getErrno(err) == 0); | 69 | if (@ptrToInt(addr) & (alignment - 1) == 0) { |
| 71 | } | 70 | return @ptrCast([*]u8, addr)[0..n]; |
| 72 | const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size); | 71 | } |
| 73 | const unused_end_len = addr + alloc_size - aligned_end_addr; | ||
| 74 | if (unused_end_len != 0) { | ||
| 75 | const err = p.munmap(aligned_end_addr, unused_end_len); | ||
| 76 | assert(p.getErrno(err) == 0); | ||
| 77 | } | ||
| 78 | 72 | ||
| 79 | return @intToPtr([*]u8, aligned_addr)[0..n]; | 73 | // If it wasn't, actually do an explicitely aligned allocation. |
| 80 | }, | 74 | w.VirtualFree(addr, 0, w.MEM_RELEASE); |
| 81 | .windows => { | 75 | const alloc_size = n + alignment; |
| 82 | const w = os.windows; | 76 | |
| 83 | 77 | const final_addr = while (true) { | |
| 84 | // Although officially it's at least aligned to page boundary, | 78 | // Reserve a range of memory large enough to find a sufficiently |
| 85 | // Windows is known to reserve pages on a 64K boundary. It's | 79 | // aligned address. |
| 86 | // even more likely that the requested alignment is <= 64K than | 80 | const reserved_addr = w.VirtualAlloc( |
| 87 | // 4K, so we're just allocating blindly and hoping for the best. | ||
| 88 | // see https://devblogs.microsoft.com/oldnewthing/?p=42223 | ||
| 89 | const addr = w.VirtualAlloc( | ||
| 90 | null, | 81 | null, |
| 82 | alloc_size, | ||
| 83 | w.MEM_RESERVE, | ||
| 84 | w.PAGE_NOACCESS, | ||
| 85 | ) catch return error.OutOfMemory; | ||
| 86 | const aligned_addr = mem.alignForward(@ptrToInt(reserved_addr), alignment); | ||
| 87 | |||
| 88 | // Release the reserved pages (not actually used). | ||
| 89 | w.VirtualFree(reserved_addr, 0, w.MEM_RELEASE); | ||
| 90 | |||
| 91 | // At this point, it is possible that another thread has | ||
| 92 | // obtained some memory space that will cause the next | ||
| 93 | // VirtualAlloc call to fail. To handle this, we will retry | ||
| 94 | // until it succeeds. | ||
| 95 | return w.VirtualAlloc( | ||
| 96 | @intToPtr(*c_void, aligned_addr), | ||
| 91 | n, | 97 | n, |
| 92 | w.MEM_COMMIT | w.MEM_RESERVE, | 98 | w.MEM_COMMIT | w.MEM_RESERVE, |
| 93 | w.PAGE_READWRITE, | 99 | w.PAGE_READWRITE, |
| 94 | ) orelse return error.OutOfMemory; | 100 | ) catch continue; |
| 101 | }; | ||
| 95 | 102 | ||
| 96 | // If the allocation is sufficiently aligned, use it. | 103 | return @ptrCast([*]u8, final_addr)[0..n]; |
| 97 | if (@ptrToInt(addr) & (alignment - 1) == 0) { | 104 | } |
| 98 | return @ptrCast([*]u8, addr)[0..n]; | ||
| 99 | } | ||
| 100 | 105 | ||
| 101 | // If it wasn't, actually do an explicitely aligned allocation. | 106 | const alloc_size = if (alignment <= os.page_size) n else n + alignment; |
| 102 | if (w.VirtualFree(addr, 0, w.MEM_RELEASE) == 0) unreachable; | 107 | const addr = os.mmap( |
| 103 | const alloc_size = n + alignment; | 108 | null, |
| 104 | 109 | alloc_size, | |
| 105 | const final_addr = while (true) { | 110 | os.PROT_READ | os.PROT_WRITE, |
| 106 | // Reserve a range of memory large enough to find a sufficiently | 111 | os.MAP_PRIVATE | os.MAP_ANONYMOUS, |
| 107 | // aligned address. | 112 | -1, |
| 108 | const reserved_addr = w.VirtualAlloc( | 113 | 0, |
| 109 | null, | 114 | ) catch return error.OutOfMemory; |
| 110 | alloc_size, | 115 | if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n]; |
| 111 | w.MEM_RESERVE, | 116 | |
| 112 | w.PAGE_NOACCESS, | 117 | const aligned_addr = mem.alignForward(addr, alignment); |
| 113 | ) orelse return error.OutOfMemory; | 118 | |
| 114 | const aligned_addr = mem.alignForward(@ptrToInt(reserved_addr), alignment); | 119 | // Unmap the extra bytes that were only requested in order to guarantee |
| 115 | 120 | // that the range of memory we were provided had a proper alignment in | |
| 116 | // Release the reserved pages (not actually used). | 121 | // it somewhere. The extra bytes could be at the beginning, or end, or both. |
| 117 | if (w.VirtualFree(reserved_addr, 0, w.MEM_RELEASE) == 0) unreachable; | 122 | const unused_start_len = aligned_addr - addr; |
| 118 | 123 | if (unused_start_len != 0) { | |
| 119 | // At this point, it is possible that another thread has | 124 | os.munmap(addr, unused_start_len); |
| 120 | // obtained some memory space that will cause the next | 125 | } |
| 121 | // VirtualAlloc call to fail. To handle this, we will retry | 126 | const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size); |
| 122 | // until it succeeds. | 127 | const unused_end_len = addr + alloc_size - aligned_end_addr; |
| 123 | if (w.VirtualAlloc( | 128 | if (unused_end_len != 0) { |
| 124 | @intToPtr(*c_void, aligned_addr), | 129 | os.munmap(aligned_end_addr, unused_end_len); |
| 125 | n, | ||
| 126 | w.MEM_COMMIT | w.MEM_RESERVE, | ||
| 127 | w.PAGE_READWRITE, | ||
| 128 | )) |ptr| break ptr; | ||
| 129 | } else unreachable; // TODO else unreachable should not be necessary | ||
| 130 | |||
| 131 | return @ptrCast([*]u8, final_addr)[0..n]; | ||
| 132 | }, | ||
| 133 | else => @compileError("Unsupported OS"), | ||
| 134 | } | 130 | } |
| 131 | |||
| 132 | return @intToPtr([*]u8, aligned_addr)[0..n]; | ||
| 135 | } | 133 | } |
| 136 | 134 | ||
| 137 | fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { | 135 | fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { |
| 138 | switch (builtin.os) { | 136 | if (os.windows.is_the_target) { |
| 139 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | 137 | const w = os.windows; |
| 138 | if (new_size == 0) { | ||
| 139 | // From the docs: | ||
| 140 | // "If the dwFreeType parameter is MEM_RELEASE, this parameter | ||
| 141 | // must be 0 (zero). The function frees the entire region that | ||
| 142 | // is reserved in the initial allocation call to VirtualAlloc." | ||
| 143 | // So we can only use MEM_RELEASE when actually releasing the | ||
| 144 | // whole allocation. | ||
| 145 | w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE); | ||
| 146 | } else { | ||
| 140 | const base_addr = @ptrToInt(old_mem.ptr); | 147 | const base_addr = @ptrToInt(old_mem.ptr); |
| 141 | const old_addr_end = base_addr + old_mem.len; | 148 | const old_addr_end = base_addr + old_mem.len; |
| 142 | const new_addr_end = base_addr + new_size; | 149 | const new_addr_end = base_addr + new_size; |
| 143 | const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size); | 150 | const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size); |
| 144 | if (old_addr_end > new_addr_end_rounded) { | 151 | if (old_addr_end > new_addr_end_rounded) { |
| 145 | _ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded); | 152 | // For shrinking that is not releasing, we will only |
| 146 | } | 153 | // decommit the pages not needed anymore. |
| 147 | return old_mem[0..new_size]; | 154 | w.VirtualFree( |
| 148 | }, | 155 | @intToPtr(*c_void, new_addr_end_rounded), |
| 149 | .windows => { | 156 | old_addr_end - new_addr_end_rounded, |
| 150 | const w = os.windows; | 157 | w.MEM_DECOMMIT, |
| 151 | if (new_size == 0) { | 158 | ); |
| 152 | // From the docs: | ||
| 153 | // "If the dwFreeType parameter is MEM_RELEASE, this parameter | ||
| 154 | // must be 0 (zero). The function frees the entire region that | ||
| 155 | // is reserved in the initial allocation call to VirtualAlloc." | ||
| 156 | // So we can only use MEM_RELEASE when actually releasing the | ||
| 157 | // whole allocation. | ||
| 158 | if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable; | ||
| 159 | } else { | ||
| 160 | const base_addr = @ptrToInt(old_mem.ptr); | ||
| 161 | const old_addr_end = base_addr + old_mem.len; | ||
| 162 | const new_addr_end = base_addr + new_size; | ||
| 163 | const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size); | ||
| 164 | if (old_addr_end > new_addr_end_rounded) { | ||
| 165 | // For shrinking that is not releasing, we will only | ||
| 166 | // decommit the pages not needed anymore. | ||
| 167 | if (w.VirtualFree( | ||
| 168 | @intToPtr(*c_void, new_addr_end_rounded), | ||
| 169 | old_addr_end - new_addr_end_rounded, | ||
| 170 | w.MEM_DECOMMIT, | ||
| 171 | ) == 0) unreachable; | ||
| 172 | } | ||
| 173 | } | 159 | } |
| 174 | return old_mem[0..new_size]; | 160 | } |
| 175 | }, | 161 | return old_mem[0..new_size]; |
| 176 | else => @compileError("Unsupported OS"), | ||
| 177 | } | 162 | } |
| 163 | const base_addr = @ptrToInt(old_mem.ptr); | ||
| 164 | const old_addr_end = base_addr + old_mem.len; | ||
| 165 | const new_addr_end = base_addr + new_size; | ||
| 166 | const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size); | ||
| 167 | if (old_addr_end > new_addr_end_rounded) { | ||
| 168 | os.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded); | ||
| 169 | } | ||
| 170 | return old_mem[0..new_size]; | ||
| 178 | } | 171 | } |
| 179 | 172 | ||
| 180 | fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 { | 173 | fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 { |
| 181 | switch (builtin.os) { | 174 | if (os.windows.is_the_target) { |
| 182 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { | 175 | if (old_mem.len == 0) { |
| 183 | if (new_size <= old_mem.len and new_align <= old_align) { | 176 | return alloc(allocator, new_size, new_align); |
| 184 | return shrink(allocator, old_mem, old_align, new_size, new_align); | 177 | } |
| 185 | } | ||
| 186 | const result = try alloc(allocator, new_size, new_align); | ||
| 187 | if (old_mem.len != 0) { | ||
| 188 | @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len)); | ||
| 189 | _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len); | ||
| 190 | } | ||
| 191 | return result; | ||
| 192 | }, | ||
| 193 | .windows => { | ||
| 194 | if (old_mem.len == 0) { | ||
| 195 | return alloc(allocator, new_size, new_align); | ||
| 196 | } | ||
| 197 | |||
| 198 | if (new_size <= old_mem.len and new_align <= old_align) { | ||
| 199 | return shrink(allocator, old_mem, old_align, new_size, new_align); | ||
| 200 | } | ||
| 201 | |||
| 202 | const w = os.windows; | ||
| 203 | const base_addr = @ptrToInt(old_mem.ptr); | ||
| 204 | 178 | ||
| 205 | if (new_align > old_align and base_addr & (new_align - 1) != 0) { | 179 | if (new_size <= old_mem.len and new_align <= old_align) { |
| 206 | // Current allocation doesn't satisfy the new alignment. | 180 | return shrink(allocator, old_mem, old_align, new_size, new_align); |
| 207 | // For now we'll do a new one no matter what, but maybe | 181 | } |
| 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; | ||
| 213 | 182 | ||
| 214 | return result; | 183 | const w = os.windows; |
| 215 | } | 184 | const base_addr = @ptrToInt(old_mem.ptr); |
| 216 | 185 | ||
| 217 | const old_addr_end = base_addr + old_mem.len; | 186 | if (new_align > old_align and base_addr & (new_align - 1) != 0) { |
| 218 | const old_addr_end_rounded = mem.alignForward(old_addr_end, os.page_size); | 187 | // Current allocation doesn't satisfy the new alignment. |
| 219 | const new_addr_end = base_addr + new_size; | 188 | // For now we'll do a new one no matter what, but maybe |
| 220 | const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size); | 189 | // there is something smarter to do instead. |
| 221 | if (new_addr_end_rounded == old_addr_end_rounded) { | 190 | const result = try alloc(allocator, new_size, new_align); |
| 222 | // The reallocation fits in the already allocated pages. | 191 | assert(old_mem.len != 0); |
| 223 | return @ptrCast([*]u8, old_mem.ptr)[0..new_size]; | 192 | @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len)); |
| 224 | } | 193 | w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE); |
| 225 | assert(new_addr_end_rounded > old_addr_end_rounded); | ||
| 226 | 194 | ||
| 227 | // We need to commit new pages. | 195 | return result; |
| 228 | const additional_size = new_addr_end - old_addr_end_rounded; | 196 | } |
| 229 | const realloc_addr = w.VirtualAlloc( | ||
| 230 | @intToPtr(*c_void, old_addr_end_rounded), | ||
| 231 | additional_size, | ||
| 232 | w.MEM_COMMIT | w.MEM_RESERVE, | ||
| 233 | w.PAGE_READWRITE, | ||
| 234 | ) orelse { | ||
| 235 | // Committing new pages at the end of the existing allocation | ||
| 236 | // failed, we need to try a new one. | ||
| 237 | const new_alloc_mem = try alloc(allocator, new_size, new_align); | ||
| 238 | @memcpy(new_alloc_mem.ptr, old_mem.ptr, old_mem.len); | ||
| 239 | if (w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE) == 0) unreachable; | ||
| 240 | |||
| 241 | return new_alloc_mem; | ||
| 242 | }; | ||
| 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 | return @ptrCast([*]u8, old_mem.ptr)[0..new_size]; | 204 | return @ptrCast([*]u8, old_mem.ptr)[0..new_size]; |
| 246 | }, | 205 | } |
| 247 | else => @compileError("Unsupported OS"), | 206 | assert(new_addr_end_rounded > old_addr_end_rounded); |
| 207 | |||
| 208 | // We need to commit new pages. | ||
| 209 | const additional_size = new_addr_end - old_addr_end_rounded; | ||
| 210 | const realloc_addr = w.kernel32.VirtualAlloc( | ||
| 211 | @intToPtr(*c_void, old_addr_end_rounded), | ||
| 212 | additional_size, | ||
| 213 | w.MEM_COMMIT | w.MEM_RESERVE, | ||
| 214 | w.PAGE_READWRITE, | ||
| 215 | ) orelse { | ||
| 216 | // Committing new pages at the end of the existing allocation | ||
| 217 | // failed, we need to try a new one. | ||
| 218 | const new_alloc_mem = try alloc(allocator, new_size, new_align); | ||
| 219 | @memcpy(new_alloc_mem.ptr, old_mem.ptr, old_mem.len); | ||
| 220 | w.VirtualFree(old_mem.ptr, 0, w.MEM_RELEASE); | ||
| 221 | |||
| 222 | return new_alloc_mem; | ||
| 223 | }; | ||
| 224 | |||
| 225 | assert(@ptrToInt(realloc_addr) == old_addr_end_rounded); | ||
| 226 | return @ptrCast([*]u8, old_mem.ptr)[0..new_size]; | ||
| 227 | } | ||
| 228 | if (new_size <= old_mem.len and new_align <= old_align) { | ||
| 229 | return shrink(allocator, old_mem, old_align, new_size, new_align); | ||
| 248 | } | 230 | } |
| 231 | const result = try alloc(allocator, new_size, new_align); | ||
| 232 | if (old_mem.len != 0) { | ||
| 233 | @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len)); | ||
| 234 | os.munmap(@ptrToInt(old_mem.ptr), old_mem.len); | ||
| 235 | } | ||
| 236 | return result; | ||
| 249 | } | 237 | } |
| 250 | }; | 238 | }; |
| 251 | 239 |
std/mem.zig+3-3| ... | @@ -1466,17 +1466,17 @@ test "std.mem.alignForward" { | ... | @@ -1466,17 +1466,17 @@ test "std.mem.alignForward" { |
| 1466 | pub fn getBaseAddress() usize { | 1466 | pub fn getBaseAddress() usize { |
| 1467 | switch (builtin.os) { | 1467 | switch (builtin.os) { |
| 1468 | .linux => { | 1468 | .linux => { |
| 1469 | const base = std.os.posix.getauxval(std.elf.AT_BASE); | 1469 | const base = std.os.system.getauxval(std.elf.AT_BASE); |
| 1470 | if (base != 0) { | 1470 | if (base != 0) { |
| 1471 | return base; | 1471 | return base; |
| 1472 | } | 1472 | } |
| 1473 | const phdr = std.os.posix.getauxval(std.elf.AT_PHDR); | 1473 | const phdr = std.os.system.getauxval(std.elf.AT_PHDR); |
| 1474 | return phdr - @sizeOf(std.elf.Ehdr); | 1474 | return phdr - @sizeOf(std.elf.Ehdr); |
| 1475 | }, | 1475 | }, |
| 1476 | .macosx, .freebsd, .netbsd => { | 1476 | .macosx, .freebsd, .netbsd => { |
| 1477 | return @ptrToInt(&std.c._mh_execute_header); | 1477 | return @ptrToInt(&std.c._mh_execute_header); |
| 1478 | }, | 1478 | }, |
| 1479 | .windows => return @ptrToInt(windows.GetModuleHandleW(null)), | 1479 | .windows => return @ptrToInt(windows.kernel32.GetModuleHandleW(null)), |
| 1480 | else => @compileError("Unsupported OS"), | 1480 | else => @compileError("Unsupported OS"), |
| 1481 | } | 1481 | } |
| 1482 | } | 1482 | } |
std/mutex.zig+2-2| ... | @@ -152,9 +152,9 @@ test "std.Mutex" { | ... | @@ -152,9 +152,9 @@ test "std.Mutex" { |
| 152 | testing.expect(context.data == TestContext.incr_count); | 152 | testing.expect(context.data == TestContext.incr_count); |
| 153 | } else { | 153 | } else { |
| 154 | const thread_count = 10; | 154 | const thread_count = 10; |
| 155 | var threads: [thread_count]*std.os.Thread = undefined; | 155 | var threads: [thread_count]*std.Thread = undefined; |
| 156 | for (threads) |*t| { | 156 | for (threads) |*t| { |
| 157 | t.* = try std.os.spawnThread(&context, worker); | 157 | t.* = try std.Thread.spawn(&context, worker); |
| 158 | } | 158 | } |
| 159 | for (threads) |t| | 159 | for (threads) |t| |
| 160 | t.wait(); | 160 | t.wait(); |
std/net.zig+12-12| ... | @@ -2,8 +2,8 @@ const std = @import("std.zig"); | ... | @@ -2,8 +2,8 @@ const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const net = @This(); | 4 | const net = @This(); |
| 5 | const posix = std.os.posix; | ||
| 6 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const os = std.os; | ||
| 7 | 7 | ||
| 8 | pub const TmpWinAddr = struct { | 8 | pub const TmpWinAddr = struct { |
| 9 | family: u8, | 9 | family: u8, |
| ... | @@ -12,7 +12,7 @@ pub const TmpWinAddr = struct { | ... | @@ -12,7 +12,7 @@ pub const TmpWinAddr = struct { |
| 12 | 12 | ||
| 13 | pub const OsAddress = switch (builtin.os) { | 13 | pub const OsAddress = switch (builtin.os) { |
| 14 | builtin.Os.windows => TmpWinAddr, | 14 | builtin.Os.windows => TmpWinAddr, |
| 15 | else => posix.sockaddr, | 15 | else => os.sockaddr, |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | pub const Address = struct { | 18 | pub const Address = struct { |
| ... | @@ -20,9 +20,9 @@ pub const Address = struct { | ... | @@ -20,9 +20,9 @@ pub const Address = struct { |
| 20 | 20 | ||
| 21 | pub fn initIp4(ip4: u32, _port: u16) Address { | 21 | pub fn initIp4(ip4: u32, _port: u16) Address { |
| 22 | return Address{ | 22 | return Address{ |
| 23 | .os_addr = posix.sockaddr{ | 23 | .os_addr = os.sockaddr{ |
| 24 | .in = posix.sockaddr_in{ | 24 | .in = os.sockaddr_in{ |
| 25 | .family = posix.AF_INET, | 25 | .family = os.AF_INET, |
| 26 | .port = mem.nativeToBig(u16, _port), | 26 | .port = mem.nativeToBig(u16, _port), |
| 27 | .addr = ip4, | 27 | .addr = ip4, |
| 28 | .zero = []u8{0} ** 8, | 28 | .zero = []u8{0} ** 8, |
| ... | @@ -33,10 +33,10 @@ pub const Address = struct { | ... | @@ -33,10 +33,10 @@ pub const Address = struct { |
| 33 | 33 | ||
| 34 | pub fn initIp6(ip6: *const Ip6Addr, _port: u16) Address { | 34 | pub fn initIp6(ip6: *const Ip6Addr, _port: u16) Address { |
| 35 | return Address{ | 35 | return Address{ |
| 36 | .family = posix.AF_INET6, | 36 | .family = os.AF_INET6, |
| 37 | .os_addr = posix.sockaddr{ | 37 | .os_addr = os.sockaddr{ |
| 38 | .in6 = posix.sockaddr_in6{ | 38 | .in6 = os.sockaddr_in6{ |
| 39 | .family = posix.AF_INET6, | 39 | .family = os.AF_INET6, |
| 40 | .port = mem.nativeToBig(u16, _port), | 40 | .port = mem.nativeToBig(u16, _port), |
| 41 | .flowinfo = 0, | 41 | .flowinfo = 0, |
| 42 | .addr = ip6.addr, | 42 | .addr = ip6.addr, |
| ... | @@ -50,18 +50,18 @@ pub const Address = struct { | ... | @@ -50,18 +50,18 @@ pub const Address = struct { |
| 50 | return mem.bigToNative(u16, self.os_addr.in.port); | 50 | return mem.bigToNative(u16, self.os_addr.in.port); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | pub fn initPosix(addr: posix.sockaddr) Address { | 53 | pub fn initPosix(addr: os.sockaddr) Address { |
| 54 | return Address{ .os_addr = addr }; | 54 | return Address{ .os_addr = addr }; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | pub fn format(self: *const Address, out_stream: var) !void { | 57 | pub fn format(self: *const Address, out_stream: var) !void { |
| 58 | switch (self.os_addr.in.family) { | 58 | switch (self.os_addr.in.family) { |
| 59 | posix.AF_INET => { | 59 | os.AF_INET => { |
| 60 | const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port); | 60 | const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port); |
| 61 | const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]); | 61 | const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]); |
| 62 | try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port); | 62 | try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port); |
| 63 | }, | 63 | }, |
| 64 | posix.AF_INET6 => { | 64 | os.AF_INET6 => { |
| 65 | const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port); | 65 | const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port); |
| 66 | try out_stream.print("[TODO render ip6 address]:{}", native_endian_port); | 66 | try out_stream.print("[TODO render ip6 address]:{}", native_endian_port); |
| 67 | }, | 67 | }, |
std/os.zig+19-16| ... | @@ -164,7 +164,7 @@ pub fn raise(sig: u8) RaiseError!void { | ... | @@ -164,7 +164,7 @@ pub fn raise(sig: u8) RaiseError!void { |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | if (windows.is_the_target) { | 166 | if (windows.is_the_target) { |
| 167 | @compileError("TODO implement std.posix.raise for Windows"); | 167 | @compileError("TODO implement std.os.raise for Windows"); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | var set: system.sigset_t = undefined; | 170 | var set: system.sigset_t = undefined; |
| ... | @@ -690,20 +690,6 @@ pub fn getenvC(key: [*]const u8) ?[]const u8 { | ... | @@ -690,20 +690,6 @@ pub fn getenvC(key: [*]const u8) ?[]const u8 { |
| 690 | return getenv(mem.toSliceConst(u8, key)); | 690 | return getenv(mem.toSliceConst(u8, key)); |
| 691 | } | 691 | } |
| 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 | pub const GetCwdError = error{ | 693 | pub const GetCwdError = error{ |
| 708 | NameTooLong, | 694 | NameTooLong, |
| 709 | CurrentWorkingDirectoryUnlinked, | 695 | CurrentWorkingDirectoryUnlinked, |
| ... | @@ -1198,7 +1184,7 @@ pub fn isatty(handle: fd_t) bool { | ... | @@ -1198,7 +1184,7 @@ pub fn isatty(handle: fd_t) bool { |
| 1198 | return windows.kernel32.GetConsoleMode(handle, &out) != 0; | 1184 | return windows.kernel32.GetConsoleMode(handle, &out) != 0; |
| 1199 | } | 1185 | } |
| 1200 | if (wasi.is_the_target) { | 1186 | if (wasi.is_the_target) { |
| 1201 | @compileError("TODO implement std.os.posix.isatty for WASI"); | 1187 | @compileError("TODO implement std.os.isatty for WASI"); |
| 1202 | } | 1188 | } |
| 1203 | if (linux.is_the_target) { | 1189 | if (linux.is_the_target) { |
| 1204 | var wsz: system.winsize = undefined; | 1190 | var wsz: system.winsize = undefined; |
| ... | @@ -2365,6 +2351,23 @@ pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void { | ... | @@ -2365,6 +2351,23 @@ pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void { |
| 2365 | } | 2351 | } |
| 2366 | } | 2352 | } |
| 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 | /// Used to convert a slice to a null terminated slice on the stack. | 2371 | /// Used to convert a slice to a null terminated slice on the stack. |
| 2369 | /// TODO https://github.com/ziglang/zig/issues/287 | 2372 | /// TODO https://github.com/ziglang/zig/issues/287 |
| 2370 | pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 { | 2373 | pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 { |
std/os/bits/linux.zig+25| ... | @@ -1,3 +1,5 @@ | ... | @@ -1,3 +1,5 @@ |
| 1 | const std = @import("../../std.zig"); | ||
| 2 | |||
| 1 | pub use @import("linux/errno.zig"); | 3 | pub use @import("linux/errno.zig"); |
| 2 | pub use switch (builtin.arch) { | 4 | pub use switch (builtin.arch) { |
| 3 | .x86_64 => @import("linux/x86_64.zig"), | 5 | .x86_64 => @import("linux/x86_64.zig"), |
| ... | @@ -907,3 +909,26 @@ pub const pthread_attr_t = extern struct { | ... | @@ -907,3 +909,26 @@ pub const pthread_attr_t = extern struct { |
| 907 | __size: [56]u8, | 909 | __size: [56]u8, |
| 908 | __align: c_long, | 910 | __align: c_long, |
| 909 | }; | 911 | }; |
| 912 | |||
| 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,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 | const std = @import("../std.zig"); | 8 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 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 | pub const is_the_target = builtin.os == .linux; | 16 | pub const is_the_target = builtin.os == .linux; |
| 4 | pub const sys = @import("linux/sys.zig"); | 17 | pub use switch (builtin.arch) { |
| 5 | pub use if (builtin.link_libc) std.c else sys; | 18 | .x86_64 => @import("linux/x86_64.zig"), |
| 19 | .aarch64 => @import("linux/arm64.zig"), | ||
| 20 | else => struct {}, | ||
| 21 | }; | ||
| 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 | test "" { | 877 | test "" { |
| 8 | if (is_the_target) { | 878 | if (is_the_target) { |
std/os/linux/sys.zig deleted-859| ... | @@ -1,859 +0,0 @@ | ||
| 1 | // This file provides the system interface functions for Linux matching those | ||
| 2 | // that are provided by libc, whether or not libc is linked. The following | ||
| 3 | // abstractions are made: | ||
| 4 | // * Work around kernel bugs and limitations. For example, see sendmmsg. | ||
| 5 | // * Implement all the syscalls in the same way that libc functions will | ||
| 6 | // provide `rename` when only the `renameat` syscall exists. | ||
| 7 | // * Does not support POSIX thread cancellation. | ||
| 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,6 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const os = std.os; | ||
| 2 | const mem = std.mem; | 3 | const mem = std.mem; |
| 3 | const posix = std.os.posix; | ||
| 4 | const elf = std.elf; | 4 | const elf = std.elf; |
| 5 | const builtin = @import("builtin"); | 5 | const builtin = @import("builtin"); |
| 6 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| ... | @@ -237,9 +237,14 @@ pub fn allocateTLS(size: usize) usize { | ... | @@ -237,9 +237,14 @@ pub fn allocateTLS(size: usize) usize { |
| 237 | return @ptrToInt(&main_thread_tls_buffer); | 237 | return @ptrToInt(&main_thread_tls_buffer); |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | const addr = posix.mmap(null, size, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS, -1, 0); | 240 | const addr = os.mmap( |
| 241 | 241 | null, | |
| 242 | if (posix.getErrno(addr) != 0) @panic("out of memory"); | 242 | size, |
| 243 | os.PROT_READ | os.PROT_WRITE, | ||
| 244 | os.MAP_PRIVATE | os.MAP_ANONYMOUS, | ||
| 245 | -1, | ||
| 246 | 0, | ||
| 247 | ) catch @panic("out of memory"); | ||
| 243 | 248 | ||
| 244 | return addr; | 249 | return addr; |
| 245 | } | 250 | } |
std/os/linux/x86_64.zig+1-1| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | use @import("posix/x86_64.zig"); | 1 | use @import("../bits.zig"); |
| 2 | 2 | ||
| 3 | pub fn syscall0(number: usize) usize { | 3 | pub fn syscall0(number: usize) usize { |
| 4 | return asm volatile ("syscall" | 4 | return asm volatile ("syscall" |
std/os/test.zig+15-14| ... | @@ -5,6 +5,7 @@ const expect = std.testing.expect; | ... | @@ -5,6 +5,7 @@ const expect = std.testing.expect; |
| 5 | const io = std.io; | 5 | const io = std.io; |
| 6 | const mem = std.mem; | 6 | const mem = std.mem; |
| 7 | const File = std.fs.File; | 7 | const File = std.fs.File; |
| 8 | const Thread = std.Thread; | ||
| 8 | 9 | ||
| 9 | const a = std.debug.global_allocator; | 10 | const a = std.debug.global_allocator; |
| 10 | 11 | ||
| ... | @@ -37,25 +38,25 @@ test "access file" { | ... | @@ -37,25 +38,25 @@ test "access file" { |
| 37 | try os.deleteTree(a, "os_test_tmp"); | 38 | try os.deleteTree(a, "os_test_tmp"); |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | fn testThreadIdFn(thread_id: *os.Thread.Id) void { | 41 | fn testThreadIdFn(thread_id: *Thread.Id) void { |
| 41 | thread_id.* = os.Thread.getCurrentId(); | 42 | thread_id.* = Thread.getCurrentId(); |
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | test "std.os.Thread.getCurrentId" { | 45 | test "std.Thread.getCurrentId" { |
| 45 | if (builtin.single_threaded) return error.SkipZigTest; | 46 | if (builtin.single_threaded) return error.SkipZigTest; |
| 46 | 47 | ||
| 47 | var thread_current_id: os.Thread.Id = undefined; | 48 | var thread_current_id: Thread.Id = undefined; |
| 48 | const thread = try os.spawnThread(&thread_current_id, testThreadIdFn); | 49 | const thread = try Thread.spawn(&thread_current_id, testThreadIdFn); |
| 49 | const thread_id = thread.handle(); | 50 | const thread_id = thread.handle(); |
| 50 | thread.wait(); | 51 | thread.wait(); |
| 51 | if (os.Thread.use_pthreads) { | 52 | if (Thread.use_pthreads) { |
| 52 | expect(thread_current_id == thread_id); | 53 | expect(thread_current_id == thread_id); |
| 53 | } else { | 54 | } else { |
| 54 | switch (builtin.os) { | 55 | switch (builtin.os) { |
| 55 | builtin.Os.windows => expect(os.Thread.getCurrentId() != thread_current_id), | 56 | builtin.Os.windows => expect(Thread.getCurrentId() != thread_current_id), |
| 56 | else => { | 57 | else => { |
| 57 | // If the thread completes very quickly, then thread_id can be 0. See the | 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 | expect(thread_id == 0 or thread_current_id == thread_id); | 60 | expect(thread_id == 0 or thread_current_id == thread_id); |
| 60 | }, | 61 | }, |
| 61 | } | 62 | } |
| ... | @@ -67,10 +68,10 @@ test "spawn threads" { | ... | @@ -67,10 +68,10 @@ test "spawn threads" { |
| 67 | 68 | ||
| 68 | var shared_ctx: i32 = 1; | 69 | var shared_ctx: i32 = 1; |
| 69 | 70 | ||
| 70 | const thread1 = try std.os.spawnThread({}, start1); | 71 | const thread1 = try Thread.spawn({}, start1); |
| 71 | const thread2 = try std.os.spawnThread(&shared_ctx, start2); | 72 | const thread2 = try Thread.spawn(&shared_ctx, start2); |
| 72 | const thread3 = try std.os.spawnThread(&shared_ctx, start2); | 73 | const thread3 = try Thread.spawn(&shared_ctx, start2); |
| 73 | const thread4 = try std.os.spawnThread(&shared_ctx, start2); | 74 | const thread4 = try Thread.spawn(&shared_ctx, start2); |
| 74 | 75 | ||
| 75 | thread1.wait(); | 76 | thread1.wait(); |
| 76 | thread2.wait(); | 77 | thread2.wait(); |
| ... | @@ -116,8 +117,8 @@ test "AtomicFile" { | ... | @@ -116,8 +117,8 @@ test "AtomicFile" { |
| 116 | 117 | ||
| 117 | test "thread local storage" { | 118 | test "thread local storage" { |
| 118 | if (builtin.single_threaded) return error.SkipZigTest; | 119 | if (builtin.single_threaded) return error.SkipZigTest; |
| 119 | const thread1 = try std.os.spawnThread({}, testTls); | 120 | const thread1 = try Thread.spawn({}, testTls); |
| 120 | const thread2 = try std.os.spawnThread({}, testTls); | 121 | const thread2 = try Thread.spawn({}, testTls); |
| 121 | testTls({}); | 122 | testTls({}); |
| 122 | thread1.wait(); | 123 | thread1.wait(); |
| 123 | thread2.wait(); | 124 | thread2.wait(); |
std/os/windows.zig+15-1| ... | @@ -591,7 +591,7 @@ pub fn CreateFileW( | ... | @@ -591,7 +591,7 @@ pub fn CreateFileW( |
| 591 | ERROR.ACCESS_DENIED => return error.AccessDenied, | 591 | ERROR.ACCESS_DENIED => return error.AccessDenied, |
| 592 | ERROR.PIPE_BUSY => return error.PipeBusy, | 592 | ERROR.PIPE_BUSY => return error.PipeBusy, |
| 593 | ERROR.FILENAME_EXCED_RANGE => return error.NameTooLong, | 593 | ERROR.FILENAME_EXCED_RANGE => return error.NameTooLong, |
| 594 | else => |err| return unexpectedErrorWindows(err), | 594 | else => |err| return unexpectedError(err), |
| 595 | } | 595 | } |
| 596 | } | 596 | } |
| 597 | 597 | ||
| ... | @@ -1089,6 +1089,20 @@ pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError | ... | @@ -1089,6 +1089,20 @@ pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError |
| 1089 | } | 1089 | } |
| 1090 | } | 1090 | } |
| 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 | pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 { | 1106 | pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 { |
| 1093 | return sliceToPrefixedFileW(mem.toSliceConst(u8, s)); | 1107 | return sliceToPrefixedFileW(mem.toSliceConst(u8, s)); |
| 1094 | } | 1108 | } |
std/process.zig+17-17| ... | @@ -1,13 +1,13 @@ | ... | @@ -1,13 +1,13 @@ |
| 1 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const posix = std.os.posix; | 2 | const os = std.os; |
| 3 | const BufMap = std.BufMap; | 3 | const BufMap = std.BufMap; |
| 4 | const mem = std.mem; | 4 | const mem = std.mem; |
| 5 | const Allocator = mem.Allocator; | 5 | const Allocator = mem.Allocator; |
| 6 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 7 | const testing = std.testing; | 7 | const testing = std.testing; |
| 8 | 8 | ||
| 9 | pub const abort = posix.abort; | 9 | pub const abort = os.abort; |
| 10 | pub const exit = posix.exit; | 10 | pub const exit = os.exit; |
| 11 | 11 | ||
| 12 | /// Caller must free result when done. | 12 | /// Caller must free result when done. |
| 13 | /// TODO make this go through libc when we have it | 13 | /// TODO make this go through libc when we have it |
| ... | @@ -42,13 +42,13 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -42,13 +42,13 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 42 | 42 | ||
| 43 | try result.setMove(key, value); | 43 | try result.setMove(key, value); |
| 44 | } | 44 | } |
| 45 | } else if (builtin.os == Os.wasi) { | 45 | } else if (builtin.os == .wasi) { |
| 46 | var environ_count: usize = undefined; | 46 | var environ_count: usize = undefined; |
| 47 | var environ_buf_size: usize = undefined; | 47 | var environ_buf_size: usize = undefined; |
| 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 | if (environ_sizes_get_ret != os.wasi.ESUCCESS) { | 50 | if (environ_sizes_get_ret != os.wasi.ESUCCESS) { |
| 51 | return unexpectedErrorPosix(environ_sizes_get_ret); | 51 | return os.unexpectedErrno(environ_sizes_get_ret); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | // TODO: Verify that the documentation is incorrect | 54 | // TODO: Verify that the documentation is incorrect |
| ... | @@ -58,9 +58,9 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -58,9 +58,9 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 58 | var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size); | 58 | var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size); |
| 59 | defer allocator.free(environ_buf); | 59 | defer allocator.free(environ_buf); |
| 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 | if (environ_get_ret != os.wasi.ESUCCESS) { | 62 | if (environ_get_ret != os.wasi.ESUCCESS) { |
| 63 | return unexpectedErrorPosix(environ_get_ret); | 63 | return os.unexpectedErrno(environ_get_ret); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | for (environ) |env| { | 66 | for (environ) |env| { |
| ... | @@ -74,7 +74,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -74,7 +74,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 74 | } | 74 | } |
| 75 | return result; | 75 | return result; |
| 76 | } else { | 76 | } else { |
| 77 | for (posix.environ) |ptr| { | 77 | for (os.environ) |ptr| { |
| 78 | var line_i: usize = 0; | 78 | var line_i: usize = 0; |
| 79 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} | 79 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} |
| 80 | const key = ptr[0..line_i]; | 80 | const key = ptr[0..line_i]; |
| ... | @@ -331,12 +331,12 @@ pub const ArgIteratorWindows = struct { | ... | @@ -331,12 +331,12 @@ pub const ArgIteratorWindows = struct { |
| 331 | }; | 331 | }; |
| 332 | 332 | ||
| 333 | pub const ArgIterator = struct { | 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 | inner: InnerType, | 336 | inner: InnerType, |
| 337 | 337 | ||
| 338 | pub fn init() ArgIterator { | 338 | pub fn init() ArgIterator { |
| 339 | if (builtin.os == Os.wasi) { | 339 | if (builtin.os == .wasi) { |
| 340 | // TODO: Figure out a compatible interface accomodating WASI | 340 | // TODO: Figure out a compatible interface accomodating WASI |
| 341 | @compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead."); | 341 | @compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead."); |
| 342 | } | 342 | } |
| ... | @@ -348,7 +348,7 @@ pub const ArgIterator = struct { | ... | @@ -348,7 +348,7 @@ pub const ArgIterator = struct { |
| 348 | 348 | ||
| 349 | /// You must free the returned memory when done. | 349 | /// You must free the returned memory when done. |
| 350 | pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) { | 350 | pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) { |
| 351 | if (builtin.os == Os.windows) { | 351 | if (builtin.os == .windows) { |
| 352 | return self.inner.next(allocator); | 352 | return self.inner.next(allocator); |
| 353 | } else { | 353 | } else { |
| 354 | return mem.dupe(allocator, u8, self.inner.next() orelse return null); | 354 | return mem.dupe(allocator, u8, self.inner.next() orelse return null); |
| ... | @@ -373,13 +373,13 @@ pub fn args() ArgIterator { | ... | @@ -373,13 +373,13 @@ pub fn args() ArgIterator { |
| 373 | 373 | ||
| 374 | /// Caller must call argsFree on result. | 374 | /// Caller must call argsFree on result. |
| 375 | pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { | 375 | pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { |
| 376 | if (builtin.os == Os.wasi) { | 376 | if (builtin.os == .wasi) { |
| 377 | var count: usize = undefined; | 377 | var count: usize = undefined; |
| 378 | var buf_size: usize = undefined; | 378 | var buf_size: usize = undefined; |
| 379 | 379 | ||
| 380 | const args_sizes_get_ret = os.wasi.args_sizes_get(&count, &buf_size); | 380 | const args_sizes_get_ret = os.wasi.args_sizes_get(&count, &buf_size); |
| 381 | if (args_sizes_get_ret != os.wasi.ESUCCESS) { | 381 | if (args_sizes_get_ret != os.wasi.ESUCCESS) { |
| 382 | return unexpectedErrorPosix(args_sizes_get_ret); | 382 | return os.unexpectedErrno(args_sizes_get_ret); |
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | var argv = try allocator.alloc([*]u8, count); | 385 | var argv = try allocator.alloc([*]u8, count); |
| ... | @@ -388,7 +388,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { | ... | @@ -388,7 +388,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { |
| 388 | var argv_buf = try allocator.alloc(u8, buf_size); | 388 | var argv_buf = try allocator.alloc(u8, buf_size); |
| 389 | const args_get_ret = os.wasi.args_get(argv.ptr, argv_buf.ptr); | 389 | const args_get_ret = os.wasi.args_get(argv.ptr, argv_buf.ptr); |
| 390 | if (args_get_ret != os.wasi.ESUCCESS) { | 390 | if (args_get_ret != os.wasi.ESUCCESS) { |
| 391 | return unexpectedErrorPosix(args_get_ret); | 391 | return os.unexpectedErrno(args_get_ret); |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | var result_slice = try allocator.alloc([]u8, count); | 394 | var result_slice = try allocator.alloc([]u8, count); |
| ... | @@ -438,7 +438,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { | ... | @@ -438,7 +438,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 { |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void { | 440 | pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void { |
| 441 | if (builtin.os == Os.wasi) { | 441 | if (builtin.os == .wasi) { |
| 442 | const last_item = args_alloc[args_alloc.len - 1]; | 442 | const last_item = args_alloc[args_alloc.len - 1]; |
| 443 | const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated | 443 | const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated |
| 444 | const first_item_ptr = args_alloc[0].ptr; | 444 | const first_item_ptr = args_alloc[0].ptr; |
| ... | @@ -491,7 +491,7 @@ pub const UserInfo = struct { | ... | @@ -491,7 +491,7 @@ pub const UserInfo = struct { |
| 491 | /// POSIX function which gets a uid from username. | 491 | /// POSIX function which gets a uid from username. |
| 492 | pub fn getUserInfo(name: []const u8) !UserInfo { | 492 | pub fn getUserInfo(name: []const u8) !UserInfo { |
| 493 | return switch (builtin.os) { | 493 | return switch (builtin.os) { |
| 494 | .linux, .macosx, .ios, .freebsd, .netbsd => posixGetUserInfo(name), | 494 | .linux, .macosx, .watchos, .tvos, .ios, .freebsd, .netbsd => posixGetUserInfo(name), |
| 495 | else => @compileError("Unsupported OS"), | 495 | else => @compileError("Unsupported OS"), |
| 496 | }; | 496 | }; |
| 497 | } | 497 | } |
std/special/bootstrap.zig+2-2| ... | @@ -92,14 +92,14 @@ fn posixCallMainAndExit() noreturn { | ... | @@ -92,14 +92,14 @@ fn posixCallMainAndExit() noreturn { |
| 92 | } | 92 | } |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); | 95 | std.os.exit(callMainWithArgs(argc, argv, envp)); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | // This is marked inline because for some reason LLVM in release mode fails to inline it, | 98 | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 99 | // and we want fewer call frames in stack traces. | 99 | // and we want fewer call frames in stack traces. |
| 100 | inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 { | 100 | inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 { |
| 101 | std.os.ArgIteratorPosix.raw = argv[0..argc]; | 101 | std.os.ArgIteratorPosix.raw = argv[0..argc]; |
| 102 | std.os.posix.environ = envp; | 102 | std.os.environ = envp; |
| 103 | return callMain(); | 103 | return callMain(); |
| 104 | } | 104 | } |
| 105 | 105 |
std/statically_initialized_mutex.zig+2-2| ... | @@ -96,9 +96,9 @@ test "std.StaticallyInitializedMutex" { | ... | @@ -96,9 +96,9 @@ test "std.StaticallyInitializedMutex" { |
| 96 | expect(context.data == TestContext.incr_count); | 96 | expect(context.data == TestContext.incr_count); |
| 97 | } else { | 97 | } else { |
| 98 | const thread_count = 10; | 98 | const thread_count = 10; |
| 99 | var threads: [thread_count]*std.os.Thread = undefined; | 99 | var threads: [thread_count]*std.Thread = undefined; |
| 100 | for (threads) |*t| { | 100 | for (threads) |*t| { |
| 101 | t.* = try std.os.spawnThread(&context, TestContext.worker); | 101 | t.* = try std.Thread.spawn(&context, TestContext.worker); |
| 102 | } | 102 | } |
| 103 | for (threads) |t| | 103 | for (threads) |t| |
| 104 | t.wait(); | 104 | t.wait(); |
std/thread.zig+57-93| ... | @@ -1,6 +1,8 @@ | ... | @@ -1,6 +1,8 @@ |
| 1 | const builtin = @import("builtin"); | 1 | const builtin = @import("builtin"); |
| 2 | const std = @import("std.zig"); | 2 | const std = @import("std.zig"); |
| 3 | const os = std.os; | ||
| 3 | const windows = std.os.windows; | 4 | const windows = std.os.windows; |
| 5 | const c = std.c; | ||
| 4 | 6 | ||
| 5 | pub const Thread = struct { | 7 | pub const Thread = struct { |
| 6 | data: Data, | 8 | data: Data, |
| ... | @@ -13,8 +15,8 @@ pub const Thread = struct { | ... | @@ -13,8 +15,8 @@ pub const Thread = struct { |
| 13 | pub const Handle = if (use_pthreads) | 15 | pub const Handle = if (use_pthreads) |
| 14 | c.pthread_t | 16 | c.pthread_t |
| 15 | else switch (builtin.os) { | 17 | else switch (builtin.os) { |
| 16 | builtin.Os.linux => i32, | 18 | .linux => i32, |
| 17 | builtin.Os.windows => windows.HANDLE, | 19 | .windows => windows.HANDLE, |
| 18 | else => @compileError("Unsupported OS"), | 20 | else => @compileError("Unsupported OS"), |
| 19 | }; | 21 | }; |
| 20 | 22 | ||
| ... | @@ -22,7 +24,7 @@ pub const Thread = struct { | ... | @@ -22,7 +24,7 @@ pub const Thread = struct { |
| 22 | /// May be an integer or pointer depending on the platform. | 24 | /// May be an integer or pointer depending on the platform. |
| 23 | /// On Linux and POSIX, this is the same as Handle. | 25 | /// On Linux and POSIX, this is the same as Handle. |
| 24 | pub const Id = switch (builtin.os) { | 26 | pub const Id = switch (builtin.os) { |
| 25 | builtin.Os.windows => windows.DWORD, | 27 | .windows => windows.DWORD, |
| 26 | else => Handle, | 28 | else => Handle, |
| 27 | }; | 29 | }; |
| 28 | 30 | ||
| ... | @@ -33,12 +35,12 @@ pub const Thread = struct { | ... | @@ -33,12 +35,12 @@ pub const Thread = struct { |
| 33 | mmap_len: usize, | 35 | mmap_len: usize, |
| 34 | } | 36 | } |
| 35 | else switch (builtin.os) { | 37 | else switch (builtin.os) { |
| 36 | builtin.Os.linux => struct { | 38 | .linux => struct { |
| 37 | handle: Thread.Handle, | 39 | handle: Thread.Handle, |
| 38 | mmap_addr: usize, | 40 | mmap_addr: usize, |
| 39 | mmap_len: usize, | 41 | mmap_len: usize, |
| 40 | }, | 42 | }, |
| 41 | builtin.Os.windows => struct { | 43 | .windows => struct { |
| 42 | handle: Thread.Handle, | 44 | handle: Thread.Handle, |
| 43 | alloc_start: *c_void, | 45 | alloc_start: *c_void, |
| 44 | heap_handle: windows.HANDLE, | 46 | heap_handle: windows.HANDLE, |
| ... | @@ -54,8 +56,8 @@ pub const Thread = struct { | ... | @@ -54,8 +56,8 @@ pub const Thread = struct { |
| 54 | return c.pthread_self(); | 56 | return c.pthread_self(); |
| 55 | } else | 57 | } else |
| 56 | return switch (builtin.os) { | 58 | return switch (builtin.os) { |
| 57 | builtin.Os.linux => linux.gettid(), | 59 | .linux => linux.gettid(), |
| 58 | builtin.Os.windows => windows.GetCurrentThreadId(), | 60 | .windows => windows.GetCurrentThreadId(), |
| 59 | else => @compileError("Unsupported OS"), | 61 | else => @compileError("Unsupported OS"), |
| 60 | }; | 62 | }; |
| 61 | } | 63 | } |
| ... | @@ -75,28 +77,28 @@ pub const Thread = struct { | ... | @@ -75,28 +77,28 @@ pub const Thread = struct { |
| 75 | const err = c.pthread_join(self.data.handle, null); | 77 | const err = c.pthread_join(self.data.handle, null); |
| 76 | switch (err) { | 78 | switch (err) { |
| 77 | 0 => {}, | 79 | 0 => {}, |
| 78 | posix.EINVAL => unreachable, | 80 | os.EINVAL => unreachable, |
| 79 | posix.ESRCH => unreachable, | 81 | os.ESRCH => unreachable, |
| 80 | posix.EDEADLK => unreachable, | 82 | os.EDEADLK => unreachable, |
| 81 | else => unreachable, | 83 | else => unreachable, |
| 82 | } | 84 | } |
| 83 | assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0); | 85 | os.munmap(self.data.mmap_addr, self.data.mmap_len); |
| 84 | } else switch (builtin.os) { | 86 | } else switch (builtin.os) { |
| 85 | builtin.Os.linux => { | 87 | .linux => { |
| 86 | while (true) { | 88 | while (true) { |
| 87 | const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst); | 89 | const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst); |
| 88 | if (pid_value == 0) break; | 90 | if (pid_value == 0) break; |
| 89 | const rc = linux.futex_wait(&self.data.handle, linux.FUTEX_WAIT, pid_value, null); | 91 | const rc = linux.futex_wait(&self.data.handle, linux.FUTEX_WAIT, pid_value, null); |
| 90 | switch (linux.getErrno(rc)) { | 92 | switch (linux.getErrno(rc)) { |
| 91 | 0 => continue, | 93 | 0 => continue, |
| 92 | posix.EINTR => continue, | 94 | os.EINTR => continue, |
| 93 | posix.EAGAIN => continue, | 95 | os.EAGAIN => continue, |
| 94 | else => unreachable, | 96 | else => unreachable, |
| 95 | } | 97 | } |
| 96 | } | 98 | } |
| 97 | assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0); | 99 | os.munmap(self.data.mmap_addr, self.data.mmap_len); |
| 98 | }, | 100 | }, |
| 99 | builtin.Os.windows => { | 101 | .windows => { |
| 100 | assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0); | 102 | assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0); |
| 101 | assert(windows.CloseHandle(self.data.handle) != 0); | 103 | assert(windows.CloseHandle(self.data.handle) != 0); |
| 102 | assert(windows.HeapFree(self.data.heap_handle, 0, self.data.alloc_start) != 0); | 104 | assert(windows.HeapFree(self.data.heap_handle, 0, self.data.alloc_start) != 0); |
| ... | @@ -153,10 +155,10 @@ pub const Thread = struct { | ... | @@ -153,10 +155,10 @@ pub const Thread = struct { |
| 153 | extern fn threadMain(raw_arg: windows.LPVOID) windows.DWORD { | 155 | extern fn threadMain(raw_arg: windows.LPVOID) windows.DWORD { |
| 154 | const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*; | 156 | const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*; |
| 155 | switch (@typeId(@typeOf(startFn).ReturnType)) { | 157 | switch (@typeId(@typeOf(startFn).ReturnType)) { |
| 156 | builtin.TypeId.Int => { | 158 | .Int => { |
| 157 | return startFn(arg); | 159 | return startFn(arg); |
| 158 | }, | 160 | }, |
| 159 | builtin.TypeId.Void => { | 161 | .Void => { |
| 160 | startFn(arg); | 162 | startFn(arg); |
| 161 | return 0; | 163 | return 0; |
| 162 | }, | 164 | }, |
| ... | @@ -196,10 +198,10 @@ pub const Thread = struct { | ... | @@ -196,10 +198,10 @@ pub const Thread = struct { |
| 196 | const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*; | 198 | const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*; |
| 197 | 199 | ||
| 198 | switch (@typeId(@typeOf(startFn).ReturnType)) { | 200 | switch (@typeId(@typeOf(startFn).ReturnType)) { |
| 199 | builtin.TypeId.Int => { | 201 | .Int => { |
| 200 | return startFn(arg); | 202 | return startFn(arg); |
| 201 | }, | 203 | }, |
| 202 | builtin.TypeId.Void => { | 204 | .Void => { |
| 203 | startFn(arg); | 205 | startFn(arg); |
| 204 | return 0; | 206 | return 0; |
| 205 | }, | 207 | }, |
| ... | @@ -217,7 +219,7 @@ pub const Thread = struct { | ... | @@ -217,7 +219,7 @@ pub const Thread = struct { |
| 217 | } | 219 | } |
| 218 | }; | 220 | }; |
| 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 | var stack_end_offset: usize = undefined; | 224 | var stack_end_offset: usize = undefined; |
| 223 | var thread_start_offset: usize = undefined; | 225 | var thread_start_offset: usize = undefined; |
| ... | @@ -247,9 +249,8 @@ pub const Thread = struct { | ... | @@ -247,9 +249,8 @@ pub const Thread = struct { |
| 247 | } | 249 | } |
| 248 | break :blk l; | 250 | break :blk l; |
| 249 | }; | 251 | }; |
| 250 | const mmap_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0); | 252 | const mmap_addr = try os.mmap(null, mmap_len, os.PROT_READ | os.PROT_WRITE, os.MAP_PRIVATE | os.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0); |
| 251 | if (mmap_addr == posix.MAP_FAILED) return error.OutOfMemory; | 253 | errdefer os.munmap(mmap_addr, mmap_len); |
| 252 | errdefer assert(posix.munmap(mmap_addr, mmap_len) == 0); | ||
| 253 | 254 | ||
| 254 | const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset)); | 255 | const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset)); |
| 255 | thread_ptr.data.mmap_addr = mmap_addr; | 256 | thread_ptr.data.mmap_addr = mmap_addr; |
| ... | @@ -273,31 +274,30 @@ pub const Thread = struct { | ... | @@ -273,31 +274,30 @@ pub const Thread = struct { |
| 273 | const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg)); | 274 | const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg)); |
| 274 | switch (err) { | 275 | switch (err) { |
| 275 | 0 => return thread_ptr, | 276 | 0 => return thread_ptr, |
| 276 | posix.EAGAIN => return error.SystemResources, | 277 | os.EAGAIN => return error.SystemResources, |
| 277 | posix.EPERM => unreachable, | 278 | os.EPERM => unreachable, |
| 278 | posix.EINVAL => unreachable, | 279 | os.EINVAL => unreachable, |
| 279 | else => return unexpectedErrorPosix(@intCast(usize, err)), | 280 | else => return os.unexpectedErrno(@intCast(usize, err)), |
| 280 | } | 281 | } |
| 281 | } else if (builtin.os == builtin.Os.linux) { | 282 | } else if (builtin.os == .linux) { |
| 282 | var flags: u32 = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | | 283 | var flags: u32 = os.CLONE_VM | os.CLONE_FS | os.CLONE_FILES | os.CLONE_SIGHAND | |
| 283 | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | | 284 | os.CLONE_THREAD | os.CLONE_SYSVSEM | os.CLONE_PARENT_SETTID | os.CLONE_CHILD_CLEARTID | |
| 284 | posix.CLONE_DETACHED; | 285 | os.CLONE_DETACHED; |
| 285 | var newtls: usize = undefined; | 286 | var newtls: usize = undefined; |
| 286 | if (linux.tls.tls_image) |tls_img| { | 287 | if (linux.tls.tls_image) |tls_img| { |
| 287 | newtls = linux.tls.copyTLS(mmap_addr + tls_start_offset); | 288 | newtls = linux.tls.copyTLS(mmap_addr + tls_start_offset); |
| 288 | flags |= posix.CLONE_SETTLS; | 289 | flags |= os.CLONE_SETTLS; |
| 289 | } | 290 | } |
| 290 | const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle); | 291 | const rc = os.linux.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle); |
| 291 | const err = posix.getErrno(rc); | 292 | switch (os.errno(rc)) { |
| 292 | switch (err) { | ||
| 293 | 0 => return thread_ptr, | 293 | 0 => return thread_ptr, |
| 294 | posix.EAGAIN => return error.ThreadQuotaExceeded, | 294 | os.EAGAIN => return error.ThreadQuotaExceeded, |
| 295 | posix.EINVAL => unreachable, | 295 | os.EINVAL => unreachable, |
| 296 | posix.ENOMEM => return error.SystemResources, | 296 | os.ENOMEM => return error.SystemResources, |
| 297 | posix.ENOSPC => unreachable, | 297 | os.ENOSPC => unreachable, |
| 298 | posix.EPERM => unreachable, | 298 | os.EPERM => unreachable, |
| 299 | posix.EUSERS => unreachable, | 299 | os.EUSERS => unreachable, |
| 300 | else => return unexpectedErrorPosix(err), | 300 | else => |err| return os.unexpectedErrno(err), |
| 301 | } | 301 | } |
| 302 | } else { | 302 | } else { |
| 303 | @compileError("Unsupported OS"); | 303 | @compileError("Unsupported OS"); |
| ... | @@ -310,56 +310,20 @@ pub const Thread = struct { | ... | @@ -310,56 +310,20 @@ pub const Thread = struct { |
| 310 | Unexpected, | 310 | Unexpected, |
| 311 | }; | 311 | }; |
| 312 | 312 | ||
| 313 | pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize { | 313 | pub fn cpuCount() CpuCountError!usize { |
| 314 | switch (builtin.os) { | 314 | if (os.linux.is_the_target) { |
| 315 | .macosx, .freebsd, .netbsd => { | 315 | const cpu_set = try os.sched_getaffinity(0); |
| 316 | var count: c_int = undefined; | 316 | return os.CPU_COUNT(cpu_set); |
| 317 | var count_len: usize = @sizeOf(c_int); | 317 | } |
| 318 | const name = switch (builtin.os) { | 318 | if (os.windows.is_the_target) { |
| 319 | builtin.Os.macosx => c"hw.logicalcpu", | 319 | var system_info: windows.SYSTEM_INFO = undefined; |
| 320 | else => c"hw.ncpu", | 320 | windows.GetSystemInfo(&system_info); |
| 321 | }; | 321 | return @intCast(usize, system_info.dwNumberOfProcessors); |
| 322 | try posix.sysctlbyname(name, @ptrCast(*c_void, &count), &count_len, null, 0); | ||
| 323 | return @intCast(usize, count); | ||
| 324 | }, | ||
| 325 | .linux => { | ||
| 326 | const usize_count = 16; | ||
| 327 | const allocator = std.heap.stackFallback(usize_count * @sizeOf(usize), fallback_allocator).get(); | ||
| 328 | |||
| 329 | var set = try allocator.alloc(usize, usize_count); | ||
| 330 | defer allocator.free(set); | ||
| 331 | |||
| 332 | while (true) { | ||
| 333 | const rc = posix.sched_getaffinity(0, set); | ||
| 334 | const err = posix.getErrno(rc); | ||
| 335 | switch (err) { | ||
| 336 | 0 => { | ||
| 337 | if (rc < set.len * @sizeOf(usize)) { | ||
| 338 | const result = set[0 .. rc / @sizeOf(usize)]; | ||
| 339 | var sum: usize = 0; | ||
| 340 | for (result) |x| { | ||
| 341 | sum += @popCount(usize, x); | ||
| 342 | } | ||
| 343 | return sum; | ||
| 344 | } else { | ||
| 345 | set = try allocator.realloc(set, set.len * 2); | ||
| 346 | continue; | ||
| 347 | } | ||
| 348 | }, | ||
| 349 | posix.EFAULT => unreachable, | ||
| 350 | posix.EINVAL => unreachable, | ||
| 351 | posix.EPERM => return CpuCountError.PermissionDenied, | ||
| 352 | posix.ESRCH => unreachable, | ||
| 353 | else => return os.unexpectedErrorPosix(err), | ||
| 354 | } | ||
| 355 | } | ||
| 356 | }, | ||
| 357 | .windows => { | ||
| 358 | var system_info: windows.SYSTEM_INFO = undefined; | ||
| 359 | windows.GetSystemInfo(&system_info); | ||
| 360 | return @intCast(usize, system_info.dwNumberOfProcessors); | ||
| 361 | }, | ||
| 362 | else => @compileError("unsupported OS"), | ||
| 363 | } | 322 | } |
| 323 | var count: c_int = undefined; | ||
| 324 | var count_len: usize = @sizeOf(c_int); | ||
| 325 | const name = if (os.darwin.is_the_target) c"hw.logicalcpu" else c"hw.ncpu"; | ||
| 326 | try os.sysctlbyname(name, @ptrCast(*c_void, &count), &count_len, null, 0); | ||
| 327 | return @intCast(usize, count); | ||
| 364 | } | 328 | } |
| 365 | }; | 329 | }; |