From: Bob Haarman Date: Tue, 17 Apr 2018 23:37:18 +0000 (+0000) Subject: Fix lock order inversion between ManagedStatic and Statistic X-Git-Tag: android-x86-7.1-r4~2228 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=91cfb1b3cd220bdf6511e817bb72fbfe1dddb2df;p=android-x86%2Fexternal-llvm.git 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@330236 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Support/Statistic.cpp b/lib/Support/Statistic.cpp index 3f54374c670..d57300a75d1 100644 --- a/lib/Support/Statistic.cpp +++ b/lib/Support/Statistic.cpp @@ -94,10 +94,21 @@ static ManagedStatic > StatLock; void Statistic::RegisterStatistic() { // If stats are enabled, inform StatInfo that this statistic should be // printed. - sys::SmartScopedLock 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 &Lock = *StatLock; + StatisticInfo &SI = *StatInfo; + sys::SmartScopedLock 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);