mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
link: prevent deadlock when prelink tasks fail
If an error occured which prevented a prelink task from being queued, then `pending_prelink_tasks` would never be decremented, which could cause deadlocks in some cases. So, instead of calculating ahead of time the number of prelink tasks to expect, we use a simpler strategy which is much like a wait group: we add 1 to a value when we spawn a worker, and in the worker function, `defer` decrementing the value. The initial value is 1, and there's a decrement after all of the workers are spawned, so once it hits 0, prelink is done (be it with a failure or a success).
This commit is contained in:
parent
3de8bbd3d4
commit
e17a050bc6
5 changed files with 90 additions and 69 deletions
|
|
@ -2384,7 +2384,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||||
};
|
};
|
||||||
comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
|
comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
|
||||||
}
|
}
|
||||||
comp.link_task_queue.pending_prelink_tasks += @intCast(comp.c_object_table.count());
|
|
||||||
|
|
||||||
// Add a `Win32Resource` for each `rc_source_files` and one for `manifest_file`.
|
// Add a `Win32Resource` for each `rc_source_files` and one for `manifest_file`.
|
||||||
const win32_resource_count =
|
const win32_resource_count =
|
||||||
|
|
@ -2392,10 +2391,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||||
if (win32_resource_count > 0) {
|
if (win32_resource_count > 0) {
|
||||||
dev.check(.win32_resource);
|
dev.check(.win32_resource);
|
||||||
try comp.win32_resource_table.ensureTotalCapacity(gpa, win32_resource_count);
|
try comp.win32_resource_table.ensureTotalCapacity(gpa, win32_resource_count);
|
||||||
// Add this after adding logic to updateWin32Resource to pass the
|
|
||||||
// result into link.loadInput. loadInput integration is not implemented
|
|
||||||
// for Windows linking logic yet.
|
|
||||||
//comp.link_task_queue.pending_prelink_tasks += @intCast(win32_resource_count);
|
|
||||||
for (options.rc_source_files) |rc_source_file| {
|
for (options.rc_source_files) |rc_source_file| {
|
||||||
const win32_resource = try gpa.create(Win32Resource);
|
const win32_resource = try gpa.create(Win32Resource);
|
||||||
errdefer gpa.destroy(win32_resource);
|
errdefer gpa.destroy(win32_resource);
|
||||||
|
|
@ -2454,58 +2449,47 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||||
|
|
||||||
if (musl.needsCrt0(comp.config.output_mode, comp.config.link_mode, comp.config.pie)) |f| {
|
if (musl.needsCrt0(comp.config.output_mode, comp.config.link_mode, comp.config.pie)) |f| {
|
||||||
comp.queued_jobs.musl_crt_file[@intFromEnum(f)] = true;
|
comp.queued_jobs.musl_crt_file[@intFromEnum(f)] = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
switch (comp.config.link_mode) {
|
switch (comp.config.link_mode) {
|
||||||
.static => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_a)] = true,
|
.static => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_a)] = true,
|
||||||
.dynamic => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_so)] = true,
|
.dynamic => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_so)] = true,
|
||||||
}
|
}
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
} else if (target.isGnuLibC()) {
|
} else if (target.isGnuLibC()) {
|
||||||
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
||||||
|
|
||||||
if (glibc.needsCrt0(comp.config.output_mode)) |f| {
|
if (glibc.needsCrt0(comp.config.output_mode)) |f| {
|
||||||
comp.queued_jobs.glibc_crt_file[@intFromEnum(f)] = true;
|
comp.queued_jobs.glibc_crt_file[@intFromEnum(f)] = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
comp.queued_jobs.glibc_shared_objects = true;
|
comp.queued_jobs.glibc_shared_objects = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += glibc.sharedObjectsCount(target);
|
|
||||||
|
|
||||||
comp.queued_jobs.glibc_crt_file[@intFromEnum(glibc.CrtFile.libc_nonshared_a)] = true;
|
comp.queued_jobs.glibc_crt_file[@intFromEnum(glibc.CrtFile.libc_nonshared_a)] = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
} else if (target.isFreeBSDLibC()) {
|
} else if (target.isFreeBSDLibC()) {
|
||||||
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
||||||
|
|
||||||
if (freebsd.needsCrt0(comp.config.output_mode)) |f| {
|
if (freebsd.needsCrt0(comp.config.output_mode)) |f| {
|
||||||
comp.queued_jobs.freebsd_crt_file[@intFromEnum(f)] = true;
|
comp.queued_jobs.freebsd_crt_file[@intFromEnum(f)] = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
comp.queued_jobs.freebsd_shared_objects = true;
|
comp.queued_jobs.freebsd_shared_objects = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += freebsd.sharedObjectsCount();
|
|
||||||
} else if (target.isNetBSDLibC()) {
|
} else if (target.isNetBSDLibC()) {
|
||||||
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
||||||
|
|
||||||
if (netbsd.needsCrt0(comp.config.output_mode)) |f| {
|
if (netbsd.needsCrt0(comp.config.output_mode)) |f| {
|
||||||
comp.queued_jobs.netbsd_crt_file[@intFromEnum(f)] = true;
|
comp.queued_jobs.netbsd_crt_file[@intFromEnum(f)] = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
comp.queued_jobs.netbsd_shared_objects = true;
|
comp.queued_jobs.netbsd_shared_objects = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += netbsd.sharedObjectsCount();
|
|
||||||
} else if (target.isWasiLibC()) {
|
} else if (target.isWasiLibC()) {
|
||||||
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
||||||
|
|
||||||
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.execModelCrtFile(comp.config.wasi_exec_model))] = true;
|
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.execModelCrtFile(comp.config.wasi_exec_model))] = true;
|
||||||
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.CrtFile.libc_a)] = true;
|
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.CrtFile.libc_a)] = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 2;
|
|
||||||
} else if (target.isMinGW()) {
|
} else if (target.isMinGW()) {
|
||||||
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
|
||||||
|
|
||||||
const main_crt_file: mingw.CrtFile = if (is_dyn_lib) .dllcrt2_o else .crt2_o;
|
const main_crt_file: mingw.CrtFile = if (is_dyn_lib) .dllcrt2_o else .crt2_o;
|
||||||
comp.queued_jobs.mingw_crt_file[@intFromEnum(main_crt_file)] = true;
|
comp.queued_jobs.mingw_crt_file[@intFromEnum(main_crt_file)] = true;
|
||||||
comp.queued_jobs.mingw_crt_file[@intFromEnum(mingw.CrtFile.libmingw32_lib)] = true;
|
comp.queued_jobs.mingw_crt_file[@intFromEnum(mingw.CrtFile.libmingw32_lib)] = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 2;
|
|
||||||
|
|
||||||
// When linking mingw-w64 there are some import libs we always need.
|
// When linking mingw-w64 there are some import libs we always need.
|
||||||
try comp.windows_libs.ensureUnusedCapacity(gpa, mingw.always_link_libs.len);
|
try comp.windows_libs.ensureUnusedCapacity(gpa, mingw.always_link_libs.len);
|
||||||
|
|
@ -2519,7 +2503,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||||
target.isMinGW())
|
target.isMinGW())
|
||||||
{
|
{
|
||||||
comp.queued_jobs.zigc_lib = true;
|
comp.queued_jobs.zigc_lib = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2536,50 +2519,41 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||||
}
|
}
|
||||||
if (comp.wantBuildLibUnwindFromSource()) {
|
if (comp.wantBuildLibUnwindFromSource()) {
|
||||||
comp.queued_jobs.libunwind = true;
|
comp.queued_jobs.libunwind = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) {
|
if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) {
|
||||||
comp.queued_jobs.libcxx = true;
|
comp.queued_jobs.libcxx = true;
|
||||||
comp.queued_jobs.libcxxabi = true;
|
comp.queued_jobs.libcxxabi = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 2;
|
|
||||||
}
|
}
|
||||||
if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.any_sanitize_thread) {
|
if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.any_sanitize_thread) {
|
||||||
comp.queued_jobs.libtsan = true;
|
comp.queued_jobs.libtsan = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_build_compiler_rt) {
|
if (can_build_compiler_rt) {
|
||||||
if (comp.compiler_rt_strat == .lib) {
|
if (comp.compiler_rt_strat == .lib) {
|
||||||
log.debug("queuing a job to build compiler_rt_lib", .{});
|
log.debug("queuing a job to build compiler_rt_lib", .{});
|
||||||
comp.queued_jobs.compiler_rt_lib = true;
|
comp.queued_jobs.compiler_rt_lib = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
} else if (comp.compiler_rt_strat == .obj) {
|
} else if (comp.compiler_rt_strat == .obj) {
|
||||||
log.debug("queuing a job to build compiler_rt_obj", .{});
|
log.debug("queuing a job to build compiler_rt_obj", .{});
|
||||||
// In this case we are making a static library, so we ask
|
// In this case we are making a static library, so we ask
|
||||||
// for a compiler-rt object to put in it.
|
// for a compiler-rt object to put in it.
|
||||||
comp.queued_jobs.compiler_rt_obj = true;
|
comp.queued_jobs.compiler_rt_obj = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
} else if (comp.compiler_rt_strat == .dyn_lib) {
|
} else if (comp.compiler_rt_strat == .dyn_lib) {
|
||||||
// hack for stage2_x86_64 + coff
|
// hack for stage2_x86_64 + coff
|
||||||
log.debug("queuing a job to build compiler_rt_dyn_lib", .{});
|
log.debug("queuing a job to build compiler_rt_dyn_lib", .{});
|
||||||
comp.queued_jobs.compiler_rt_dyn_lib = true;
|
comp.queued_jobs.compiler_rt_dyn_lib = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.ubsan_rt_strat == .lib) {
|
if (comp.ubsan_rt_strat == .lib) {
|
||||||
log.debug("queuing a job to build ubsan_rt_lib", .{});
|
log.debug("queuing a job to build ubsan_rt_lib", .{});
|
||||||
comp.queued_jobs.ubsan_rt_lib = true;
|
comp.queued_jobs.ubsan_rt_lib = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
} else if (comp.ubsan_rt_strat == .obj) {
|
} else if (comp.ubsan_rt_strat == .obj) {
|
||||||
log.debug("queuing a job to build ubsan_rt_obj", .{});
|
log.debug("queuing a job to build ubsan_rt_obj", .{});
|
||||||
comp.queued_jobs.ubsan_rt_obj = true;
|
comp.queued_jobs.ubsan_rt_obj = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_exe_or_dyn_lib and comp.config.any_fuzz) {
|
if (is_exe_or_dyn_lib and comp.config.any_fuzz) {
|
||||||
log.debug("queuing a job to build libfuzzer", .{});
|
log.debug("queuing a job to build libfuzzer", .{});
|
||||||
comp.queued_jobs.fuzzer_lib = true;
|
comp.queued_jobs.fuzzer_lib = true;
|
||||||
comp.link_task_queue.pending_prelink_tasks += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2587,8 +2561,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||||
try comp.link_task_queue.queued_prelink.append(gpa, .load_explicitly_provided);
|
try comp.link_task_queue.queued_prelink.append(gpa, .load_explicitly_provided);
|
||||||
}
|
}
|
||||||
log.debug("queued prelink tasks: {d}", .{comp.link_task_queue.queued_prelink.items.len});
|
log.debug("queued prelink tasks: {d}", .{comp.link_task_queue.queued_prelink.items.len});
|
||||||
log.debug("pending prelink tasks: {d}", .{comp.link_task_queue.pending_prelink_tasks});
|
|
||||||
|
|
||||||
return comp;
|
return comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4408,10 +4380,8 @@ fn performAllTheWork(
|
||||||
comp.link_task_wait_group.reset();
|
comp.link_task_wait_group.reset();
|
||||||
defer comp.link_task_wait_group.wait();
|
defer comp.link_task_wait_group.wait();
|
||||||
|
|
||||||
comp.link_prog_node.increaseEstimatedTotalItems(
|
// Already-queued prelink tasks
|
||||||
comp.link_task_queue.queued_prelink.items.len + // already queued prelink tasks
|
comp.link_prog_node.increaseEstimatedTotalItems(comp.link_task_queue.queued_prelink.items.len);
|
||||||
comp.link_task_queue.pending_prelink_tasks, // prelink tasks which will be queued
|
|
||||||
);
|
|
||||||
comp.link_task_queue.start(comp);
|
comp.link_task_queue.start(comp);
|
||||||
|
|
||||||
if (comp.emit_docs != null) {
|
if (comp.emit_docs != null) {
|
||||||
|
|
@ -4427,6 +4397,7 @@ fn performAllTheWork(
|
||||||
// compiler-rt due to LLD bugs as well, e.g.:
|
// compiler-rt due to LLD bugs as well, e.g.:
|
||||||
//
|
//
|
||||||
// https://github.com/llvm/llvm-project/issues/43698#issuecomment-2542660611
|
// https://github.com/llvm/llvm-project/issues/43698#issuecomment-2542660611
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildRt, .{
|
comp.link_task_wait_group.spawnManager(buildRt, .{
|
||||||
comp,
|
comp,
|
||||||
"compiler_rt.zig",
|
"compiler_rt.zig",
|
||||||
|
|
@ -4444,6 +4415,7 @@ fn performAllTheWork(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.compiler_rt_obj and comp.compiler_rt_obj == null) {
|
if (comp.queued_jobs.compiler_rt_obj and comp.compiler_rt_obj == null) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildRt, .{
|
comp.link_task_wait_group.spawnManager(buildRt, .{
|
||||||
comp,
|
comp,
|
||||||
"compiler_rt.zig",
|
"compiler_rt.zig",
|
||||||
|
|
@ -4462,6 +4434,7 @@ fn performAllTheWork(
|
||||||
|
|
||||||
// hack for stage2_x86_64 + coff
|
// hack for stage2_x86_64 + coff
|
||||||
if (comp.queued_jobs.compiler_rt_dyn_lib and comp.compiler_rt_dyn_lib == null) {
|
if (comp.queued_jobs.compiler_rt_dyn_lib and comp.compiler_rt_dyn_lib == null) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildRt, .{
|
comp.link_task_wait_group.spawnManager(buildRt, .{
|
||||||
comp,
|
comp,
|
||||||
"compiler_rt.zig",
|
"compiler_rt.zig",
|
||||||
|
|
@ -4479,6 +4452,7 @@ fn performAllTheWork(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) {
|
if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildRt, .{
|
comp.link_task_wait_group.spawnManager(buildRt, .{
|
||||||
comp,
|
comp,
|
||||||
"fuzzer.zig",
|
"fuzzer.zig",
|
||||||
|
|
@ -4493,6 +4467,7 @@ fn performAllTheWork(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.ubsan_rt_lib and comp.ubsan_rt_lib == null) {
|
if (comp.queued_jobs.ubsan_rt_lib and comp.ubsan_rt_lib == null) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildRt, .{
|
comp.link_task_wait_group.spawnManager(buildRt, .{
|
||||||
comp,
|
comp,
|
||||||
"ubsan_rt.zig",
|
"ubsan_rt.zig",
|
||||||
|
|
@ -4509,6 +4484,7 @@ fn performAllTheWork(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.ubsan_rt_obj and comp.ubsan_rt_obj == null) {
|
if (comp.queued_jobs.ubsan_rt_obj and comp.ubsan_rt_obj == null) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildRt, .{
|
comp.link_task_wait_group.spawnManager(buildRt, .{
|
||||||
comp,
|
comp,
|
||||||
"ubsan_rt.zig",
|
"ubsan_rt.zig",
|
||||||
|
|
@ -4525,40 +4501,49 @@ fn performAllTheWork(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.glibc_shared_objects) {
|
if (comp.queued_jobs.glibc_shared_objects) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildGlibcSharedObjects, .{ comp, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildGlibcSharedObjects, .{ comp, main_progress_node });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.freebsd_shared_objects) {
|
if (comp.queued_jobs.freebsd_shared_objects) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildFreeBSDSharedObjects, .{ comp, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildFreeBSDSharedObjects, .{ comp, main_progress_node });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.netbsd_shared_objects) {
|
if (comp.queued_jobs.netbsd_shared_objects) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildNetBSDSharedObjects, .{ comp, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildNetBSDSharedObjects, .{ comp, main_progress_node });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.libunwind) {
|
if (comp.queued_jobs.libunwind) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildLibUnwind, .{ comp, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildLibUnwind, .{ comp, main_progress_node });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.libcxx) {
|
if (comp.queued_jobs.libcxx) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildLibCxx, .{ comp, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildLibCxx, .{ comp, main_progress_node });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.libcxxabi) {
|
if (comp.queued_jobs.libcxxabi) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildLibCxxAbi, .{ comp, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildLibCxxAbi, .{ comp, main_progress_node });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.libtsan) {
|
if (comp.queued_jobs.libtsan) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildLibTsan, .{ comp, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildLibTsan, .{ comp, main_progress_node });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.queued_jobs.zigc_lib and comp.zigc_static_lib == null) {
|
if (comp.queued_jobs.zigc_lib and comp.zigc_static_lib == null) {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildLibZigC, .{ comp, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildLibZigC, .{ comp, main_progress_node });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (0..@typeInfo(musl.CrtFile).@"enum".fields.len) |i| {
|
for (0..@typeInfo(musl.CrtFile).@"enum".fields.len) |i| {
|
||||||
if (comp.queued_jobs.musl_crt_file[i]) {
|
if (comp.queued_jobs.musl_crt_file[i]) {
|
||||||
const tag: musl.CrtFile = @enumFromInt(i);
|
const tag: musl.CrtFile = @enumFromInt(i);
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildMuslCrtFile, .{ comp, tag, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildMuslCrtFile, .{ comp, tag, main_progress_node });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4566,6 +4551,7 @@ fn performAllTheWork(
|
||||||
for (0..@typeInfo(glibc.CrtFile).@"enum".fields.len) |i| {
|
for (0..@typeInfo(glibc.CrtFile).@"enum".fields.len) |i| {
|
||||||
if (comp.queued_jobs.glibc_crt_file[i]) {
|
if (comp.queued_jobs.glibc_crt_file[i]) {
|
||||||
const tag: glibc.CrtFile = @enumFromInt(i);
|
const tag: glibc.CrtFile = @enumFromInt(i);
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildGlibcCrtFile, .{ comp, tag, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildGlibcCrtFile, .{ comp, tag, main_progress_node });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4573,6 +4559,7 @@ fn performAllTheWork(
|
||||||
for (0..@typeInfo(freebsd.CrtFile).@"enum".fields.len) |i| {
|
for (0..@typeInfo(freebsd.CrtFile).@"enum".fields.len) |i| {
|
||||||
if (comp.queued_jobs.freebsd_crt_file[i]) {
|
if (comp.queued_jobs.freebsd_crt_file[i]) {
|
||||||
const tag: freebsd.CrtFile = @enumFromInt(i);
|
const tag: freebsd.CrtFile = @enumFromInt(i);
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildFreeBSDCrtFile, .{ comp, tag, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildFreeBSDCrtFile, .{ comp, tag, main_progress_node });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4580,6 +4567,7 @@ fn performAllTheWork(
|
||||||
for (0..@typeInfo(netbsd.CrtFile).@"enum".fields.len) |i| {
|
for (0..@typeInfo(netbsd.CrtFile).@"enum".fields.len) |i| {
|
||||||
if (comp.queued_jobs.netbsd_crt_file[i]) {
|
if (comp.queued_jobs.netbsd_crt_file[i]) {
|
||||||
const tag: netbsd.CrtFile = @enumFromInt(i);
|
const tag: netbsd.CrtFile = @enumFromInt(i);
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildNetBSDCrtFile, .{ comp, tag, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildNetBSDCrtFile, .{ comp, tag, main_progress_node });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4587,6 +4575,7 @@ fn performAllTheWork(
|
||||||
for (0..@typeInfo(wasi_libc.CrtFile).@"enum".fields.len) |i| {
|
for (0..@typeInfo(wasi_libc.CrtFile).@"enum".fields.len) |i| {
|
||||||
if (comp.queued_jobs.wasi_libc_crt_file[i]) {
|
if (comp.queued_jobs.wasi_libc_crt_file[i]) {
|
||||||
const tag: wasi_libc.CrtFile = @enumFromInt(i);
|
const tag: wasi_libc.CrtFile = @enumFromInt(i);
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildWasiLibcCrtFile, .{ comp, tag, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildWasiLibcCrtFile, .{ comp, tag, main_progress_node });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4594,6 +4583,7 @@ fn performAllTheWork(
|
||||||
for (0..@typeInfo(mingw.CrtFile).@"enum".fields.len) |i| {
|
for (0..@typeInfo(mingw.CrtFile).@"enum".fields.len) |i| {
|
||||||
if (comp.queued_jobs.mingw_crt_file[i]) {
|
if (comp.queued_jobs.mingw_crt_file[i]) {
|
||||||
const tag: mingw.CrtFile = @enumFromInt(i);
|
const tag: mingw.CrtFile = @enumFromInt(i);
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.link_task_wait_group.spawnManager(buildMingwCrtFile, .{ comp, tag, main_progress_node });
|
comp.link_task_wait_group.spawnManager(buildMingwCrtFile, .{ comp, tag, main_progress_node });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4665,12 +4655,14 @@ fn performAllTheWork(
|
||||||
}
|
}
|
||||||
|
|
||||||
while (comp.c_object_work_queue.readItem()) |c_object| {
|
while (comp.c_object_work_queue.readItem()) |c_object| {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateCObject, .{
|
comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateCObject, .{
|
||||||
comp, c_object, main_progress_node,
|
comp, c_object, main_progress_node,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
while (comp.win32_resource_work_queue.readItem()) |win32_resource| {
|
while (comp.win32_resource_work_queue.readItem()) |win32_resource| {
|
||||||
|
comp.link_task_queue.startPrelinkItem();
|
||||||
comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateWin32Resource, .{
|
comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateWin32Resource, .{
|
||||||
comp, win32_resource, main_progress_node,
|
comp, win32_resource, main_progress_node,
|
||||||
});
|
});
|
||||||
|
|
@ -4773,15 +4765,14 @@ fn performAllTheWork(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We aren't going to queue any more prelink tasks.
|
||||||
|
comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
|
|
||||||
if (!comp.separateCodegenThreadOk()) {
|
if (!comp.separateCodegenThreadOk()) {
|
||||||
// Waits until all input files have been parsed.
|
// Waits until all input files have been parsed.
|
||||||
comp.link_task_wait_group.wait();
|
comp.link_task_wait_group.wait();
|
||||||
comp.link_task_wait_group.reset();
|
comp.link_task_wait_group.reset();
|
||||||
std.log.scoped(.link).debug("finished waiting for link_task_wait_group", .{});
|
std.log.scoped(.link).debug("finished waiting for link_task_wait_group", .{});
|
||||||
if (comp.link_task_queue.pending_prelink_tasks > 0) {
|
|
||||||
// Indicates an error occurred preventing prelink phase from completing.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.zcu != null) {
|
if (comp.zcu != null) {
|
||||||
|
|
@ -5568,6 +5559,7 @@ fn workerUpdateCObject(
|
||||||
c_object: *CObject,
|
c_object: *CObject,
|
||||||
progress_node: std.Progress.Node,
|
progress_node: std.Progress.Node,
|
||||||
) void {
|
) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
comp.updateCObject(c_object, progress_node) catch |err| switch (err) {
|
comp.updateCObject(c_object, progress_node) catch |err| switch (err) {
|
||||||
error.AnalysisFail => return,
|
error.AnalysisFail => return,
|
||||||
else => {
|
else => {
|
||||||
|
|
@ -5585,6 +5577,7 @@ fn workerUpdateWin32Resource(
|
||||||
win32_resource: *Win32Resource,
|
win32_resource: *Win32Resource,
|
||||||
progress_node: std.Progress.Node,
|
progress_node: std.Progress.Node,
|
||||||
) void {
|
) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
comp.updateWin32Resource(win32_resource, progress_node) catch |err| switch (err) {
|
comp.updateWin32Resource(win32_resource, progress_node) catch |err| switch (err) {
|
||||||
error.AnalysisFail => return,
|
error.AnalysisFail => return,
|
||||||
else => {
|
else => {
|
||||||
|
|
@ -5628,6 +5621,7 @@ fn buildRt(
|
||||||
options: RtOptions,
|
options: RtOptions,
|
||||||
out: *?CrtFile,
|
out: *?CrtFile,
|
||||||
) void {
|
) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
comp.buildOutputFromZig(
|
comp.buildOutputFromZig(
|
||||||
root_source_name,
|
root_source_name,
|
||||||
root_name,
|
root_name,
|
||||||
|
|
@ -5646,6 +5640,7 @@ fn buildRt(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.Progress.Node) void {
|
fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (musl.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
if (musl.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
||||||
comp.queued_jobs.musl_crt_file[@intFromEnum(crt_file)] = false;
|
comp.queued_jobs.musl_crt_file[@intFromEnum(crt_file)] = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5657,6 +5652,7 @@ fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.P
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std.Progress.Node) void {
|
fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (glibc.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
if (glibc.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
||||||
comp.queued_jobs.glibc_crt_file[@intFromEnum(crt_file)] = false;
|
comp.queued_jobs.glibc_crt_file[@intFromEnum(crt_file)] = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5668,6 +5664,7 @@ fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
|
fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (glibc.buildSharedObjects(comp, prog_node)) |_| {
|
if (glibc.buildSharedObjects(comp, prog_node)) |_| {
|
||||||
// The job should no longer be queued up since it succeeded.
|
// The job should no longer be queued up since it succeeded.
|
||||||
comp.queued_jobs.glibc_shared_objects = false;
|
comp.queued_jobs.glibc_shared_objects = false;
|
||||||
|
|
@ -5680,6 +5677,7 @@ fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) voi
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: std.Progress.Node) void {
|
fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (freebsd.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
if (freebsd.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
||||||
comp.queued_jobs.freebsd_crt_file[@intFromEnum(crt_file)] = false;
|
comp.queued_jobs.freebsd_crt_file[@intFromEnum(crt_file)] = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5691,6 +5689,7 @@ fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
|
fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (freebsd.buildSharedObjects(comp, prog_node)) |_| {
|
if (freebsd.buildSharedObjects(comp, prog_node)) |_| {
|
||||||
// The job should no longer be queued up since it succeeded.
|
// The job should no longer be queued up since it succeeded.
|
||||||
comp.queued_jobs.freebsd_shared_objects = false;
|
comp.queued_jobs.freebsd_shared_objects = false;
|
||||||
|
|
@ -5703,6 +5702,7 @@ fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) v
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: std.Progress.Node) void {
|
fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (netbsd.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
if (netbsd.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
||||||
comp.queued_jobs.netbsd_crt_file[@intFromEnum(crt_file)] = false;
|
comp.queued_jobs.netbsd_crt_file[@intFromEnum(crt_file)] = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5714,6 +5714,7 @@ fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: s
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
|
fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (netbsd.buildSharedObjects(comp, prog_node)) |_| {
|
if (netbsd.buildSharedObjects(comp, prog_node)) |_| {
|
||||||
// The job should no longer be queued up since it succeeded.
|
// The job should no longer be queued up since it succeeded.
|
||||||
comp.queued_jobs.netbsd_shared_objects = false;
|
comp.queued_jobs.netbsd_shared_objects = false;
|
||||||
|
|
@ -5726,6 +5727,7 @@ fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) vo
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std.Progress.Node) void {
|
fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (mingw.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
if (mingw.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
||||||
comp.queued_jobs.mingw_crt_file[@intFromEnum(crt_file)] = false;
|
comp.queued_jobs.mingw_crt_file[@intFromEnum(crt_file)] = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5737,6 +5739,7 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_node: std.Progress.Node) void {
|
fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| {
|
||||||
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false;
|
comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5748,6 +5751,7 @@ fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_no
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void {
|
fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (libunwind.buildStaticLib(comp, prog_node)) |_| {
|
if (libunwind.buildStaticLib(comp, prog_node)) |_| {
|
||||||
comp.queued_jobs.libunwind = false;
|
comp.queued_jobs.libunwind = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5757,6 +5761,7 @@ fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void {
|
fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (libcxx.buildLibCxx(comp, prog_node)) |_| {
|
if (libcxx.buildLibCxx(comp, prog_node)) |_| {
|
||||||
comp.queued_jobs.libcxx = false;
|
comp.queued_jobs.libcxx = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5766,6 +5771,7 @@ fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void {
|
fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (libcxx.buildLibCxxAbi(comp, prog_node)) |_| {
|
if (libcxx.buildLibCxxAbi(comp, prog_node)) |_| {
|
||||||
comp.queued_jobs.libcxxabi = false;
|
comp.queued_jobs.libcxxabi = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5775,6 +5781,7 @@ fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void {
|
fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
if (libtsan.buildTsan(comp, prog_node)) |_| {
|
if (libtsan.buildTsan(comp, prog_node)) |_| {
|
||||||
comp.queued_jobs.libtsan = false;
|
comp.queued_jobs.libtsan = false;
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
|
|
@ -5784,6 +5791,7 @@ fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void {
|
fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void {
|
||||||
|
defer comp.link_task_queue.finishPrelinkItem(comp);
|
||||||
comp.buildOutputFromZig(
|
comp.buildOutputFromZig(
|
||||||
"c.zig",
|
"c.zig",
|
||||||
"zigc",
|
"zigc",
|
||||||
|
|
@ -7721,6 +7729,7 @@ pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const
|
||||||
/// Only valid to call during `update`. Automatically handles queuing up a
|
/// Only valid to call during `update`. Automatically handles queuing up a
|
||||||
/// linker worker task if there is not already one.
|
/// linker worker task if there is not already one.
|
||||||
pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) void {
|
pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) void {
|
||||||
|
comp.link_prog_node.increaseEstimatedTotalItems(tasks.len);
|
||||||
comp.link_task_queue.enqueuePrelink(comp, tasks) catch |err| switch (err) {
|
comp.link_task_queue.enqueuePrelink(comp, tasks) catch |err| switch (err) {
|
||||||
error.OutOfMemory => return comp.setAllocFailure(),
|
error.OutOfMemory => return comp.setAllocFailure(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -977,10 +977,6 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sharedObjectsCount() u8 {
|
|
||||||
return libs.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
|
fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
|
||||||
assert(comp.freebsd_so_files == null);
|
assert(comp.freebsd_so_files == null);
|
||||||
comp.freebsd_so_files = so_files;
|
comp.freebsd_so_files = so_files;
|
||||||
|
|
|
||||||
|
|
@ -1130,18 +1130,6 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sharedObjectsCount(target: *const std.Target) u8 {
|
|
||||||
const target_version = target.os.versionRange().gnuLibCVersion() orelse return 0;
|
|
||||||
var count: u8 = 0;
|
|
||||||
for (libs) |lib| {
|
|
||||||
if (lib.removed_in) |rem_in| {
|
|
||||||
if (target_version.order(rem_in) != .lt) continue;
|
|
||||||
}
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
|
fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
|
||||||
const target_version = comp.getTarget().os.versionRange().gnuLibCVersion().?;
|
const target_version = comp.getTarget().os.versionRange().gnuLibCVersion().?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -642,10 +642,6 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sharedObjectsCount() u8 {
|
|
||||||
return libs.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
|
fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
|
||||||
assert(comp.netbsd_so_files == null);
|
assert(comp.netbsd_so_files == null);
|
||||||
comp.netbsd_so_files = so_files;
|
comp.netbsd_so_files = so_files;
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@ mutex: std.Thread.Mutex,
|
||||||
/// Validates that only one `flushTaskQueue` thread is running at a time.
|
/// Validates that only one `flushTaskQueue` thread is running at a time.
|
||||||
flush_safety: std.debug.SafetyLock,
|
flush_safety: std.debug.SafetyLock,
|
||||||
|
|
||||||
/// This is the number of prelink tasks which are expected but have not yet been enqueued.
|
/// This value is positive while there are still prelink tasks yet to be queued. Once they are
|
||||||
/// Guarded by `mutex`.
|
/// all queued, this value becomes 0, and ZCU tasks can be run. Guarded by `mutex`.
|
||||||
pending_prelink_tasks: u32,
|
prelink_wait_count: u32,
|
||||||
|
|
||||||
/// Prelink tasks which have been enqueued and are not yet owned by the worker thread.
|
/// Prelink tasks which have been enqueued and are not yet owned by the worker thread.
|
||||||
/// Allocated into `gpa`, guarded by `mutex`.
|
/// Allocated into `gpa`, guarded by `mutex`.
|
||||||
|
|
@ -59,7 +59,7 @@ state: union(enum) {
|
||||||
/// The link thread is currently running or queued to run.
|
/// The link thread is currently running or queued to run.
|
||||||
running,
|
running,
|
||||||
/// The link thread is not running or queued, because it has exhausted all immediately available
|
/// The link thread is not running or queued, because it has exhausted all immediately available
|
||||||
/// tasks. It should be spawned when more tasks are enqueued. If `pending_prelink_tasks` is not
|
/// tasks. It should be spawned when more tasks are enqueued. If `prelink_wait_count` is not
|
||||||
/// zero, we are specifically waiting for prelink tasks.
|
/// zero, we are specifically waiting for prelink tasks.
|
||||||
finished,
|
finished,
|
||||||
/// The link thread is not running or queued, because it is waiting for this MIR to be populated.
|
/// The link thread is not running or queued, because it is waiting for this MIR to be populated.
|
||||||
|
|
@ -73,11 +73,11 @@ state: union(enum) {
|
||||||
const max_air_bytes_in_flight = 10 * 1024 * 1024;
|
const max_air_bytes_in_flight = 10 * 1024 * 1024;
|
||||||
|
|
||||||
/// The initial `Queue` state, containing no tasks, expecting no prelink tasks, and with no running worker thread.
|
/// The initial `Queue` state, containing no tasks, expecting no prelink tasks, and with no running worker thread.
|
||||||
/// The `pending_prelink_tasks` and `queued_prelink` fields may be modified as needed before calling `start`.
|
/// The `queued_prelink` field may be appended to before calling `start`.
|
||||||
pub const empty: Queue = .{
|
pub const empty: Queue = .{
|
||||||
.mutex = .{},
|
.mutex = .{},
|
||||||
.flush_safety = .{},
|
.flush_safety = .{},
|
||||||
.pending_prelink_tasks = 0,
|
.prelink_wait_count = undefined, // set in `start`
|
||||||
.queued_prelink = .empty,
|
.queued_prelink = .empty,
|
||||||
.wip_prelink = .empty,
|
.wip_prelink = .empty,
|
||||||
.queued_zcu = .empty,
|
.queued_zcu = .empty,
|
||||||
|
|
@ -100,17 +100,49 @@ pub fn deinit(q: *Queue, comp: *Compilation) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is expected to be called exactly once, after which the caller must not directly access
|
/// This is expected to be called exactly once, after which the caller must not directly access
|
||||||
/// `queued_prelink` or `pending_prelink_tasks` any longer. This will spawn the link thread if
|
/// `queued_prelink` any longer. This will spawn the link thread if necessary.
|
||||||
/// necessary.
|
|
||||||
pub fn start(q: *Queue, comp: *Compilation) void {
|
pub fn start(q: *Queue, comp: *Compilation) void {
|
||||||
assert(q.state == .finished);
|
assert(q.state == .finished);
|
||||||
assert(q.queued_zcu.items.len == 0);
|
assert(q.queued_zcu.items.len == 0);
|
||||||
|
// Reset this to 1. We can't init it to 1 in `empty`, because it would fall to 0 on successive
|
||||||
|
// incremental updates, but we still need the initial 1.
|
||||||
|
q.prelink_wait_count = 1;
|
||||||
if (q.queued_prelink.items.len != 0) {
|
if (q.queued_prelink.items.len != 0) {
|
||||||
q.state = .running;
|
q.state = .running;
|
||||||
comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
|
comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Every call to this must be paired with a call to `finishPrelinkItem`.
|
||||||
|
pub fn startPrelinkItem(q: *Queue) void {
|
||||||
|
q.mutex.lock();
|
||||||
|
defer q.mutex.unlock();
|
||||||
|
assert(q.prelink_wait_count > 0); // must not have finished everything already
|
||||||
|
q.prelink_wait_count += 1;
|
||||||
|
}
|
||||||
|
/// This function must be called exactly one more time than `startPrelinkItem` is. The final call
|
||||||
|
/// indicates that we have finished calling `startPrelinkItem`, so once all pending items finish,
|
||||||
|
/// we are ready to move on to ZCU tasks.
|
||||||
|
pub fn finishPrelinkItem(q: *Queue, comp: *Compilation) void {
|
||||||
|
{
|
||||||
|
q.mutex.lock();
|
||||||
|
defer q.mutex.unlock();
|
||||||
|
q.prelink_wait_count -= 1;
|
||||||
|
if (q.prelink_wait_count != 0) return;
|
||||||
|
// The prelink task count dropped to 0; restart the linker thread if necessary.
|
||||||
|
switch (q.state) {
|
||||||
|
.wait_for_mir => unreachable, // we've not started zcu tasks yet
|
||||||
|
.running => return,
|
||||||
|
.finished => {},
|
||||||
|
}
|
||||||
|
assert(q.queued_prelink.items.len == 0);
|
||||||
|
// Even if there are no ZCU tasks, we must restart the linker thread to make sure
|
||||||
|
// that `link.File.prelink()` is called.
|
||||||
|
q.state = .running;
|
||||||
|
}
|
||||||
|
comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
|
||||||
|
}
|
||||||
|
|
||||||
/// Called by codegen workers after they have populated a `ZcuTask.LinkFunc.SharedMir`. If the link
|
/// Called by codegen workers after they have populated a `ZcuTask.LinkFunc.SharedMir`. If the link
|
||||||
/// thread was waiting for this MIR, it can resume.
|
/// thread was waiting for this MIR, it can resume.
|
||||||
pub fn mirReady(q: *Queue, comp: *Compilation, func_index: InternPool.Index, mir: *ZcuTask.LinkFunc.SharedMir) void {
|
pub fn mirReady(q: *Queue, comp: *Compilation, func_index: InternPool.Index, mir: *ZcuTask.LinkFunc.SharedMir) void {
|
||||||
|
|
@ -130,14 +162,14 @@ pub fn mirReady(q: *Queue, comp: *Compilation, func_index: InternPool.Index, mir
|
||||||
comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
|
comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that `tasks.len` is
|
/// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that
|
||||||
/// less than or equal to `q.pending_prelink_tasks`. Also asserts that `tasks.len` is not 0.
|
/// `prelink_wait_count` is not yet 0. Also asserts that `tasks.len` is not 0.
|
||||||
pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Allocator.Error!void {
|
pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Allocator.Error!void {
|
||||||
{
|
{
|
||||||
q.mutex.lock();
|
q.mutex.lock();
|
||||||
defer q.mutex.unlock();
|
defer q.mutex.unlock();
|
||||||
|
assert(q.prelink_wait_count > 0);
|
||||||
try q.queued_prelink.appendSlice(comp.gpa, tasks);
|
try q.queued_prelink.appendSlice(comp.gpa, tasks);
|
||||||
q.pending_prelink_tasks -= @intCast(tasks.len);
|
|
||||||
switch (q.state) {
|
switch (q.state) {
|
||||||
.wait_for_mir => unreachable, // we've not started zcu tasks yet
|
.wait_for_mir => unreachable, // we've not started zcu tasks yet
|
||||||
.running => return,
|
.running => return,
|
||||||
|
|
@ -167,7 +199,7 @@ pub fn enqueueZcu(q: *Queue, comp: *Compilation, task: ZcuTask) Allocator.Error!
|
||||||
try q.queued_zcu.append(comp.gpa, task);
|
try q.queued_zcu.append(comp.gpa, task);
|
||||||
switch (q.state) {
|
switch (q.state) {
|
||||||
.running, .wait_for_mir => return,
|
.running, .wait_for_mir => return,
|
||||||
.finished => if (q.pending_prelink_tasks != 0) return,
|
.finished => if (q.prelink_wait_count > 0) return,
|
||||||
}
|
}
|
||||||
// Restart the linker thread, unless it would immediately be blocked
|
// Restart the linker thread, unless it would immediately be blocked
|
||||||
if (task == .link_func and task.link_func.mir.status.load(.acquire) == .pending) {
|
if (task == .link_func and task.link_func.mir.status.load(.acquire) == .pending) {
|
||||||
|
|
@ -194,7 +226,7 @@ fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void {
|
||||||
defer q.mutex.unlock();
|
defer q.mutex.unlock();
|
||||||
std.mem.swap(std.ArrayListUnmanaged(PrelinkTask), &q.queued_prelink, &q.wip_prelink);
|
std.mem.swap(std.ArrayListUnmanaged(PrelinkTask), &q.queued_prelink, &q.wip_prelink);
|
||||||
if (q.wip_prelink.items.len == 0) {
|
if (q.wip_prelink.items.len == 0) {
|
||||||
if (q.pending_prelink_tasks == 0) {
|
if (q.prelink_wait_count == 0) {
|
||||||
break :prelink; // prelink is done
|
break :prelink; // prelink is done
|
||||||
} else {
|
} else {
|
||||||
// We're expecting more prelink tasks so can't move on to ZCU tasks.
|
// We're expecting more prelink tasks so can't move on to ZCU tasks.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue