Skip to content

Commit

Permalink
[lld] fix data race in ELF/ICF.cpp
Browse files Browse the repository at this point in the history
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

llvm-svn: 329088
  • Loading branch information
inglorion committed Apr 3, 2018
1 parent 901acfa commit 8c63baf
Showing 1 changed file with 18 additions and 12 deletions.
30 changes: 18 additions & 12 deletions lld/ELF/ICF.cpp
Expand Up @@ -362,17 +362,12 @@ template <class ELFT> size_t ICF<ELFT>::findBoundary(size_t Begin, size_t End) {
// 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;
}
Expand All @@ -392,12 +387,23 @@ void ICF<ELFT>::forEachClass(std::function<void(size_t, size_t)> Fn) {
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;
}
Expand Down

0 comments on commit 8c63baf

Please sign in to comment.