diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-03-18 22:39:59 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-03-19 11:45:09 -0700 |
| commit | cd62005f19ff966d2c42de4daeb9a1e4b644bf76 (patch) | |
| tree | 4bb316708afaf79c971808df792d8fe86274789b /lib/std/Thread.zig | |
| parent | 7057bffc14602add697eb566b83934b7ad3fd81c (diff) | |
| download | zig-cd62005f19ff966d2c42de4daeb9a1e4b644bf76.tar.gz zig-cd62005f19ff966d2c42de4daeb9a1e4b644bf76.zip | |
extract std.posix from std.os
closes #5019
Diffstat (limited to 'lib/std/Thread.zig')
| -rw-r--r-- | lib/std/Thread.zig | 144 |
1 files changed, 72 insertions, 72 deletions
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index e895183331..abdeb00360 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -5,9 +5,11 @@ const std = @import("std.zig"); const builtin = @import("builtin"); const math = std.math; -const os = std.os; const assert = std.debug.assert; const target = builtin.target; +const native_os = builtin.os.tag; +const posix = std.posix; +const windows = std.os.windows; pub const Futex = @import("Thread/Futex.zig"); pub const ResetEvent = @import("Thread/ResetEvent.zig"); @@ -18,23 +20,23 @@ pub const RwLock = @import("Thread/RwLock.zig"); pub const Pool = @import("Thread/Pool.zig"); pub const WaitGroup = @import("Thread/WaitGroup.zig"); -pub const use_pthreads = target.os.tag != .windows and target.os.tag != .wasi and builtin.link_libc; +pub const use_pthreads = native_os != .windows and native_os != .wasi and builtin.link_libc; const Thread = @This(); -const Impl = if (target.os.tag == .windows) +const Impl = if (native_os == .windows) WindowsThreadImpl else if (use_pthreads) PosixThreadImpl -else if (target.os.tag == .linux) +else if (native_os == .linux) LinuxThreadImpl -else if (target.os.tag == .wasi) +else if (native_os == .wasi) WasiThreadImpl else UnsupportedImpl; impl: Impl, -pub const max_name_len = switch (target.os.tag) { +pub const max_name_len = switch (native_os) { .linux => 15, .windows => 31, .macos, .ios, .watchos, .tvos => 63, @@ -50,7 +52,7 @@ pub const SetNameError = error{ NameTooLong, Unsupported, Unexpected, -} || os.PrctlError || os.WriteError || std.fs.File.OpenError || std.fmt.BufPrintError; +} || posix.PrctlError || posix.WriteError || std.fs.File.OpenError || std.fmt.BufPrintError; pub fn setName(self: Thread, name: []const u8) SetNameError!void { if (name.len > max_name_len) return error.NameTooLong; @@ -62,21 +64,21 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { break :blk name_buf[0..name.len :0]; }; - switch (target.os.tag) { + switch (native_os) { .linux => if (use_pthreads) { if (self.getHandle() == std.c.pthread_self()) { // Set the name of the calling thread (no thread id required). - const err = try os.prctl(.SET_NAME, .{@intFromPtr(name_with_terminator.ptr)}); - switch (@as(os.E, @enumFromInt(err))) { + const err = try posix.prctl(.SET_NAME, .{@intFromPtr(name_with_terminator.ptr)}); + switch (@as(posix.E, @enumFromInt(err))) { .SUCCESS => return, - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } } else { const err = std.c.pthread_setname_np(self.getHandle(), name_with_terminator.ptr); switch (err) { .SUCCESS => return, .RANGE => unreachable, - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } } } else { @@ -95,21 +97,21 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { const byte_len = math.cast(c_ushort, len * 2) orelse return error.NameTooLong; // Note: NT allocates its own copy, no use-after-free here. - const unicode_string = os.windows.UNICODE_STRING{ + const unicode_string = windows.UNICODE_STRING{ .Length = byte_len, .MaximumLength = byte_len, .Buffer = &buf, }; - switch (os.windows.ntdll.NtSetInformationThread( + switch (windows.ntdll.NtSetInformationThread( self.getHandle(), .ThreadNameInformation, &unicode_string, - @sizeOf(os.windows.UNICODE_STRING), + @sizeOf(windows.UNICODE_STRING), )) { .SUCCESS => return, .NOT_IMPLEMENTED => return error.Unsupported, - else => |err| return os.windows.unexpectedStatus(err), + else => |err| return windows.unexpectedStatus(err), } }, .macos, .ios, .watchos, .tvos => if (use_pthreads) { @@ -119,7 +121,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { const err = std.c.pthread_setname_np(name_with_terminator.ptr); switch (err) { .SUCCESS => return, - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } }, .netbsd, .solaris, .illumos => if (use_pthreads) { @@ -129,7 +131,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { .INVAL => unreachable, .SRCH => unreachable, .NOMEM => unreachable, - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } }, .freebsd, .openbsd => if (use_pthreads) { @@ -148,7 +150,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { .FAULT => unreachable, .NAMETOOLONG => unreachable, // already checked .SRCH => unreachable, - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } }, else => {}, @@ -159,7 +161,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { pub const GetNameError = error{ Unsupported, Unexpected, -} || os.PrctlError || os.ReadError || std.fs.File.OpenError || std.fmt.BufPrintError; +} || posix.PrctlError || posix.ReadError || std.fs.File.OpenError || std.fmt.BufPrintError; /// On Windows, the result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). /// On other platforms, the result is an opaque sequence of bytes with no particular encoding. @@ -167,21 +169,21 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co buffer_ptr[max_name_len] = 0; var buffer: [:0]u8 = buffer_ptr; - switch (target.os.tag) { + switch (native_os) { .linux => if (use_pthreads) { if (self.getHandle() == std.c.pthread_self()) { // Get the name of the calling thread (no thread id required). - const err = try os.prctl(.GET_NAME, .{@intFromPtr(buffer.ptr)}); - switch (@as(os.E, @enumFromInt(err))) { + const err = try posix.prctl(.GET_NAME, .{@intFromPtr(buffer.ptr)}); + switch (@as(posix.E, @enumFromInt(err))) { .SUCCESS => return std.mem.sliceTo(buffer, 0), - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } } else { const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1); switch (err) { .SUCCESS => return std.mem.sliceTo(buffer, 0), .RANGE => unreachable, - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } } } else { @@ -196,10 +198,10 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co return if (data_len >= 1) buffer[0 .. data_len - 1] else null; }, .windows => { - const buf_capacity = @sizeOf(os.windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len); - var buf: [buf_capacity]u8 align(@alignOf(os.windows.UNICODE_STRING)) = undefined; + const buf_capacity = @sizeOf(windows.UNICODE_STRING) + (@sizeOf(u16) * max_name_len); + var buf: [buf_capacity]u8 align(@alignOf(windows.UNICODE_STRING)) = undefined; - switch (os.windows.ntdll.NtQueryInformationThread( + switch (windows.ntdll.NtQueryInformationThread( self.getHandle(), .ThreadNameInformation, &buf, @@ -207,12 +209,12 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co null, )) { .SUCCESS => { - const string = @as(*const os.windows.UNICODE_STRING, @ptrCast(&buf)); + const string = @as(*const windows.UNICODE_STRING, @ptrCast(&buf)); const len = std.unicode.wtf16LeToWtf8(buffer, string.Buffer.?[0 .. string.Length / 2]); return if (len > 0) buffer[0..len] else null; }, .NOT_IMPLEMENTED => return error.Unsupported, - else => |err| return os.windows.unexpectedStatus(err), + else => |err| return windows.unexpectedStatus(err), } }, .macos, .ios, .watchos, .tvos => if (use_pthreads) { @@ -220,7 +222,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co switch (err) { .SUCCESS => return std.mem.sliceTo(buffer, 0), .SRCH => unreachable, - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } }, .netbsd, .solaris, .illumos => if (use_pthreads) { @@ -229,7 +231,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co .SUCCESS => return std.mem.sliceTo(buffer, 0), .INVAL => unreachable, .SRCH => unreachable, - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } }, .freebsd, .openbsd => if (use_pthreads) { @@ -246,7 +248,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co .INVAL => unreachable, .FAULT => unreachable, .SRCH => unreachable, - else => |e| return os.unexpectedErrno(e), + else => |e| return posix.unexpectedErrno(e), } }, else => {}, @@ -255,7 +257,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co } /// Represents an ID per thread guaranteed to be unique only within a process. -pub const Id = switch (target.os.tag) { +pub const Id = switch (native_os) { .linux, .dragonfly, .netbsd, @@ -265,7 +267,7 @@ pub const Id = switch (target.os.tag) { .wasi, => u32, .macos, .ios, .watchos, .tvos => u64, - .windows => os.windows.DWORD, + .windows => windows.DWORD, else => usize, }; @@ -368,13 +370,13 @@ pub const YieldError = error{ /// Yields the current thread potentially allowing other threads to run. pub fn yield() YieldError!void { - if (builtin.os.tag == .windows) { + if (native_os == .windows) { // The return value has to do with how many other threads there are; it is not // an error condition on Windows. - _ = os.windows.kernel32.SwitchToThread(); + _ = windows.kernel32.SwitchToThread(); return; } - switch (os.errno(os.system.sched_yield())) { + switch (posix.errno(posix.system.sched_yield())) { .SUCCESS => return, .NOSYS => return error.SystemCannotYield, else => return error.SystemCannotYield, @@ -390,7 +392,7 @@ const Completion = std.atomic.Value(enum(u8) { /// Used by the Thread implementations to call the spawned function with the arguments. fn callFn(comptime f: anytype, args: anytype) switch (Impl) { - WindowsThreadImpl => std.os.windows.DWORD, + WindowsThreadImpl => windows.DWORD, LinuxThreadImpl => u8, PosixThreadImpl => ?*anyopaque, else => unreachable, @@ -470,13 +472,11 @@ const UnsupportedImpl = struct { fn unsupported(unused: anytype) noreturn { _ = unused; - @compileError("Unsupported operating system " ++ @tagName(target.os.tag)); + @compileError("Unsupported operating system " ++ @tagName(native_os)); } }; const WindowsThreadImpl = struct { - const windows = os.windows; - pub const ThreadHandle = windows.HANDLE; fn getCurrentId() windows.DWORD { @@ -584,7 +584,7 @@ const PosixThreadImpl = struct { pub const ThreadHandle = c.pthread_t; fn getCurrentId() Id { - switch (target.os.tag) { + switch (native_os) { .linux => { return LinuxThreadImpl.getCurrentId(); }, @@ -616,15 +616,15 @@ const PosixThreadImpl = struct { } fn getCpuCount() !usize { - switch (target.os.tag) { + switch (native_os) { .linux => { return LinuxThreadImpl.getCpuCount(); }, .openbsd => { var count: c_int = undefined; var count_size: usize = @sizeOf(c_int); - const mib = [_]c_int{ os.CTL.HW, os.system.HW.NCPUONLINE }; - os.sysctl(&mib, &count, &count_size, null, 0) catch |err| switch (err) { + const mib = [_]c_int{ std.c.CTL.HW, std.c.HW.NCPUONLINE }; + std.c.sysctl(&mib, &count, &count_size, null, 0) catch |err| switch (err) { error.NameTooLong, error.UnknownName => unreachable, else => |e| return e, }; @@ -634,25 +634,25 @@ const PosixThreadImpl = struct { // The "proper" way to get the cpu count would be to query // /dev/kstat via ioctls, and traverse a linked list for each // cpu. - const rc = c.sysconf(os._SC.NPROCESSORS_ONLN); - return switch (os.errno(rc)) { + const rc = c.sysconf(std.c._SC.NPROCESSORS_ONLN); + return switch (posix.errno(rc)) { .SUCCESS => @as(usize, @intCast(rc)), - else => |err| os.unexpectedErrno(err), + else => |err| posix.unexpectedErrno(err), }; }, .haiku => { - var system_info: os.system.system_info = undefined; - const rc = os.system.get_system_info(&system_info); // always returns B_OK - return switch (os.errno(rc)) { + var system_info: std.c.system_info = undefined; + const rc = std.c.get_system_info(&system_info); // always returns B_OK + return switch (posix.errno(rc)) { .SUCCESS => @as(usize, @intCast(system_info.cpu_count)), - else => |err| os.unexpectedErrno(err), + else => |err| posix.unexpectedErrno(err), }; }, else => { var count: c_int = undefined; var count_len: usize = @sizeOf(c_int); const name = if (comptime target.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; - os.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) { + posix.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) { error.NameTooLong, error.UnknownName => unreachable, else => |e| return e, }; @@ -699,7 +699,7 @@ const PosixThreadImpl = struct { .AGAIN => return error.SystemResources, .PERM => unreachable, .INVAL => unreachable, - else => |err| return os.unexpectedErrno(err), + else => |err| return posix.unexpectedErrno(err), } } @@ -1013,7 +1013,7 @@ const WasiThreadImpl = struct { }; const LinuxThreadImpl = struct { - const linux = os.linux; + const linux = std.os.linux; pub const ThreadHandle = i32; @@ -1028,9 +1028,9 @@ const LinuxThreadImpl = struct { } fn getCpuCount() !usize { - const cpu_set = try os.sched_getaffinity(0); + const cpu_set = try posix.sched_getaffinity(0); // TODO: should not need this usize cast - return @as(usize, os.CPU_COUNT(cpu_set)); + return @as(usize, posix.CPU_COUNT(cpu_set)); } thread: *ThreadCompletion, @@ -1228,10 +1228,10 @@ const LinuxThreadImpl = struct { // map all memory needed without read/write permissions // to avoid committing the whole region right away // anonymous mapping ensures file descriptor limits are not exceeded - const mapped = os.mmap( + const mapped = posix.mmap( null, map_bytes, - os.PROT.NONE, + posix.PROT.NONE, .{ .TYPE = .PRIVATE, .ANONYMOUS = true }, -1, 0, @@ -1244,24 +1244,24 @@ const LinuxThreadImpl = struct { else => |e| return e, }; assert(mapped.len >= map_bytes); - errdefer os.munmap(mapped); + errdefer posix.munmap(mapped); // map everything but the guard page as read/write - os.mprotect( + posix.mprotect( @alignCast(mapped[guard_offset..]), - os.PROT.READ | os.PROT.WRITE, + posix.PROT.READ | posix.PROT.WRITE, ) catch |err| switch (err) { error.AccessDenied => unreachable, else => |e| return e, }; // Prepare the TLS segment and prepare a user_desc struct when needed on x86 - var tls_ptr = os.linux.tls.prepareTLS(mapped[tls_offset..]); - var user_desc: if (target.cpu.arch == .x86) os.linux.user_desc else void = undefined; + var tls_ptr = linux.tls.prepareTLS(mapped[tls_offset..]); + var user_desc: if (target.cpu.arch == .x86) linux.user_desc else void = undefined; if (target.cpu.arch == .x86) { defer tls_ptr = @intFromPtr(&user_desc); user_desc = .{ - .entry_number = os.linux.tls.tls_image.gdt_entry_number, + .entry_number = linux.tls.tls_image.gdt_entry_number, .base_addr = tls_ptr, .limit = 0xfffff, .flags = .{ @@ -1286,7 +1286,7 @@ const LinuxThreadImpl = struct { linux.CLONE.PARENT_SETTID | linux.CLONE.CHILD_CLEARTID | linux.CLONE.SIGHAND | linux.CLONE.SYSVSEM | linux.CLONE.SETTLS; - switch (linux.getErrno(linux.clone( + switch (linux.E.init(linux.clone( Instance.entryFn, @intFromPtr(&mapped[stack_offset]), flags, @@ -1302,7 +1302,7 @@ const LinuxThreadImpl = struct { .NOSPC => unreachable, .PERM => unreachable, .USERS => unreachable, - else => |err| return os.unexpectedErrno(err), + else => |err| return posix.unexpectedErrno(err), } } @@ -1319,7 +1319,7 @@ const LinuxThreadImpl = struct { } fn join(self: Impl) void { - defer os.munmap(self.thread.mapped); + defer posix.munmap(self.thread.mapped); var spin: u8 = 10; while (true) { @@ -1334,7 +1334,7 @@ const LinuxThreadImpl = struct { continue; } - switch (linux.getErrno(linux.futex_wait( + switch (linux.E.init(linux.futex_wait( &self.thread.child_tid.raw, linux.FUTEX.WAIT, tid, @@ -1383,7 +1383,7 @@ test "setName, getName" { // Wait for the main thread to have set the thread field in the context. ctx.start_wait_event.wait(); - switch (target.os.tag) { + switch (native_os) { .windows => testThreadName(&ctx.thread) catch |err| switch (err) { error.Unsupported => return error.SkipZigTest, else => return err, @@ -1406,7 +1406,7 @@ test "setName, getName" { context.start_wait_event.set(); context.test_done_event.wait(); - switch (target.os.tag) { + switch (native_os) { .macos, .ios, .watchos, .tvos => { const res = thread.setName("foobar"); try std.testing.expectError(error.Unsupported, res); |
