[Lldb-commits] [lldb] r157858 - in /lldb/trunk/tools/debugserver/source: DNBArch.h MacOSX/MachThread.cpp MacOSX/MachThread.h MacOSX/MachThreadList.cpp MacOSX/i386/DNBArchImplI386.cpp MacOSX/i386/DNBArchImplI386.h MacOSX/x86_64/DNBArchImplX86_64.cpp MacOSX/x86_64/DNBArchImplX86_64.h

Johnny Chen johnny.chen at apple.com
Fri Jun 1 16:43:06 PDT 2012


Author: johnny
Date: Fri Jun  1 18:43:05 2012
New Revision: 157858

URL: http://llvm.org/viewvc/llvm-project?rev=157858&view=rev
Log:
rdar://problem/11320188

Designate MachThreadList as a transaction coordinator when doing Enable/DisableHardwareWatchpoint on the list of threads.
In case the operation (iterating on the threads and doing enable/disable) fails in the middle, we rollback the already
enabled/disabled threads to their checkpointed states.  When all the threads succeed in enable/disable, we ask each thread
to finsih the transaction and commit the change of the debug state.

Modified:
    lldb/trunk/tools/debugserver/source/DNBArch.h
    lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h
    lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
    lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
    lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h

Modified: lldb/trunk/tools/debugserver/source/DNBArch.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/DNBArch.h?rev=157858&r1=157857&r2=157858&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/DNBArch.h (original)
+++ lldb/trunk/tools/debugserver/source/DNBArch.h Fri Jun  1 18:43:05 2012
@@ -82,6 +82,19 @@
     virtual bool            DisableHardwareWatchpoint (uint32_t hw_index) { return false; }
     virtual uint32_t        GetHardwareWatchpointHit() { return INVALID_NUB_HW_INDEX; }
     virtual bool            StepNotComplete () { return false; }
+
+protected:
+    friend class MachThread;
+
+    enum
+    {
+        Trans_Pending = 0,      // Transaction is pending, and checkpoint state has been snapshotted.
+        Trans_Done = 1,         // Transaction is done, the current state is committed, and checkpoint state is irrelevant.
+        Trans_Rolled_Back = 2   // Transaction is done, the current state has been rolled back to the checkpoint state.
+    };
+    virtual bool StartTransForHWP() { return true; }
+    virtual bool RollbackTransForHWP() { return true; }
+    virtual bool FinishTransForHWP() { return true; }
 };
 
 

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp?rev=157858&r1=157857&r2=157858&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachThread.cpp Fri Jun  1 18:43:05 2012
@@ -700,6 +700,18 @@
 }
 
 bool
+MachThread::RollbackTransForHWP()
+{
+    return m_arch_ap->RollbackTransForHWP();
+}
+
+bool
+MachThread::FinishTransForHWP()
+{
+    return m_arch_ap->FinishTransForHWP();
+}
+
+bool
 MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp)
 {
     if (bp != NULL && bp->IsHardware())

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h?rev=157858&r1=157857&r2=157858&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachThread.h Fri Jun  1 18:43:05 2012
@@ -66,6 +66,8 @@
     bool            DisableHardwareBreakpoint (const DNBBreakpoint *breakpoint);
     bool            DisableHardwareWatchpoint (const DNBBreakpoint *watchpoint);
     uint32_t        NumSupportedHardwareWatchpoints () const;
+    bool            RollbackTransForHWP();
+    bool            FinishTransForHWP();
 
     nub_state_t     GetState();
     void            SetState(nub_state_t state);

Modified: lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp?rev=157858&r1=157857&r2=157858&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/MachThreadList.cpp Fri Jun  1 18:43:05 2012
@@ -478,8 +478,17 @@
         for (uint32_t idx = 0; idx < num_threads; ++idx)
         {
             if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp)) == INVALID_NUB_HW_INDEX)
+            {
+                // We know that idx failed for some reason.  Let's rollback the transaction for [0, idx).
+                for (uint32_t i = 0; i < idx; ++i)
+                    m_threads[i]->RollbackTransForHWP();
                 return INVALID_NUB_HW_INDEX;
+            }
         }
+        // Notify each thread to commit the pending transaction.
+        for (uint32_t idx = 0; idx < num_threads; ++idx)
+            m_threads[idx]->FinishTransForHWP();
+
         // Use an arbitrary thread to signal the completion of our transaction.
         if (num_threads)
             m_threads[0]->HardwareWatchpointStateChanged();
@@ -498,8 +507,17 @@
         for (uint32_t idx = 0; idx < num_threads; ++idx)
         {
             if (!m_threads[idx]->DisableHardwareWatchpoint(wp))
+            {
+                // We know that idx failed for some reason.  Let's rollback the transaction for [0, idx).
+                for (uint32_t i = 0; i < idx; ++i)
+                    m_threads[i]->RollbackTransForHWP();
                 return false;
+            }
         }
+        // Notify each thread to commit the pending transaction.
+        for (uint32_t idx = 0; idx < num_threads; ++idx)
+            m_threads[idx]->FinishTransForHWP();
+
         // Use an arbitrary thread to signal the completion of our transaction.
         if (num_threads)
             m_threads[0]->HardwareWatchpointStateChanged();

Modified: lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp?rev=157858&r1=157857&r2=157858&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp Fri Jun  1 18:43:05 2012
@@ -818,6 +818,42 @@
     }
 }
 
+bool
+DNBArchImplI386::StartTransForHWP()
+{
+    if (m_2pc_trans_state != Trans_Done || m_2pc_trans_state != Trans_Rolled_Back)
+        DNBLogError ("%s inconsistent state detected, expected %d or %d, got: %d", __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state);
+    m_2pc_dbg_checkpoint = m_state.context.dbg;
+    m_2pc_trans_state = Trans_Pending;
+    return true;
+}
+bool
+DNBArchImplI386::RollbackTransForHWP()
+{
+    m_state.context.dbg = m_2pc_dbg_checkpoint;
+    if (m_2pc_trans_state != Trans_Pending)
+        DNBLogError ("%s inconsistent state detected, expected %d, got: %d", __FUNCTION__, Trans_Pending, m_2pc_trans_state);
+    m_2pc_trans_state = Trans_Rolled_Back;
+    kern_return_t kret = SetDBGState();
+    DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret);
+
+    if (kret == KERN_SUCCESS)
+        return true;
+    else
+        return false;
+}
+bool
+DNBArchImplI386::FinishTransForHWP()
+{
+    m_2pc_trans_state = Trans_Done;
+    return true;
+}
+DNBArchImplI386::DBG
+DNBArchImplI386::GetDBGCheckpoint()
+{
+    return m_2pc_dbg_checkpoint;
+}
+
 uint32_t
 DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write)
 {
@@ -842,7 +878,6 @@
         uint32_t i = 0;
 
         DBG &debug_state = m_state.context.dbg;
-        DBG dsCheckPoint = m_state.context.dbg;
         for (i = 0; i < num_hw_watchpoints; ++i)
         {
             if (IsWatchpointVacant(debug_state, i))
@@ -852,6 +887,8 @@
         // See if we found an available hw breakpoint slot above
         if (i < num_hw_watchpoints)
         {
+            StartTransForHWP();
+
             // Modify our local copy of the debug state, first.
             SetWatchpoint(debug_state, i, addr, size, read, write);
             // Now set the watch point in the inferior.
@@ -860,8 +897,8 @@
 
             if (kret == KERN_SUCCESS)
                 return i;
-            else // Recovery block.
-                m_state.context.dbg = dsCheckPoint;
+            else // Revert to the previous debug state voluntarily.  The transaction coordinator knows that we have failed.
+                m_state.context.dbg = GetDBGCheckpoint();
         }
         else
         {
@@ -880,9 +917,10 @@
     if (kret == KERN_SUCCESS)
     {
         DBG &debug_state = m_state.context.dbg;
-        DBG dsCheckPoint = m_state.context.dbg;
         if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index))
         {
+            StartTransForHWP();
+
             // Modify our local copy of the debug state, first.
             ClearWatchpoint(debug_state, hw_index);
             // Now disable the watch point in the inferior.
@@ -892,8 +930,8 @@
 
             if (kret == KERN_SUCCESS)
                 return true;
-            else // Recovery block.
-                m_state.context.dbg = dsCheckPoint;
+            else // Revert to the previous debug state voluntarily.  The transaction coordinator knows that we have failed.
+                m_state.context.dbg = GetDBGCheckpoint();
         }
     }
     return false;

Modified: lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h?rev=157858&r1=157857&r2=157858&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h Fri Jun  1 18:43:05 2012
@@ -231,8 +231,15 @@
     static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index);
     static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
 
+    virtual bool StartTransForHWP();
+    virtual bool RollbackTransForHWP();
+    virtual bool FinishTransForHWP();
+    DBG GetDBGCheckpoint();
+
     MachThread *m_thread;
     State       m_state;
+    DBG         m_2pc_dbg_checkpoint;
+    uint32_t    m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)?
 };
 
 #endif    // #if defined (__i386__) || defined (__x86_64__)

Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp?rev=157858&r1=157857&r2=157858&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp Fri Jun  1 18:43:05 2012
@@ -795,6 +795,42 @@
     }
 }
 
+bool
+DNBArchImplX86_64::StartTransForHWP()
+{
+    if (m_2pc_trans_state != Trans_Done || m_2pc_trans_state != Trans_Rolled_Back)
+        DNBLogError ("%s inconsistent state detected, expected %d or %d, got: %d", __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state);
+    m_2pc_dbg_checkpoint = m_state.context.dbg;
+    m_2pc_trans_state = Trans_Pending;
+    return true;
+}
+bool
+DNBArchImplX86_64::RollbackTransForHWP()
+{
+    m_state.context.dbg = m_2pc_dbg_checkpoint;
+    if (m_2pc_trans_state != Trans_Pending)
+        DNBLogError ("%s inconsistent state detected, expected %d, got: %d", __FUNCTION__, Trans_Pending, m_2pc_trans_state);
+    m_2pc_trans_state = Trans_Rolled_Back;
+    kern_return_t kret = SetDBGState();
+    DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret);
+
+    if (kret == KERN_SUCCESS)
+        return true;
+    else
+        return false;
+}
+bool
+DNBArchImplX86_64::FinishTransForHWP()
+{
+    m_2pc_trans_state = Trans_Done;
+    return true;
+}
+DNBArchImplX86_64::DBG
+DNBArchImplX86_64::GetDBGCheckpoint()
+{
+    return m_2pc_dbg_checkpoint;
+}
+
 uint32_t
 DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write)
 {
@@ -819,7 +855,6 @@
         uint32_t i = 0;
 
         DBG &debug_state = m_state.context.dbg;
-        DBG dsCheckPoint = m_state.context.dbg;
         for (i = 0; i < num_hw_watchpoints; ++i)
         {
             if (IsWatchpointVacant(debug_state, i))
@@ -829,6 +864,8 @@
         // See if we found an available hw breakpoint slot above
         if (i < num_hw_watchpoints)
         {
+            StartTransForHWP();
+
             // Modify our local copy of the debug state, first.
             SetWatchpoint(debug_state, i, addr, size, read, write);
             // Now set the watch point in the inferior.
@@ -837,8 +874,8 @@
 
             if (kret == KERN_SUCCESS)
                 return i;
-            else // Recovery block.
-                m_state.context.dbg = dsCheckPoint;
+            else // Revert to the previous debug state voluntarily.  The transaction coordinator knows that we have failed.
+                m_state.context.dbg = GetDBGCheckpoint();
         }
         else
         {
@@ -857,9 +894,10 @@
     if (kret == KERN_SUCCESS)
     {
         DBG &debug_state = m_state.context.dbg;
-        DBG dsCheckPoint = m_state.context.dbg;
         if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index))
         {
+            StartTransForHWP();
+
             // Modify our local copy of the debug state, first.
             ClearWatchpoint(debug_state, hw_index);
             // Now disable the watch point in the inferior.
@@ -869,8 +907,8 @@
 
             if (kret == KERN_SUCCESS)
                 return true;
-            else // Recovery block.
-                m_state.context.dbg = dsCheckPoint;
+            else // Revert to the previous debug state voluntarily.  The transaction coordinator knows that we have failed.
+                m_state.context.dbg = GetDBGCheckpoint();
         }
     }
     return false;

Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h?rev=157858&r1=157857&r2=157858&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h Fri Jun  1 18:43:05 2012
@@ -238,8 +238,15 @@
     static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index);
     static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
 
+    virtual bool StartTransForHWP();
+    virtual bool RollbackTransForHWP();
+    virtual bool FinishTransForHWP();
+    DBG GetDBGCheckpoint();
+
     MachThread *m_thread;
-    State        m_state;    
+    State       m_state;
+    DBG         m_2pc_dbg_checkpoint;
+    uint32_t    m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)?
 };
 
 #endif    // #if defined (__i386__) || defined (__x86_64__)





More information about the lldb-commits mailing list