Skip to content

Commit

Permalink
[lld] fix data race in ICF.cpp
Browse files Browse the repository at this point in the history
Summary: Fixes PR36823.

Reviewers: ruiu, pcc, rnk

Reviewed By: ruiu

Subscribers: llvm-commits

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

llvm-svn: 328610
  • Loading branch information
inglorion committed Mar 27, 2018
1 parent a63d333 commit 3ddeb33
Showing 1 changed file with 17 additions and 9 deletions.
26 changes: 17 additions & 9 deletions lld/COFF/ICF.cpp
Original file line number Diff line number Diff line change
@@ -168,6 +168,7 @@ bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) {
return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq);
}

// Find the first Chunk after Begin that has a different class from Begin.
size_t ICF::findBoundary(size_t Begin, size_t End) {
for (size_t I = Begin + 1; I < End; ++I)
if (Chunks[Begin]->Class[Cnt % 2] != Chunks[I]->Class[Cnt % 2])
@@ -177,11 +178,8 @@ size_t ICF::findBoundary(size_t Begin, size_t End) {

void ICF::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, Chunks.size());
size_t Mid = findBoundary(Begin, End);
Fn(Begin, Mid);
Begin = Mid;
}
@@ -197,12 +195,22 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {
return;
}

// 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 = Chunks.size() / NumShards;
for_each_n(parallel::par, size_t(0), NumShards, [&](size_t I) {
size_t End = (I == NumShards - 1) ? Chunks.size() : (I + 1) * Step;
forEachClassRange(I * Step, End, Fn);
size_t Boundaries[NumShards + 1];
Boundaries[0] = 0;
Boundaries[NumShards] = Chunks.size();
for_each_n(parallel::par, size_t(1), NumShards, [&](size_t I) {
Boundaries[I] = findBoundary((I - 1) * Step, Chunks.size());
});
for_each_n(parallel::par, size_t(1), NumShards + 1, [&](size_t I) {
if (Boundaries[I - 1] < Boundaries[I]) {
forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn);
}
});
++Cnt;
}

0 comments on commit 3ddeb33

Please sign in to comment.