| ... | @@ -25,7 +25,8 @@ run_queue: std.SinglyLinkedList = .{}, | ... | @@ -25,7 +25,8 @@ run_queue: std.SinglyLinkedList = .{}, |
| 25 | join_requested: bool = false, | 25 | join_requested: bool = false, |
| 26 | threads: std.ArrayList(std.Thread), | 26 | threads: std.ArrayList(std.Thread), |
| 27 | stack_size: usize, | 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 | concurrent_count: usize, | 30 | concurrent_count: usize, |
| 30 | | 31 | |
| 31 | wsa: if (is_windows) Wsa else struct {} = .{}, | 32 | wsa: if (is_windows) Wsa else struct {} = .{}, |
| ... | @@ -34,6 +35,21 @@ have_signal_handler: bool, | ... | @@ -34,6 +35,21 @@ have_signal_handler: bool, |
| 34 | old_sig_io: if (have_sig_io) posix.Sigaction else void, | 35 | old_sig_io: if (have_sig_io) posix.Sigaction else void, |
| 35 | old_sig_pipe: if (have_sig_pipe) posix.Sigaction else void, | 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 | threadlocal var current_closure: ?*Closure = null; | 53 | threadlocal var current_closure: ?*Closure = null; |
| 38 | | 54 | |
| 39 | const max_iovecs_len = 8; | 55 | const max_iovecs_len = 8; |
| ... | @@ -104,18 +120,21 @@ pub fn init( | ... | @@ -104,18 +120,21 @@ pub fn init( |
| 104 | /// here. | 120 | /// here. |
| 105 | gpa: Allocator, | 121 | gpa: Allocator, |
| 106 | ) Threaded { | 122 | ) Threaded { |
| | 123 | const cpu_count = std.Thread.getCpuCount(); |
| | 124 | |
| 107 | var t: Threaded = .{ | 125 | var t: Threaded = .{ |
| 108 | .allocator = gpa, | 126 | .allocator = gpa, |
| 109 | .threads = .empty, | 127 | .threads = .empty, |
| 110 | .stack_size = std.Thread.SpawnConfig.default_stack_size, | 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 | .concurrent_count = 0, | 131 | .concurrent_count = 0, |
| 113 | .old_sig_io = undefined, | 132 | .old_sig_io = undefined, |
| 114 | .old_sig_pipe = undefined, | 133 | .old_sig_pipe = undefined, |
| 115 | .have_signal_handler = false, | 134 | .have_signal_handler = false, |
| 116 | }; | 135 | }; |
| 117 | | 136 | |
| 118 | if (t.cpu_count) |n| { | 137 | if (cpu_count) |n| { |
| 119 | t.threads.ensureTotalCapacityPrecise(gpa, n - 1) catch {}; | 138 | t.threads.ensureTotalCapacityPrecise(gpa, n - 1) catch {}; |
| 120 | } else |_| {} | 139 | } else |_| {} |
| 121 | | 140 | |
| ... | @@ -145,7 +164,8 @@ pub const init_single_threaded: Threaded = .{ | ... | @@ -145,7 +164,8 @@ pub const init_single_threaded: Threaded = .{ |
| 145 | .allocator = .failing, | 164 | .allocator = .failing, |
| 146 | .threads = .empty, | 165 | .threads = .empty, |
| 147 | .stack_size = std.Thread.SpawnConfig.default_stack_size, | 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 | .concurrent_count = 0, | 169 | .concurrent_count = 0, |
| 150 | .old_sig_io = undefined, | 170 | .old_sig_io = undefined, |
| 151 | .old_sig_pipe = undefined, | 171 | .old_sig_pipe = undefined, |
| ... | @@ -166,6 +186,18 @@ pub fn deinit(t: *Threaded) void { | ... | @@ -166,6 +186,18 @@ pub fn deinit(t: *Threaded) void { |
| 166 | t.* = undefined; | 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 | fn join(t: *Threaded) void { | 201 | fn join(t: *Threaded) void { |
| 170 | if (builtin.single_threaded) return; | 202 | if (builtin.single_threaded) return; |
| 171 | { | 203 | { |
| ... | @@ -497,7 +529,7 @@ fn async( | ... | @@ -497,7 +529,7 @@ fn async( |
| 497 | } | 529 | } |
| 498 | | 530 | |
| 499 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 531 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 500 | const cpu_count = t.cpu_count catch { | 532 | const cpu_count = t.getThreadCapacity() orelse { |
| 501 | return concurrent(userdata, result.len, result_alignment, context, context_alignment, start) catch { | 533 | return concurrent(userdata, result.len, result_alignment, context, context_alignment, start) catch { |
| 502 | start(context.ptr, result.ptr); | 534 | start(context.ptr, result.ptr); |
| 503 | return null; | 535 | return null; |
| ... | @@ -556,7 +588,7 @@ fn concurrent( | ... | @@ -556,7 +588,7 @@ fn concurrent( |
| 556 | if (builtin.single_threaded) return error.ConcurrencyUnavailable; | 588 | if (builtin.single_threaded) return error.ConcurrencyUnavailable; |
| 557 | | 589 | |
| 558 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 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 | const gpa = t.allocator; | 593 | const gpa = t.allocator; |
| 562 | const ac = AsyncClosure.init(gpa, .concurrent, result_len, result_alignment, context, context_alignment, start) catch { | 594 | const ac = AsyncClosure.init(gpa, .concurrent, result_len, result_alignment, context, context_alignment, start) catch { |
| ... | @@ -685,7 +717,7 @@ fn groupAsync( | ... | @@ -685,7 +717,7 @@ fn groupAsync( |
| 685 | if (builtin.single_threaded) return start(group, context.ptr); | 717 | if (builtin.single_threaded) return start(group, context.ptr); |
| 686 | | 718 | |
| 687 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 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 | const gpa = t.allocator; | 722 | const gpa = t.allocator; |
| 691 | const gc = GroupClosure.init(gpa, t, group, context, context_alignment, start) catch { | 723 | const gc = GroupClosure.init(gpa, t, group, context, context_alignment, start) catch { |