summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/tools/debugserver/source/DNBArch.h13
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThread.cpp12
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThread.h2
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp18
-rw-r--r--lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp50
-rw-r--r--lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h7
-rw-r--r--lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp50
-rw-r--r--lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h9
8 files changed, 148 insertions, 13 deletions
diff --git a/lldb/tools/debugserver/source/DNBArch.h b/lldb/tools/debugserver/source/DNBArch.h
index db0c614c28b..08e7042f43f 100644
--- a/lldb/tools/debugserver/source/DNBArch.h
+++ b/lldb/tools/debugserver/source/DNBArch.h
@@ -82,6 +82,19 @@ public:
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; }
};
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp
index aca47f9120f..f9e3dd569f6 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp
@@ -700,6 +700,18 @@ MachThread::HardwareWatchpointStateChanged ()
}
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())
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h
index 724043ab039..90bd05f2dc7 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachThread.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h
@@ -66,6 +66,8 @@ public:
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);
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp
index e2aa0f2eedd..b8044fe6c7f 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp
@@ -478,8 +478,17 @@ MachThreadList::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const
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 @@ MachThreadList::DisableHardwareWatchpoint (const DNBBreakpoint* wp) const
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();
diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
index 3962b9b6c5d..9a1abfbf286 100644
--- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
@@ -818,6 +818,42 @@ DNBArchImplI386::GetWatchAddress(const DBG &debug_state, uint32_t hw_index)
}
}
+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 @@ DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, boo
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 @@ DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, boo
// 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 @@ DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, boo
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 @@ DNBArchImplI386::DisableHardwareWatchpoint (uint32_t hw_index)
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 @@ DNBArchImplI386::DisableHardwareWatchpoint (uint32_t hw_index)
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;
diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
index 316aed2ba50..7a282bd8577 100644
--- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
+++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
@@ -231,8 +231,15 @@ protected:
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__)
diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
index 94aa9a18664..2a8cf69c26a 100644
--- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
@@ -795,6 +795,42 @@ DNBArchImplX86_64::GetWatchAddress(const DBG &debug_state, uint32_t hw_index)
}
}
+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 @@ DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, b
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 @@ DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, b
// 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 @@ DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, b
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 @@ DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index)
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 @@ DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index)
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;
diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h
index 04c07bc0dd1..148780ee414 100644
--- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h
+++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h
@@ -238,8 +238,15 @@ protected:
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__)
OpenPOWER on IntegriCloud