[lld] r203889 - [PECOFF] Make WinLinkDriver::parse() and allocate*() functions thread-safe.
Rui Ueyama
ruiu at google.com
Thu Mar 13 21:28:38 PDT 2014
Author: ruiu
Date: Thu Mar 13 23:28:38 2014
New Revision: 203889
URL: http://llvm.org/viewvc/llvm-project?rev=203889&view=rev
Log:
[PECOFF] Make WinLinkDriver::parse() and allocate*() functions thread-safe.
Looks like a major cause of instability on Windows is this thread-safety bug.
Modified:
lld/trunk/include/lld/Driver/Driver.h
lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
lld/trunk/lib/Driver/WinLinkDriver.cpp
Modified: lld/trunk/include/lld/Driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/Driver.h?rev=203889&r1=203888&r2=203889&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/Driver.h (original)
+++ lld/trunk/include/lld/Driver/Driver.h Thu Mar 13 23:28:38 2014
@@ -115,6 +115,9 @@ public:
bool isDirective = false);
private:
+ static bool doParse(int argc, const char *argv[], PECOFFLinkingContext &info,
+ raw_ostream &diagnostics, bool isDirective);
+
WinLinkDriver() LLVM_DELETED_FUNCTION;
};
Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=203889&r1=203888&r2=203889&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Thu Mar 13 23:28:38 2014
@@ -19,6 +19,7 @@
#include "llvm/Support/COFF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/Mutex.h"
#include <map>
#include <set>
@@ -35,9 +36,10 @@ class Group;
class PECOFFLinkingContext : public LinkingContext {
public:
PECOFFLinkingContext()
- : _baseAddress(invalidBaseAddress), _stackReserve(1024 * 1024),
- _stackCommit(4096), _heapReserve(1024 * 1024), _heapCommit(4096),
- _noDefaultLibAll(false), _sectionDefaultAlignment(4096),
+ : _mutex(true), _allocMutex(false), _baseAddress(invalidBaseAddress),
+ _stackReserve(1024 * 1024), _stackCommit(4096),
+ _heapReserve(1024 * 1024), _heapCommit(4096), _noDefaultLibAll(false),
+ _sectionDefaultAlignment(4096),
_subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
_machineType(llvm::COFF::IMAGE_FILE_MACHINE_I386), _imageVersion(0, 0),
_minOSVersion(6, 0), _nxCompat(true), _largeAddressAware(false),
@@ -234,7 +236,9 @@ public:
const std::set<ExportDesc> &getDllExports() const { return _dllExports; }
StringRef allocate(StringRef ref) const {
+ _allocMutex.acquire();
char *x = _allocator.Allocate<char>(ref.size() + 1);
+ _allocMutex.release();
memcpy(x, ref.data(), ref.size());
x[ref.size()] = '\0';
return x;
@@ -242,13 +246,18 @@ public:
ArrayRef<uint8_t> allocate(ArrayRef<uint8_t> array) const {
size_t size = array.size();
+ _allocMutex.acquire();
uint8_t *p = _allocator.Allocate<uint8_t>(size);
+ _allocMutex.release();
memcpy(p, array.data(), size);
return ArrayRef<uint8_t>(p, p + array.size());
}
template <typename T> T &allocateCopy(const T &x) const {
- return *new (_allocator) T(x);
+ _allocMutex.acquire();
+ T *r = new (_allocator) T(x);
+ _allocMutex.release();
+ return *r;
}
virtual bool hasInputGraph() { return !!_inputGraph; }
@@ -256,6 +265,9 @@ public:
void setLibraryGroup(Group *group) { _libraryGroup = group; }
Group *getLibraryGroup() const { return _libraryGroup; }
+ void lock() { _mutex.acquire(); }
+ void unlock() { _mutex.release(); }
+
protected:
/// Method to create a internal file for the entry symbol
std::unique_ptr<File> createEntrySymbolFile() const override;
@@ -268,7 +280,10 @@ private:
invalidBaseAddress = UINT64_MAX,
pe32DefaultBaseAddress = 0x400000U,
pe32PlusDefaultBaseAddress = 0x140000000U
- };
+ };
+
+ llvm::sys::SmartMutex<false> _mutex;
+ mutable llvm::sys::SmartMutex<false> _allocMutex;
// The start address for the program. The default value for the executable is
// 0x400000, but can be altered using /base command line option.
Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=203889&r1=203888&r2=203889&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Thu Mar 13 23:28:38 2014
@@ -767,9 +767,9 @@ bool WinLinkDriver::linkPECOFF(int argc,
return link(context, diag);
}
-bool WinLinkDriver::parse(int argc, const char *argv[],
- PECOFFLinkingContext &ctx, raw_ostream &diag,
- bool isReadingDirectiveSection) {
+bool WinLinkDriver::doParse(int argc, const char *argv[],
+ PECOFFLinkingContext &ctx, raw_ostream &diag,
+ bool isReadingDirectiveSection) {
std::map<StringRef, StringRef> failIfMismatchMap;
// Parse the options.
std::unique_ptr<llvm::opt::InputArgList> parsedArgs =
@@ -1251,4 +1251,16 @@ bool WinLinkDriver::parse(int argc, cons
return ctx.validate(diag);
}
+// Parse may be called from multiple threads simultaneously to parse .drectve
+// sections. doParse() is not thread-safe because it mutates the context
+// object. This function wraps doParse() with a mutex.
+bool WinLinkDriver::parse(int argc, const char *argv[],
+ PECOFFLinkingContext &ctx, raw_ostream &diag,
+ bool isReadingDirectiveSection) {
+ ctx.lock();
+ bool r = doParse(argc, argv, ctx, diag, isReadingDirectiveSection);
+ ctx.unlock();
+ return r;
+}
+
} // namespace lld
More information about the llvm-commits
mailing list