authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-13 22:54:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-13 22:54:16-07:00
loge5aef96293336fa25e6f094bf82d189176e8d1a7
tree197612b613650d003c226b7e772cd470d5953f8e
parent97ea5da18d0a26d55447082d37f6a0945da42d1f

stage2: CRT files retain locks on the build artifacts


4 files changed, 42 insertions(+), 25 deletions(-)

src-self-hosted/Compilation.zig+14-3
...@@ -70,13 +70,24 @@ libc_static_lib: ?[]const u8 = null,...@@ -70,13 +70,24 @@ libc_static_lib: ?[]const u8 = null,
70/// For example `Scrt1.o` and `libc.so.6`. These are populated after building libc from source,70/// For example `Scrt1.o` and `libc.so.6`. These are populated after building libc from source,
71/// The set of needed CRT (C runtime) files differs depending on the target and compilation settings.71/// The set of needed CRT (C runtime) files differs depending on the target and compilation settings.
72/// The key is the basename, and the value is the absolute path to the completed build artifact.72/// The key is the basename, and the value is the absolute path to the completed build artifact.
73crt_files: std.StringHashMapUnmanaged([]const u8) = .{},73crt_files: std.StringHashMapUnmanaged(CRTFile) = .{},
7474
75/// Keeping track of this possibly open resource so we can close it later.75/// Keeping track of this possibly open resource so we can close it later.
76owned_link_dir: ?std.fs.Dir,76owned_link_dir: ?std.fs.Dir,
7777
78pub const InnerError = Module.InnerError;78pub const InnerError = Module.InnerError;
7979
80pub const CRTFile = struct {
81 lock: std.cache_hash.Lock,
82 full_object_path: []const u8,
83
84 fn deinit(self: *CRTFile, gpa: *Allocator) void {
85 self.lock.release();
86 gpa.free(self.full_object_path);
87 self.* = undefined;
88 }
89};
90
80/// For passing to a C compiler.91/// For passing to a C compiler.
81pub const CSourceFile = struct {92pub const CSourceFile = struct {
82 src_path: []const u8,93 src_path: []const u8,
...@@ -625,7 +636,7 @@ pub fn destroy(self: *Compilation) void {...@@ -625,7 +636,7 @@ pub fn destroy(self: *Compilation) void {
625 var it = self.crt_files.iterator();636 var it = self.crt_files.iterator();
626 while (it.next()) |entry| {637 while (it.next()) |entry| {
627 gpa.free(entry.key);638 gpa.free(entry.key);
628 gpa.free(entry.value);639 entry.value.deinit(gpa);
629 }640 }
630 self.crt_files.deinit(gpa);641 self.crt_files.deinit(gpa);
631 }642 }
...@@ -1512,7 +1523,7 @@ fn detectLibCFromLibCInstallation(arena: *Allocator, target: Target, lci: *const...@@ -1512,7 +1523,7 @@ fn detectLibCFromLibCInstallation(arena: *Allocator, target: Target, lci: *const
15121523
1513pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 {1524pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 {
1514 if (comp.wantBuildGLibCFromSource()) {1525 if (comp.wantBuildGLibCFromSource()) {
1515 return comp.crt_files.get(basename).?;1526 return comp.crt_files.get(basename).?.full_object_path;
1516 }1527 }
1517 const lci = comp.bin_file.options.libc_installation orelse return error.LibCInstallationNotAvailable;1528 const lci = comp.bin_file.options.libc_installation orelse return error.LibCInstallationNotAvailable;
1518 const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir;1529 const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir;
src-self-hosted/glibc.zig+4-1
...@@ -648,5 +648,8 @@ fn build_libc_object(comp: *Compilation, basename: []const u8, c_source_file: Co...@@ -648,5 +648,8 @@ fn build_libc_object(comp: *Compilation, basename: []const u8, c_source_file: Co
648 try comp.gpa.dupe(u8, basename);648 try comp.gpa.dupe(u8, basename);
649649
650 // TODO obtain a lock on the artifact and put that in crt_files as well.650 // TODO obtain a lock on the artifact and put that in crt_files as well.
651 comp.crt_files.putAssumeCapacityNoClobber(basename, artifact_path);651 comp.crt_files.putAssumeCapacityNoClobber(basename, .{
652 .full_object_path = artifact_path,
653 .lock = sub_compilation.bin_file.toOwnedLock(),
654 });
652}655}
src-self-hosted/link.zig+18
...@@ -90,6 +90,10 @@ pub const File = struct {...@@ -90,6 +90,10 @@ pub const File = struct {
90 /// this location, and then this path can be placed on the LLD linker line.90 /// this location, and then this path can be placed on the LLD linker line.
91 intermediary_basename: ?[]const u8 = null,91 intermediary_basename: ?[]const u8 = null,
9292
93 /// Prevents other processes from clobbering files in the output directory
94 /// of this linking operation.
95 lock: ?std.cache_hash.Lock = null,
96
93 pub const LinkBlock = union {97 pub const LinkBlock = union {
94 elf: Elf.TextBlock,98 elf: Elf.TextBlock,
95 coff: Coff.TextBlock,99 coff: Coff.TextBlock,
...@@ -228,7 +232,21 @@ pub const File = struct {...@@ -228,7 +232,21 @@ pub const File = struct {
228 }232 }
229 }233 }
230234
235 pub fn releaseLock(self: *File) void {
236 if (self.lock) |*lock| {
237 lock.release();
238 self.lock = null;
239 }
240 }
241
242 pub fn toOwnedLock(self: *File) std.cache_hash.Lock {
243 const lock = self.lock.?;
244 self.lock = null;
245 return lock;
246 }
247
231 pub fn destroy(base: *File) void {248 pub fn destroy(base: *File) void {
249 base.releaseLock();
232 if (base.file) |f| f.close();250 if (base.file) |f| f.close();
233 if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path);251 if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path);
234 switch (base.tag) {252 switch (base.tag) {
src-self-hosted/link/Elf.zig+6-21
...@@ -123,9 +123,6 @@ dbg_info_decl_free_list: std.AutoHashMapUnmanaged(*TextBlock, void) = .{},...@@ -123,9 +123,6 @@ dbg_info_decl_free_list: std.AutoHashMapUnmanaged(*TextBlock, void) = .{},
123dbg_info_decl_first: ?*TextBlock = null,123dbg_info_decl_first: ?*TextBlock = null,
124dbg_info_decl_last: ?*TextBlock = null,124dbg_info_decl_last: ?*TextBlock = null,
125125
126/// Prevents other processes from clobbering the output file this is linking.
127lock: ?std.cache_hash.Lock = null,
128
129/// `alloc_num / alloc_den` is the factor of padding when allocating.126/// `alloc_num / alloc_den` is the factor of padding when allocating.
130const alloc_num = 4;127const alloc_num = 4;
131const alloc_den = 3;128const alloc_den = 3;
...@@ -290,21 +287,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf {...@@ -290,21 +287,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf {
290 return self;287 return self;
291}288}
292289
293pub fn releaseLock(self: *Elf) void {
294 if (self.lock) |*lock| {
295 lock.release();
296 self.lock = null;
297 }
298}
299
300pub fn toOwnedLock(self: *Elf) std.cache_hash.Lock {
301 const lock = self.lock.?;
302 self.lock = null;
303 return lock;
304}
305
306pub fn deinit(self: *Elf) void {290pub fn deinit(self: *Elf) void {
307 self.releaseLock();
308 self.sections.deinit(self.base.allocator);291 self.sections.deinit(self.base.allocator);
309 self.program_headers.deinit(self.base.allocator);292 self.program_headers.deinit(self.base.allocator);
310 self.shstrtab.deinit(self.base.allocator);293 self.shstrtab.deinit(self.base.allocator);
...@@ -1253,7 +1236,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1253,7 +1236,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1253 const id_symlink_basename = "id.txt";1236 const id_symlink_basename = "id.txt";
12541237
1255 // We are about to obtain this lock, so here we give other processes a chance first.1238 // We are about to obtain this lock, so here we give other processes a chance first.
1256 self.releaseLock();1239 self.base.releaseLock();
12571240
1258 var ch = comp.cache_parent.obtain();1241 var ch = comp.cache_parent.obtain();
1259 defer ch.deinit();1242 defer ch.deinit();
...@@ -1302,14 +1285,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1302,14 +1285,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1302 const digest = ch.final();1285 const digest = ch.final();
13031286
1304 var prev_digest_buf: [digest.len]u8 = undefined;1287 var prev_digest_buf: [digest.len]u8 = undefined;
1305 const prev_digest: []u8 = directory.handle.readLink(id_symlink_basename, &prev_digest_buf) catch blk: {1288 const prev_digest: []u8 = directory.handle.readLink(id_symlink_basename, &prev_digest_buf) catch |err| blk: {
1289 log.debug("ELF LLD new_digest={} readlink error: {}", .{digest, @errorName(err)});
1306 // Handle this as a cache miss.1290 // Handle this as a cache miss.
1307 mem.set(u8, &prev_digest_buf, 0);1291 mem.set(u8, &prev_digest_buf, 0);
1308 break :blk &prev_digest_buf;1292 break :blk &prev_digest_buf;
1309 };1293 };
1294 log.debug("ELF LLD prev_digest={} new_digest={}", .{prev_digest, digest});
1310 if (mem.eql(u8, prev_digest, &digest)) {1295 if (mem.eql(u8, prev_digest, &digest)) {
1311 // Hot diggity dog! The output binary is already there.1296 // Hot diggity dog! The output binary is already there.
1312 self.lock = ch.toOwnedLock();1297 self.base.lock = ch.toOwnedLock();
1313 return;1298 return;
1314 }1299 }
13151300
...@@ -1611,7 +1596,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1611,7 +1596,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1611 };1596 };
1612 // We hang on to this lock so that the output file path can be used without1597 // We hang on to this lock so that the output file path can be used without
1613 // other processes clobbering it.1598 // other processes clobbering it.
1614 self.lock = ch.toOwnedLock();1599 self.base.lock = ch.toOwnedLock();
1615}1600}
16161601
1617fn append_diagnostic(context: usize, ptr: [*]const u8, len: usize) callconv(.C) void {1602fn append_diagnostic(context: usize, ptr: [*]const u8, len: usize) callconv(.C) void {