From a9667b5a859a589056f23df2b74b91fede0bbbfa Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 14 Jan 2021 20:41:37 -0700 Subject: organize std lib concurrency primitives and add RwLock * move concurrency primitives that always operate on kernel threads to the std.Thread namespace * remove std.SpinLock. Nobody should use this in a non-freestanding environment; the other primitives are always preferable. In freestanding, it will be necessary to put custom spin logic in there, so there are no use cases for a std lib version. * move some std lib files to the top level fields convention * add std.Thread.spinLoopHint * add std.Thread.Condition * add std.Thread.Semaphore * new implementation of std.Thread.Mutex for Windows and non-pthreads Linux * add std.Thread.RwLock Implementations provided by @kprotty --- lib/std/Thread.zig | 558 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 558 insertions(+) create mode 100644 lib/std/Thread.zig (limited to 'lib/std/Thread.zig') diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig new file mode 100644 index 0000000000..f878f43539 --- /dev/null +++ b/lib/std/Thread.zig @@ -0,0 +1,558 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2015-2021 Zig Contributors +// This file is part of [zig](https://ziglang.org/), which is MIT licensed. +// The MIT license requires this copyright notice to be included in all copies +// and substantial portions of the software. + +//! This struct represents a kernel thread, and acts as a namespace for concurrency +//! primitives that operate on kernel threads. For concurrency primitives that support +//! both evented I/O and async I/O, see the respective names in the top level std namespace. + +data: Data, + +pub const AutoResetEvent = @import("Thread/AutoResetEvent.zig"); +pub const ResetEvent = @import("Thread/ResetEvent.zig"); +pub const StaticResetEvent = @import("Thread/StaticResetEvent.zig"); +pub const Mutex = @import("Thread/Mutex.zig"); +pub const Semaphore = @import("Thread/Semaphore.zig"); +pub const Condition = @import("Thread/Condition.zig"); + +pub const use_pthreads = std.Target.current.os.tag != .windows and builtin.link_libc; + +const Thread = @This(); +const std = @import("std.zig"); +const builtin = std.builtin; +const os = std.os; +const mem = std.mem; +const windows = std.os.windows; +const c = std.c; +const assert = std.debug.assert; + +const bad_startfn_ret = "expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"; + +/// Represents a kernel thread handle. +/// May be an integer or a pointer depending on the platform. +/// On Linux and POSIX, this is the same as Id. +pub const Handle = if (use_pthreads) + c.pthread_t +else switch (std.Target.current.os.tag) { + .linux => i32, + .windows => windows.HANDLE, + else => void, +}; + +/// Represents a unique ID per thread. +/// May be an integer or pointer depending on the platform. +/// On Linux and POSIX, this is the same as Handle. +pub const Id = switch (std.Target.current.os.tag) { + .windows => windows.DWORD, + else => Handle, +}; + +pub const Data = if (use_pthreads) + struct { + handle: Thread.Handle, + memory: []u8, + } +else switch (std.Target.current.os.tag) { + .linux => struct { + handle: Thread.Handle, + memory: []align(mem.page_size) u8, + }, + .windows => struct { + handle: Thread.Handle, + alloc_start: *c_void, + heap_handle: windows.HANDLE, + }, + else => struct {}, +}; + +/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock"). +pub fn spinLoopHint() void { + switch (std.Target.current.cpu.arch) { + .i386, .x86_64 => asm volatile ("pause" + : + : + : "memory" + ), + .arm, .aarch64 => asm volatile ("yield" + : + : + : "memory" + ), + else => {}, + } +} + +/// Returns the ID of the calling thread. +/// Makes a syscall every time the function is called. +/// On Linux and POSIX, this Id is the same as a Handle. +pub fn getCurrentId() Id { + if (use_pthreads) { + return c.pthread_self(); + } else + return switch (std.Target.current.os.tag) { + .linux => os.linux.gettid(), + .windows => windows.kernel32.GetCurrentThreadId(), + else => @compileError("Unsupported OS"), + }; +} + +/// Returns the handle of this thread. +/// On Linux and POSIX, this is the same as Id. +/// On Linux, it is possible that the thread spawned with `spawn` +/// finishes executing entirely before the clone syscall completes. In this +/// case, this function will return 0 rather than the no-longer-existing thread's +/// pid. +pub fn handle(self: Thread) Handle { + return self.data.handle; +} + +pub fn wait(self: *Thread) void { + if (use_pthreads) { + const err = c.pthread_join(self.data.handle, null); + switch (err) { + 0 => {}, + os.EINVAL => unreachable, + os.ESRCH => unreachable, + os.EDEADLK => unreachable, + else => unreachable, + } + std.heap.c_allocator.free(self.data.memory); + std.heap.c_allocator.destroy(self); + } else switch (std.Target.current.os.tag) { + .linux => { + while (true) { + const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst); + if (pid_value == 0) break; + const rc = os.linux.futex_wait(&self.data.handle, os.linux.FUTEX_WAIT, pid_value, null); + switch (os.linux.getErrno(rc)) { + 0 => continue, + os.EINTR => continue, + os.EAGAIN => continue, + else => unreachable, + } + } + os.munmap(self.data.memory); + }, + .windows => { + windows.WaitForSingleObjectEx(self.data.handle, windows.INFINITE, false) catch unreachable; + windows.CloseHandle(self.data.handle); + windows.HeapFree(self.data.heap_handle, 0, self.data.alloc_start); + }, + else => @compileError("Unsupported OS"), + } +} + +pub const SpawnError = error{ + /// A system-imposed limit on the number of threads was encountered. + /// There are a number of limits that may trigger this error: + /// * the RLIMIT_NPROC soft resource limit (set via setrlimit(2)), + /// which limits the number of processes and threads for a real + /// user ID, was reached; + /// * the kernel's system-wide limit on the number of processes and + /// threads, /proc/sys/kernel/threads-max, was reached (see + /// proc(5)); + /// * the maximum number of PIDs, /proc/sys/kernel/pid_max, was + /// reached (see proc(5)); or + /// * the PID limit (pids.max) imposed by the cgroup "process num‐ + /// ber" (PIDs) controller was reached. + ThreadQuotaExceeded, + + /// The kernel cannot allocate sufficient memory to allocate a task structure + /// for the child, or to copy those parts of the caller's context that need to + /// be copied. + SystemResources, + + /// Not enough userland memory to spawn the thread. + OutOfMemory, + + /// `mlockall` is enabled, and the memory needed to spawn the thread + /// would exceed the limit. + LockedMemoryLimitExceeded, + + Unexpected, +}; + +/// caller must call wait on the returned thread +/// fn startFn(@TypeOf(context)) T +/// where T is u8, noreturn, void, or !void +/// caller must call wait on the returned thread +pub fn spawn(context: anytype, comptime startFn: anytype) SpawnError!*Thread { + if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode"); + // TODO compile-time call graph analysis to determine stack upper bound + // https://github.com/ziglang/zig/issues/157 + const default_stack_size = 16 * 1024 * 1024; + + const Context = @TypeOf(context); + comptime assert(@typeInfo(@TypeOf(startFn)).Fn.args[0].arg_type.? == Context); + + if (std.Target.current.os.tag == .windows) { + const WinThread = struct { + const OuterContext = struct { + thread: Thread, + inner: Context, + }; + fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD { + const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*; + + switch (@typeInfo(@typeInfo(@TypeOf(startFn)).Fn.return_type.?)) { + .NoReturn => { + startFn(arg); + }, + .Void => { + startFn(arg); + return 0; + }, + .Int => |info| { + if (info.bits != 8) { + @compileError(bad_startfn_ret); + } + return startFn(arg); + }, + .ErrorUnion => |info| { + if (info.payload != void) { + @compileError(bad_startfn_ret); + } + startFn(arg) catch |err| { + std.debug.warn("error: {s}\n", .{@errorName(err)}); + if (@errorReturnTrace()) |trace| { + std.debug.dumpStackTrace(trace.*); + } + }; + return 0; + }, + else => @compileError(bad_startfn_ret), + } + } + }; + + const heap_handle = windows.kernel32.GetProcessHeap() orelse return error.OutOfMemory; + const byte_count = @alignOf(WinThread.OuterContext) + @sizeOf(WinThread.OuterContext); + const bytes_ptr = windows.kernel32.HeapAlloc(heap_handle, 0, byte_count) orelse return error.OutOfMemory; + errdefer assert(windows.kernel32.HeapFree(heap_handle, 0, bytes_ptr) != 0); + const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count]; + const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext) catch unreachable; + outer_context.* = WinThread.OuterContext{ + .thread = Thread{ + .data = Thread.Data{ + .heap_handle = heap_handle, + .alloc_start = bytes_ptr, + .handle = undefined, + }, + }, + .inner = context, + }; + + const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner); + outer_context.thread.data.handle = windows.kernel32.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse { + switch (windows.kernel32.GetLastError()) { + else => |err| return windows.unexpectedError(err), + } + }; + return &outer_context.thread; + } + + const MainFuncs = struct { + fn linuxThreadMain(ctx_addr: usize) callconv(.C) u8 { + const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*; + + switch (@typeInfo(@typeInfo(@TypeOf(startFn)).Fn.return_type.?)) { + .NoReturn => { + startFn(arg); + }, + .Void => { + startFn(arg); + return 0; + }, + .Int => |info| { + if (info.bits != 8) { + @compileError(bad_startfn_ret); + } + return startFn(arg); + }, + .ErrorUnion => |info| { + if (info.payload != void) { + @compileError(bad_startfn_ret); + } + startFn(arg) catch |err| { + std.debug.warn("error: {s}\n", .{@errorName(err)}); + if (@errorReturnTrace()) |trace| { + std.debug.dumpStackTrace(trace.*); + } + }; + return 0; + }, + else => @compileError(bad_startfn_ret), + } + } + fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void { + const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), ctx)).*; + + switch (@typeInfo(@typeInfo(@TypeOf(startFn)).Fn.return_type.?)) { + .NoReturn => { + startFn(arg); + }, + .Void => { + startFn(arg); + return null; + }, + .Int => |info| { + if (info.bits != 8) { + @compileError(bad_startfn_ret); + } + // pthreads don't support exit status, ignore value + _ = startFn(arg); + return null; + }, + .ErrorUnion => |info| { + if (info.payload != void) { + @compileError(bad_startfn_ret); + } + startFn(arg) catch |err| { + std.debug.warn("error: {s}\n", .{@errorName(err)}); + if (@errorReturnTrace()) |trace| { + std.debug.dumpStackTrace(trace.*); + } + }; + return null; + }, + else => @compileError(bad_startfn_ret), + } + } + }; + + if (Thread.use_pthreads) { + var attr: c.pthread_attr_t = undefined; + if (c.pthread_attr_init(&attr) != 0) return error.SystemResources; + defer assert(c.pthread_attr_destroy(&attr) == 0); + + const thread_obj = try std.heap.c_allocator.create(Thread); + errdefer std.heap.c_allocator.destroy(thread_obj); + if (@sizeOf(Context) > 0) { + thread_obj.data.memory = try std.heap.c_allocator.allocAdvanced( + u8, + @alignOf(Context), + @sizeOf(Context), + .at_least, + ); + errdefer std.heap.c_allocator.free(thread_obj.data.memory); + mem.copy(u8, thread_obj.data.memory, mem.asBytes(&context)); + } else { + thread_obj.data.memory = @as([*]u8, undefined)[0..0]; + } + + // Use the same set of parameters used by the libc-less impl. + assert(c.pthread_attr_setstacksize(&attr, default_stack_size) == 0); + assert(c.pthread_attr_setguardsize(&attr, mem.page_size) == 0); + + const err = c.pthread_create( + &thread_obj.data.handle, + &attr, + MainFuncs.posixThreadMain, + thread_obj.data.memory.ptr, + ); + switch (err) { + 0 => return thread_obj, + os.EAGAIN => return error.SystemResources, + os.EPERM => unreachable, + os.EINVAL => unreachable, + else => return os.unexpectedErrno(@intCast(usize, err)), + } + + return thread_obj; + } + + var guard_end_offset: usize = undefined; + var stack_end_offset: usize = undefined; + var thread_start_offset: usize = undefined; + var context_start_offset: usize = undefined; + var tls_start_offset: usize = undefined; + const mmap_len = blk: { + var l: usize = mem.page_size; + // Allocate a guard page right after the end of the stack region + guard_end_offset = l; + // The stack itself, which grows downwards. + l = mem.alignForward(l + default_stack_size, mem.page_size); + stack_end_offset = l; + // Above the stack, so that it can be in the same mmap call, put the Thread object. + l = mem.alignForward(l, @alignOf(Thread)); + thread_start_offset = l; + l += @sizeOf(Thread); + // Next, the Context object. + if (@sizeOf(Context) != 0) { + l = mem.alignForward(l, @alignOf(Context)); + context_start_offset = l; + l += @sizeOf(Context); + } + // Finally, the Thread Local Storage, if any. + l = mem.alignForward(l, os.linux.tls.tls_image.alloc_align); + tls_start_offset = l; + l += os.linux.tls.tls_image.alloc_size; + // Round the size to the page size. + break :blk mem.alignForward(l, mem.page_size); + }; + + const mmap_slice = mem: { + // Map the whole stack with no rw permissions to avoid + // committing the whole region right away + const mmap_slice = os.mmap( + null, + mmap_len, + os.PROT_NONE, + os.MAP_PRIVATE | os.MAP_ANONYMOUS, + -1, + 0, + ) catch |err| switch (err) { + error.MemoryMappingNotSupported => unreachable, + error.AccessDenied => unreachable, + error.PermissionDenied => unreachable, + else => |e| return e, + }; + errdefer os.munmap(mmap_slice); + + // Map everything but the guard page as rw + os.mprotect( + mmap_slice[guard_end_offset..], + os.PROT_READ | os.PROT_WRITE, + ) catch |err| switch (err) { + error.AccessDenied => unreachable, + else => |e| return e, + }; + + break :mem mmap_slice; + }; + + const mmap_addr = @ptrToInt(mmap_slice.ptr); + + const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset)); + thread_ptr.data.memory = mmap_slice; + + var arg: usize = undefined; + if (@sizeOf(Context) != 0) { + arg = mmap_addr + context_start_offset; + const context_ptr = @alignCast(@alignOf(Context), @intToPtr(*Context, arg)); + context_ptr.* = context; + } + + if (std.Target.current.os.tag == .linux) { + const flags: u32 = os.CLONE_VM | os.CLONE_FS | os.CLONE_FILES | + os.CLONE_SIGHAND | os.CLONE_THREAD | os.CLONE_SYSVSEM | + os.CLONE_PARENT_SETTID | os.CLONE_CHILD_CLEARTID | + os.CLONE_DETACHED | os.CLONE_SETTLS; + // This structure is only needed when targeting i386 + var user_desc: if (std.Target.current.cpu.arch == .i386) os.linux.user_desc else void = undefined; + + const tls_area = mmap_slice[tls_start_offset..]; + const tp_value = os.linux.tls.prepareTLS(tls_area); + + const newtls = blk: { + if (std.Target.current.cpu.arch == .i386) { + user_desc = os.linux.user_desc{ + .entry_number = os.linux.tls.tls_image.gdt_entry_number, + .base_addr = tp_value, + .limit = 0xfffff, + .seg_32bit = 1, + .contents = 0, // Data + .read_exec_only = 0, + .limit_in_pages = 1, + .seg_not_present = 0, + .useable = 1, + }; + break :blk @ptrToInt(&user_desc); + } else { + break :blk tp_value; + } + }; + + const rc = os.linux.clone( + MainFuncs.linuxThreadMain, + mmap_addr + stack_end_offset, + flags, + arg, + &thread_ptr.data.handle, + newtls, + &thread_ptr.data.handle, + ); + switch (os.errno(rc)) { + 0 => return thread_ptr, + os.EAGAIN => return error.ThreadQuotaExceeded, + os.EINVAL => unreachable, + os.ENOMEM => return error.SystemResources, + os.ENOSPC => unreachable, + os.EPERM => unreachable, + os.EUSERS => unreachable, + else => |err| return os.unexpectedErrno(err), + } + } else { + @compileError("Unsupported OS"); + } +} + +pub const CpuCountError = error{ + PermissionDenied, + SystemResources, + Unexpected, +}; + +pub fn cpuCount() CpuCountError!usize { + if (std.Target.current.os.tag == .linux) { + const cpu_set = try os.sched_getaffinity(0); + return @as(usize, os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast + } + if (std.Target.current.os.tag == .windows) { + return os.windows.peb().NumberOfProcessors; + } + if (std.Target.current.os.tag == .openbsd) { + var count: c_int = undefined; + var count_size: usize = @sizeOf(c_int); + const mib = [_]c_int{ os.CTL_HW, os.HW_NCPUONLINE }; + os.sysctl(&mib, &count, &count_size, null, 0) catch |err| switch (err) { + error.NameTooLong, error.UnknownName => unreachable, + else => |e| return e, + }; + return @intCast(usize, count); + } + var count: c_int = undefined; + var count_len: usize = @sizeOf(c_int); + const name = if (comptime std.Target.current.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; + os.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) { + error.NameTooLong, error.UnknownName => unreachable, + else => |e| return e, + }; + return @intCast(usize, count); +} + +pub fn getCurrentThreadId() u64 { + switch (std.Target.current.os.tag) { + .linux => { + // Use the syscall directly as musl doesn't provide a wrapper. + return @bitCast(u32, os.linux.gettid()); + }, + .windows => { + return os.windows.kernel32.GetCurrentThreadId(); + }, + .macos, .ios, .watchos, .tvos => { + var thread_id: u64 = undefined; + // Pass thread=null to get the current thread ID. + assert(c.pthread_threadid_np(null, &thread_id) == 0); + return thread_id; + }, + .netbsd => { + return @bitCast(u32, c._lwp_self()); + }, + .freebsd => { + return @bitCast(u32, c.pthread_getthreadid_np()); + }, + .openbsd => { + return @bitCast(u32, c.getthrid()); + }, + else => { + @compileError("getCurrentThreadId not implemented for this platform"); + }, + } +} + +test "" { + std.testing.refAllDecls(@This()); +} -- cgit v1.2.3 From 19f893c6bbb3f5ab4e8d943b0ac2fefa94e5d666 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 14 Jan 2021 22:42:29 -0700 Subject: std.Thread: avoid compile errors for single-threaded OS's --- lib/std/Thread.zig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/std/Thread.zig') diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index f878f43539..82111c5759 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -554,5 +554,7 @@ pub fn getCurrentThreadId() u64 { } test "" { - std.testing.refAllDecls(@This()); + if (!builtin.single_threaded) { + std.testing.refAllDecls(@This()); + } } -- cgit v1.2.3 From 134f5fd3d690cfdce2ab7d622cb233b3e510bf3a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 22 Jan 2021 15:45:28 +0100 Subject: std: Update `test ""` to `test` where it makes sense --- lib/std/Thread.zig | 2 +- lib/std/build.zig | 2 +- lib/std/build/emit_raw.zig | 2 +- lib/std/c.zig | 2 +- lib/std/compress.zig | 2 +- lib/std/fs.zig | 2 +- lib/std/io.zig | 2 +- lib/std/io/c_writer.zig | 2 +- lib/std/math.zig | 2 +- lib/std/math/big.zig | 2 +- lib/std/math/big/int.zig | 2 +- lib/std/net.zig | 2 +- lib/std/os.zig | 2 +- lib/std/os/linux.zig | 2 +- lib/std/rand.zig | 2 +- lib/std/special/compiler_rt/shift.zig | 2 +- lib/std/special/compiler_rt/sparc.zig | 1 - lib/std/std.zig | 2 +- lib/std/target.zig | 2 +- lib/std/testing.zig | 2 +- lib/std/valgrind.zig | 2 +- lib/std/zig.zig | 2 +- lib/std/zig/system.zig | 2 +- src/codegen/aarch64.zig | 2 +- 24 files changed, 23 insertions(+), 24 deletions(-) (limited to 'lib/std/Thread.zig') diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 82111c5759..ea878bbdb0 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -553,7 +553,7 @@ pub fn getCurrentThreadId() u64 { } } -test "" { +test { if (!builtin.single_threaded) { std.testing.refAllDecls(@This()); } diff --git a/lib/std/build.zig b/lib/std/build.zig index 381488d800..3e6cf7a981 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -2985,7 +2985,7 @@ test "LibExeObjStep.addPackage" { std.testing.expectEqualStrings(pkg_top.name, dupe.name); } -test "" { +test { // The only purpose of this test is to get all these untested functions // to be referenced to avoid regression so it is okay to skip some targets. if (comptime std.Target.current.cpu.arch.ptrBitWidth() == 64) { diff --git a/lib/std/build/emit_raw.zig b/lib/std/build/emit_raw.zig index 3d2c6124c1..721b38b7a2 100644 --- a/lib/std/build/emit_raw.zig +++ b/lib/std/build/emit_raw.zig @@ -223,6 +223,6 @@ pub const InstallRawStep = struct { } }; -test "" { +test { std.testing.refAllDecls(InstallRawStep); } diff --git a/lib/std/c.zig b/lib/std/c.zig index 6b389c23ef..b5ee8cd893 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -14,7 +14,7 @@ pub const parse = @import("c/parse.zig").parse; pub const ast = @import("c/ast.zig"); pub const builtins = @import("c/builtins.zig"); -test "" { +test { _ = tokenizer; } diff --git a/lib/std/compress.zig b/lib/std/compress.zig index e7971fae8f..972031c182 100644 --- a/lib/std/compress.zig +++ b/lib/std/compress.zig @@ -9,7 +9,7 @@ pub const deflate = @import("compress/deflate.zig"); pub const gzip = @import("compress/gzip.zig"); pub const zlib = @import("compress/zlib.zig"); -test "" { +test { _ = gzip; _ = zlib; } diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 89984cda07..17c0cb7b1d 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -2475,7 +2475,7 @@ fn copy_file(fd_in: os.fd_t, fd_out: os.fd_t) CopyFileError!void { } } -test "" { +test { if (builtin.os.tag != .wasi) { _ = makeDirAbsolute; _ = makeDirAbsoluteZ; diff --git a/lib/std/io.zig b/lib/std/io.zig index e9a03445f6..240faaa452 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -171,7 +171,7 @@ test "null_writer" { null_writer.writeAll("yay" ** 10) catch |err| switch (err) {}; } -test "" { +test { _ = @import("io/bit_reader.zig"); _ = @import("io/bit_writer.zig"); _ = @import("io/buffered_atomic_file.zig"); diff --git a/lib/std/io/c_writer.zig b/lib/std/io/c_writer.zig index ec8718e381..fa7d7eb13a 100644 --- a/lib/std/io/c_writer.zig +++ b/lib/std/io/c_writer.zig @@ -34,7 +34,7 @@ fn cWriterWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!u } } -test "" { +test { if (!builtin.link_libc) return error.SkipZigTest; const filename = "tmp_io_test_file.txt"; diff --git a/lib/std/math.zig b/lib/std/math.zig index 77eed37304..de243135a1 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -278,7 +278,7 @@ pub const Complex = complex.Complex; pub const big = @import("math/big.zig"); -test "" { +test { std.testing.refAllDecls(@This()); } diff --git a/lib/std/math/big.zig b/lib/std/math/big.zig index 80649f867c..8ae214c666 100644 --- a/lib/std/math/big.zig +++ b/lib/std/math/big.zig @@ -20,7 +20,7 @@ comptime { assert(limb_info.signedness == .unsigned); } -test "" { +test { _ = int; _ = Rational; _ = Limb; diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 504083dcce..3cd72dd8e4 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -2344,6 +2344,6 @@ fn fixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Mutable { }; } -test "" { +test { _ = @import("int_test.zig"); } diff --git a/lib/std/net.zig b/lib/std/net.zig index 6fe2d1cd08..28ae2b9857 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -1769,6 +1769,6 @@ pub const StreamServer = struct { } }; -test "" { +test { _ = @import("net/test.zig"); } diff --git a/lib/std/os.zig b/lib/std/os.zig index 8c3ea7baa8..ece47828d1 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -43,7 +43,7 @@ comptime { assert(@import("std") == std); // std lib tests require --override-lib-dir } -test "" { +test { _ = darwin; _ = freebsd; _ = linux; diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 37f30da1df..ffc1029708 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1355,7 +1355,7 @@ pub fn madvise(address: [*]u8, len: usize, advice: u32) usize { return syscall3(.madvise, @ptrToInt(address), len, advice); } -test "" { +test { if (builtin.os.tag == .linux) { _ = @import("linux/test.zig"); } diff --git a/lib/std/rand.zig b/lib/std/rand.zig index 8e6aab63df..d0d400b5b0 100644 --- a/lib/std/rand.zig +++ b/lib/std/rand.zig @@ -602,6 +602,6 @@ test "CSPRNG" { expect(a ^ b ^ c != 0); } -test "" { +test { std.testing.refAllDecls(@This()); } diff --git a/lib/std/special/compiler_rt/shift.zig b/lib/std/special/compiler_rt/shift.zig index 0c9938343f..46712738ab 100644 --- a/lib/std/special/compiler_rt/shift.zig +++ b/lib/std/special/compiler_rt/shift.zig @@ -124,7 +124,7 @@ pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 { return __lshrdi3(a, b); } -test "" { +test { _ = @import("ashrdi3_test.zig"); _ = @import("ashrti3_test.zig"); diff --git a/lib/std/special/compiler_rt/sparc.zig b/lib/std/special/compiler_rt/sparc.zig index 72e297c514..e66bb25886 100644 --- a/lib/std/special/compiler_rt/sparc.zig +++ b/lib/std/special/compiler_rt/sparc.zig @@ -68,7 +68,6 @@ pub fn _Qp_fge(a: *f128, b: *f128) callconv(.C) bool { return cmp == @enumToInt(FCMP.Greater) or cmp == @enumToInt(FCMP.Equal); } - // Casting pub fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void { diff --git a/lib/std/std.zig b/lib/std/std.zig index d085d4fc41..780579debf 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -86,7 +86,7 @@ comptime { _ = start; } -test "" { +test { if (builtin.os.tag == .windows) { // We only test the Windows-relevant stuff to save memory because the CI // server is hitting OOM. TODO revert this after stage2 arrives. diff --git a/lib/std/target.zig b/lib/std/target.zig index 155ba046d2..70a5f08612 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1577,6 +1577,6 @@ pub const Target = struct { } }; -test "" { +test { std.testing.refAllDecls(Target.Cpu.Arch); } diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 288eb5b662..26938367e9 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -443,7 +443,7 @@ fn printLine(line: []const u8) void { print("{s}\n", .{line}); } -test "" { +test { expectEqualStrings("foo", "foo"); } diff --git a/lib/std/valgrind.zig b/lib/std/valgrind.zig index 4ae273694b..6930652fbc 100644 --- a/lib/std/valgrind.zig +++ b/lib/std/valgrind.zig @@ -262,7 +262,7 @@ pub fn monitorCommand(command: [*]u8) bool { pub const memcheck = @import("valgrind/memcheck.zig"); pub const callgrind = @import("valgrind/callgrind.zig"); -test "" { +test { _ = @import("valgrind/memcheck.zig"); _ = @import("valgrind/callgrind.zig"); } diff --git a/lib/std/zig.zig b/lib/std/zig.zig index c39eb6b05f..5b564864ad 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -255,6 +255,6 @@ test "parseCharLiteral" { std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{FFFF}x'", &bad_index)); } -test "" { +test { @import("std").testing.refAllDecls(@This()); } diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index d8a9998274..2d9f286dd6 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -898,6 +898,6 @@ pub const NativeTargetInfo = struct { } }; -test "" { +test { _ = @import("system/macos.zig"); } diff --git a/src/codegen/aarch64.zig b/src/codegen/aarch64.zig index e7860790f4..8abc616e2f 100644 --- a/src/codegen/aarch64.zig +++ b/src/codegen/aarch64.zig @@ -906,7 +906,7 @@ pub const Instruction = union(enum) { } }; -test "" { +test { testing.refAllDecls(@This()); } -- cgit v1.2.3 From 5f35dc0c0d0530d5a1d028c56a763def3d1fd250 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 24 Feb 2021 21:29:01 -0700 Subject: zig fmt the std lib --- lib/std/Thread.zig | 23 ++---- lib/std/Thread/Semaphore.zig | 2 +- lib/std/array_hash_map.zig | 6 +- lib/std/base64.zig | 6 +- lib/std/build.zig | 4 +- lib/std/c/builtins.zig | 136 ++++++++++++++++++++++++++---------- lib/std/c/parse.zig | 3 +- lib/std/coff.zig | 3 +- lib/std/crypto/aegis.zig | 8 +-- lib/std/crypto/bcrypt.zig | 4 +- lib/std/dwarf.zig | 6 +- lib/std/event/batch.zig | 19 ++--- lib/std/fmt.zig | 6 +- lib/std/log.zig | 7 +- lib/std/meta.zig | 21 +++--- lib/std/meta/trait.zig | 8 +-- lib/std/os.zig | 5 +- lib/std/os/bits/netbsd.zig | 16 +++-- lib/std/os/windows/bits.zig | 12 ++-- lib/std/special/compiler_rt/arm.zig | 20 ++---- 20 files changed, 176 insertions(+), 139 deletions(-) (limited to 'lib/std/Thread.zig') diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index ea878bbdb0..80de19fe19 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -70,16 +70,8 @@ else switch (std.Target.current.os.tag) { /// Signals the processor that it is inside a busy-wait spin-loop ("spin lock"). pub fn spinLoopHint() void { switch (std.Target.current.cpu.arch) { - .i386, .x86_64 => asm volatile ("pause" - : - : - : "memory" - ), - .arm, .aarch64 => asm volatile ("yield" - : - : - : "memory" - ), + .i386, .x86_64 => asm volatile ("pause" ::: "memory"), + .arm, .aarch64 => asm volatile ("yield" ::: "memory"), else => {}, } } @@ -90,12 +82,11 @@ pub fn spinLoopHint() void { pub fn getCurrentId() Id { if (use_pthreads) { return c.pthread_self(); - } else - return switch (std.Target.current.os.tag) { - .linux => os.linux.gettid(), - .windows => windows.kernel32.GetCurrentThreadId(), - else => @compileError("Unsupported OS"), - }; + } else return switch (std.Target.current.os.tag) { + .linux => os.linux.gettid(), + .windows => windows.kernel32.GetCurrentThreadId(), + else => @compileError("Unsupported OS"), + }; } /// Returns the handle of this thread. diff --git a/lib/std/Thread/Semaphore.zig b/lib/std/Thread/Semaphore.zig index a899cd9b6f..169975b362 100644 --- a/lib/std/Thread/Semaphore.zig +++ b/lib/std/Thread/Semaphore.zig @@ -10,7 +10,7 @@ mutex: Mutex = .{}, cond: Condition = .{}, -//! It is OK to initialize this field to any value. +/// It is OK to initialize this field to any value. permits: usize = 0, const Semaphore = @This(); diff --git a/lib/std/array_hash_map.zig b/lib/std/array_hash_map.zig index 5008b3a4af..7b0d9ea4dd 100644 --- a/lib/std/array_hash_map.zig +++ b/lib/std/array_hash_map.zig @@ -1237,8 +1237,7 @@ test "shrink" { if (i < 17) { testing.expect(gop.found_existing == true); testing.expect(gop.entry.value == i * 10); - } else - testing.expect(gop.found_existing == false); + } else testing.expect(gop.found_existing == false); } // Test `shrinkAndFree`. @@ -1251,8 +1250,7 @@ test "shrink" { if (i < 15) { testing.expect(gop.found_existing == true); testing.expect(gop.entry.value == i * 10); - } else - testing.expect(gop.found_existing == false); + } else testing.expect(gop.found_existing == false); } } diff --git a/lib/std/base64.zig b/lib/std/base64.zig index 12066d1175..e6a780c239 100644 --- a/lib/std/base64.zig +++ b/lib/std/base64.zig @@ -222,12 +222,10 @@ pub const Base64DecoderWithIgnore = struct { } else if (decoder_with_ignore.char_is_ignored[c]) { // we can even ignore chars during the padding continue; - } else - return error.InvalidCharacter; + } else return error.InvalidCharacter; } break; - } else - return error.InvalidCharacter; + } else return error.InvalidCharacter; } switch (available_chars) { diff --git a/lib/std/build.zig b/lib/std/build.zig index f52b863d3f..6cd50e7dd8 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -2763,7 +2763,9 @@ pub const InstallDirectoryOptions = struct { .install_dir = self.install_dir.dupe(b), .install_subdir = b.dupe(self.install_subdir), .exclude_extensions = if (self.exclude_extensions) |extensions| - b.dupeStrings(extensions) else null, + b.dupeStrings(extensions) + else + null, }; } }; diff --git a/lib/std/c/builtins.zig b/lib/std/c/builtins.zig index 2b386c82f4..c11bf0a391 100644 --- a/lib/std/c/builtins.zig +++ b/lib/std/c/builtins.zig @@ -6,12 +6,22 @@ const std = @import("std"); -pub fn __builtin_bswap16(val: u16) callconv(.Inline) u16 { return @byteSwap(u16, val); } -pub fn __builtin_bswap32(val: u32) callconv(.Inline) u32 { return @byteSwap(u32, val); } -pub fn __builtin_bswap64(val: u64) callconv(.Inline) u64 { return @byteSwap(u64, val); } +pub fn __builtin_bswap16(val: u16) callconv(.Inline) u16 { + return @byteSwap(u16, val); +} +pub fn __builtin_bswap32(val: u32) callconv(.Inline) u32 { + return @byteSwap(u32, val); +} +pub fn __builtin_bswap64(val: u64) callconv(.Inline) u64 { + return @byteSwap(u64, val); +} -pub fn __builtin_signbit(val: f64) callconv(.Inline) c_int { return @boolToInt(std.math.signbit(val)); } -pub fn __builtin_signbitf(val: f32) callconv(.Inline) c_int { return @boolToInt(std.math.signbit(val)); } +pub fn __builtin_signbit(val: f64) callconv(.Inline) c_int { + return @boolToInt(std.math.signbit(val)); +} +pub fn __builtin_signbitf(val: f32) callconv(.Inline) c_int { + return @boolToInt(std.math.signbit(val)); +} pub fn __builtin_popcount(val: c_uint) callconv(.Inline) c_int { // popcount of a c_uint will never exceed the capacity of a c_int @@ -31,40 +41,96 @@ pub fn __builtin_clz(val: c_uint) callconv(.Inline) c_int { return @bitCast(c_int, @as(c_uint, @clz(c_uint, val))); } -pub fn __builtin_sqrt(val: f64) callconv(.Inline) f64 { return @sqrt(val); } -pub fn __builtin_sqrtf(val: f32) callconv(.Inline) f32 { return @sqrt(val); } +pub fn __builtin_sqrt(val: f64) callconv(.Inline) f64 { + return @sqrt(val); +} +pub fn __builtin_sqrtf(val: f32) callconv(.Inline) f32 { + return @sqrt(val); +} -pub fn __builtin_sin(val: f64) callconv(.Inline) f64 { return @sin(val); } -pub fn __builtin_sinf(val: f32) callconv(.Inline) f32 { return @sin(val); } -pub fn __builtin_cos(val: f64) callconv(.Inline) f64 { return @cos(val); } -pub fn __builtin_cosf(val: f32) callconv(.Inline) f32 { return @cos(val); } +pub fn __builtin_sin(val: f64) callconv(.Inline) f64 { + return @sin(val); +} +pub fn __builtin_sinf(val: f32) callconv(.Inline) f32 { + return @sin(val); +} +pub fn __builtin_cos(val: f64) callconv(.Inline) f64 { + return @cos(val); +} +pub fn __builtin_cosf(val: f32) callconv(.Inline) f32 { + return @cos(val); +} -pub fn __builtin_exp(val: f64) callconv(.Inline) f64 { return @exp(val); } -pub fn __builtin_expf(val: f32) callconv(.Inline) f32 { return @exp(val); } -pub fn __builtin_exp2(val: f64) callconv(.Inline) f64 { return @exp2(val); } -pub fn __builtin_exp2f(val: f32) callconv(.Inline) f32 { return @exp2(val); } -pub fn __builtin_log(val: f64) callconv(.Inline) f64 { return @log(val); } -pub fn __builtin_logf(val: f32) callconv(.Inline) f32 { return @log(val); } -pub fn __builtin_log2(val: f64) callconv(.Inline) f64 { return @log2(val); } -pub fn __builtin_log2f(val: f32) callconv(.Inline) f32 { return @log2(val); } -pub fn __builtin_log10(val: f64) callconv(.Inline) f64 { return @log10(val); } -pub fn __builtin_log10f(val: f32) callconv(.Inline) f32 { return @log10(val); } +pub fn __builtin_exp(val: f64) callconv(.Inline) f64 { + return @exp(val); +} +pub fn __builtin_expf(val: f32) callconv(.Inline) f32 { + return @exp(val); +} +pub fn __builtin_exp2(val: f64) callconv(.Inline) f64 { + return @exp2(val); +} +pub fn __builtin_exp2f(val: f32) callconv(.Inline) f32 { + return @exp2(val); +} +pub fn __builtin_log(val: f64) callconv(.Inline) f64 { + return @log(val); +} +pub fn __builtin_logf(val: f32) callconv(.Inline) f32 { + return @log(val); +} +pub fn __builtin_log2(val: f64) callconv(.Inline) f64 { + return @log2(val); +} +pub fn __builtin_log2f(val: f32) callconv(.Inline) f32 { + return @log2(val); +} +pub fn __builtin_log10(val: f64) callconv(.Inline) f64 { + return @log10(val); +} +pub fn __builtin_log10f(val: f32) callconv(.Inline) f32 { + return @log10(val); +} // Standard C Library bug: The absolute value of the most negative integer remains negative. -pub fn __builtin_abs(val: c_int) callconv(.Inline) c_int { return std.math.absInt(val) catch std.math.minInt(c_int); } -pub fn __builtin_fabs(val: f64) callconv(.Inline) f64 { return @fabs(val); } -pub fn __builtin_fabsf(val: f32) callconv(.Inline) f32 { return @fabs(val); } - -pub fn __builtin_floor(val: f64) callconv(.Inline) f64 { return @floor(val); } -pub fn __builtin_floorf(val: f32) callconv(.Inline) f32 { return @floor(val); } -pub fn __builtin_ceil(val: f64) callconv(.Inline) f64 { return @ceil(val); } -pub fn __builtin_ceilf(val: f32) callconv(.Inline) f32 { return @ceil(val); } -pub fn __builtin_trunc(val: f64) callconv(.Inline) f64 { return @trunc(val); } -pub fn __builtin_truncf(val: f32) callconv(.Inline) f32 { return @trunc(val); } -pub fn __builtin_round(val: f64) callconv(.Inline) f64 { return @round(val); } -pub fn __builtin_roundf(val: f32) callconv(.Inline) f32 { return @round(val); } - -pub fn __builtin_strlen(s: [*c]const u8) callconv(.Inline) usize { return std.mem.lenZ(s); } +pub fn __builtin_abs(val: c_int) callconv(.Inline) c_int { + return std.math.absInt(val) catch std.math.minInt(c_int); +} +pub fn __builtin_fabs(val: f64) callconv(.Inline) f64 { + return @fabs(val); +} +pub fn __builtin_fabsf(val: f32) callconv(.Inline) f32 { + return @fabs(val); +} + +pub fn __builtin_floor(val: f64) callconv(.Inline) f64 { + return @floor(val); +} +pub fn __builtin_floorf(val: f32) callconv(.Inline) f32 { + return @floor(val); +} +pub fn __builtin_ceil(val: f64) callconv(.Inline) f64 { + return @ceil(val); +} +pub fn __builtin_ceilf(val: f32) callconv(.Inline) f32 { + return @ceil(val); +} +pub fn __builtin_trunc(val: f64) callconv(.Inline) f64 { + return @trunc(val); +} +pub fn __builtin_truncf(val: f32) callconv(.Inline) f32 { + return @trunc(val); +} +pub fn __builtin_round(val: f64) callconv(.Inline) f64 { + return @round(val); +} +pub fn __builtin_roundf(val: f32) callconv(.Inline) f32 { + return @round(val); +} + +pub fn __builtin_strlen(s: [*c]const u8) callconv(.Inline) usize { + return std.mem.lenZ(s); +} pub fn __builtin_strcmp(s1: [*c]const u8, s2: [*c]const u8) callconv(.Inline) c_int { return @as(c_int, std.cstr.cmp(s1, s2)); } diff --git a/lib/std/c/parse.zig b/lib/std/c/parse.zig index 3d17938d7a..29d4ba2fe1 100644 --- a/lib/std/c/parse.zig +++ b/lib/std/c/parse.zig @@ -300,8 +300,7 @@ const Parser = struct { try node.initializers.push((try parser.initializer(dr)) orelse return parser.err(.{ .ExpectedInitializer = .{ .token = parser.it.index }, })); - } else - try node.initializers.push(&dr.base); + } else try node.initializers.push(&dr.base); if (parser.eatToken(.Comma) != null) break; dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{ .ExpectedDeclarator = .{ .token = parser.it.index }, diff --git a/lib/std/coff.zig b/lib/std/coff.zig index 85000bf8cb..edeff89cc5 100644 --- a/lib/std/coff.zig +++ b/lib/std/coff.zig @@ -173,8 +173,7 @@ pub const Coff = struct { skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 18 * @sizeOf(u32); } else if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 12 * @sizeOf(u32) + 5 * @sizeOf(u64); - } else - return error.InvalidPEMagic; + } else return error.InvalidPEMagic; try self.in_file.seekBy(skip_size); diff --git a/lib/std/crypto/aegis.zig b/lib/std/crypto/aegis.zig index 089dc06be4..2983f68ce8 100644 --- a/lib/std/crypto/aegis.zig +++ b/lib/std/crypto/aegis.zig @@ -81,8 +81,8 @@ const State128L = struct { while (i < 7) : (i += 1) { state.update(tmp, tmp); } - return blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).xorBlocks(blocks[4]). - xorBlocks(blocks[5]).xorBlocks(blocks[6]).toBytes(); + return blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).xorBlocks(blocks[4]) + .xorBlocks(blocks[5]).xorBlocks(blocks[6]).toBytes(); } }; @@ -244,8 +244,8 @@ const State256 = struct { while (i < 7) : (i += 1) { state.update(tmp); } - return blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).xorBlocks(blocks[4]). - xorBlocks(blocks[5]).toBytes(); + return blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).xorBlocks(blocks[4]) + .xorBlocks(blocks[5]).toBytes(); } }; diff --git a/lib/std/crypto/bcrypt.zig b/lib/std/crypto/bcrypt.zig index 6d333c45cb..caceb6d7b9 100644 --- a/lib/std/crypto/bcrypt.zig +++ b/lib/std/crypto/bcrypt.zig @@ -109,9 +109,7 @@ const State = struct { } } - const Halves = struct { - l: u32, r: u32 - }; + const Halves = struct { l: u32, r: u32 }; fn feistelF(state: State, x: u32) u32 { var r = state.sboxes[0][@truncate(u8, x >> 24)]; diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index 6769a139da..7df3a1bff6 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -213,13 +213,11 @@ const LineNumberProgram = struct { return error.MissingDebugInfo; } else if (self.prev_file - 1 >= self.file_entries.items.len) { return error.InvalidDebugInfo; - } else - &self.file_entries.items[self.prev_file - 1]; + } else &self.file_entries.items[self.prev_file - 1]; const dir_name = if (file_entry.dir_index >= self.include_dirs.len) { return error.InvalidDebugInfo; - } else - self.include_dirs[file_entry.dir_index]; + } else self.include_dirs[file_entry.dir_index]; const file_name = try fs.path.join(self.file_entries.allocator, &[_][]const u8{ dir_name, file_entry.file_name }); errdefer self.file_entries.allocator.free(file_name); return debug.LineInfo{ diff --git a/lib/std/event/batch.zig b/lib/std/event/batch.zig index 72e0bd13fc..5368c5336d 100644 --- a/lib/std/event/batch.zig +++ b/lib/std/event/batch.zig @@ -98,15 +98,16 @@ pub fn Batch( /// This function is *not* thread-safe. It must be called from one thread at /// a time, however, it need not be the same thread. pub fn wait(self: *Self) CollectedResult { - for (self.jobs) |*job| if (job.frame) |f| { - job.result = if (async_ok) await f else nosuspend await f; - if (CollectedResult != void) { - job.result catch |err| { - self.collected_result = err; - }; - } - job.frame = null; - }; + for (self.jobs) |*job| + if (job.frame) |f| { + job.result = if (async_ok) await f else nosuspend await f; + if (CollectedResult != void) { + job.result catch |err| { + self.collected_result = err; + }; + } + job.frame = null; + }; return self.collected_result; } }; diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index e5ce457091..fca21000cf 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -646,8 +646,7 @@ pub fn formatIntValue( const int_value = if (@TypeOf(value) == comptime_int) blk: { const Int = math.IntFittingRange(value, value); break :blk @as(Int, value); - } else - value; + } else value; if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "d")) { radix = 10; @@ -1087,8 +1086,7 @@ pub fn formatInt( const int_value = if (@TypeOf(value) == comptime_int) blk: { const Int = math.IntFittingRange(value, value); break :blk @as(Int, value); - } else - value; + } else value; const value_info = @typeInfo(@TypeOf(int_value)).Int; diff --git a/lib/std/log.zig b/lib/std/log.zig index 43c00a6d0e..215e611bc1 100644 --- a/lib/std/log.zig +++ b/lib/std/log.zig @@ -3,9 +3,6 @@ // This file is part of [zig](https://ziglang.org/), which is MIT licensed. // The MIT license requires this copyright notice to be included in all copies // and substantial portions of the software. -const std = @import("std.zig"); -const builtin = std.builtin; -const root = @import("root"); //! std.log is a standardized interface for logging which allows for the logging //! of programs and libraries using this interface to be formatted and filtered @@ -77,6 +74,10 @@ const root = @import("root"); //! [err] (nice_library): Something went very wrong, sorry //! ``` +const std = @import("std.zig"); +const builtin = std.builtin; +const root = @import("root"); + pub const Level = enum { /// Emergency: a condition that cannot be handled, usually followed by a /// panic. diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 30f69ae9a5..7ec29dcd0e 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -534,9 +534,7 @@ pub fn fieldNames(comptime T: type) *const [fields(T).len][]const u8 { } test "std.meta.fieldNames" { - const E1 = enum { - A, B - }; + const E1 = enum { A, B }; const E2 = error{A}; const S1 = struct { a: u8, @@ -1002,19 +1000,19 @@ pub fn sizeof(target: anytype) usize { // Note: sizeof(void) is 1 on clang/gcc and 0 on MSVC. return 1; } else { - @compileError("Cannot use C sizeof on opaque type "++@typeName(T)); + @compileError("Cannot use C sizeof on opaque type " ++ @typeName(T)); } }, .Optional => |opt| { if (@typeInfo(opt.child) == .Pointer) { return sizeof(opt.child); } else { - @compileError("Cannot use C sizeof on non-pointer optional "++@typeName(T)); + @compileError("Cannot use C sizeof on non-pointer optional " ++ @typeName(T)); } }, .Pointer => |ptr| { if (ptr.size == .Slice) { - @compileError("Cannot use C sizeof on slice type "++@typeName(T)); + @compileError("Cannot use C sizeof on slice type " ++ @typeName(T)); } // for strings, sizeof("a") returns 2. // normal pointer decay scenarios from C are handled @@ -1024,8 +1022,9 @@ pub fn sizeof(target: anytype) usize { if (ptr.size == .One and ptr.is_const and @typeInfo(ptr.child) == .Array) { const array_info = @typeInfo(ptr.child).Array; if ((array_info.child == u8 or array_info.child == u16) and - array_info.sentinel != null and - array_info.sentinel.? == 0) { + array_info.sentinel != null and + array_info.sentinel.? == 0) + { // length of the string plus one for the null terminator. return (array_info.len + 1) * @sizeOf(array_info.child); } @@ -1067,10 +1066,10 @@ test "sizeof" { testing.expect(sizeof(S) == 4); - testing.expect(sizeof([_]u32{4, 5, 6}) == 12); + testing.expect(sizeof([_]u32{ 4, 5, 6 }) == 12); testing.expect(sizeof([3]u32) == 12); testing.expect(sizeof([3:0]u32) == 16); - testing.expect(sizeof(&[_]u32{4, 5, 6}) == ptr_size); + testing.expect(sizeof(&[_]u32{ 4, 5, 6 }) == ptr_size); testing.expect(sizeof(*u32) == ptr_size); testing.expect(sizeof([*]u32) == ptr_size); @@ -1082,7 +1081,7 @@ test "sizeof" { testing.expect(sizeof(null) == ptr_size); testing.expect(sizeof("foobar") == 7); - testing.expect(sizeof(&[_:0]u16{'f','o','o','b','a','r'}) == 14); + testing.expect(sizeof(&[_:0]u16{ 'f', 'o', 'o', 'b', 'a', 'r' }) == 14); testing.expect(sizeof(*const [4:0]u8) == 5); testing.expect(sizeof(*[4:0]u8) == ptr_size); testing.expect(sizeof([*]const [4:0]u8) == ptr_size); diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig index 8e54293533..e67f9b9bc4 100644 --- a/lib/std/meta/trait.zig +++ b/lib/std/meta/trait.zig @@ -544,15 +544,11 @@ test "std.meta.trait.hasUniqueRepresentation" { testing.expect(hasUniqueRepresentation(TestStruct3)); - const TestStruct4 = struct { - a: []const u8 - }; + const TestStruct4 = struct { a: []const u8 }; testing.expect(!hasUniqueRepresentation(TestStruct4)); - const TestStruct5 = struct { - a: TestStruct4 - }; + const TestStruct5 = struct { a: TestStruct4 }; testing.expect(!hasUniqueRepresentation(TestStruct5)); diff --git a/lib/std/os.zig b/lib/std/os.zig index c2431ff12c..61d9749415 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -3263,8 +3263,9 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne .WSAEADDRNOTAVAIL => return error.AddressNotAvailable, .WSAECONNREFUSED => return error.ConnectionRefused, .WSAETIMEDOUT => return error.ConnectionTimedOut, - .WSAEHOSTUNREACH // TODO: should we return NetworkUnreachable in this case as well? - , .WSAENETUNREACH => return error.NetworkUnreachable, + .WSAEHOSTUNREACH, // TODO: should we return NetworkUnreachable in this case as well? + .WSAENETUNREACH, + => return error.NetworkUnreachable, .WSAEFAULT => unreachable, .WSAEINVAL => unreachable, .WSAEISCONN => unreachable, diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig index f8b950ea86..57ae70ddbf 100644 --- a/lib/std/os/bits/netbsd.zig +++ b/lib/std/os/bits/netbsd.zig @@ -836,13 +836,15 @@ pub const ucontext_t = extern struct { sigmask: sigset_t, stack: stack_t, mcontext: mcontext_t, - __pad: [switch (builtin.arch) { - .i386 => 4, - .mips, .mipsel, .mips64, .mips64el => 14, - .arm, .armeb, .thumb, .thumbeb => 1, - .sparc, .sparcel, .sparcv9 => if (@sizeOf(usize) == 4) 43 else 8, - else => 0, - }]u32, + __pad: [ + switch (builtin.arch) { + .i386 => 4, + .mips, .mipsel, .mips64, .mips64el => 14, + .arm, .armeb, .thumb, .thumbeb => 1, + .sparc, .sparcel, .sparcv9 => if (@sizeOf(usize) == 4) 43 else 8, + else => 0, + } + ]u32, }; pub const EPERM = 1; // Operation not permitted diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index 8461378da0..cbeb0b483d 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -1315,11 +1315,13 @@ pub const PEB = extern struct { ImageSubSystemMinorVersion: ULONG, // note: there is padding here on 64 bit ActiveProcessAffinityMask: KAFFINITY, - GdiHandleBuffer: [switch (@sizeOf(usize)) { - 4 => 0x22, - 8 => 0x3C, - else => unreachable, - }]ULONG, + GdiHandleBuffer: [ + switch (@sizeOf(usize)) { + 4 => 0x22, + 8 => 0x3C, + else => unreachable, + } + ]ULONG, // Fields appended in 5.0 (Windows 2000): PostProcessInitRoutine: PVOID, diff --git a/lib/std/special/compiler_rt/arm.zig b/lib/std/special/compiler_rt/arm.zig index b958748c4f..f100f8293c 100644 --- a/lib/std/special/compiler_rt/arm.zig +++ b/lib/std/special/compiler_rt/arm.zig @@ -66,10 +66,7 @@ pub fn __aeabi_uidivmod() callconv(.Naked) void { \\ ldr r1, [sp] \\ add sp, #4 \\ pop {pc} - : - : - : "memory" - ); + ::: "memory"); unreachable; } @@ -86,10 +83,7 @@ pub fn __aeabi_uldivmod() callconv(.Naked) void { \\ ldr r3, [sp, #12] \\ add sp, #16 \\ pop {r4, pc} - : - : - : "memory" - ); + ::: "memory"); unreachable; } @@ -104,10 +98,7 @@ pub fn __aeabi_idivmod() callconv(.Naked) void { \\ ldr r1, [sp] \\ add sp, #4 \\ pop {pc} - : - : - : "memory" - ); + ::: "memory"); unreachable; } @@ -124,9 +115,6 @@ pub fn __aeabi_ldivmod() callconv(.Naked) void { \\ ldr r3, [sp, #12] \\ add sp, #16 \\ pop {r4, pc} - : - : - : "memory" - ); + ::: "memory"); unreachable; } -- cgit v1.2.3 From c17396691ce116a949618cb03d740997c7e80788 Mon Sep 17 00:00:00 2001 From: Al Hoang <3811822-hoanga@users.noreply.gitlab.com> Date: Sun, 17 Jan 2021 13:29:00 -0600 Subject: initial support for haiku sync update * add cpu count * use haiku find_directory * add definitions and exports for building in haiku --- lib/std/Thread.zig | 10 +++++ lib/std/c/haiku.zig | 22 ++++++++++- lib/std/crypto/tlcsprng.zig | 1 + lib/std/fs.zig | 29 +++++++++++++-- lib/std/fs/get_app_data_dir.zig | 15 +++++--- lib/std/os.zig | 6 +++ lib/std/os/bits/haiku.zig | 82 ++++++++++++++++++++++++++++++----------- lib/std/target.zig | 3 +- src/libc_installation.zig | 1 + 9 files changed, 136 insertions(+), 33 deletions(-) (limited to 'lib/std/Thread.zig') diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 80de19fe19..52f625edf4 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -504,6 +504,13 @@ pub fn cpuCount() CpuCountError!usize { }; return @intCast(usize, count); } + if (std.Target.current.os.tag == .haiku) { + var count: u32 = undefined; + var system_info: os.system_info = undefined; + const rc = os.system.get_system_info(&system_info); + count = system_info.cpu_count; + return @intCast(usize, count); + } var count: c_int = undefined; var count_len: usize = @sizeOf(c_int); const name = if (comptime std.Target.current.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; @@ -538,6 +545,9 @@ pub fn getCurrentThreadId() u64 { .openbsd => { return @bitCast(u32, c.getthrid()); }, + .haiku => { + return @bitCast(u32, c.find_thread(null)); + }, else => { @compileError("getCurrentThreadId not implemented for this platform"); }, diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig index a00e3ec534..e361a7520e 100644 --- a/lib/std/c/haiku.zig +++ b/lib/std/c/haiku.zig @@ -14,10 +14,21 @@ extern "c" fn _errnop() *c_int; pub const _errno = _errnop; -pub extern "c" fn _kern_read_dir(fd: c_int, buf_ptr: [*]u8, nbytes: usize, maxcount: u32) usize; +pub extern "c" fn find_directory(which: c_int, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64; + +pub extern "c" fn find_thread(thread_name: ?*c_void) i32; + +pub extern "c" fn get_system_info(system_info: *system_info) usize; +// TODO revisit if abi changes or better option becomes apparent pub extern "c" fn _get_next_image_info(team: c_int, cookie: *i32, image_info: *image_info) usize; +pub extern "c" fn _kern_read_dir(fd: c_int, buf_ptr: [*]u8, nbytes: usize, maxcount: u32) usize; + +pub extern "c" fn _kern_read_stat(fd: c_int, path_ptr: [*]u8, traverse_link: bool, libc_stat: *libc_stat, stat_size: i32) usize; + +pub extern "c" fn _kern_get_current_team() i32; + pub const sem_t = extern struct { _magic: u32, _kern: extern struct { @@ -27,6 +38,14 @@ pub const sem_t = extern struct { _padding: u32, }; +pub const pthread_attr_t = extern struct { + __detach_state: i32, + __sched_priority: i32, + __stack_size: i32, + __guard_size: i32, + __stack_address: ?*c_void, +}; + pub const pthread_mutex_t = extern struct { flags: u32 = 0, lock: i32 = 0, @@ -34,7 +53,6 @@ pub const pthread_mutex_t = extern struct { owner: i32 = -1, owner_count: i32 = 0, }; - pub const pthread_cond_t = extern struct { flags: u32 = 0, unused: i32 = -42, diff --git a/lib/std/crypto/tlcsprng.zig b/lib/std/crypto/tlcsprng.zig index 07844efc1b..115a7ab882 100644 --- a/lib/std/crypto/tlcsprng.zig +++ b/lib/std/crypto/tlcsprng.zig @@ -29,6 +29,7 @@ const os_has_fork = switch (std.Target.current.os.tag) { .solaris, .tvos, .watchos, + .haiku, => true, else => false, diff --git a/lib/std/fs.zig b/lib/std/fs.zig index d6ed1dfd7c..79385708af 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -472,8 +472,25 @@ pub const Dir = struct { continue :start_over; } - // TODO: determine entry kind - const entry_kind = Entry.Kind.File; + var stat_info: os.libc_stat = undefined; + const rc2 = os.system._kern_read_stat( + self.dir.fd, + &haiku_entry.d_name, + false, + &stat_info, + 0, + ); + const statmode = stat_info.mode & os.S_IFMT; + + const entry_kind = switch (statmode) { + os.S_IFDIR => Entry.Kind.Directory, + os.S_IFBLK => Entry.Kind.BlockDevice, + os.S_IFCHR => Entry.Kind.CharacterDevice, + os.S_IFLNK => Entry.Kind.SymLink, + os.S_IFREG => Entry.Kind.File, + os.S_IFIFO => Entry.Kind.NamedPipe, + else => Entry.Kind.Unknown, + }; return Entry{ .name = name, @@ -676,7 +693,13 @@ pub const Dir = struct { pub fn iterate(self: Dir) Iterator { switch (builtin.os.tag) { - .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, => return Iterator{ + .macos, + .ios, + .freebsd, + .netbsd, + .dragonfly, + .openbsd, + => return Iterator{ .dir = self, .seek = 0, .index = 0, diff --git a/lib/std/fs/get_app_data_dir.zig b/lib/std/fs/get_app_data_dir.zig index 2199761acb..18f8458eb2 100644 --- a/lib/std/fs/get_app_data_dir.zig +++ b/lib/std/fs/get_app_data_dir.zig @@ -57,11 +57,16 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD return fs.path.join(allocator, &[_][]const u8{ home_dir, ".local", "share", appname }); }, .haiku => { - const home_dir = os.getenv("HOME") orelse { - // TODO look in /etc/passwd - return error.AppDataDirUnavailable; - }; - return fs.path.join(allocator, &[_][]const u8{ home_dir, "config", "settings", appname }); + var dir_path_ptr: [*:0]u8 = undefined; + // TODO look into directory_which + const be_user_settings = 0xbbe; + const rc = os.system.find_directory(be_user_settings, -1, true, dir_path_ptr, 1) ; + const settings_dir = try allocator.dupeZ(u8, mem.spanZ(dir_path_ptr)); + defer allocator.free(settings_dir); + switch (rc) { + 0 => return fs.path.join(allocator, &[_][]const u8{ settings_dir, appname }), + else => return error.AppDataDirUnavailable, + } }, else => @compileError("Unsupported OS"), } diff --git a/lib/std/os.zig b/lib/std/os.zig index a9578e530e..8d5c680b26 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -3941,6 +3941,9 @@ pub fn sysctl( if (builtin.os.tag == .wasi) { @panic("unsupported"); } + if (builtin.os.tag == .haiku) { + @panic("unsupported"); + } const name_len = math.cast(c_uint, name.len) catch return error.NameTooLong; switch (errno(system.sysctl(name.ptr, name_len, oldp, oldlenp, newp, newlen))) { @@ -3965,6 +3968,9 @@ pub fn sysctlbynameZ( if (builtin.os.tag == .wasi) { @panic("unsupported"); } + if (builtin.os.tag == .haiku) { + @panic("unsupported"); + } switch (errno(system.sysctlbyname(name, oldp, oldlenp, newp, newlen))) { 0 => return, diff --git a/lib/std/os/bits/haiku.zig b/lib/std/os/bits/haiku.zig index c4f6b694aa..59631fd40e 100644 --- a/lib/std/os/bits/haiku.zig +++ b/lib/std/os/bits/haiku.zig @@ -6,8 +6,6 @@ const std = @import("../../std.zig"); const maxInt = std.math.maxInt; -// See https://svnweb.freebsd.org/base/head/sys/sys/_types.h?view=co -// TODO: audit pid_t/mode_t. They should likely be i32 and u16, respectively pub const fd_t = c_int; pub const pid_t = c_int; pub const uid_t = u32; @@ -30,6 +28,11 @@ pub const Kevent = extern struct { // Modes and flags for dlopen() // include/dlfcn.h +pub const POLLIN = 0x0001; +pub const POLLERR = 0x0004; +pub const POLLNVAL = 0x1000; +pub const POLLHUP = 0x0080; + /// Bind function calls lazily. pub const RTLD_LAZY = 1; @@ -119,41 +122,43 @@ pub const msghdr_const = extern struct { pub const off_t = i64; pub const ino_t = u64; -pub const libc_stat = extern struct { - dev: u64, - ino: ino_t, - nlink: usize, +pub const nfds_t = u32; - mode: u16, - __pad0: u16, - uid: uid_t, - gid: gid_t, - __pad1: u32, - rdev: u64, +pub const pollfd = extern struct { + fd: i32, + events: i16, + revents: i16, +}; +pub const libc_stat = extern struct { + dev: i32, + ino: u64, + mode: u32, + nlink: i32, + uid: i32, + gid: i32, + size: i64, + rdev: i32, + blksize: i32, atim: timespec, mtim: timespec, ctim: timespec, - birthtim: timespec, - - size: off_t, + crtim: timespec, + st_type: u32, blocks: i64, - blksize: isize, - flags: u32, - gen: u64, - __spare: [10]u64, pub fn atime(self: @This()) timespec { return self.atim; } - pub fn mtime(self: @This()) timespec { return self.mtim; } - pub fn ctime(self: @This()) timespec { return self.ctim; } + pub fn crtime(self: @This()) timespec { + return self.crtim; + } }; pub const timespec = extern struct { @@ -192,6 +197,34 @@ pub const image_info = extern struct { abi: i32, }; +pub const system_info = extern struct { + boot_time: i64, + cpu_count: u32, + max_pages: u64, + used_pages: u64, + cached_pages: u64, + block_cache_pages: u64, + ignored_pages: u64, + needed_memory: u64, + free_memory: u64, + max_swap_pages: u64, + free_swap_pages: u64, + page_faults: u32, + max_sems: u32, + used_sems: u32, + max_ports: u32, + used_ports: u32, + max_threads: u32, + used_threads: u32, + max_teams: u32, + used_teams: u32, + kernel_name: [256]u8, + kernel_build_date: [32]u8, + kernel_build_time: [32]u8, + kernel_version: i64, + abi: u32, +}; + pub const in_port_t = u16; pub const sa_family_t = u8; @@ -1408,3 +1441,10 @@ pub const rlimit = extern struct { pub const SHUT_RD = 0; pub const SHUT_WR = 1; pub const SHUT_RDWR = 2; + +// TODO fill out if needed +pub const directory_which = extern enum(c_int) { + B_USER_SETTINGS_DIRECTORY = 0xbbe, + + _, +}; diff --git a/lib/std/target.zig b/lib/std/target.zig index ece5361927..bf0492624d 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1566,8 +1566,7 @@ pub const Target = struct { .other, => return result, - // Operating systems in this list have been verified as not having a standard - // dynamic linker path. + // TODO revisit when multi-arch for Haiku is available .haiku => return copy(&result, "/system/runtime_loader"), // TODO go over each item in this list and either move it to the above list, or diff --git a/src/libc_installation.zig b/src/libc_installation.zig index 05c85578ea..6700787925 100644 --- a/src/libc_installation.zig +++ b/src/libc_installation.zig @@ -196,6 +196,7 @@ pub const LibCInstallation = struct { switch (Target.current.os.tag) { .freebsd, .netbsd, .openbsd => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"), .linux, .dragonfly => batch.add(&async self.findNativeCrtDirPosix(args)), + .haiku => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/system/develop/lib"), else => {}, } break :blk batch.wait(); -- cgit v1.2.3 From 37a1d08de2ce263439713180f57741d16fb27e23 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 25 Feb 2021 16:54:32 -0700 Subject: haiku: minor fixups * no isHaiku() function since there is not more than one os tag that this applies to. * clean up some control flow into a switch * add some TODO comments to investigate panics that suspiciously look like they should be compile errors (see #363) --- lib/std/Thread.zig | 66 +++++++++++++++++++++++++++++------------------------- lib/std/os.zig | 10 ++++----- lib/std/target.zig | 4 ---- 3 files changed, 40 insertions(+), 40 deletions(-) (limited to 'lib/std/Thread.zig') diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 52f625edf4..77277bd154 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -487,38 +487,42 @@ pub const CpuCountError = error{ }; pub fn cpuCount() CpuCountError!usize { - if (std.Target.current.os.tag == .linux) { - const cpu_set = try os.sched_getaffinity(0); - return @as(usize, os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast - } - if (std.Target.current.os.tag == .windows) { - return os.windows.peb().NumberOfProcessors; - } - if (std.Target.current.os.tag == .openbsd) { - var count: c_int = undefined; - var count_size: usize = @sizeOf(c_int); - const mib = [_]c_int{ os.CTL_HW, os.HW_NCPUONLINE }; - os.sysctl(&mib, &count, &count_size, null, 0) catch |err| switch (err) { - error.NameTooLong, error.UnknownName => unreachable, - else => |e| return e, - }; - return @intCast(usize, count); - } - if (std.Target.current.os.tag == .haiku) { - var count: u32 = undefined; - var system_info: os.system_info = undefined; - const rc = os.system.get_system_info(&system_info); - count = system_info.cpu_count; - return @intCast(usize, count); + switch (std.Target.current.os.tag) { + .linux => { + const cpu_set = try os.sched_getaffinity(0); + return @as(usize, os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast + }, + .windows => { + return os.windows.peb().NumberOfProcessors; + }, + .openbsd => { + var count: c_int = undefined; + var count_size: usize = @sizeOf(c_int); + const mib = [_]c_int{ os.CTL_HW, os.HW_NCPUONLINE }; + os.sysctl(&mib, &count, &count_size, null, 0) catch |err| switch (err) { + error.NameTooLong, error.UnknownName => unreachable, + else => |e| return e, + }; + return @intCast(usize, count); + }, + .haiku => { + var count: u32 = undefined; + var system_info: os.system_info = undefined; + const rc = os.system.get_system_info(&system_info); + count = system_info.cpu_count; + return @intCast(usize, count); + }, + else => { + var count: c_int = undefined; + var count_len: usize = @sizeOf(c_int); + const name = if (comptime std.Target.current.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; + os.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) { + error.NameTooLong, error.UnknownName => unreachable, + else => |e| return e, + }; + return @intCast(usize, count); + }, } - var count: c_int = undefined; - var count_len: usize = @sizeOf(c_int); - const name = if (comptime std.Target.current.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; - os.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) { - error.NameTooLong, error.UnknownName => unreachable, - else => |e| return e, - }; - return @intCast(usize, count); } pub fn getCurrentThreadId() u64 { diff --git a/lib/std/os.zig b/lib/std/os.zig index 8d5c680b26..6b13ec94c9 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -3892,7 +3892,7 @@ pub fn pipe2(flags: u32) PipeError![2]fd_t { } } } - if (comptime std.Target.current.isHaiku()) { + if (std.Target.current.os.tag == .haiku) { var fds: [2]fd_t = try pipe(); if (flags == 0) return fds; errdefer { @@ -3939,10 +3939,10 @@ pub fn sysctl( newlen: usize, ) SysCtlError!void { if (builtin.os.tag == .wasi) { - @panic("unsupported"); + @panic("unsupported"); // TODO should be compile error, not panic } if (builtin.os.tag == .haiku) { - @panic("unsupported"); + @panic("unsupported"); // TODO should be compile error, not panic } const name_len = math.cast(c_uint, name.len) catch return error.NameTooLong; @@ -3966,10 +3966,10 @@ pub fn sysctlbynameZ( newlen: usize, ) SysCtlError!void { if (builtin.os.tag == .wasi) { - @panic("unsupported"); + @panic("unsupported"); // TODO should be compile error, not panic } if (builtin.os.tag == .haiku) { - @panic("unsupported"); + @panic("unsupported"); // TODO should be compile error, not panic } switch (errno(system.sysctlbyname(name, oldp, oldlenp, newp, newlen))) { diff --git a/lib/std/target.zig b/lib/std/target.zig index bf0492624d..7e05f35932 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1339,10 +1339,6 @@ pub const Target = struct { return self.os.tag.isDarwin(); } - pub fn isHaiku(self: Target) bool { - return self.os.tag == .haiku; - } - pub fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool { return os_tag == .linux and abi.isGnu(); } -- cgit v1.2.3