authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-09-27 11:42:31+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-09-29 10:32:09-07:00
log1ecbc16172649c5f11c2c5173a42f04a3c7e5d2b
treebefb3f8c6a8a7a038d791049d468c004f1b4ee2c
parentebb8683ef1298e5d45f8d9912cf161954cc7ca99
signature Commit is signed but in an unrecognized format.

link: delete a few unnecessary `tid` parameters


8 files changed, 98 insertions(+), 104 deletions(-)

src/Compilation.zig+1-1
......@@ -4427,7 +4427,7 @@ fn performAllTheWork(
44274427 comp.windows_libs_num_done = @intCast(comp.windows_libs.count());
44284428 try misc_group.await(io);
44294429
4430 comp.link_queue.wait(io);
4430 try comp.link_queue.wait(io);
44314431}
44324432
44334433fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node) void {
src/Zcu/PerThread.zig+9-8
......@@ -138,6 +138,15 @@ pub fn update(
138138 const gpa = comp.gpa;
139139 const io = comp.io;
140140
141 if (!zcu.backendSupportsFeature(.separate_thread)) {
142 // We may still be running the linker on a separate thread at the moment, but once prelink
143 // completes, we need that thread to exit so that we can process all ZCU link tasks on the
144 // main thread. We signal this condition by immediately closing the ZCU task queue. It's
145 // important that we do this before enqueueing *any* ZCU link tasks: otherwise those tasks
146 // will run on the linker thread which is meant to be for prelink only!
147 comp.link_queue.finishZcuQueue(comp);
148 }
149
141150 {
142151 const tracy_trace = traceNamed(@src(), "astgen");
143152 defer tracy_trace.end();
......@@ -269,14 +278,6 @@ pub fn update(
269278
270279 try zcu.flushRetryableFailures();
271280
272 if (!zcu.backendSupportsFeature(.separate_thread)) {
273 // Close the ZCU task queue. Prelink may still be running, but the closed
274 // queue will cause the linker task to exit once prelink finishes. The
275 // closed queue also communicates to `enqueueZcu` that it should wait for
276 // the linker task to finish and then run ZCU tasks serially.
277 comp.link_queue.finishZcuQueue(comp);
278 }
279
280281 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
281282 if (comp.bin_file != null) {
282283 zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0);
src/crash_report.zig+7-8
......@@ -86,21 +86,20 @@ pub const CodegenFunc = if (enabled) struct {
8686
8787pub const LinkerOp = if (enabled) struct {
8888 lf: *link.File,
89 tid: Zcu.PerThread.Id,
9089 threadlocal var current: ?LinkerOp = null;
91 pub fn start(lf: *link.File, tid: Zcu.PerThread.Id) void {
90 pub fn start(lf: *link.File) void {
9291 std.debug.assert(current == null);
93 current = .{ .lf = lf, .tid = tid };
92 current = .{ .lf = lf };
9493 }
95 pub fn stop(lf: *link.File, tid: Zcu.PerThread.Id) void {
96 std.debug.assert(current.?.lf == lf and current.?.tid == tid);
94 pub fn stop(lf: *link.File) void {
95 std.debug.assert(current.?.lf == lf);
9796 current = null;
9897 }
9998} else struct {
10099 const current: ?noreturn = null;
101100 // Dummy implementation
102 pub fn start(_: *link.File, _: Zcu.PerThread.Id) void {}
103 pub fn stop(_: *link.File, _: Zcu.PerThread.Id) void {}
101 pub fn start(_: *link.File) void {}
102 pub fn stop(_: *link.File) void {}
104103};
105104
106105fn dumpCrashContext() Io.Writer.Error!void {
......@@ -132,7 +131,7 @@ fn dumpCrashContext() Io.Writer.Error!void {
132131 try dumpCrashContextSema(anal, w, &S.crash_heap);
133132 } else if (LinkerOp.current) |linker_op| {
134133 try w.writeAll("Linker snapshot:\n");
135 switch (try linker_op.lf.dump(w, linker_op.tid)) {
134 switch (try linker_op.lf.dump(w)) {
136135 .unimplemented => try w.writeAll("(backend does not support link snapshots)"),
137136 .needs_extensions => try w.writeAll("(build with -Ddebug-extensions to dump linker state)"),
138137 .disabled => try w.writeAll("(run with --debug-link-snapshot to dump linker state)"),
src/link.zig+10-10
......@@ -950,12 +950,12 @@ pub const File = struct {
950950 }
951951 }
952952
953 pub fn idle(base: *File, tid: Zcu.PerThread.Id) Error!bool {
953 fn idle(base: *File) Error!bool {
954954 switch (base.tag) {
955955 else => return false,
956956 inline .elf2, .coff, .macho2 => |tag| {
957957 dev.check(tag.devFeature());
958 return @as(*tag.Type(), @fieldParentPtr("base", base)).idle(tid);
958 return @as(*tag.Type(), @fieldParentPtr("base", base)).idle();
959959 },
960960 }
961961 }
......@@ -974,8 +974,8 @@ pub const File = struct {
974974 /// Commit pending changes and write headers. Takes into account final output mode.
975975 /// `arena` has the lifetime of the call to `Compilation.update`.
976976 pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) Error!void {
977 crash_report.LinkerOp.start(base, tid);
978 defer crash_report.LinkerOp.stop(base, tid);
977 crash_report.LinkerOp.start(base);
978 defer crash_report.LinkerOp.stop(base);
979979
980980 const comp = base.comp;
981981 const io = comp.io;
......@@ -1026,8 +1026,8 @@ pub const File = struct {
10261026 ) Error!void {
10271027 assert(pt.zcu.llvm_object == null);
10281028
1029 crash_report.LinkerOp.start(base, pt.tid);
1030 defer crash_report.LinkerOp.stop(base, pt.tid);
1029 crash_report.LinkerOp.start(base);
1030 defer crash_report.LinkerOp.stop(base);
10311031
10321032 switch (base.tag) {
10331033 .lld => unreachable,
......@@ -1115,7 +1115,7 @@ pub const File = struct {
11151115 enabled,
11161116 };
11171117
1118 pub fn dump(base: *File, w: *Io.Writer, tid: Zcu.PerThread.Id) !DumpResult {
1118 pub fn dump(base: *File, w: *Io.Writer) !DumpResult {
11191119 if (!build_options.enable_debug_extensions) return .not_built;
11201120 switch (base.tag) {
11211121 .elf,
......@@ -1129,7 +1129,7 @@ pub const File = struct {
11291129 => return .unimplemented,
11301130 inline else => |tag| {
11311131 dev.check(tag.devFeature());
1132 return @as(*tag.Type(), @fieldParentPtr("base", base)).dump(w, tid);
1132 return @as(*tag.Type(), @fieldParentPtr("base", base)).dump(w);
11331133 },
11341134 }
11351135 }
......@@ -1910,8 +1910,8 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
19101910 }
19111911 }
19121912}
1913pub fn doIdleTask(comp: *Compilation, tid: Zcu.PerThread.Id) Error!bool {
1914 return if (comp.bin_file) |lf| lf.idle(tid) else false;
1913pub fn doIdleTask(comp: *Compilation) Error!bool {
1914 return if (comp.bin_file) |lf| lf.idle() else false;
19151915}
19161916/// After the main pipeline is done, but before flush, the compilation may need to link one final
19171917/// `Nav` into the binary: the `builtin.test_functions` value. Since the link thread isn't running
src/link/Coff.zig+12-13
......@@ -5916,13 +5916,14 @@ pub fn flush(
59165916 prog_node: std.Progress.Node,
59175917) link.Error!void {
59185918 _ = arena;
5919 _ = tid;
59195920 const sub_prog_node = prog_node.start("COFF Flush", 0);
59205921 defer sub_prog_node.end();
59215922
59225923 const comp = coff.base.comp;
59235924
59245925 while (try coff.resolve()) {}
5925 while (try coff.idle(tid)) {}
5926 while (try coff.idle()) {}
59265927
59275928 // This has to occur after all other flushMoved / flushResized have resolved,
59285929 // but it will also generate one more set of resizes and moves.
......@@ -5942,7 +5943,7 @@ pub fn flush(
59425943 ),
59435944 };
59445945 }
5945 while (try coff.idle(tid)) {}
5946 while (try coff.idle()) {}
59465947
59475948 if (coff.isImage())
59485949 try coff.reportUndefs();
......@@ -5957,7 +5958,7 @@ pub fn flush(
59575958 };
59585959
59595960 if (coff.options.enable_link_snapshots)
5960 coff.dumpStderr(tid) catch |err|
5961 coff.dumpStderr() catch |err|
59615962 return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err});
59625963}
59635964
......@@ -6069,8 +6070,7 @@ fn resolve(coff: *Coff) !bool {
60696070 return false;
60706071}
60716072
6072pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
6073 _ = tid;
6073pub fn idle(coff: *Coff) !bool {
60746074 // Idle tasks should not modify create / modify nodes, otherwise the output is not reproducible.
60756075 coff.mf.nodes_lock.lock();
60766076 defer coff.mf.nodes_lock.unlock();
......@@ -7457,7 +7457,7 @@ fn updateExportInner(
74577457
74587458 try coff.genPending(pt);
74597459 while (try coff.resolve()) {}
7460 while (try coff.idle(pt.tid)) {}
7460 while (try coff.idle()) {}
74617461
74627462 const machine = coff.targetLoad(&coff.headerPtr().machine);
74637463 const exported_ni = exported_si.node(coff);
......@@ -7595,21 +7595,21 @@ fn updateExportInner(
75957595 }
75967596}
75977597
7598fn dumpStderr(coff: *Coff, tid: Zcu.PerThread.Id) Io.File.Writer.Error!void {
7598fn dumpStderr(coff: *Coff) Io.File.Writer.Error!void {
75997599 const comp = coff.base.comp;
76007600 const io = comp.io;
76017601 var buffer: [512]u8 = undefined;
76027602 const stderr = try io.lockStderr(&buffer, null);
76037603 defer io.unlockStderr();
76047604 const w = &stderr.file_writer.interface;
7605 _ = coff.dump(w, tid) catch |err| switch (err) {
7605 _ = coff.dump(w) catch |err| switch (err) {
76067606 error.WriteFailed => return stderr.file_writer.err.?,
76077607 };
76087608}
76097609
7610pub fn dump(coff: *Coff, w: *Io.Writer, tid: Zcu.PerThread.Id) Io.Writer.Error!link.File.DumpResult {
7610pub fn dump(coff: *Coff, w: *Io.Writer) Io.Writer.Error!link.File.DumpResult {
76117611 if (coff.options.enable_link_snapshots) {
7612 try coff.printNode(tid, w, .root, 0);
7612 try coff.printNode(w, .root, 0);
76137613 try w.writeAll("Section table:\n");
76147614 for (coff.section_table.keys(), coff.section_table.values()) |name, sec|
76157615 try coff.printSection(w, name, sec.si);
......@@ -7762,9 +7762,8 @@ fn printNodeName(
77627762 }
77637763}
77647764
7765pub fn printNode(
7765fn printNode(
77667766 coff: *Coff,
7767 tid: Zcu.PerThread.Id,
77687767 w: *Io.Writer,
77697768 ni: MappedFile.Node.Index,
77707769 indent: usize,
......@@ -7792,7 +7791,7 @@ pub fn printNode(
77927791 // non-leaf, just print children
77937792 var child_ni = first_ni;
77947793 while (true) {
7795 try coff.printNode(tid, w, child_ni, indent + 1);
7794 try coff.printNode(w, child_ni, indent + 1);
77967795 child_ni = child_ni.next(&coff.mf).unwrap() orelse break;
77977796 }
77987797 return;
src/link/Elf2.zig+17-23
......@@ -9726,8 +9726,9 @@ pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
97269726 };
97279727}
97289728fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void {
9729 const zcu = pt.zcu;
9730 const gpa = zcu.gpa;
9729 const comp = elf.base.comp;
9730 const gpa = comp.gpa;
9731 const zcu = comp.zcu.?;
97319732 const ip = &zcu.intern_pool;
97329733
97339734 const nav = ip.getNav(nav_index);
......@@ -9823,7 +9824,7 @@ pub fn updateContainerType(
98239824 ),
98249825 };
98259826}
9826pub fn updateContainerTypeInner(
9827fn updateContainerTypeInner(
98279828 elf: *Elf,
98289829 pt: Zcu.PerThread,
98299830 ty: InternPool.Index,
......@@ -10227,7 +10228,8 @@ pub fn flush(
1022710228 tid: Zcu.PerThread.Id,
1022810229 prog_node: std.Progress.Node,
1022910230) link.Error!void {
10230 elf.flushInner(arena, tid, prog_node) catch |err| switch (err) {
10231 _ = tid;
10232 elf.flushInner(arena, prog_node) catch |err| switch (err) {
1023110233 else => |e| return e,
1023210234 error.MappedFileIo => return elf.base.comp.link_diags.fail(
1023310235 "failed to write output file: {t}",
......@@ -10238,7 +10240,6 @@ pub fn flush(
1023810240fn flushInner(
1023910241 elf: *Elf,
1024010242 arena: std.mem.Allocator,
10241 tid: Zcu.PerThread.Id,
1024210243 prog_node: std.Progress.Node,
1024310244) Error!void {
1024410245 const comp = elf.base.comp;
......@@ -10266,7 +10267,7 @@ fn flushInner(
1026610267
1026710268 try elf.prepareDynamic();
1026810269
10269 while (try elf.idle(tid)) {}
10270 while (try elf.idle()) {}
1027010271
1027110272 assert(elf.input_pending_index == elf.inputs.items.len);
1027210273 assert(elf.input_section_pending_index == elf.input_sections.items.len);
......@@ -10323,13 +10324,11 @@ fn flushInner(
1032310324 try elf.mf.flush();
1032410325
1032510326 if (elf.options.enable_link_snapshots)
10326 elf.dumpStderr(tid) catch |err|
10327 elf.dumpStderr() catch |err|
1032710328 return diags.fail("dumping link snapshot failed: {t}", .{err});
1032810329}
1032910330
10330pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool {
10331 _ = tid;
10332
10331pub fn idle(elf: *Elf) link.Error!bool {
1033310332 // This function is called non-deterministically, and so must not affect the layout of any nodes.
1033410333 elf.mf.nodes_lock.lock();
1033510334 defer elf.mf.nodes_lock.unlock();
......@@ -12126,19 +12125,15 @@ pub fn updateExports(
1212612125 export_indices: []const Zcu.Export.Index,
1212712126) link.Error!void {
1212812127 for (export_indices) |export_index| {
12129 elf.updateExportInner(pt, export_index) catch |err| switch (err) {
12128 elf.updateExportInner(export_index) catch |err| switch (err) {
1213012129 else => |e| return e,
1213112130 error.MappedFileIo => return elf.base.comp.link_diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}),
1213212131 };
1213312132 }
1213412133 try elf.genPending(pt);
1213512134}
12136fn updateExportInner(
12137 elf: *Elf,
12138 pt: Zcu.PerThread,
12139 export_index: Zcu.Export.Index,
12140) Error!void {
12141 const zcu = pt.zcu;
12135fn updateExportInner(elf: *Elf, export_index: Zcu.Export.Index) Error!void {
12136 const zcu = elf.base.comp.zcu.?;
1214212137 const ip = &zcu.intern_pool;
1214312138
1214412139 const @"export" = export_index.ptr(zcu);
......@@ -12213,21 +12208,21 @@ fn updateExportInner(
1221312208 };
1221412209}
1221512210
12216fn dumpStderr(elf: *Elf, tid: Zcu.PerThread.Id) Io.File.Writer.Error!void {
12211fn dumpStderr(elf: *Elf) Io.File.Writer.Error!void {
1221712212 const comp = elf.base.comp;
1221812213 const io = comp.io;
1221912214 var buffer: [512]u8 = undefined;
1222012215 const stderr = try io.lockStderr(&buffer, null);
1222112216 defer io.unlockStderr();
1222212217 const w = &stderr.file_writer.interface;
12223 _ = elf.dump(w, tid) catch |err| switch (err) {
12218 _ = elf.dump(w) catch |err| switch (err) {
1222412219 error.WriteFailed => return stderr.file_writer.err.?,
1222512220 };
1222612221}
1222712222
12228pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) Io.Writer.Error!link.File.DumpResult {
12223pub fn dump(elf: *Elf, w: *Io.Writer) Io.Writer.Error!link.File.DumpResult {
1222912224 if (elf.options.enable_link_snapshots) {
12230 try elf.printNode(tid, w, .root, 0);
12225 try elf.printNode(w, .root, 0);
1223112226 return .enabled;
1223212227 }
1223312228 return .disabled;
......@@ -12235,7 +12230,6 @@ pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) Io.Writer.Error!lin
1223512230
1223612231pub fn printNode(
1223712232 elf: *Elf,
12238 tid: Zcu.PerThread.Id,
1223912233 w: *Io.Writer,
1224012234 ni: MappedFile.Node.Index,
1224112235 indent: usize,
......@@ -12366,7 +12360,7 @@ pub fn printNode(
1236612360 // non-leaf, just print children
1236712361 var child_ni = first_ni;
1236812362 while (true) {
12369 try elf.printNode(tid, w, child_ni, indent + 1);
12363 try elf.printNode(w, child_ni, indent + 1);
1237012364 child_ni = child_ni.next(&elf.mf).unwrap() orelse break;
1237112365 }
1237212366 return;
src/link/MachO2.zig+9-11
......@@ -1100,10 +1100,11 @@ pub fn flush(
11001100) link.Error!void {
11011101 const diags = &macho.base.comp.link_diags;
11021102 _ = arena;
1103 _ = tid;
11031104 _ = prog_node;
11041105
11051106 try macho.updateSegmentLoadAddresses();
1106 while (try macho.idle(tid)) {}
1107 while (try macho.idle()) {}
11071108
11081109 if (macho.lc.entry_point) |entry_point_lc| {
11091110 // TODO: actually find the entry point.
......@@ -1120,7 +1121,7 @@ pub fn flush(
11201121 };
11211122
11221123 if (macho.options.enable_link_snapshots)
1123 macho.dumpStderr(tid) catch |err|
1124 macho.dumpStderr() catch |err|
11241125 return diags.fail("dumping link snapshot failed: {t}", .{err});
11251126}
11261127pub fn updateErrorData(macho: *MachO, pt: Zcu.PerThread) link.Error!void {
......@@ -1128,9 +1129,7 @@ pub fn updateErrorData(macho: *MachO, pt: Zcu.PerThread) link.Error!void {
11281129 _ = pt;
11291130 @panic("TODO");
11301131}
1131pub fn idle(macho: *MachO, tid: Zcu.PerThread.Id) link.Error!bool {
1132 _ = tid;
1133
1132pub fn idle(macho: *MachO) link.Error!bool {
11341133 macho.mf.nodes_lock.lock();
11351134 defer macho.mf.nodes_lock.unlock();
11361135
......@@ -1253,28 +1252,27 @@ pub fn updateExports(
12531252 @panic("TODO");
12541253}
12551254
1256fn dumpStderr(macho: *MachO, tid: Zcu.PerThread.Id) Io.File.Writer.Error!void {
1255fn dumpStderr(macho: *MachO) Io.File.Writer.Error!void {
12571256 const comp = macho.base.comp;
12581257 const io = comp.io;
12591258 var buffer: [512]u8 = undefined;
12601259 const stderr = try io.lockStderr(&buffer, null);
12611260 defer io.unlockStderr();
12621261 const w = &stderr.file_writer.interface;
1263 _ = macho.dump(w, tid) catch |err| switch (err) {
1262 _ = macho.dump(w) catch |err| switch (err) {
12641263 error.WriteFailed => return stderr.file_writer.err.?,
12651264 };
12661265}
12671266
1268pub fn dump(macho: *MachO, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult {
1267pub fn dump(macho: *MachO, w: *Io.Writer) !link.File.DumpResult {
12691268 if (macho.options.enable_link_snapshots) {
1270 try macho.printNode(tid, w, .root, 0);
1269 try macho.printNode(w, .root, 0);
12711270 return .enabled;
12721271 }
12731272 return .disabled;
12741273}
12751274fn printNode(
12761275 macho: *const MachO,
1277 tid: Zcu.PerThread.Id,
12781276 w: *Io.Writer,
12791277 ni: MappedFile.Node.Index,
12801278 indent: usize,
......@@ -1310,7 +1308,7 @@ fn printNode(
13101308 // non-leaf, just print children
13111309 var child_ni = first_ni;
13121310 while (true) {
1313 try macho.printNode(tid, w, child_ni, indent + 1);
1311 try macho.printNode(w, child_ni, indent + 1);
13141312 child_ni = child_ni.next(&macho.mf).unwrap() orelse break;
13151313 }
13161314 return;
src/link/Queue.zig+33-30
......@@ -17,7 +17,7 @@
1717/// set to `null` by the main thread after it is canceled. It is not otherwise modified; as such, it
1818/// may be checked non-atomically. If a task is being queued and this is `null`, tasks must be run
1919/// eagerly.
20future: ?std.Io.Future(void),
20future: ?std.Io.Future(Io.Cancelable!void),
2121
2222/// This is only used if `future == null` during prelink. In that case, it is used to ensure that
2323/// only one prelink task is run at a time.
......@@ -42,15 +42,15 @@ pub const empty: Queue = .{
4242
4343pub fn cancel(q: *Queue, io: Io) void {
4444 if (q.future) |*f| {
45 f.cancel(io);
46 q.future = null;
45 defer q.future = null;
46 f.cancel(io) catch {};
4747 }
4848}
4949
50pub fn wait(q: *Queue, io: Io) void {
50pub fn wait(q: *Queue, io: Io) Io.Cancelable!void {
5151 if (q.future) |*f| {
52 f.await(io);
53 q.future = null;
52 defer q.future = null;
53 try f.await(io);
5454 }
5555}
5656
......@@ -107,11 +107,13 @@ pub fn enqueueZcu(
107107 } else |err| switch (err) {
108108 error.Canceled => |e| return e,
109109 error.Closed => {
110 // The linker is still processing prelink tasks. Wait for those
111 // to finish, after which the linker task will exist, and ZCU
112 // tasks will be run non-concurrently. This logic exists for
113 // backends which do not support `Zcu.Feature.separate_thread`.
114 q.wait(io);
110 // This path is hit if the backend does not support `Zcu.Feature.separate_thread`.
111 // In that case, the linker processes *prelink* tasks on a thread, but once prelink
112 // completes we want to move processing to the main thread for all ZCU tasks. To
113 // achieve this, `Compilation.update` immmediately closes the ZCU task queue at the
114 // start of the update, causing `runLinkTasks` to exit as soon as prelink completes.
115 // So here we just need to wait for that, then fall back to the single-threaded path.
116 try q.wait(io);
115117 },
116118 }
117119 }
......@@ -148,7 +150,7 @@ pub fn finishZcuQueue(q: *Queue, comp: *Compilation) void {
148150 }
149151}
150152
151fn runLinkTasks(q: *Queue, comp: *Compilation) void {
153fn runLinkTasks(q: *Queue, comp: *Compilation) Io.Cancelable!void {
152154 const io = comp.io;
153155 const tid: Zcu.PerThread.Id = .acquire(io);
154156 defer tid.release(io);
......@@ -159,12 +161,19 @@ fn runLinkTasks(q: *Queue, comp: *Compilation) void {
159161 var task_buf: [128]PrelinkTask = undefined;
160162 const limit: usize = if (have_idle_tasks) 0 else 1;
161163 const n = q.prelink_queue.get(io, &task_buf, limit) catch |err| switch (err) {
162 error.Canceled => return,
164 error.Canceled => |e| return e,
163165 error.Closed => break :prelink_tasks,
164166 };
165167 if (n == 0) {
166168 assert(have_idle_tasks);
167 have_idle_tasks = runIdleTask(comp, tid);
169 have_idle_tasks = link.doIdleTask(comp) catch |err| switch (err) {
170 error.Canceled => |e| return e,
171 error.AlreadyReported => false,
172 error.OutOfMemory => more_idle_tasks: {
173 comp.link_diags.setAllocFailure();
174 break :more_idle_tasks false;
175 },
176 };
168177 } else for (task_buf[0..n]) |task| {
169178 link.doPrelinkTask(comp, task);
170179 have_idle_tasks = true;
......@@ -181,8 +190,8 @@ fn runLinkTasks(q: *Queue, comp: *Compilation) void {
181190 break :prelink;
182191 }
183192 lf.prelink() catch |err| switch (err) {
193 error.Canceled => |e| return e,
184194 error.OutOfMemory => comp.link_diags.setAllocFailure(),
185 error.Canceled => @panic("TODO"),
186195 error.AlreadyReported => {},
187196 };
188197 }
......@@ -191,31 +200,25 @@ fn runLinkTasks(q: *Queue, comp: *Compilation) void {
191200 var task_buf: [128]ZcuTask = undefined;
192201 const limit: usize = if (have_idle_tasks) 0 else 1;
193202 const n = q.zcu_queue.get(io, &task_buf, limit) catch |err| switch (err) {
194 error.Canceled => return,
203 error.Canceled => |e| return e,
195204 error.Closed => break :zcu_tasks,
196205 };
197206 if (n == 0) {
198207 assert(have_idle_tasks);
199 have_idle_tasks = runIdleTask(comp, tid);
208 have_idle_tasks = link.doIdleTask(comp) catch |err| switch (err) {
209 error.Canceled => |e| return e,
210 error.AlreadyReported => false,
211 error.OutOfMemory => more_idle_tasks: {
212 comp.link_diags.setAllocFailure();
213 break :more_idle_tasks false;
214 },
215 };
200216 } else for (task_buf[0..n]) |task| {
201217 link.doZcuTask(comp, tid, task);
202218 have_idle_tasks = true;
203219 }
204220 }
205221}
206fn runIdleTask(comp: *Compilation, tid: Zcu.PerThread.Id) bool {
207 return link.doIdleTask(comp, tid) catch |err| switch (err) {
208 error.OutOfMemory => have_more: {
209 comp.link_diags.setAllocFailure();
210 break :have_more false;
211 },
212 error.AlreadyReported => false,
213 error.Canceled => {
214 comp.io.recancel();
215 return false;
216 },
217 };
218}
219222
220223const std = @import("std");
221224const assert = std.debug.assert;