[llvm] r330236 - Fix lock order inversion between ManagedStatic and Statistic
Bob Haarman via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 17 16:37:18 PDT 2018
Author: inglorion
Date: Tue Apr 17 16:37:18 2018
New Revision: 330236
URL: http://llvm.org/viewvc/llvm-project?rev=330236&view=rev
Log:
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
Modified:
llvm/trunk/lib/Support/Statistic.cpp
Modified: llvm/trunk/lib/Support/Statistic.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Statistic.cpp?rev=330236&r1=330235&r2=330236&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Statistic.cpp (original)
+++ llvm/trunk/lib/Support/Statistic.cpp Tue Apr 17 16:37:18 2018
@@ -94,10 +94,21 @@ static ManagedStatic<sys::SmartMutex<tru
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);
More information about the llvm-commits
mailing list