| ... | ... | @@ -25,7 +25,8 @@ run_queue: std.SinglyLinkedList = .{}, |
| 25 | 25 | join_requested: bool = false, |
| 26 | 26 | threads: std.ArrayList(std.Thread), |
| 27 | 27 | stack_size: usize, |
| 28 | | cpu_count: std.Thread.CpuCountError!usize, |
| 28 | thread_capacity: std.atomic.Value(ThreadCapacity), |
| 29 | thread_capacity_error: ?std.Thread.CpuCountError, |
| 29 | 30 | concurrent_count: usize, |
| 30 | 31 | |
| 31 | 32 | wsa: if (is_windows) Wsa else struct {} = .{}, |
| ... | ... | @@ -34,6 +35,21 @@ have_signal_handler: bool, |
| 34 | 35 | old_sig_io: if (have_sig_io) posix.Sigaction else void, |
| 35 | 36 | old_sig_pipe: if (have_sig_pipe) posix.Sigaction else void, |
| 36 | 37 | |
| 38 | pub const ThreadCapacity = enum(usize) { |
| 39 | unknown = 0, |
| 40 | _, |
| 41 | |
| 42 | pub fn init(n: usize) ThreadCapacity { |
| 43 | assert(n != 0); |
| 44 | return @enumFromInt(n); |
| 45 | } |
| 46 | |
| 47 | pub fn get(tc: ThreadCapacity) ?usize { |
| 48 | if (tc == .unknown) return null; |
| 49 | return @intFromEnum(tc); |
| 50 | } |
| 51 | }; |
| 52 | |
| 37 | 53 | threadlocal var current_closure: ?*Closure = null; |
| 38 | 54 | |
| 39 | 55 | const max_iovecs_len = 8; |
| ... | ... | @@ -104,18 +120,21 @@ pub fn init( |
| 104 | 120 | /// here. |
| 105 | 121 | gpa: Allocator, |
| 106 | 122 | ) Threaded { |
| 123 | const cpu_count = std.Thread.getCpuCount(); |
| 124 | |
| 107 | 125 | var t: Threaded = .{ |
| 108 | 126 | .allocator = gpa, |
| 109 | 127 | .threads = .empty, |
| 110 | 128 | .stack_size = std.Thread.SpawnConfig.default_stack_size, |
| 111 | | .cpu_count = std.Thread.getCpuCount(), |
| 129 | .thread_capacity = .init(if (cpu_count) |n| .init(n) else |_| .unknown), |
| 130 | .thread_capacity_error = if (cpu_count) |_| null else |e| e, |
| 112 | 131 | .concurrent_count = 0, |
| 113 | 132 | .old_sig_io = undefined, |
| 114 | 133 | .old_sig_pipe = undefined, |
| 115 | 134 | .have_signal_handler = false, |
| 116 | 135 | }; |
| 117 | 136 | |
| 118 | | if (t.cpu_count) |n| { |
| 137 | if (cpu_count) |n| { |
| 119 | 138 | t.threads.ensureTotalCapacityPrecise(gpa, n - 1) catch {}; |
| 120 | 139 | } else |_| {} |
| 121 | 140 | |
| ... | ... | @@ -145,7 +164,8 @@ pub const init_single_threaded: Threaded = .{ |
| 145 | 164 | .allocator = .failing, |
| 146 | 165 | .threads = .empty, |
| 147 | 166 | .stack_size = std.Thread.SpawnConfig.default_stack_size, |
| 148 | | .cpu_count = 1, |
| 167 | .thread_capacity = .init(.init(1)), |
| 168 | .thread_capacity_error = null, |
| 149 | 169 | .concurrent_count = 0, |
| 150 | 170 | .old_sig_io = undefined, |
| 151 | 171 | .old_sig_pipe = undefined, |
| ... | ... | @@ -166,6 +186,18 @@ pub fn deinit(t: *Threaded) void { |
| 166 | 186 | t.* = undefined; |
| 167 | 187 | } |
| 168 | 188 | |
| 189 | pub fn setThreadCapacity(t: *Threaded, n: usize) void { |
| 190 | t.thread_capacity.store(.init(n), .monotonic); |
| 191 | } |
| 192 | |
| 193 | pub fn getThreadCapacity(t: *Threaded) ?usize { |
| 194 | return t.thread_capacity.load(.monotonic).get(); |
| 195 | } |
| 196 | |
| 197 | pub fn getCurrentThreadId() usize { |
| 198 | @panic("TODO"); |
| 199 | } |
| 200 | |
| 169 | 201 | fn join(t: *Threaded) void { |
| 170 | 202 | if (builtin.single_threaded) return; |
| 171 | 203 | { |
| ... | ... | @@ -497,7 +529,7 @@ fn async( |
| 497 | 529 | } |
| 498 | 530 | |
| 499 | 531 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 500 | | const cpu_count = t.cpu_count catch { |
| 532 | const cpu_count = t.getThreadCapacity() orelse { |
| 501 | 533 | return concurrent(userdata, result.len, result_alignment, context, context_alignment, start) catch { |
| 502 | 534 | start(context.ptr, result.ptr); |
| 503 | 535 | return null; |
| ... | ... | @@ -556,7 +588,7 @@ fn concurrent( |
| 556 | 588 | if (builtin.single_threaded) return error.ConcurrencyUnavailable; |
| 557 | 589 | |
| 558 | 590 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 559 | | const cpu_count = t.cpu_count catch 1; |
| 591 | const cpu_count = t.getThreadCapacity() orelse 1; |
| 560 | 592 | |
| 561 | 593 | const gpa = t.allocator; |
| 562 | 594 | const ac = AsyncClosure.init(gpa, .concurrent, result_len, result_alignment, context, context_alignment, start) catch { |
| ... | ... | @@ -685,7 +717,7 @@ fn groupAsync( |
| 685 | 717 | if (builtin.single_threaded) return start(group, context.ptr); |
| 686 | 718 | |
| 687 | 719 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 688 | | const cpu_count = t.cpu_count catch 1; |
| 720 | const cpu_count = t.getThreadCapacity() orelse 1; |
| 689 | 721 | |
| 690 | 722 | const gpa = t.allocator; |
| 691 | 723 | const gc = GroupClosure.init(gpa, t, group, context, context_alignment, start) catch { |