diff options
author | Bob Haarman <llvm@inglorion.net> | 2018-04-17 23:37:18 +0000 |
---|---|---|
committer | Bob Haarman <llvm@inglorion.net> | 2018-04-17 23:37:18 +0000 |
commit | 37a9269cc75a03665ab78eeff4cead1509e1770d (patch) | |
tree | 51b58dee86415ab920c830852e995d4bff300a6a /llvm/lib/Support/Statistic.cpp | |
parent | 3108802f1696a3635d7e1edcc3fbe523381ed5df (diff) | |
download | bcm5719-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.cpp | 15 |
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); |