jankratochvil updated this revision to Diff 149037.
jankratochvil edited the summary of this revision.

https://reviews.llvm.org/D40470

Files:
  source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
  source/Plugins/SymbolFile/DWARF/DWARFUnit.h

Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -13,6 +13,7 @@
 #include "DWARFDIE.h"
 #include "DWARFDebugInfoEntry.h"
 #include "lldb/lldb-enumerations.h"
+#include "llvm/Support/RWMutex.h"
 
 class DWARFUnit;
 class DWARFCompileUnit;
@@ -172,10 +173,17 @@
   void *m_user_data = nullptr;
   // The compile unit debug information entry item
   DWARFDebugInfoEntry::collection m_die_array;
+  mutable llvm::sys::RWMutex m_die_array_mutex;
+  // It gets increased by ExtractDIEsIfNeeded() and decreased by ClearDIEs().
+  // BuildAddressRangeTable and SymbolFileDWARF::Index can populate m_die_array
+  // only temporarily while other functions calling only
+  // ExtractDIEsIfNeeded() will keep m_die_array populated forever.
+  uint32_t m_die_array_usecount = 0;
   // GetUnitDIEPtrOnly() needs to return pointer to the first DIE.
   // But the first element of m_die_array after ExtractUnitDIEIfNeeded()
   // would possibly move in memory after later ExtractDIEsIfNeeded().
   DWARFDebugInfoEntry m_first_die;
+  llvm::sys::RWMutex m_first_die_mutex;
   // A table similar to the .debug_aranges table, but this one points to the
   // exact DW_TAG_subprogram DIEs
   std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap;
@@ -206,14 +214,17 @@
   // if needed.
   const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
     ExtractUnitDIEIfNeeded();
+    // m_first_die_mutex is not required as m_first_die is never cleared.
     if (!m_first_die)
       return NULL;
     return &m_first_die;
   }
 
   // Get all DWARF debug informration entries. Parse all DIEs if needed.
   const DWARFDebugInfoEntry *DIEPtr() {
     ExtractDIEsIfNeeded();
+    // m_die_array_mutex is not required as ExtractDIEsIfNeeded() has not
+    // been matched by ClearDIEs().
     if (m_die_array.empty())
       return NULL;
     return &m_die_array[0];
Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -39,6 +39,12 @@
 // Parses first DIE of a compile unit.
 //----------------------------------------------------------------------
 void DWARFUnit::ExtractUnitDIEIfNeeded() {
+  {
+    llvm::sys::ScopedReader lock(m_first_die_mutex);
+    if (m_first_die)
+      return; // Already parsed
+  }
+  llvm::sys::ScopedWriter lock(m_first_die_mutex);
   if (m_first_die)
     return; // Already parsed
 
@@ -69,8 +75,19 @@
 // Parses a compile unit and indexes its DIEs if it hasn't already been done.
 //----------------------------------------------------------------------
 bool DWARFUnit::ExtractDIEsIfNeeded() {
+  {
+    llvm::sys::ScopedReader lock(m_die_array_mutex);
+    if (!m_die_array.empty())
+      return 0; // Already parsed
+  }
+  llvm::sys::ScopedWriter lock(m_die_array_mutex);
   if (!m_die_array.empty())
     return 0; // Already parsed
+  // Protect against use count overflow.
+  if (m_die_array_usecount
+      < std::numeric_limits<decltype(m_die_array_usecount)>::max())
+    ++m_die_array_usecount;
+  llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex);
 
   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
   Timer scoped_timer(
@@ -227,6 +244,7 @@
   }
 }
 
+// m_die_array_mutex must be already held as read/write.
 void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
   uint64_t base_addr = cu_die.GetAttributeValueAsAddress(
       m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
@@ -280,11 +298,14 @@
 				    DWARFDIECollection &dies,
 				    uint32_t depth) const {
   size_t old_size = dies.Size();
-  DWARFDebugInfoEntry::const_iterator pos;
-  DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
-  for (pos = m_die_array.begin(); pos != end; ++pos) {
-    if (pos->Tag() == tag)
-      dies.Append(DWARFDIE(this, &(*pos)));
+  {
+    llvm::sys::ScopedReader lock(m_die_array_mutex);
+    DWARFDebugInfoEntry::const_iterator pos;
+    DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+    for (pos = m_die_array.begin(); pos != end; ++pos) {
+      if (pos->Tag() == tag)
+        dies.Append(DWARFDIE(this, &(*pos)));
+    }
   }
 
   // Return the number of DIEs added to the collection
@@ -325,9 +346,18 @@
   m_base_obj_offset = base_obj_offset;
 }
 
+// It may be called only after: ExtractDIEsIfNeeded() == true
 void DWARFUnit::ClearDIEs() {
-  m_die_array.clear();
-  m_die_array.shrink_to_fit();
+  {
+    llvm::sys::ScopedWriter lock(m_die_array_mutex);
+    lldbassert(!m_die_array.empty());
+    lldbassert(m_die_array_usecount > 0);
+    if (--m_die_array_usecount > 0)
+      return;
+
+    m_die_array.clear();
+    m_die_array.shrink_to_fit();
+  }
 
   if (m_dwo_symbol_file)
     m_dwo_symbol_file->GetCompileUnit()->ClearDIEs();
@@ -472,6 +502,8 @@
 
     if (ContainsDIEOffset(die_offset)) {
       ExtractDIEsIfNeeded();
+      // m_die_array_mutex is not required as ExtractDIEsIfNeeded() has
+      // not been matched by ClearDIEs().
       DWARFDebugInfoEntry::const_iterator end = m_die_array.cend();
       DWARFDebugInfoEntry::const_iterator pos =
           lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to