[lld] r329088 - [lld] fix data race in ELF/ICF.cpp

Bob Haarman via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 3 10:27:40 PDT 2018


Author: inglorion
Date: Tue Apr  3 10:27:39 2018
New Revision: 329088

URL: http://llvm.org/viewvc/llvm-project?rev=329088&view=rev
Log:
[lld] fix data race in ELF/ICF.cpp

Summary:
r328610 fixed a data race in the COFF linker. This change makes a
similar fix to the ELF linker.

Reviewers: ruiu, pcc, rnk

Reviewed By: ruiu

Subscribers: emaste, llvm-commits, arichardson

Differential Revision: https://reviews.llvm.org/D45192

Modified:
    lld/trunk/ELF/ICF.cpp

Modified: lld/trunk/ELF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ICF.cpp?rev=329088&r1=329087&r2=329088&view=diff
==============================================================================
--- lld/trunk/ELF/ICF.cpp (original)
+++ lld/trunk/ELF/ICF.cpp Tue Apr  3 10:27:39 2018
@@ -362,17 +362,12 @@ template <class ELFT> size_t ICF<ELFT>::
 // vector. Therefore, Sections vector can be considered as contiguous
 // groups of sections, grouped by the class.
 //
-// This function calls Fn on every group that starts within [Begin, End).
-// Note that a group must start in that range but doesn't necessarily
-// have to end before End.
+// This function calls Fn on every group within [Begin, End).
 template <class ELFT>
 void ICF<ELFT>::forEachClassRange(size_t Begin, size_t End,
                                   std::function<void(size_t, size_t)> Fn) {
-  if (Begin > 0)
-    Begin = findBoundary(Begin - 1, End);
-
   while (Begin < End) {
-    size_t Mid = findBoundary(Begin, Sections.size());
+    size_t Mid = findBoundary(Begin, End);
     Fn(Begin, Mid);
     Begin = Mid;
   }
@@ -392,12 +387,23 @@ void ICF<ELFT>::forEachClass(std::functi
   Current = Cnt % 2;
   Next = (Cnt + 1) % 2;
 
-  // Split sections into 256 shards and call Fn in parallel.
-  size_t NumShards = 256;
+  // Shard into non-overlapping intervals, and call Fn in parallel.
+  // The sharding must be completed before any calls to Fn are made
+  // so that Fn can modify the Chunks in its shard without causing data
+  // races.
+  const size_t NumShards = 256;
   size_t Step = Sections.size() / NumShards;
-  parallelForEachN(0, NumShards, [&](size_t I) {
-    size_t End = (I == NumShards - 1) ? Sections.size() : (I + 1) * Step;
-    forEachClassRange(I * Step, End, Fn);
+  size_t Boundaries[NumShards + 1];
+  Boundaries[0] = 0;
+  Boundaries[NumShards] = Sections.size();
+
+  parallelForEachN(1, NumShards, [&](size_t I) {
+    Boundaries[I] = findBoundary((I - 1) * Step, Sections.size());
+  });
+
+  parallelForEachN(1, NumShards + 1, [&](size_t I) {
+    if (Boundaries[I - 1] < Boundaries[I])
+      forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn);
   });
   ++Cnt;
 }




More information about the llvm-commits mailing list