| author | |
| committer | |
| log | c15a6fa9d0e11398f65e8ecc1903e07f4c57add6 |
| tree | 556306ecdb10cf6841b488e6950e49d2db92005c |
| parent | 57f36c420124b3b65d3036f10c4e8c675be29cf4 |
5 files changed, 117 insertions(+), 2 deletions(-)
std/event.zig+2-2| ... | @@ -150,8 +150,8 @@ pub const Loop = struct { | ... | @@ -150,8 +150,8 @@ pub const Loop = struct { |
| 150 | /// TODO copy elision / named return values so that the threads referencing *Loop | 150 | /// TODO copy elision / named return values so that the threads referencing *Loop |
| 151 | /// have the correct pointer value. | 151 | /// have the correct pointer value. |
| 152 | fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void { | 152 | fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void { |
| 153 | // TODO check the actual cpu core count | 153 | const core_count = try std.os.cpuCount(allocator); |
| 154 | return self.initInternal(allocator, 4); | 154 | return self.initInternal(allocator, core_count); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | /// Thread count is the total thread count. The thread pool size will be | 157 | /// Thread count is the total thread count. The thread pool size will be |
std/heap.zig+67| ... | @@ -361,6 +361,73 @@ pub const ThreadSafeFixedBufferAllocator = struct { | ... | @@ -361,6 +361,73 @@ pub const ThreadSafeFixedBufferAllocator = struct { |
| 361 | fn free(allocator: *Allocator, bytes: []u8) void {} | 361 | fn free(allocator: *Allocator, bytes: []u8) void {} |
| 362 | }; | 362 | }; |
| 363 | 363 | ||
| 364 | pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) StackFallbackAllocator(size) { | ||
| 365 | return StackFallbackAllocator(size){ | ||
| 366 | .buffer = undefined, | ||
| 367 | .fallback_allocator = fallback_allocator, | ||
| 368 | .fixed_buffer_allocator = undefined, | ||
| 369 | .allocator = Allocator{ | ||
| 370 | .allocFn = StackFallbackAllocator(size).alloc, | ||
| 371 | .reallocFn = StackFallbackAllocator(size).realloc, | ||
| 372 | .freeFn = StackFallbackAllocator(size).free, | ||
| 373 | }, | ||
| 374 | }; | ||
| 375 | } | ||
| 376 | |||
| 377 | pub fn StackFallbackAllocator(comptime size: usize) type { | ||
| 378 | return struct { | ||
| 379 | const Self = this; | ||
| 380 | |||
| 381 | buffer: [size]u8, | ||
| 382 | allocator: Allocator, | ||
| 383 | fallback_allocator: *Allocator, | ||
| 384 | fixed_buffer_allocator: FixedBufferAllocator, | ||
| 385 | |||
| 386 | pub fn get(self: *Self) *Allocator { | ||
| 387 | self.fixed_buffer_allocator = FixedBufferAllocator.init(self.buffer[0..]); | ||
| 388 | return &self.allocator; | ||
| 389 | } | ||
| 390 | |||
| 391 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 { | ||
| 392 | const self = @fieldParentPtr(Self, "allocator", allocator); | ||
| 393 | return FixedBufferAllocator.alloc(&self.fixed_buffer_allocator.allocator, n, alignment) catch | ||
| 394 | self.fallback_allocator.allocFn(self.fallback_allocator, n, alignment); | ||
| 395 | } | ||
| 396 | |||
| 397 | fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 { | ||
| 398 | const self = @fieldParentPtr(Self, "allocator", allocator); | ||
| 399 | const in_buffer = @ptrToInt(old_mem.ptr) >= @ptrToInt(&self.buffer) and | ||
| 400 | @ptrToInt(old_mem.ptr) < @ptrToInt(&self.buffer) + self.buffer.len; | ||
| 401 | if (in_buffer) { | ||
| 402 | return FixedBufferAllocator.realloc( | ||
| 403 | &self.fixed_buffer_allocator.allocator, | ||
| 404 | old_mem, | ||
| 405 | new_size, | ||
| 406 | alignment, | ||
| 407 | ) catch { | ||
| 408 | const result = try self.fallback_allocator.allocFn( | ||
| 409 | self.fallback_allocator, | ||
| 410 | new_size, | ||
| 411 | alignment, | ||
| 412 | ); | ||
| 413 | mem.copy(u8, result, old_mem); | ||
| 414 | return result; | ||
| 415 | }; | ||
| 416 | } | ||
| 417 | return self.fallback_allocator.reallocFn(self.fallback_allocator, old_mem, new_size, alignment); | ||
| 418 | } | ||
| 419 | |||
| 420 | fn free(allocator: *Allocator, bytes: []u8) void { | ||
| 421 | const self = @fieldParentPtr(Self, "allocator", allocator); | ||
| 422 | const in_buffer = @ptrToInt(bytes.ptr) >= @ptrToInt(&self.buffer) and | ||
| 423 | @ptrToInt(bytes.ptr) < @ptrToInt(&self.buffer) + self.buffer.len; | ||
| 424 | if (!in_buffer) { | ||
| 425 | return self.fallback_allocator.freeFn(self.fallback_allocator, bytes); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | }; | ||
| 429 | } | ||
| 430 | |||
| 364 | test "c_allocator" { | 431 | test "c_allocator" { |
| 365 | if (builtin.link_libc) { | 432 | if (builtin.link_libc) { |
| 366 | var slice = c_allocator.alloc(u8, 50) catch return; | 433 | var slice = c_allocator.alloc(u8, 50) catch return; |
std/os/index.zig+39| ... | @@ -2748,3 +2748,42 @@ pub fn posixFStat(fd: i32) !posix.Stat { | ... | @@ -2748,3 +2748,42 @@ pub fn posixFStat(fd: i32) !posix.Stat { |
| 2748 | 2748 | ||
| 2749 | return stat; | 2749 | return stat; |
| 2750 | } | 2750 | } |
| 2751 | |||
| 2752 | pub const CpuCountError = error{ | ||
| 2753 | OutOfMemory, | ||
| 2754 | PermissionDenied, | ||
| 2755 | Unexpected, | ||
| 2756 | }; | ||
| 2757 | |||
| 2758 | pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize { | ||
| 2759 | const usize_count = 16; | ||
| 2760 | const allocator = std.heap.stackFallback(usize_count * @sizeOf(usize), fallback_allocator).get(); | ||
| 2761 | |||
| 2762 | var set = try allocator.alloc(usize, usize_count); | ||
| 2763 | defer allocator.free(set); | ||
| 2764 | |||
| 2765 | while (true) { | ||
| 2766 | const rc = posix.sched_getaffinity(0, set); | ||
| 2767 | const err = posix.getErrno(rc); | ||
| 2768 | switch (err) { | ||
| 2769 | 0 => { | ||
| 2770 | if (rc < set.len * @sizeOf(usize)) { | ||
| 2771 | const result = set[0 .. rc / @sizeOf(usize)]; | ||
| 2772 | var sum: usize = 0; | ||
| 2773 | for (result) |x| { | ||
| 2774 | sum += @popCount(x); | ||
| 2775 | } | ||
| 2776 | return sum; | ||
| 2777 | } else { | ||
| 2778 | set = try allocator.realloc(usize, set, set.len * 2); | ||
| 2779 | continue; | ||
| 2780 | } | ||
| 2781 | }, | ||
| 2782 | posix.EFAULT => unreachable, | ||
| 2783 | posix.EINVAL => unreachable, | ||
| 2784 | posix.EPERM => return CpuCountError.PermissionDenied, | ||
| 2785 | posix.ESRCH => unreachable, | ||
| 2786 | else => return os.unexpectedErrorPosix(err), | ||
| 2787 | } | ||
| 2788 | } | ||
| 2789 | } |
std/os/linux/index.zig+4| ... | @@ -1197,6 +1197,10 @@ pub fn fremovexattr(fd: usize, name: [*]const u8) usize { | ... | @@ -1197,6 +1197,10 @@ pub fn fremovexattr(fd: usize, name: [*]const u8) usize { |
| 1197 | return syscall2(SYS_fremovexattr, fd, @ptrToInt(name)); | 1197 | return syscall2(SYS_fremovexattr, fd, @ptrToInt(name)); |
| 1198 | } | 1198 | } |
| 1199 | 1199 | ||
| 1200 | pub fn sched_getaffinity(pid: i32, set: []usize) usize { | ||
| 1201 | return syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), set.len * @sizeOf(usize), @ptrToInt(set.ptr)); | ||
| 1202 | } | ||
| 1203 | |||
| 1200 | pub const epoll_data = packed union { | 1204 | pub const epoll_data = packed union { |
| 1201 | ptr: usize, | 1205 | ptr: usize, |
| 1202 | fd: i32, | 1206 | fd: i32, |
std/os/test.zig+5| ... | @@ -58,3 +58,8 @@ fn start2(ctx: *i32) u8 { | ... | @@ -58,3 +58,8 @@ fn start2(ctx: *i32) u8 { |
| 58 | _ = @atomicRmw(i32, ctx, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst); | 58 | _ = @atomicRmw(i32, ctx, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst); |
| 59 | return 0; | 59 | return 0; |
| 60 | } | 60 | } |
| 61 | |||
| 62 | test "cpu count" { | ||
| 63 | const cpu_count = try std.os.cpuCount(a); | ||
| 64 | assert(cpu_count >= 1); | ||
| 65 | } |