diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -489,8 +489,7 @@ class RelocationBaseSection : public SyntheticSection { public: RelocationBaseSection(StringRef name, uint32_t type, int32_t dynamicTag, - int32_t sizeDynamicTag, bool combreloc, - unsigned concurrency); + int32_t sizeDynamicTag, bool combreloc); /// Add a dynamic relocation without writing an addend to the output section. /// This overload can be used if the addends are written directly instead of /// using relocations on the input section (e.g. MipsGotSection::writeTo()). @@ -566,7 +565,7 @@ using Elf_Rela = typename ELFT::Rela; public: - RelocationSection(StringRef name, bool combreloc, unsigned concurrency); + RelocationSection(StringRef name, bool combreloc); void writeTo(uint8_t *buf) override; }; @@ -576,7 +575,7 @@ using Elf_Rela = typename ELFT::Rela; public: - AndroidPackedRelocationSection(StringRef name, unsigned concurrency); + AndroidPackedRelocationSection(StringRef name); bool updateAllocSize() override; size_t getSize() const override { return relocData.size(); } @@ -597,7 +596,7 @@ class RelrBaseSection : public SyntheticSection { public: - RelrBaseSection(unsigned concurrency); + RelrBaseSection(); void mergeRels(); bool isNeeded() const override { return !relocs.empty() || @@ -615,7 +614,7 @@ using Elf_Relr = typename ELFT::Relr; public: - RelrSection(unsigned concurrency); + RelrSection(); bool updateAllocSize() override; size_t getSize() const override { return relrRelocs.size() * this->entsize; } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1582,11 +1582,10 @@ RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type, int32_t dynamicTag, int32_t sizeDynamicTag, - bool combreloc, - unsigned concurrency) + bool combreloc) : SyntheticSection(SHF_ALLOC, type, config->wordsize, name), dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag), - relocsVec(concurrency), combreloc(combreloc) {} + relocsVec(llvm::parallel::getMaxThreadsNum()), combreloc(combreloc) {} void RelocationBaseSection::addSymbolReloc( RelType dynType, InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym, @@ -1673,12 +1672,10 @@ } template -RelocationSection::RelocationSection(StringRef name, bool combreloc, - unsigned concurrency) +RelocationSection::RelocationSection(StringRef name, bool combreloc) : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL, config->isRela ? DT_RELA : DT_REL, - config->isRela ? DT_RELASZ : DT_RELSZ, combreloc, - concurrency) { + config->isRela ? DT_RELASZ : DT_RELSZ, combreloc) { this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); } @@ -1694,11 +1691,11 @@ } } -RelrBaseSection::RelrBaseSection(unsigned concurrency) +RelrBaseSection::RelrBaseSection() : SyntheticSection(SHF_ALLOC, config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR, config->wordsize, ".relr.dyn"), - relocsVec(concurrency) {} + relocsVec(llvm::parallel::getMaxThreadsNum()) {} void RelrBaseSection::mergeRels() { size_t newSize = relocs.size(); @@ -1712,12 +1709,12 @@ template AndroidPackedRelocationSection::AndroidPackedRelocationSection( - StringRef name, unsigned concurrency) + StringRef name) : RelocationBaseSection( name, config->isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL, config->isRela ? DT_ANDROID_RELA : DT_ANDROID_REL, config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ, - /*combreloc=*/false, concurrency) { + /*combreloc=*/false) { this->entsize = 1; } @@ -1964,9 +1961,7 @@ return relocData.size() != oldSize; } -template -RelrSection::RelrSection(unsigned concurrency) - : RelrBaseSection(concurrency) { +template RelrSection::RelrSection() : RelrBaseSection() { this->entsize = config->wordsize; } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -317,7 +317,6 @@ StringRef relaDynName = config->isRela ? ".rela.dyn" : ".rel.dyn"; - const unsigned threadCount = config->threadCount; for (Partition &part : partitions) { auto add = [&](SyntheticSection &sec) { sec.partition = part.getNumber(); @@ -351,11 +350,11 @@ } if (config->androidPackDynRelocs) - part.relaDyn = std::make_unique>( - relaDynName, threadCount); + part.relaDyn = + std::make_unique>(relaDynName); else part.relaDyn = std::make_unique>( - relaDynName, config->zCombreloc, threadCount); + relaDynName, config->zCombreloc); if (config->hasDynSymTab) { add(*part.dynSymTab); @@ -387,7 +386,7 @@ } if (config->relrPackDynRelocs) { - part.relrDyn = std::make_unique>(threadCount); + part.relrDyn = std::make_unique>(); add(*part.relrDyn); } @@ -468,8 +467,7 @@ // We always need to add rel[a].plt to output if it has entries. // Even for static linking it can contain R_[*]_IRELATIVE relocations. in.relaPlt = std::make_unique>( - config->isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false, - /*threadCount=*/1); + config->isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false); add(*in.relaPlt); // The relaIplt immediately follows .rel[a].dyn to ensure that the IRelative @@ -480,7 +478,7 @@ // behaviour by placing the iplt section in .rel.plt. in.relaIplt = std::make_unique>( config->androidPackDynRelocs ? in.relaPlt->name : relaDynName, - /*sort=*/false, /*threadCount=*/1); + /*sort=*/false); add(*in.relaIplt); if ((config->emachine == EM_386 || config->emachine == EM_X86_64) && diff --git a/llvm/include/llvm/Support/Parallel.h b/llvm/include/llvm/Support/Parallel.h --- a/llvm/include/llvm/Support/Parallel.h +++ b/llvm/include/llvm/Support/Parallel.h @@ -40,8 +40,11 @@ inline unsigned getThreadIndex() { return threadIndex; } #endif + +size_t getMaxThreadsNum(); #else inline unsigned getThreadIndex() { return 0; } +inline size_t getMaxThreadsNum() { return 1; } #endif namespace detail { diff --git a/llvm/lib/Support/Parallel.cpp b/llvm/lib/Support/Parallel.cpp --- a/llvm/lib/Support/Parallel.cpp +++ b/llvm/lib/Support/Parallel.cpp @@ -24,11 +24,13 @@ #if LLVM_ENABLE_THREADS #ifdef _WIN32 -static thread_local unsigned threadIndex; +// Initialize thread index with zero for main thread. +static thread_local unsigned threadIndex = 0; unsigned getThreadIndex() { return threadIndex; } #else -thread_local unsigned threadIndex; +// Initialize thread index with zero for main thread. +thread_local unsigned threadIndex = 0; #endif namespace detail { @@ -40,6 +42,7 @@ public: virtual ~Executor() = default; virtual void add(std::function func) = 0; + virtual size_t getThreadsNum() const = 0; static Executor *getDefaultExecutor(); }; @@ -49,20 +52,21 @@ class ThreadPoolExecutor : public Executor { public: explicit ThreadPoolExecutor(ThreadPoolStrategy S = hardware_concurrency()) { - unsigned ThreadCount = S.compute_thread_count(); + ThreadCount = S.compute_thread_count(); // Spawn all but one of the threads in another thread as spawning threads // can take a while. Threads.reserve(ThreadCount); Threads.resize(1); std::lock_guard Lock(Mutex); - Threads[0] = std::thread([this, ThreadCount, S] { + Threads[0] = std::thread([this, S] { for (unsigned I = 1; I < ThreadCount; ++I) { - Threads.emplace_back([=] { work(S, I); }); + Threads.emplace_back([=] { work(S, I + 1); }); if (Stop) break; } ThreadsCreated.set_value(); - work(S, 0); + // Start thread indexes from 1, as 0 is used for main thread. + work(S, 1); }); } @@ -102,6 +106,11 @@ Cond.notify_one(); } + size_t getThreadsNum() const override { + // Return number of created threads plus main thread. + return ThreadCount + 1; + } + private: void work(ThreadPoolStrategy S, unsigned ThreadID) { threadIndex = ThreadID; @@ -124,6 +133,7 @@ std::condition_variable Cond; std::promise ThreadsCreated; std::vector Threads; + unsigned ThreadCount; }; Executor *Executor::getDefaultExecutor() { @@ -155,6 +165,10 @@ } // namespace detail #endif +size_t getMaxThreadsNum() { + return detail::Executor::getDefaultExecutor()->getThreadsNum(); +} + static std::atomic TaskGroupInstances; // Latch::sync() called by the dtor may cause one thread to block. If is a dead