summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support/Statistic.cpp
diff options
context:
space:
mode:
authorBob Haarman <llvm@inglorion.net>2018-04-17 23:37:18 +0000
committerBob Haarman <llvm@inglorion.net>2018-04-17 23:37:18 +0000
commit37a9269cc75a03665ab78eeff4cead1509e1770d (patch)
tree51b58dee86415ab920c830852e995d4bff300a6a /llvm/lib/Support/Statistic.cpp
parent3108802f1696a3635d7e1edcc3fbe523381ed5df (diff)
downloadbcm5719-llvm-37a9269cc75a03665ab78eeff4cead1509e1770d.tar.gz
bcm5719-llvm-37a9269cc75a03665ab78eeff4cead1509e1770d.zip
Fix lock order inversion between ManagedStatic and Statistic
Summary: Statistic and ManagedStatic both use mutexes. There was a lock order inversion where, during initialization, Statistic's mutex would be held while taking ManagedStatic's, and in llvm_shutdown, ManagedStatic's mutex would be held while taking Statistic's mutex. This change causes Statistic's initialization code to avoid holding its mutex while calling ManagedStatic's methods, avoiding the inversion. Reviewers: dsanders, rtereshin Reviewed By: dsanders Subscribers: hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D45398 llvm-svn: 330236
Diffstat (limited to 'llvm/lib/Support/Statistic.cpp')
-rw-r--r--llvm/lib/Support/Statistic.cpp15
1 files changed, 13 insertions, 2 deletions
diff --git a/llvm/lib/Support/Statistic.cpp b/llvm/lib/Support/Statistic.cpp
index 3f54374c670..d57300a75d1 100644
--- a/llvm/lib/Support/Statistic.cpp
+++ b/llvm/lib/Support/Statistic.cpp
@@ -94,10 +94,21 @@ static ManagedStatic<sys::SmartMutex<true> > StatLock;
void Statistic::RegisterStatistic() {
// If stats are enabled, inform StatInfo that this statistic should be
// printed.
- sys::SmartScopedLock<true> Writer(*StatLock);
+ // llvm_shutdown calls destructors while holding the ManagedStatic mutex.
+ // These destructors end up calling PrintStatistics, which takes StatLock.
+ // Since dereferencing StatInfo and StatLock can require taking the
+ // ManagedStatic mutex, doing so with StatLock held would lead to a lock
+ // order inversion. To avoid that, we dereference the ManagedStatics first,
+ // and only take StatLock afterwards.
if (!Initialized.load(std::memory_order_relaxed)) {
+ sys::SmartMutex<true> &Lock = *StatLock;
+ StatisticInfo &SI = *StatInfo;
+ sys::SmartScopedLock<true> Writer(Lock);
+ // Check Initialized again after acquiring the lock.
+ if (Initialized.load(std::memory_order_relaxed))
+ return;
if (Stats || Enabled)
- StatInfo->addStatistic(this);
+ SI.addStatistic(this);
// Remember we have been registered.
Initialized.store(true, std::memory_order_release);
OpenPOWER on IntegriCloud