Made FuncUnwinders threadsafe.

Other small cleanups as well.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@123088 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp
index 126ddd2..e09ad92 100644
--- a/source/Symbol/FuncUnwinders.cpp
+++ b/source/Symbol/FuncUnwinders.cpp
@@ -33,14 +33,15 @@
     m_unwind_table(unwind_table), 
     m_assembly_profiler(assembly_profiler), 
     m_range(range), 
+    m_mutex (Mutex::eMutexTypeNormal),
     m_unwind_at_call_site_ap (), 
     m_unwind_at_non_call_site_ap (), 
-    m_fast_unwind_ap (), 
-    m_arch_default_unwind (NULL), 
+    m_unwind_fast_ap (), 
+    m_unwind_arch_default (NULL), 
     m_tried_unwind_at_call_site (false),
     m_tried_unwind_at_non_call_site (false),
-    m_tried_fast_unwind (false),
-    m_tried_arch_default_unwind (false),
+    m_tried_unwind_fast (false),
+    m_tried_unwind_arch_default (false),
     m_first_non_prologue_insn() 
 {
 }
@@ -52,6 +53,19 @@
 UnwindPlan*
 FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
 {
+    // Lock the mutex to ensure we can always give out the most appropriate
+    // information. We want to make sure if someone requests a call site unwind
+    // plan, that they get one and don't run into a race condition where one
+    // thread has started to create the unwind plan and has put it into 
+    // m_unwind_at_call_site_ap, and have another thread enter this function
+    // and return the partially filled in m_unwind_at_call_site_ap pointer.
+    // We also want to make sure that we lock out other unwind plans from
+    // being accessed until this one is done creating itself in case someone
+    // had some code like:
+    //  UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
+    //  if (best_unwind_plan == NULL)
+    //      best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
+    Mutex::Locker locker (m_mutex);
     if (m_tried_unwind_at_call_site == false && m_unwind_at_call_site_ap.get() == NULL)
     {
         m_tried_unwind_at_call_site = true;
@@ -82,6 +96,19 @@
 UnwindPlan*
 FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
 {
+    // Lock the mutex to ensure we can always give out the most appropriate
+    // information. We want to make sure if someone requests an unwind
+    // plan, that they get one and don't run into a race condition where one
+    // thread has started to create the unwind plan and has put it into 
+    // the auto_ptr member variable, and have another thread enter this function
+    // and return the partially filled pointer contained in the auto_ptr.
+    // We also want to make sure that we lock out other unwind plans from
+    // being accessed until this one is done creating itself in case someone
+    // had some code like:
+    //  UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
+    //  if (best_unwind_plan == NULL)
+    //      best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
+    Mutex::Locker locker (m_mutex);
     if (m_tried_unwind_at_non_call_site == false && m_unwind_at_non_call_site_ap.get() == NULL)
     {
         m_tried_unwind_at_non_call_site = true;
@@ -95,22 +122,48 @@
 UnwindPlan*
 FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
 {
-    if (m_tried_fast_unwind == false && m_fast_unwind_ap.get() == NULL)
+    // Lock the mutex to ensure we can always give out the most appropriate
+    // information. We want to make sure if someone requests an unwind
+    // plan, that they get one and don't run into a race condition where one
+    // thread has started to create the unwind plan and has put it into 
+    // the auto_ptr member variable, and have another thread enter this function
+    // and return the partially filled pointer contained in the auto_ptr.
+    // We also want to make sure that we lock out other unwind plans from
+    // being accessed until this one is done creating itself in case someone
+    // had some code like:
+    //  UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
+    //  if (best_unwind_plan == NULL)
+    //      best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
+    Mutex::Locker locker (m_mutex);
+    if (m_tried_unwind_fast == false && m_unwind_fast_ap.get() == NULL)
     {
-        m_tried_fast_unwind = true;
-        m_fast_unwind_ap.reset (new UnwindPlan);
-        if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_fast_unwind_ap))
-            m_fast_unwind_ap.reset();
+        m_tried_unwind_fast = true;
+        m_unwind_fast_ap.reset (new UnwindPlan);
+        if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_fast_ap))
+            m_unwind_fast_ap.reset();
     }
-    return m_fast_unwind_ap.get();
+    return m_unwind_fast_ap.get();
 }
 
 UnwindPlan*
 FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
 {
-    if (m_tried_arch_default_unwind == false && m_arch_default_unwind == NULL)
+    // Lock the mutex to ensure we can always give out the most appropriate
+    // information. We want to make sure if someone requests an unwind
+    // plan, that they get one and don't run into a race condition where one
+    // thread has started to create the unwind plan and has put it into 
+    // the auto_ptr member variable, and have another thread enter this function
+    // and return the partially filled pointer contained in the auto_ptr.
+    // We also want to make sure that we lock out other unwind plans from
+    // being accessed until this one is done creating itself in case someone
+    // had some code like:
+    //  UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
+    //  if (best_unwind_plan == NULL)
+    //      best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
+    Mutex::Locker locker (m_mutex);
+    if (m_tried_unwind_arch_default == false && m_unwind_arch_default == NULL)
     {
-        m_tried_arch_default_unwind = true;
+        m_tried_unwind_arch_default = true;
         Address current_pc;
         Target *target = thread.CalculateTarget();
         if (target)
@@ -118,11 +171,11 @@
             ArchSpec arch = target->GetArchitecture ();
             ArchDefaultUnwindPlan *arch_default = ArchDefaultUnwindPlan::FindPlugin (arch);
             if (arch_default)
-                m_arch_default_unwind = arch_default->GetArchDefaultUnwindPlan (thread, current_pc);
+                m_unwind_arch_default = arch_default->GetArchDefaultUnwindPlan (thread, current_pc);
         }
     }
 
-    return m_arch_default_unwind;
+    return m_unwind_arch_default;
 }
 
 Address&