Commit 04d3da4bd1

Andrew Kelley <superjoe30@gmail.com>
2018-07-09 07:08:33
std.os.cpuCount implementation for macos
1 parent 50d70d5
Changed files (3)
std/c/darwin.zig
@@ -13,6 +13,10 @@ pub extern "c" fn kevent(kq: c_int, changelist: [*]const Kevent, nchanges: c_int
 pub extern "c" fn kevent64(kq: c_int, changelist: [*]const kevent64_s, nchanges: c_int,
     eventlist: [*]kevent64_s, nevents: c_int, flags: c_uint, timeout: ?*const timespec) c_int;
 
+pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
+pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
+pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
+
 pub use @import("../os/darwin_errno.zig");
 
 pub const _errno = __error;
std/os/darwin.zig
@@ -520,6 +520,18 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
     return errnoWrap(c.symlink(existing, new));
 }
 
+pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
+    return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen));
+}
+
+pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
+    return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen));
+}
+
+pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize {
+    return errnoWrap(c.sysctlnametomib(name, wibp, sizep));
+}
+
 pub fn rename(old: [*]const u8, new: [*]const u8) usize {
     return errnoWrap(c.rename(old, new));
 }
std/os/index.zig
@@ -2756,35 +2756,57 @@ pub const CpuCountError = error{
 };
 
 pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
-    const usize_count = 16;
-    const allocator = std.heap.stackFallback(usize_count * @sizeOf(usize), fallback_allocator).get();
+    switch (builtin.os) {
+        builtin.Os.macosx => {
+            var count: c_int = undefined;
+            var count_len: usize = @sizeOf(c_int);
+            const rc = posix.sysctlbyname(c"hw.ncpu", @ptrCast(*c_void, &count), &count_len, null, 0);
+            const err = posix.getErrno(rc);
+            switch (err) {
+                0 => return @intCast(usize, count),
+                posix.EFAULT => unreachable,
+                posix.EINVAL => unreachable,
+                posix.ENOMEM => return CpuCountError.OutOfMemory,
+                posix.ENOTDIR => unreachable,
+                posix.EISDIR => unreachable,
+                posix.ENOENT => unreachable,
+                posix.EPERM => unreachable,
+                else => return os.unexpectedErrorPosix(err),
+            }
+        },
+        builtin.Os.linux => {
+            const usize_count = 16;
+            const allocator = std.heap.stackFallback(usize_count * @sizeOf(usize), fallback_allocator).get();
 
-    var set = try allocator.alloc(usize, usize_count);
-    defer allocator.free(set);
+            var set = try allocator.alloc(usize, usize_count);
+            defer allocator.free(set);
 
-    while (true) {
-        const rc = posix.sched_getaffinity(0, set);
-        const err = posix.getErrno(rc);
-        switch (err) {
-            0 => {
-                if (rc < set.len * @sizeOf(usize)) {
-                    const result = set[0 .. rc / @sizeOf(usize)];
-                    var sum: usize = 0;
-                    for (result) |x| {
-                        sum += @popCount(x);
-                    }
-                    return sum;
-                } else {
-                    set = try allocator.realloc(usize, set, set.len * 2);
-                    continue;
+            while (true) {
+                const rc = posix.sched_getaffinity(0, set);
+                const err = posix.getErrno(rc);
+                switch (err) {
+                    0 => {
+                        if (rc < set.len * @sizeOf(usize)) {
+                            const result = set[0 .. rc / @sizeOf(usize)];
+                            var sum: usize = 0;
+                            for (result) |x| {
+                                sum += @popCount(x);
+                            }
+                            return sum;
+                        } else {
+                            set = try allocator.realloc(usize, set, set.len * 2);
+                            continue;
+                        }
+                    },
+                    posix.EFAULT => unreachable,
+                    posix.EINVAL => unreachable,
+                    posix.EPERM => return CpuCountError.PermissionDenied,
+                    posix.ESRCH => unreachable,
+                    else => return os.unexpectedErrorPosix(err),
                 }
-            },
-            posix.EFAULT => unreachable,
-            posix.EINVAL => unreachable,
-            posix.EPERM => return CpuCountError.PermissionDenied,
-            posix.ESRCH => unreachable,
-            else => return os.unexpectedErrorPosix(err),
-        }
+            }
+        },
+        else => @compileError("unsupported OS"),
     }
 }