authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-23 14:04:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-23 14:08:03-07:00
log322d71139d2e28f9332b5397ae8b14d04e27b5df
treef211f676366dd0dcdc7ac403b15776f09cd34f4d
parentd210f733f80731487f8f83caf621e04506f50bb4

link.MachO: remove buggy multi-threading

thread-sanitizer reports data races here when running test-link. I tried only removing the ones that triggered races, but after 10 back and forths with the compiler and tsan, I got impatient and removed all of them. next time, let's be sure the test suite runs tsan-clean before merging any changes that add parallelism. after this commit, `zig build test-link` completes without any tsan warnings. closes #21778

2 files changed, 48 insertions(+), 92 deletions(-)

src/link/MachO.zig+35-68
...@@ -875,18 +875,13 @@ pub fn parseInputFiles(self: *MachO) !void {...@@ -875,18 +875,13 @@ pub fn parseInputFiles(self: *MachO) !void {
875 defer tracy.end();875 defer tracy.end();
876876
877 const diags = &self.base.comp.link_diags;877 const diags = &self.base.comp.link_diags;
878 const tp = self.base.comp.thread_pool;
879 var wg: WaitGroup = .{};
880878
881 {879 {
882 wg.reset();
883 defer wg.wait();
884
885 for (self.objects.items) |index| {880 for (self.objects.items) |index| {
886 tp.spawnWg(&wg, parseInputFileWorker, .{ self, self.getFile(index).? });881 parseInputFileWorker(self, self.getFile(index).?);
887 }882 }
888 for (self.dylibs.items) |index| {883 for (self.dylibs.items) |index| {
889 tp.spawnWg(&wg, parseInputFileWorker, .{ self, self.getFile(index).? });884 parseInputFileWorker(self, self.getFile(index).?);
890 }885 }
891 }886 }
892887
...@@ -1269,17 +1264,13 @@ fn markLive(self: *MachO) void {...@@ -1269,17 +1264,13 @@ fn markLive(self: *MachO) void {
1269}1264}
12701265
1271fn convertTentativeDefsAndResolveSpecialSymbols(self: *MachO) !void {1266fn convertTentativeDefsAndResolveSpecialSymbols(self: *MachO) !void {
1272 const tp = self.base.comp.thread_pool;
1273 const diags = &self.base.comp.link_diags;1267 const diags = &self.base.comp.link_diags;
1274 var wg: WaitGroup = .{};
1275 {1268 {
1276 wg.reset();
1277 defer wg.wait();
1278 for (self.objects.items) |index| {1269 for (self.objects.items) |index| {
1279 tp.spawnWg(&wg, convertTentativeDefinitionsWorker, .{ self, self.getFile(index).?.object });1270 convertTentativeDefinitionsWorker(self, self.getFile(index).?.object);
1280 }1271 }
1281 if (self.getInternalObject()) |obj| {1272 if (self.getInternalObject()) |obj| {
1282 tp.spawnWg(&wg, resolveSpecialSymbolsWorker, .{ self, obj });1273 resolveSpecialSymbolsWorker(self, obj);
1283 }1274 }
1284 }1275 }
1285 if (diags.hasErrors()) return error.LinkFailure;1276 if (diags.hasErrors()) return error.LinkFailure;
...@@ -1327,19 +1318,15 @@ pub fn dedupLiterals(self: *MachO) !void {...@@ -1327,19 +1318,15 @@ pub fn dedupLiterals(self: *MachO) !void {
1327 try object.resolveLiterals(&lp, self);1318 try object.resolveLiterals(&lp, self);
1328 }1319 }
13291320
1330 const tp = self.base.comp.thread_pool;
1331 var wg: WaitGroup = .{};
1332 {1321 {
1333 wg.reset();
1334 defer wg.wait();
1335 if (self.getZigObject()) |zo| {1322 if (self.getZigObject()) |zo| {
1336 tp.spawnWg(&wg, File.dedupLiterals, .{ zo.asFile(), lp, self });1323 File.dedupLiterals(zo.asFile(), lp, self);
1337 }1324 }
1338 for (self.objects.items) |index| {1325 for (self.objects.items) |index| {
1339 tp.spawnWg(&wg, File.dedupLiterals, .{ self.getFile(index).?, lp, self });1326 File.dedupLiterals(self.getFile(index).?, lp, self);
1340 }1327 }
1341 if (self.getInternalObject()) |object| {1328 if (self.getInternalObject()) |object| {
1342 tp.spawnWg(&wg, File.dedupLiterals, .{ object.asFile(), lp, self });1329 File.dedupLiterals(object.asFile(), lp, self);
1343 }1330 }
1344 }1331 }
1345}1332}
...@@ -1357,21 +1344,17 @@ fn checkDuplicates(self: *MachO) !void {...@@ -1357,21 +1344,17 @@ fn checkDuplicates(self: *MachO) !void {
1357 const tracy = trace(@src());1344 const tracy = trace(@src());
1358 defer tracy.end();1345 defer tracy.end();
13591346
1360 const tp = self.base.comp.thread_pool;
1361 const diags = &self.base.comp.link_diags;1347 const diags = &self.base.comp.link_diags;
13621348
1363 var wg: WaitGroup = .{};
1364 {1349 {
1365 wg.reset();
1366 defer wg.wait();
1367 if (self.getZigObject()) |zo| {1350 if (self.getZigObject()) |zo| {
1368 tp.spawnWg(&wg, checkDuplicatesWorker, .{ self, zo.asFile() });1351 checkDuplicatesWorker(self, zo.asFile());
1369 }1352 }
1370 for (self.objects.items) |index| {1353 for (self.objects.items) |index| {
1371 tp.spawnWg(&wg, checkDuplicatesWorker, .{ self, self.getFile(index).? });1354 checkDuplicatesWorker(self, self.getFile(index).?);
1372 }1355 }
1373 if (self.getInternalObject()) |obj| {1356 if (self.getInternalObject()) |obj| {
1374 tp.spawnWg(&wg, checkDuplicatesWorker, .{ self, obj.asFile() });1357 checkDuplicatesWorker(self, obj.asFile());
1375 }1358 }
1376 }1359 }
13771360
...@@ -1428,23 +1411,17 @@ fn scanRelocs(self: *MachO) !void {...@@ -1428,23 +1411,17 @@ fn scanRelocs(self: *MachO) !void {
1428 const tracy = trace(@src());1411 const tracy = trace(@src());
1429 defer tracy.end();1412 defer tracy.end();
14301413
1431 const tp = self.base.comp.thread_pool;
1432 const diags = &self.base.comp.link_diags;1414 const diags = &self.base.comp.link_diags;
14331415
1434 var wg: WaitGroup = .{};
1435
1436 {1416 {
1437 wg.reset();
1438 defer wg.wait();
1439
1440 if (self.getZigObject()) |zo| {1417 if (self.getZigObject()) |zo| {
1441 tp.spawnWg(&wg, scanRelocsWorker, .{ self, zo.asFile() });1418 scanRelocsWorker(self, zo.asFile());
1442 }1419 }
1443 for (self.objects.items) |index| {1420 for (self.objects.items) |index| {
1444 tp.spawnWg(&wg, scanRelocsWorker, .{ self, self.getFile(index).? });1421 scanRelocsWorker(self, self.getFile(index).?);
1445 }1422 }
1446 if (self.getInternalObject()) |obj| {1423 if (self.getInternalObject()) |obj| {
1447 tp.spawnWg(&wg, scanRelocsWorker, .{ self, obj.asFile() });1424 scanRelocsWorker(self, obj.asFile());
1448 }1425 }
1449 }1426 }
14501427
...@@ -1888,38 +1865,34 @@ fn calcSectionSizes(self: *MachO) !void {...@@ -1888,38 +1865,34 @@ fn calcSectionSizes(self: *MachO) !void {
1888 header.@"align" = 3;1865 header.@"align" = 3;
1889 }1866 }
18901867
1891 const tp = self.base.comp.thread_pool;
1892 var wg: WaitGroup = .{};
1893 {1868 {
1894 wg.reset();
1895 defer wg.wait();
1896 const slice = self.sections.slice();1869 const slice = self.sections.slice();
1897 for (slice.items(.header), slice.items(.atoms), 0..) |header, atoms, i| {1870 for (slice.items(.header), slice.items(.atoms), 0..) |header, atoms, i| {
1898 if (atoms.items.len == 0) continue;1871 if (atoms.items.len == 0) continue;
1899 if (self.requiresThunks() and header.isCode()) continue;1872 if (self.requiresThunks() and header.isCode()) continue;
1900 tp.spawnWg(&wg, calcSectionSizeWorker, .{ self, @as(u8, @intCast(i)) });1873 calcSectionSizeWorker(self, @as(u8, @intCast(i)));
1901 }1874 }
19021875
1903 if (self.requiresThunks()) {1876 if (self.requiresThunks()) {
1904 for (slice.items(.header), slice.items(.atoms), 0..) |header, atoms, i| {1877 for (slice.items(.header), slice.items(.atoms), 0..) |header, atoms, i| {
1905 if (!header.isCode()) continue;1878 if (!header.isCode()) continue;
1906 if (atoms.items.len == 0) continue;1879 if (atoms.items.len == 0) continue;
1907 tp.spawnWg(&wg, createThunksWorker, .{ self, @as(u8, @intCast(i)) });1880 createThunksWorker(self, @as(u8, @intCast(i)));
1908 }1881 }
1909 }1882 }
19101883
1911 // At this point, we can also calculate most of the symtab and data-in-code linkedit section sizes1884 // At this point, we can also calculate most of the symtab and data-in-code linkedit section sizes
1912 if (self.getZigObject()) |zo| {1885 if (self.getZigObject()) |zo| {
1913 tp.spawnWg(&wg, File.calcSymtabSize, .{ zo.asFile(), self });1886 File.calcSymtabSize(zo.asFile(), self);
1914 }1887 }
1915 for (self.objects.items) |index| {1888 for (self.objects.items) |index| {
1916 tp.spawnWg(&wg, File.calcSymtabSize, .{ self.getFile(index).?, self });1889 File.calcSymtabSize(self.getFile(index).?, self);
1917 }1890 }
1918 for (self.dylibs.items) |index| {1891 for (self.dylibs.items) |index| {
1919 tp.spawnWg(&wg, File.calcSymtabSize, .{ self.getFile(index).?, self });1892 File.calcSymtabSize(self.getFile(index).?, self);
1920 }1893 }
1921 if (self.getInternalObject()) |obj| {1894 if (self.getInternalObject()) |obj| {
1922 tp.spawnWg(&wg, File.calcSymtabSize, .{ obj.asFile(), self });1895 File.calcSymtabSize(obj.asFile(), self);
1923 }1896 }
1924 }1897 }
19251898
...@@ -2403,23 +2376,18 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {...@@ -2403,23 +2376,18 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
2403 try self.strtab.resize(gpa, cmd.strsize);2376 try self.strtab.resize(gpa, cmd.strsize);
2404 self.strtab.items[0] = 0;2377 self.strtab.items[0] = 0;
24052378
2406 const tp = self.base.comp.thread_pool;
2407 var wg: WaitGroup = .{};
2408 {2379 {
2409 wg.reset();
2410 defer wg.wait();
2411
2412 for (self.objects.items) |index| {2380 for (self.objects.items) |index| {
2413 tp.spawnWg(&wg, writeAtomsWorker, .{ self, self.getFile(index).? });2381 writeAtomsWorker(self, self.getFile(index).?);
2414 }2382 }
2415 if (self.getZigObject()) |zo| {2383 if (self.getZigObject()) |zo| {
2416 tp.spawnWg(&wg, writeAtomsWorker, .{ self, zo.asFile() });2384 writeAtomsWorker(self, zo.asFile());
2417 }2385 }
2418 if (self.getInternalObject()) |obj| {2386 if (self.getInternalObject()) |obj| {
2419 tp.spawnWg(&wg, writeAtomsWorker, .{ self, obj.asFile() });2387 writeAtomsWorker(self, obj.asFile());
2420 }2388 }
2421 for (self.thunks.items) |thunk| {2389 for (self.thunks.items) |thunk| {
2422 tp.spawnWg(&wg, writeThunkWorker, .{ self, thunk });2390 writeThunkWorker(self, thunk);
2423 }2391 }
24242392
2425 const slice = self.sections.slice();2393 const slice = self.sections.slice();
...@@ -2434,34 +2402,34 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {...@@ -2434,34 +2402,34 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
2434 }) |maybe_sect_id| {2402 }) |maybe_sect_id| {
2435 if (maybe_sect_id) |sect_id| {2403 if (maybe_sect_id) |sect_id| {
2436 const out = slice.items(.out)[sect_id].items;2404 const out = slice.items(.out)[sect_id].items;
2437 tp.spawnWg(&wg, writeSyntheticSectionWorker, .{ self, sect_id, out });2405 writeSyntheticSectionWorker(self, sect_id, out);
2438 }2406 }
2439 }2407 }
24402408
2441 if (self.la_symbol_ptr_sect_index) |_| {2409 if (self.la_symbol_ptr_sect_index) |_| {
2442 tp.spawnWg(&wg, updateLazyBindSizeWorker, .{self});2410 updateLazyBindSizeWorker(self);
2443 }2411 }
24442412
2445 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .rebase });2413 updateLinkeditSizeWorker(self, .rebase);
2446 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .bind });2414 updateLinkeditSizeWorker(self, .bind);
2447 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .weak_bind });2415 updateLinkeditSizeWorker(self, .weak_bind);
2448 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .export_trie });2416 updateLinkeditSizeWorker(self, .export_trie);
2449 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .data_in_code });2417 updateLinkeditSizeWorker(self, .data_in_code);
24502418
2451 if (self.getZigObject()) |zo| {2419 if (self.getZigObject()) |zo| {
2452 tp.spawnWg(&wg, File.writeSymtab, .{ zo.asFile(), self, self });2420 File.writeSymtab(zo.asFile(), self, self);
2453 }2421 }
2454 for (self.objects.items) |index| {2422 for (self.objects.items) |index| {
2455 tp.spawnWg(&wg, File.writeSymtab, .{ self.getFile(index).?, self, self });2423 File.writeSymtab(self.getFile(index).?, self, self);
2456 }2424 }
2457 for (self.dylibs.items) |index| {2425 for (self.dylibs.items) |index| {
2458 tp.spawnWg(&wg, File.writeSymtab, .{ self.getFile(index).?, self, self });2426 File.writeSymtab(self.getFile(index).?, self, self);
2459 }2427 }
2460 if (self.getInternalObject()) |obj| {2428 if (self.getInternalObject()) |obj| {
2461 tp.spawnWg(&wg, File.writeSymtab, .{ obj.asFile(), self, self });2429 File.writeSymtab(obj.asFile(), self, self);
2462 }2430 }
2463 if (self.requiresThunks()) for (self.thunks.items) |th| {2431 if (self.requiresThunks()) for (self.thunks.items) |th| {
2464 tp.spawnWg(&wg, Thunk.writeSymtab, .{ th, self, self });2432 Thunk.writeSymtab(th, self, self);
2465 };2433 };
2466 }2434 }
24672435
...@@ -5370,7 +5338,6 @@ const Thunk = @import("MachO/Thunk.zig");...@@ -5370,7 +5338,6 @@ const Thunk = @import("MachO/Thunk.zig");
5370const TlvPtrSection = synthetic.TlvPtrSection;5338const TlvPtrSection = synthetic.TlvPtrSection;
5371const Value = @import("../Value.zig");5339const Value = @import("../Value.zig");
5372const UnwindInfo = @import("MachO/UnwindInfo.zig");5340const UnwindInfo = @import("MachO/UnwindInfo.zig");
5373const WaitGroup = std.Thread.WaitGroup;
5374const WeakBind = bind.WeakBind;5341const WeakBind = bind.WeakBind;
5375const ZigObject = @import("MachO/ZigObject.zig");5342const ZigObject = @import("MachO/ZigObject.zig");
5376const dev = @import("../dev.zig");5343const dev = @import("../dev.zig");
src/link/MachO/relocatable.zig+13-24
...@@ -290,38 +290,33 @@ fn calcSectionSizes(macho_file: *MachO) !void {...@@ -290,38 +290,33 @@ fn calcSectionSizes(macho_file: *MachO) !void {
290 zo.calcNumRelocs(macho_file);290 zo.calcNumRelocs(macho_file);
291 }291 }
292292
293 const tp = macho_file.base.comp.thread_pool;
294 var wg: WaitGroup = .{};
295 {293 {
296 wg.reset();
297 defer wg.wait();
298
299 for (macho_file.sections.items(.atoms), 0..) |atoms, i| {294 for (macho_file.sections.items(.atoms), 0..) |atoms, i| {
300 if (atoms.items.len == 0) continue;295 if (atoms.items.len == 0) continue;
301 tp.spawnWg(&wg, calcSectionSizeWorker, .{ macho_file, @as(u8, @intCast(i)) });296 calcSectionSizeWorker(macho_file, @as(u8, @intCast(i)));
302 }297 }
303298
304 if (macho_file.eh_frame_sect_index) |_| {299 if (macho_file.eh_frame_sect_index) |_| {
305 tp.spawnWg(&wg, calcEhFrameSizeWorker, .{macho_file});300 calcEhFrameSizeWorker(macho_file);
306 }301 }
307302
308 if (macho_file.unwind_info_sect_index) |_| {303 if (macho_file.unwind_info_sect_index) |_| {
309 for (macho_file.objects.items) |index| {304 for (macho_file.objects.items) |index| {
310 tp.spawnWg(&wg, Object.calcCompactUnwindSizeRelocatable, .{305 Object.calcCompactUnwindSizeRelocatable(
311 macho_file.getFile(index).?.object,306 macho_file.getFile(index).?.object,
312 macho_file,307 macho_file,
313 });308 );
314 }309 }
315 }310 }
316311
317 for (macho_file.objects.items) |index| {312 for (macho_file.objects.items) |index| {
318 tp.spawnWg(&wg, File.calcSymtabSize, .{ macho_file.getFile(index).?, macho_file });313 File.calcSymtabSize(macho_file.getFile(index).?, macho_file);
319 }314 }
320 if (macho_file.getZigObject()) |zo| {315 if (macho_file.getZigObject()) |zo| {
321 tp.spawnWg(&wg, File.calcSymtabSize, .{ zo.asFile(), macho_file });316 File.calcSymtabSize(zo.asFile(), macho_file);
322 }317 }
323318
324 tp.spawnWg(&wg, MachO.updateLinkeditSizeWorker, .{ macho_file, .data_in_code });319 MachO.updateLinkeditSizeWorker(macho_file, .data_in_code);
325 }320 }
326321
327 if (macho_file.unwind_info_sect_index) |_| {322 if (macho_file.unwind_info_sect_index) |_| {
...@@ -601,29 +596,24 @@ fn writeSections(macho_file: *MachO) !void {...@@ -601,29 +596,24 @@ fn writeSections(macho_file: *MachO) !void {
601 try macho_file.strtab.resize(gpa, cmd.strsize);596 try macho_file.strtab.resize(gpa, cmd.strsize);
602 macho_file.strtab.items[0] = 0;597 macho_file.strtab.items[0] = 0;
603598
604 const tp = macho_file.base.comp.thread_pool;
605 var wg: WaitGroup = .{};
606 {599 {
607 wg.reset();
608 defer wg.wait();
609
610 for (macho_file.objects.items) |index| {600 for (macho_file.objects.items) |index| {
611 tp.spawnWg(&wg, writeAtomsWorker, .{ macho_file, macho_file.getFile(index).? });601 writeAtomsWorker(macho_file, macho_file.getFile(index).?);
612 tp.spawnWg(&wg, File.writeSymtab, .{ macho_file.getFile(index).?, macho_file, macho_file });602 File.writeSymtab(macho_file.getFile(index).?, macho_file, macho_file);
613 }603 }
614604
615 if (macho_file.getZigObject()) |zo| {605 if (macho_file.getZigObject()) |zo| {
616 tp.spawnWg(&wg, writeAtomsWorker, .{ macho_file, zo.asFile() });606 writeAtomsWorker(macho_file, zo.asFile());
617 tp.spawnWg(&wg, File.writeSymtab, .{ zo.asFile(), macho_file, macho_file });607 File.writeSymtab(zo.asFile(), macho_file, macho_file);
618 }608 }
619609
620 if (macho_file.eh_frame_sect_index) |_| {610 if (macho_file.eh_frame_sect_index) |_| {
621 tp.spawnWg(&wg, writeEhFrameWorker, .{macho_file});611 writeEhFrameWorker(macho_file);
622 }612 }
623613
624 if (macho_file.unwind_info_sect_index) |_| {614 if (macho_file.unwind_info_sect_index) |_| {
625 for (macho_file.objects.items) |index| {615 for (macho_file.objects.items) |index| {
626 tp.spawnWg(&wg, writeCompactUnwindWorker, .{ macho_file, macho_file.getFile(index).?.object });616 writeCompactUnwindWorker(macho_file, macho_file.getFile(index).?.object);
627 }617 }
628 }618 }
629 }619 }
...@@ -777,4 +767,3 @@ const File = @import("file.zig").File;...@@ -777,4 +767,3 @@ const File = @import("file.zig").File;
777const MachO = @import("../MachO.zig");767const MachO = @import("../MachO.zig");
778const Object = @import("Object.zig");768const Object = @import("Object.zig");
779const Symbol = @import("Symbol.zig");769const Symbol = @import("Symbol.zig");
780const WaitGroup = std.Thread.WaitGroup;