[PATCH] D45398: Fix lock order inversion between ManagedStatic and Statistic

Bob Haarman via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 9 11:36:52 PDT 2018


inglorion updated this revision to Diff 141696.
inglorion added a comment.

Thanks for looking, @dsanders. Does this comment make things clearer?


https://reviews.llvm.org/D45398

Files:
  llvm/lib/Support/Statistic.cpp


Index: llvm/lib/Support/Statistic.cpp
===================================================================
--- llvm/lib/Support/Statistic.cpp
+++ llvm/lib/Support/Statistic.cpp
@@ -94,10 +94,21 @@
 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 include 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);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D45398.141696.patch
Type: text/x-patch
Size: 1293 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180409/90db7a9a/attachment.bin>


More information about the llvm-commits mailing list