From 504ad56815c3deb38319ac7989dd6c50c559b780 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 23 Oct 2024 14:46:46 -0700 Subject: [PATCH] link.flushTaskQueue: move safety lock The safety lock needs to happen after check() --- src/ThreadSafeQueue.zig | 9 +++++---- src/link.zig | 22 ++++++++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/ThreadSafeQueue.zig b/src/ThreadSafeQueue.zig index 1cf6aaaa3a4c384471b2df43ee8f30fe54248fe3..74bbdc418f4326fb8e7992c9b1f39846f5715ba6 100644 --- a/src/ThreadSafeQueue.zig +++ b/src/ThreadSafeQueue.zig @@ -52,12 +52,13 @@ pub fn ThreadSafeQueue(comptime T: type) type { self.mutex.lock(); defer self.mutex.unlock(); try self.shared.appendSlice(gpa, items); - const was_waiting = switch (self.state) { + return switch (self.state) { .run => false, - .wait => true, + .wait => { + self.state = .run; + return true; + }, }; - self.state = .run; - return was_waiting; } /// Safe only to call exactly once when initially starting the worker. diff --git a/src/link.zig b/src/link.zig index 6f1814140469bd2262bcc560b19d2d9a5da80456..cd777b86c40249193d2a800b31af3f4daed67f8f 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1365,11 +1365,11 @@ pub const File = struct { /// from the rest of compilation. All tasks performed here are /// single-threaded with respect to one another. pub fn flushTaskQueue(tid: usize, comp: *Compilation) void { - comp.link_task_queue_safety.lock(); - defer comp.link_task_queue_safety.unlock(); - const prog_node = comp.work_queue_progress_node.start("Parse Linker Inputs", 0); - defer prog_node.end(); + // As soon as check() is called, another `flushTaskQueue` call could occur, + // so the safety lock must go after the check. while (comp.link_task_queue.check()) |tasks| { + comp.link_task_queue_safety.lock(); + defer comp.link_task_queue_safety.unlock(); for (tasks) |task| doTask(comp, tid, task); } } @@ -1412,6 +1412,8 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void { const diags = &comp.link_diags; switch (task) { .load_explicitly_provided => if (comp.bin_file) |base| { + const prog_node = comp.work_queue_progress_node.start("Parse Linker Inputs", comp.link_inputs.len); + defer prog_node.end(); for (comp.link_inputs) |input| { base.loadInput(input) catch |err| switch (err) { error.LinkFailure => return, // error reported via diags @@ -1423,9 +1425,13 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void { .dso_exact => diags.addError("failed to handle dso_exact: {s}", .{@errorName(e)}), }, }; + prog_node.completeOne(); } }, .load_host_libc => if (comp.bin_file) |base| { + const prog_node = comp.work_queue_progress_node.start("Linker Parse Host libc", 0); + defer prog_node.end(); + const target = comp.root_mod.resolved_target.result; const flags = target_util.libcFullLinkFlags(target); const crt_dir = comp.libc_installation.?.crt_dir.?; @@ -1482,18 +1488,24 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void { } }, .load_object => |path| if (comp.bin_file) |base| { + const prog_node = comp.work_queue_progress_node.start("Linker Parse Object", 0); + defer prog_node.end(); base.openLoadObject(path) catch |err| switch (err) { error.LinkFailure => return, // error reported via diags else => |e| diags.addParseError(path, "failed to parse object: {s}", .{@errorName(e)}), }; }, .load_archive => |path| if (comp.bin_file) |base| { + const prog_node = comp.work_queue_progress_node.start("Linker Parse Archive", 0); + defer prog_node.end(); base.openLoadArchive(path, null) catch |err| switch (err) { error.LinkFailure => return, // error reported via link_diags else => |e| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}), }; }, .load_dso => |path| if (comp.bin_file) |base| { + const prog_node = comp.work_queue_progress_node.start("Linker Parse Shared Library", 0); + defer prog_node.end(); base.openLoadDso(path, .{ .preferred_mode = .dynamic, .search_strategy = .paths_first, @@ -1503,6 +1515,8 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void { }; }, .load_input => |input| if (comp.bin_file) |base| { + const prog_node = comp.work_queue_progress_node.start("Linker Parse Input", 0); + defer prog_node.end(); base.loadInput(input) catch |err| switch (err) { error.LinkFailure => return, // error reported via link_diags else => |e| { -- 2.54.0