diff options
| -rw-r--r-- | lld/ELF/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lld/ELF/Driver.cpp | 1 | ||||
| -rw-r--r-- | lld/ELF/Error.cpp | 3 | ||||
| -rw-r--r-- | lld/ELF/Filesystem.cpp | 6 | ||||
| -rw-r--r-- | lld/ELF/Threads.cpp | 29 | ||||
| -rw-r--r-- | lld/ELF/Threads.h | 4 |
6 files changed, 41 insertions, 3 deletions
diff --git a/lld/ELF/CMakeLists.txt b/lld/ELF/CMakeLists.txt index 42e80551a63..e53626af3ef 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -40,6 +40,7 @@ add_lld_library(lldELF Symbols.cpp SyntheticSections.cpp Target.cpp + Threads.cpp Thunks.cpp Writer.cpp diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 32d4c2df35b..d1412756c96 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -89,6 +89,7 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, Config->Argv = {Args.begin(), Args.end()}; Driver->main(Args, CanExitEarly); + waitForBackgroundThreads(); // Exit immediately if we don't need to return to the caller. // This saves time because the overhead of calling destructors diff --git a/lld/ELF/Error.cpp b/lld/ELF/Error.cpp index dce57776ebe..f2d40a01306 100644 --- a/lld/ELF/Error.cpp +++ b/lld/ELF/Error.cpp @@ -9,6 +9,7 @@ #include "Error.h" #include "Config.h" +#include "Threads.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Error.h" @@ -100,6 +101,8 @@ void elf::error(const Twine &Msg) { } void elf::exitLld(int Val) { + waitForBackgroundThreads(); + // Dealloc/destroy ManagedStatic variables before calling // _exit(). In a non-LTO build, this is a nop. In an LTO // build allows us to get the output of -time-passes. diff --git a/lld/ELF/Filesystem.cpp b/lld/ELF/Filesystem.cpp index d468ae0c618..03dd2e8d177 100644 --- a/lld/ELF/Filesystem.cpp +++ b/lld/ELF/Filesystem.cpp @@ -13,9 +13,9 @@ #include "Filesystem.h" #include "Config.h" -#include "llvm/Support/FileSystem.h" +#include "Threads.h" #include "llvm/Support/FileOutputBuffer.h" -#include <thread> +#include "llvm/Support/FileSystem.h" using namespace llvm; @@ -55,7 +55,7 @@ void elf::unlinkAsync(StringRef Path) { } // Remove TempPath in background. - std::thread([=] { ::remove(TempPath.str().str().c_str()); }).detach(); + runBackground([=] { ::remove(TempPath.str().str().c_str()); }); } // Simulate file creation to see if Path is writable. diff --git a/lld/ELF/Threads.cpp b/lld/ELF/Threads.cpp new file mode 100644 index 00000000000..b3625b9e278 --- /dev/null +++ b/lld/ELF/Threads.cpp @@ -0,0 +1,29 @@ +//===- Threads.cpp --------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Threads.h" +#include <thread> + +static std::vector<std::thread> Threads; + +// Runs a given function in a new thread. +void lld::elf::runBackground(std::function<void()> Fn) { + Threads.emplace_back(Fn); +} + +// Wait for all threads spawned for runBackground() to finish. +// +// You need to call this function from the main thread before exiting +// because it is not defined what will happen to non-main threads when +// the main thread exits. +void lld::elf::waitForBackgroundThreads() { + for (std::thread &T : Threads) + if (T.joinable()) + T.join(); +} diff --git a/lld/ELF/Threads.h b/lld/ELF/Threads.h index 2df0204be58..f29e4e96f99 100644 --- a/lld/ELF/Threads.h +++ b/lld/ELF/Threads.h @@ -81,6 +81,10 @@ inline void parallelForEachN(size_t Begin, size_t End, else for_each_n(llvm::parallel::seq, Begin, End, Fn); } + +void runBackground(std::function<void()> Fn); +void waitForBackgroundThreads(); + } // namespace elf } // namespace lld |

