forked from OSchip/llvm-project
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
This commit is contained in:
parent
3108802f16
commit
37a9269cc7
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue