mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 00:20:25 +08:00
[libclang] Implement ConcurrencyCheck using a recursive mutex to allow re-entrancy in the same thread.
The checks are performed only in DEBUG, it becomes no-op in release mode. llvm-svn: 141582
This commit is contained in:
@@ -151,16 +151,6 @@ private:
|
||||
/// destroyed.
|
||||
SmallVector<llvm::sys::Path, 4> TemporaryFiles;
|
||||
|
||||
/// \brief Simple hack to allow us to assert that ASTUnit is not being
|
||||
/// used concurrently, which is not supported.
|
||||
///
|
||||
/// Clients should create instances of the ConcurrencyCheck class whenever
|
||||
/// using the ASTUnit in a way that isn't intended to be concurrent, which is
|
||||
/// just about any usage.
|
||||
unsigned int ConcurrencyCheckValue;
|
||||
static const unsigned int CheckLocked = 28573289;
|
||||
static const unsigned int CheckUnlocked = 9803453;
|
||||
|
||||
/// \brief Counter that determines when we want to try building a
|
||||
/// precompiled preamble.
|
||||
///
|
||||
@@ -406,21 +396,37 @@ private:
|
||||
unsigned MaxLines = 0);
|
||||
void RealizeTopLevelDeclsFromPreamble();
|
||||
|
||||
/// \brief Allows us to assert that ASTUnit is not being used concurrently,
|
||||
/// which is not supported.
|
||||
///
|
||||
/// Clients should create instances of the ConcurrencyCheck class whenever
|
||||
/// using the ASTUnit in a way that isn't intended to be concurrent, which is
|
||||
/// just about any usage.
|
||||
/// Becomes a noop in release mode; only useful for debug mode checking.
|
||||
class ConcurrencyState {
|
||||
void *Mutex; // a llvm::sys::MutexImpl in debug;
|
||||
|
||||
public:
|
||||
ConcurrencyState();
|
||||
~ConcurrencyState();
|
||||
|
||||
void start();
|
||||
void finish();
|
||||
};
|
||||
ConcurrencyState ConcurrencyCheckValue;
|
||||
|
||||
public:
|
||||
class ConcurrencyCheck {
|
||||
volatile ASTUnit &Self;
|
||||
ASTUnit &Self;
|
||||
|
||||
public:
|
||||
explicit ConcurrencyCheck(ASTUnit &Self)
|
||||
: Self(Self)
|
||||
{
|
||||
assert(Self.ConcurrencyCheckValue == CheckUnlocked &&
|
||||
"Concurrent access to ASTUnit!");
|
||||
Self.ConcurrencyCheckValue = CheckLocked;
|
||||
Self.ConcurrencyCheckValue.start();
|
||||
}
|
||||
|
||||
~ConcurrencyCheck() {
|
||||
Self.ConcurrencyCheckValue = CheckUnlocked;
|
||||
Self.ConcurrencyCheckValue.finish();
|
||||
}
|
||||
};
|
||||
friend class ConcurrencyCheck;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Mutex.h"
|
||||
#include "llvm/Support/CrashRecoveryContext.h"
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
@@ -99,7 +100,6 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
|
||||
TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
|
||||
OwnsRemappedFileBuffers(true),
|
||||
NumStoredDiagnosticsFromDriver(0),
|
||||
ConcurrencyCheckValue(CheckUnlocked),
|
||||
PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
|
||||
ShouldCacheCodeCompletionResults(false),
|
||||
NestedMacroExpansions(true),
|
||||
@@ -114,7 +114,6 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
|
||||
}
|
||||
|
||||
ASTUnit::~ASTUnit() {
|
||||
ConcurrencyCheckValue = CheckLocked;
|
||||
CleanTemporaryFiles();
|
||||
if (!PreambleFile.empty())
|
||||
llvm::sys::Path(PreambleFile).eraseFromDisk();
|
||||
@@ -2414,3 +2413,30 @@ void ASTUnit::PreambleData::countLines() const {
|
||||
if (Buffer.back() != '\n')
|
||||
++NumLines;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
ASTUnit::ConcurrencyState::ConcurrencyState() {
|
||||
Mutex = new llvm::sys::MutexImpl(/*recursive=*/true);
|
||||
}
|
||||
|
||||
ASTUnit::ConcurrencyState::~ConcurrencyState() {
|
||||
delete static_cast<llvm::sys::MutexImpl *>(Mutex);
|
||||
}
|
||||
|
||||
void ASTUnit::ConcurrencyState::start() {
|
||||
bool acquired = static_cast<llvm::sys::MutexImpl *>(Mutex)->tryacquire();
|
||||
assert(acquired && "Concurrent access to ASTUnit!");
|
||||
}
|
||||
|
||||
void ASTUnit::ConcurrencyState::finish() {
|
||||
static_cast<llvm::sys::MutexImpl *>(Mutex)->release();
|
||||
}
|
||||
|
||||
#else // NDEBUG
|
||||
|
||||
ASTUnit::ConcurrencyState::ConcurrencyState() {}
|
||||
ASTUnit::ConcurrencyState::~ConcurrencyState() {}
|
||||
void ASTUnit::ConcurrencyState::start() {}
|
||||
void ASTUnit::ConcurrencyState::finish() {}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user