tberghammer created this revision.
tberghammer added reviewers: labath, clayborg.
tberghammer added a subscriber: lldb-commits.

Make SymbolFileDWARF::GetCachedSectionData thread safe

http://reviews.llvm.org/D13942

Files:
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h

Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -23,11 +23,6 @@
 
     ~SymbolFileDWARFDwo() override = default;
     
-    const lldb_private::DWARFDataExtractor&
-    GetCachedSectionData(uint32_t got_flag,
-                         lldb::SectionType sect_type,
-                         lldb_private::DWARFDataExtractor &data) override;
-    
     lldb::CompUnitSP
     ParseCompileUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) override;
 
@@ -44,6 +39,9 @@
     GetTypeSystemForLanguage(lldb::LanguageType language) override;
 
 protected:
+    const lldb_private::DWARFDataExtractor&
+    GetSectionDataNoLock(lldb::SectionType sect_type, DWARFDataSegment& data_segment) override;
+
     DIEToTypePtr&
     GetDIEToType() override;
 
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -28,37 +28,37 @@
 }
 
 const lldb_private::DWARFDataExtractor&
-SymbolFileDWARFDwo::GetCachedSectionData(uint32_t got_flag,
-                                         lldb::SectionType sect_type,
-                                         lldb_private::DWARFDataExtractor &data)
+SymbolFileDWARFDwo::GetSectionDataNoLock(lldb::SectionType sect_type,
+                                         DWARFDataSegment& data_segment)
 {
-    if (!m_flags.IsClear (got_flag))
-        return data;
-
     const SectionList* section_list = m_obj_file->GetSectionList(false /* update_module_section_list */);
     if (section_list)
     {
         SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
         if (section_sp)
         {
             // See if we memory mapped the DWARF segment?
-            if (m_dwarf_data.GetByteSize())
+            std::lock_guard<std::mutex> dwarf_data_lock(m_dwarf_data.m_mutex);
+            if (m_dwarf_data.m_data.GetByteSize())
             {
-                data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize());
-                m_flags.Set (got_flag);
-                return data;
+                data_segment.m_data.SetData(m_dwarf_data.m_data,
+                                            section_sp->GetOffset (),
+                                            section_sp->GetFileSize());
+                data_segment.m_is_set.store(true);
+                return data_segment.m_data;
             }
 
-            if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0)
+            if (m_obj_file->ReadSectionData(section_sp.get(), data_segment.m_data) != 0)
             {
-                m_flags.Set (got_flag);
-                return data;
+                data_segment.m_is_set.store(true);
+                return data_segment.m_data;
             }
 
-            data.Clear();
+            data_segment.m_data.Clear();
         }
     }
-    return SymbolFileDWARF::GetCachedSectionData(got_flag, sect_type, data);
+
+    return SymbolFileDWARF::GetSectionDataNoLock(sect_type, data_segment);
 }
 
 lldb::CompUnitSP
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -14,6 +14,7 @@
 // C++ Includes
 #include <list>
 #include <map>
+#include <mutex>
 #include <set>
 #include <vector>
 
@@ -265,32 +266,16 @@
 
     DWARFDebugRanges*
     DebugRanges();
+
     const DWARFDebugRanges*
     DebugRanges() const;
 
-    virtual const lldb_private::DWARFDataExtractor&
-    GetCachedSectionData (uint32_t got_flag, 
-                          lldb::SectionType sect_type, 
-                          lldb_private::DWARFDataExtractor &data);
-
     static bool
     SupportedVersion(uint16_t version);
 
     DWARFDIE
     GetDeclContextDIEContainingDIE (const DWARFDIE &die);
 
-    lldb_private::Flags&
-    GetFlags ()
-    {
-        return m_flags;
-    }
-
-    const lldb_private::Flags&
-    GetFlags () const
-    {
-        return m_flags;
-    }
-
     bool
     HasForwardDeclForClangType (const lldb_private::CompilerType &compiler_type);
 
@@ -326,36 +311,32 @@
     typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::opaque_compiler_type_t> DIEToClangType;
     typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> ClangTypeToDIE;
 
-    enum
+    struct DWARFDataSegment
     {
-        flagsGotDebugAbbrevData     = (1 << 0),
-        flagsGotDebugAddrData       = (1 << 1),
-        flagsGotDebugArangesData    = (1 << 2),
-        flagsGotDebugFrameData      = (1 << 3),
-        flagsGotDebugInfoData       = (1 << 4),
-        flagsGotDebugLineData       = (1 << 5),
-        flagsGotDebugLocData        = (1 << 6),
-        flagsGotDebugMacInfoData    = (1 << 7),
-        flagsGotDebugPubNamesData   = (1 << 8),
-        flagsGotDebugPubTypesData   = (1 << 9),
-        flagsGotDebugRangesData     = (1 << 10),
-        flagsGotDebugStrData        = (1 << 11),
-        flagsGotDebugStrOffsetsData = (1 << 12),
-        flagsGotAppleNamesData      = (1 << 13),
-        flagsGotAppleTypesData      = (1 << 14),
-        flagsGotAppleNamespacesData = (1 << 15),
-        flagsGotAppleObjCData       = (1 << 16)
+        DWARFDataSegment() :
+            m_is_set (false)
+        {}
+
+        lldb_private::DWARFDataExtractor m_data;
+        std::atomic_bool                 m_is_set;
+        std::mutex                       m_mutex;
     };
-    
+
+    DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF);
+
+    const lldb_private::DWARFDataExtractor&
+    GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment);
+
+    virtual const lldb_private::DWARFDataExtractor&
+    GetSectionDataNoLock (lldb::SectionType sect_type, DWARFDataSegment& data_segment);
+
     bool
     DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx);
 
     bool
     DIEInDeclContext (const lldb_private::CompilerDeclContext *parent_decl_ctx,
                       const DWARFDIE &die);
 
-    DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF);
-
     virtual DWARFCompileUnit*
     GetDWARFCompileUnit (lldb_private::CompileUnit *comp_unit);
 
@@ -542,22 +523,22 @@
 
     lldb::ModuleWP                        m_debug_map_module_wp;
     SymbolFileDWARFDebugMap *             m_debug_map_symfile;
-    lldb_private::Flags                   m_flags;
-    lldb_private::DWARFDataExtractor      m_dwarf_data;
-    lldb_private::DWARFDataExtractor      m_data_debug_abbrev;
-    lldb_private::DWARFDataExtractor      m_data_debug_addr;
-    lldb_private::DWARFDataExtractor      m_data_debug_aranges;
-    lldb_private::DWARFDataExtractor      m_data_debug_frame;
-    lldb_private::DWARFDataExtractor      m_data_debug_info;
-    lldb_private::DWARFDataExtractor      m_data_debug_line;
-    lldb_private::DWARFDataExtractor      m_data_debug_loc;
-    lldb_private::DWARFDataExtractor      m_data_debug_ranges;
-    lldb_private::DWARFDataExtractor      m_data_debug_str;
-    lldb_private::DWARFDataExtractor      m_data_debug_str_offsets;
-    lldb_private::DWARFDataExtractor      m_data_apple_names;
-    lldb_private::DWARFDataExtractor      m_data_apple_types;
-    lldb_private::DWARFDataExtractor      m_data_apple_namespaces;
-    lldb_private::DWARFDataExtractor      m_data_apple_objc;
+
+    DWARFDataSegment                      m_dwarf_data;
+    DWARFDataSegment                      m_data_debug_abbrev;
+    DWARFDataSegment                      m_data_debug_addr;
+    DWARFDataSegment                      m_data_debug_aranges;
+    DWARFDataSegment                      m_data_debug_frame;
+    DWARFDataSegment                      m_data_debug_info;
+    DWARFDataSegment                      m_data_debug_line;
+    DWARFDataSegment                      m_data_debug_loc;
+    DWARFDataSegment                      m_data_debug_ranges;
+    DWARFDataSegment                      m_data_debug_str;
+    DWARFDataSegment                      m_data_debug_str_offsets;
+    DWARFDataSegment                      m_data_apple_names;
+    DWARFDataSegment                      m_data_apple_types;
+    DWARFDataSegment                      m_data_apple_namespaces;
+    DWARFDataSegment                      m_data_apple_objc;
 
     // The unique pointer items below are generated on demand if and when someone accesses
     // them through a non const version of this class.
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -429,7 +429,6 @@
     UserID (0),  // Used by SymbolFileDWARFDebugMap to when this class parses .o files to contain the .o file index/ID
     m_debug_map_module_wp (),
     m_debug_map_symfile (NULL),
-    m_flags(),
     m_data_debug_abbrev (),
     m_data_debug_aranges (),
     m_data_debug_frame (),
@@ -509,47 +508,62 @@
     if (module_sp)
     {
         const SectionList *section_list = module_sp->GetSectionList();
-
         const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get();
 
         // Memory map the DWARF mach-o segment so we have everything mmap'ed
         // to keep our heap memory usage down.
         if (section)
-            m_obj_file->MemoryMapSectionData(section, m_dwarf_data);
+        {
+            std::lock_guard<std::mutex> lock(m_dwarf_data.m_mutex);
+            m_obj_file->MemoryMapSectionData(section, m_dwarf_data.m_data);
+        }
     }
-    get_apple_names_data();
-    if (m_data_apple_names.GetByteSize() > 0)
+
+    const DWARFDataExtractor& data_apple_names = get_apple_names_data();
+    if (data_apple_names.GetByteSize() > 0)
     {
-        m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names, get_debug_str_data(), ".apple_names"));
+        std::lock_guard<std::mutex> lock(m_data_apple_names.m_mutex);
+        m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names.m_data,
+                                                                  get_debug_str_data(),
+                                                                  ".apple_names"));
         if (m_apple_names_ap->IsValid())
             m_using_apple_tables = true;
         else
             m_apple_names_ap.reset();
     }
-    get_apple_types_data();
-    if (m_data_apple_types.GetByteSize() > 0)
+    const DWARFDataExtractor& data_apple_types = get_apple_types_data();
+    if (data_apple_types.GetByteSize() > 0)
     {
-        m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types, get_debug_str_data(), ".apple_types"));
+        std::lock_guard<std::mutex> lock(m_data_apple_types.m_mutex);
+        m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types.m_data,
+                                                                  get_debug_str_data(),
+                                                                  ".apple_types"));
         if (m_apple_types_ap->IsValid())
             m_using_apple_tables = true;
         else
             m_apple_types_ap.reset();
     }
 
-    get_apple_namespaces_data();
-    if (m_data_apple_namespaces.GetByteSize() > 0)
+    const DWARFDataExtractor& data_apple_namespaces = get_apple_namespaces_data();
+    if (data_apple_namespaces.GetByteSize() > 0)
     {
-        m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces, get_debug_str_data(), ".apple_namespaces"));
+        std::lock_guard<std::mutex> lock(m_data_apple_namespaces.m_mutex);
+        m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces.m_data,
+                                                                       get_debug_str_data(),
+                                                                       ".apple_namespaces"));
         if (m_apple_namespaces_ap->IsValid())
             m_using_apple_tables = true;
         else
             m_apple_namespaces_ap.reset();
     }
 
-    get_apple_objc_data();
-    if (m_data_apple_objc.GetByteSize() > 0)
+    const DWARFDataExtractor& data_apple_objc = get_apple_objc_data();
+    if (data_apple_objc.GetByteSize() > 0)
     {
-        m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc, get_debug_str_data(), ".apple_objc"));
+        std::lock_guard<std::mutex> lock(m_data_apple_objc.m_mutex);
+        m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc.m_data,
+                                                                 get_debug_str_data(),
+                                                                 ".apple_objc"));
         if (m_apple_objc_ap->IsValid())
             m_using_apple_tables = true;
         else
@@ -592,45 +606,37 @@
             if (section)
                 debug_abbrev_file_size = section->GetFileSize();
             else
-                m_flags.Set (flagsGotDebugAbbrevData);
+                m_data_debug_abbrev.m_is_set.store(true);
 
             section = section_list->FindSectionByType (eSectionTypeDWARFDebugAranges, true).get();
             if (!section)
-                m_flags.Set (flagsGotDebugArangesData);
+                m_data_debug_aranges.m_is_set.store(true);
 
             section = section_list->FindSectionByType (eSectionTypeDWARFDebugFrame, true).get();
             if (!section)
-                m_flags.Set (flagsGotDebugFrameData);
+                m_data_debug_frame.m_is_set.store(true);
 
             section = section_list->FindSectionByType (eSectionTypeDWARFDebugLine, true).get();
             if (section)
                 debug_line_file_size = section->GetFileSize();
             else
-                m_flags.Set (flagsGotDebugLineData);
+                m_data_debug_line.m_is_set.store(true);
 
             section = section_list->FindSectionByType (eSectionTypeDWARFDebugLoc, true).get();
             if (!section)
-                m_flags.Set (flagsGotDebugLocData);
+                m_data_debug_loc.m_is_set.store(true);
 
             section = section_list->FindSectionByType (eSectionTypeDWARFDebugMacInfo, true).get();
-            if (!section)
-                m_flags.Set (flagsGotDebugMacInfoData);
-
             section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubNames, true).get();
-            if (!section)
-                m_flags.Set (flagsGotDebugPubNamesData);
-
             section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubTypes, true).get();
-            if (!section)
-                m_flags.Set (flagsGotDebugPubTypesData);
 
             section = section_list->FindSectionByType (eSectionTypeDWARFDebugRanges, true).get();
             if (!section)
-                m_flags.Set (flagsGotDebugRangesData);
+                m_data_debug_ranges.m_is_set.store(true);
 
             section = section_list->FindSectionByType (eSectionTypeDWARFDebugStr, true).get();
             if (!section)
-                m_flags.Set (flagsGotDebugStrData);
+                m_data_debug_str.m_is_set.store(true);
         }
         else
         {
@@ -665,116 +671,133 @@
 }
 
 const DWARFDataExtractor&
-SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DWARFDataExtractor &data)
+SymbolFileDWARF::GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment)
 {
-    if (m_flags.IsClear (got_flag))
+    // Return the data without locking the mutex if it is already set
+    if (data_segment.m_is_set.load())
+        return data_segment.m_data;
+
+    std::lock_guard<std::mutex> lock(data_segment.m_mutex);
+
+    // Check again if the data is set as it can be loaded while we were waiting for the mutex    
+    if (data_segment.m_is_set.load())
+        return data_segment.m_data;
+
+    return GetSectionDataNoLock (sect_type, data_segment);
+}
+
+const DWARFDataExtractor&
+SymbolFileDWARF::GetSectionDataNoLock (lldb::SectionType sect_type, DWARFDataSegment& data_segment)
+{
+    ModuleSP module_sp (m_obj_file->GetModule());
+    const SectionList *section_list = module_sp->GetSectionList();
+    if (section_list)
     {
-        ModuleSP module_sp (m_obj_file->GetModule());
-        m_flags.Set (got_flag);
-        const SectionList *section_list = module_sp->GetSectionList();
-        if (section_list)
+        SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
+        if (section_sp)
         {
-            SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
-            if (section_sp)
+            // See if we memory mapped the DWARF segment?
+            std::lock_guard<std::mutex> dwarf_data_lock(m_dwarf_data.m_mutex);
+            if (m_dwarf_data.m_data.GetByteSize())
             {
-                // See if we memory mapped the DWARF segment?
-                if (m_dwarf_data.GetByteSize())
-                {
-                    data.SetData(m_dwarf_data, section_sp->GetOffset (), section_sp->GetFileSize());
-                }
-                else
-                {
-                    if (m_obj_file->ReadSectionData (section_sp.get(), data) == 0)
-                        data.Clear();
-                }
+                data_segment.m_data.SetData(m_dwarf_data.m_data,
+                                            section_sp->GetOffset (),
+                                            section_sp->GetFileSize());
+            }
+            else
+            {
+                if (m_obj_file->ReadSectionData (section_sp.get(), data_segment.m_data) == 0)
+                    data_segment.m_data.Clear();
             }
         }
     }
-    return data;
+    data_segment.m_is_set.store(true);
+
+    return data_segment.m_data;
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_abbrev_data()
 {
-    return GetCachedSectionData (flagsGotDebugAbbrevData, eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
+    return GetCachedSectionData (eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_addr_data()
 {
-    return GetCachedSectionData (flagsGotDebugAddrData, eSectionTypeDWARFDebugAddr, m_data_debug_addr);
+    return GetCachedSectionData (eSectionTypeDWARFDebugAddr, m_data_debug_addr);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_aranges_data()
 {
-    return GetCachedSectionData (flagsGotDebugArangesData, eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
+    return GetCachedSectionData (eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_frame_data()
 {
-    return GetCachedSectionData (flagsGotDebugFrameData, eSectionTypeDWARFDebugFrame, m_data_debug_frame);
+    return GetCachedSectionData (eSectionTypeDWARFDebugFrame, m_data_debug_frame);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_info_data()
 {
-    return GetCachedSectionData (flagsGotDebugInfoData, eSectionTypeDWARFDebugInfo, m_data_debug_info);
+    return GetCachedSectionData (eSectionTypeDWARFDebugInfo, m_data_debug_info);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_line_data()
 {
-    return GetCachedSectionData (flagsGotDebugLineData, eSectionTypeDWARFDebugLine, m_data_debug_line);
+    return GetCachedSectionData (eSectionTypeDWARFDebugLine, m_data_debug_line);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_loc_data()
 {
-    return GetCachedSectionData (flagsGotDebugLocData, eSectionTypeDWARFDebugLoc, m_data_debug_loc);
+    return GetCachedSectionData (eSectionTypeDWARFDebugLoc, m_data_debug_loc);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_ranges_data()
 {
-    return GetCachedSectionData (flagsGotDebugRangesData, eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
+    return GetCachedSectionData (eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_str_data()
 {
-    return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str);
+    return GetCachedSectionData (eSectionTypeDWARFDebugStr, m_data_debug_str);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_debug_str_offsets_data()
 {
-    return GetCachedSectionData (flagsGotDebugStrOffsetsData, eSectionTypeDWARFDebugStrOffsets, m_data_debug_str_offsets);
+    return GetCachedSectionData (eSectionTypeDWARFDebugStrOffsets, m_data_debug_str_offsets);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_apple_names_data()
 {
-    return GetCachedSectionData (flagsGotAppleNamesData, eSectionTypeDWARFAppleNames, m_data_apple_names);
+    return GetCachedSectionData (eSectionTypeDWARFAppleNames, m_data_apple_names);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_apple_types_data()
 {
-    return GetCachedSectionData (flagsGotAppleTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types);
+    return GetCachedSectionData (eSectionTypeDWARFAppleTypes, m_data_apple_types);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_apple_namespaces_data()
 {
-    return GetCachedSectionData (flagsGotAppleNamespacesData, eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
+    return GetCachedSectionData (eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
 }
 
 const DWARFDataExtractor&
 SymbolFileDWARF::get_apple_objc_data()
 {
-    return GetCachedSectionData (flagsGotAppleObjCData, eSectionTypeDWARFAppleObjC, m_data_apple_objc);
+    return GetCachedSectionData (eSectionTypeDWARFAppleObjC, m_data_apple_objc);
 }
 
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to