Changed the formerly pure virtual function:

namespace lldb_private {
    class Thread
    {
        virtual lldb::StopInfoSP
        GetPrivateStopReason() = 0;
    };
}

To not be virtual. The lldb_private::Thread now handles the correct caching and will call a new pure virtual function:

namespace lldb_private {
    class Thread
    {
        virtual bool
        CalculateStopInfo() = 0;
    }
}

This function must be overridden by thead lldb_private::Thread subclass and the only thing it needs to do is to set the Thread::StopInfo() with the current stop reason and return true, or return false if there is no stop reason. The  lldb_private::Thread class will take care of calling this function only when it is required. This allows lldb_private::Thread subclasses to be a bit simpler and not all need to duplicate the cache and invalidation settings.

Also renamed:

lldb::StopInfoSP
lldb_private::Thread::GetPrivateStopReason();

To:

lldb::StopInfoSP
lldb_private::Thread::GetPrivateStopInfo();

Also cleaned up a case where the ThreadPlanStepOverBreakpoint might not re-set its breakpoint if the thread disappears (which was happening due to a bug when using the OperatingSystem plug-ins with memory threads and real threads).

llvm-svn: 181501
This commit is contained in:
Greg Clayton 2013-05-09 01:55:29 +00:00
parent 083fcdb414
commit 6e0ff1a3cb
19 changed files with 240 additions and 400 deletions

View File

@ -848,13 +848,7 @@ public:
virtual lldb::user_id_t
GetProtocolID () const
{
return m_protocol_tid.GetID();
}
virtual void
SetProtocolID (lldb::user_id_t api_tid)
{
return m_protocol_tid.SetID(api_tid);
return GetID();
}
//------------------------------------------------------------------
@ -905,7 +899,19 @@ public:
// valid. The stop info may be a "checkpointed and restored" stop info, so if it is still around it is right
// even if you have not calculated this yourself, or if it disagrees with what you might have calculated.
virtual lldb::StopInfoSP
GetPrivateStopReason () = 0;
GetPrivateStopInfo ();
//----------------------------------------------------------------------
// Ask the thread subclass to set its stop info.
//
// Thread subclasses should call Thread::SetStopInfo(...) with the
// reason the thread stopped.
//
// @return
// True if Thread::SetStopInfo(...) was called, false otherwise.
//----------------------------------------------------------------------
virtual bool
CalculateStopInfo () = 0;
//----------------------------------------------------------------------
// Gets the temporary resume state for a thread.
@ -1002,9 +1008,10 @@ protected:
// Classes that inherit from Process can see and modify these
//------------------------------------------------------------------
lldb::ProcessWP m_process_wp; ///< The process that owns this thread.
lldb::StopInfoSP m_actual_stop_info_sp; ///< The private stop reason for this thread
lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread
uint32_t m_stop_info_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that
// the thread's m_stop_info_sp is current and you don't have to fetch it again
const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread for easy UI/command line access.
UserID m_protocol_tid; ///< The thread ID used in the system level debugging or protocol functions calls. This is usually the same as the Thread::GetID(), but not always.
lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this thread's current register state.
lldb::StateType m_state; ///< The state of our process.
mutable Mutex m_state_mutex; ///< Multithreaded protection for m_state.
@ -1020,8 +1027,6 @@ protected:
/// It gets set in Thread::ShoudResume.
std::unique_ptr<lldb_private::Unwind> m_unwinder_ap;
bool m_destroy_called; // This is used internally to make sure derived Thread classes call DestroyThread.
uint32_t m_thread_stop_reason_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that
// the thread's m_actual_stop_info_sp is current and you don't have to fetch it again
LazyBool m_override_should_notify;
private:
//------------------------------------------------------------------

View File

@ -410,6 +410,13 @@ public:
virtual bool
MischiefManaged ();
virtual void
ThreadDestroyed ()
{
// Any cleanup that a plan might want to do in case the thread goes away
// in the middle of the plan being queued on a thread can be done here.
}
bool
GetPrivate ()
{
@ -537,7 +544,7 @@ protected:
lldb::StopInfoSP
GetPrivateStopReason()
{
return m_thread.GetPrivateStopReason ();
return m_thread.GetPrivateStopInfo ();
}
void

View File

@ -32,6 +32,7 @@ public:
virtual lldb::StateType GetPlanRunState ();
virtual bool WillStop ();
virtual bool MischiefManaged ();
virtual void ThreadDestroyed ();
void SetAutoContinue (bool do_it);
virtual bool ShouldAutoContinue(Event *event_ptr);
@ -39,11 +40,13 @@ protected:
virtual bool DoPlanExplainsStop (Event *event_ptr);
virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
void ReenableBreakpointSite ();
private:
lldb::addr_t m_breakpoint_addr;
lldb::user_id_t m_breakpoint_site_id;
bool m_auto_continue;
bool m_reenabled_breakpoint_site;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverBreakpoint);

View File

@ -198,36 +198,39 @@ OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list,
{
uint32_t i;
const uint32_t num_threads = threads_list.GetSize();
for (i=0; i<num_threads; ++i)
if (num_threads > 0)
{
PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
if (thread_dict)
for (i=0; i<num_threads; ++i)
{
if (thread_dict.GetItemForKey("core"))
PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
if (thread_dict)
{
// We have some threads that are saying they are on a "core", which means
// they map the threads that are gotten from the lldb_private::Process subclass
// so clear the new threads list so the core threads don't show up
new_thread_list.Clear();
break;
if (thread_dict.GetItemForKey("core"))
{
// We have some threads that are saying they are on a "core", which means
// they map the threads that are gotten from the lldb_private::Process subclass
// so clear the new threads list so the core threads don't show up
new_thread_list.Clear();
break;
}
}
}
for (i=0; i<num_threads; ++i)
{
PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
if (thread_dict)
{
ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, NULL));
if (thread_sp)
new_thread_list.AddThread(thread_sp);
}
}
}
for (i=0; i<num_threads; ++i)
{
PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
if (thread_dict)
{
ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, NULL));
if (thread_sp)
new_thread_list.AddThread(thread_sp);
}
}
}
else
{
if (new_thread_list.GetSize(false) == 0)
new_thread_list = old_thread_list;
}
return new_thread_list.GetSize(false) > 0;
}

View File

@ -385,11 +385,16 @@ ProcessKDP::DoResume ()
if (kernel_thread_sp)
{
const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState();
if (log)
log->Printf ("ProcessKDP::DoResume() thread_resume_state = %s", StateAsCString(thread_resume_state));
switch (thread_resume_state)
{
case eStateSuspended:
// Nothing to do here when a thread will stay suspended
// we just leave the CPU mask bit set to zero for the thread
if (log)
log->Printf ("ProcessKDP::DoResume() = suspended???");
break;
case eStateStepping:
@ -398,6 +403,8 @@ ProcessKDP::DoResume ()
if (reg_ctx_sp)
{
if (log)
log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);");
reg_ctx_sp->HardwareSingleStep (true);
resume = true;
}
@ -412,15 +419,17 @@ ProcessKDP::DoResume ()
{
lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext());
if (reg_ctx_sp)
{
reg_ctx_sp->HardwareSingleStep (false);
resume = true;
}
else
{
error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID());
}
if (reg_ctx_sp)
{
if (log)
log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (false);");
reg_ctx_sp->HardwareSingleStep (false);
resume = true;
}
else
{
error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID());
}
}
break;
@ -540,22 +549,15 @@ ProcessKDP::DoDetach(bool keep_stopped)
// If we are going to keep the target stopped, then don't send the disconnect message.
if (!keep_stopped && m_comm.IsConnected())
{
bool disconnect_success = m_comm.SendRequestDisconnect();
if (!disconnect_success)
{
if (log)
log->PutCString ("ProcessKDP::DoDetach(): send disconnect request failed");
}
ConnectionStatus comm_disconnect_result = m_comm.Disconnect ();
const bool success = m_comm.SendRequestDisconnect();
if (log)
{
if (comm_disconnect_result == eConnectionStatusSuccess)
log->PutCString ("ProcessKDP::DoDetach() conncection channel shutdown successfully");
if (success)
log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
else
log->PutCString ("ProcessKDP::DoDetach() connection channel shutdown failed");
}
m_comm.Disconnect ();
}
}
StopAsyncThread ();

View File

@ -148,26 +148,23 @@ ThreadKDP::CreateRegisterContextForFrame (StackFrame *frame)
return reg_ctx_sp;
}
lldb::StopInfoSP
ThreadKDP::GetPrivateStopReason ()
bool
ThreadKDP::CalculateStopInfo ()
{
ProcessSP process_sp (GetProcess());
if (process_sp)
{
const uint32_t process_stop_id = process_sp->GetStopID();
if (m_thread_stop_reason_stop_id != process_stop_id ||
(m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
if (m_cached_stop_info_sp)
{
if (IsStillAtLastBreakpointHit())
return m_actual_stop_info_sp;
if (m_cached_stop_info_sp)
SetStopInfo (m_cached_stop_info_sp);
else
SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
SetStopInfo (m_cached_stop_info_sp);
}
else
{
SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
}
return true;
}
return m_actual_stop_info_sp;
return false;
}
void

View File

@ -89,13 +89,10 @@ protected:
lldb::addr_t m_thread_dispatch_qaddr;
lldb::StopInfoSP m_cached_stop_info_sp;
//------------------------------------------------------------------
// Member variables.
// Protected member functions.
//------------------------------------------------------------------
virtual lldb::StopInfoSP
GetPrivateStopReason ();
virtual bool
CalculateStopInfo ();
};
#endif // liblldb_ThreadKDP_h_

View File

@ -138,10 +138,11 @@ POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
return reg_ctx_sp;
}
lldb::StopInfoSP
POSIXThread::GetPrivateStopReason()
bool
POSIXThread::CalculateStopInfo()
{
return m_actual_stop_info_sp;
SetStopInfo (m_actual_stop_info_sp);
return true;
}
Unwind *

View File

@ -97,8 +97,8 @@ private:
ProcessMonitor &
GetMonitor();
lldb::StopInfoSP
GetPrivateStopReason();
virtual bool
CalculateStopInfo();
void BreakNotify(const ProcessMessage &message);
void WatchNotify(const ProcessMessage &message);

View File

@ -99,209 +99,34 @@ ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame)
return reg_ctx_sp;
}
//class StopInfoThreadMemory : public StopInfo
//{
//public:
// //------------------------------------------------------------------
// // Constructors and Destructors
// //------------------------------------------------------------------
// StopInfoThreadMemory (Thread &thread,
// uint64_t value,
// StopInfoSP &backing_stop_info_sp) :
// StopInfo (thread, value),
// m_backing_stop_info_sp (backing_stop_info_sp)
// {
// }
//
// virtual
// ~StopInfoThreadMemory()
// {
// }
//
// virtual bool
// IsValid () const
// {
// ThreadSP backing_thread_sp (m_thread.GetBackingThread());
// if (backing_thread_sp)
// return backing_thread_sp->IsValid();
// return StopInfo::IsValid();
// }
//
// virtual Thread &
// GetThread()
// {
// return m_thread;
// }
//
// virtual const Thread &
// GetThread() const
// {
// return m_thread;
// }
//
// virtual uint64_t
// GetValue() const
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->GetValue();
// return StopInfo::GetValue();
// }
//
// virtual lldb::StopReason
// GetStopReason () const
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->GetStopReason();
// return eStopReasonNone;
// }
//
// // ShouldStopSynchronous will get called before any thread plans are consulted, and if it says we should
// // resume the target, then we will just immediately resume. This should not run any code in or resume the
// // target.
//
// virtual bool
// ShouldStopSynchronous (Event *event_ptr)
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->ShouldStopSynchronous(event_ptr);
// return StopInfo::ShouldStopSynchronous (event_ptr);
// }
//
// // If should stop returns false, check if we should notify of this event
// virtual bool
// ShouldNotify (Event *event_ptr)
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->ShouldNotify(event_ptr);
// return StopInfo::ShouldNotify (event_ptr);
// }
//
// virtual void
// WillResume (lldb::StateType resume_state)
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->WillResume(resume_state);
// return StopInfo::WillResume (resume_state);
// }
//
// virtual const char *
// GetDescription ()
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->GetDescription();
// return StopInfo::GetDescription();
// }
//
// virtual void
// SetDescription (const char *desc_cstr)
// {
// if (m_backing_stop_info_sp)
// m_backing_stop_info_sp->SetDescription(desc_cstr);
// StopInfo::SetDescription(desc_cstr);
// }
//
// // Sometimes the thread plan logic will know that it wants a given stop to stop or not,
// // regardless of what the ordinary logic for that StopInfo would dictate. The main example
// // of this is the ThreadPlanCallFunction, which for instance knows - based on how that particular
// // expression was executed - whether it wants all breakpoints to auto-continue or not.
// // Use OverrideShouldStop on the StopInfo to implement this.
//
// virtual void
// OverrideShouldStop (bool override_value)
// {
// if (m_backing_stop_info_sp)
// m_backing_stop_info_sp->OverrideShouldStop(override_value);
// StopInfo::OverrideShouldStop (override_value);
// }
//
// virtual bool
// GetOverrideShouldStop()
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->GetOverrideShouldStop();
// return StopInfo::GetOverrideShouldStop();
// }
//
// virtual bool
// GetOverriddenShouldStopValue ()
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->GetOverriddenShouldStopValue();
// return StopInfo::GetOverriddenShouldStopValue();
// }
//
// virtual void
// PerformAction (Event *event_ptr)
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->PerformAction(event_ptr);
// return StopInfo::PerformAction(event_ptr);
// }
//
// virtual bool
// ShouldStop (Event *event_ptr)
// {
// if (m_backing_stop_info_sp)
// return m_backing_stop_info_sp->ShouldStop(event_ptr);
// return StopInfo::ShouldStop(event_ptr);
// }
//
//
//protected:
// StopInfoSP m_backing_stop_info_sp;
//
//private:
// DISALLOW_COPY_AND_ASSIGN (StopInfoThreadMemory);
//};
lldb::StopInfoSP
ThreadMemory::GetPrivateStopReason ()
bool
ThreadMemory::CalculateStopInfo ()
{
if (m_actual_stop_info_sp)
return m_actual_stop_info_sp;
if (m_backing_thread_sp)
{
lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopReason());
lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopInfo());
if (backing_stop_info_sp)
{
m_actual_stop_info_sp = backing_stop_info_sp;
m_actual_stop_info_sp->SetThread (shared_from_this());
return m_actual_stop_info_sp;
backing_stop_info_sp->SetThread (shared_from_this());
SetStopInfo (backing_stop_info_sp);
return true;
}
}
ProcessSP process_sp (GetProcess());
if (process_sp)
else
{
const uint32_t process_stop_id = process_sp->GetStopID();
if (m_thread_stop_reason_stop_id != process_stop_id ||
(m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
{
if (IsStillAtLastBreakpointHit())
return m_actual_stop_info_sp;
ProcessSP process_sp (GetProcess());
// If GetGDBProcess().SetThreadStopInfo() doesn't find a stop reason
// for this thread, then m_actual_stop_info_sp will not ever contain
// a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
// check will never be able to tell us if we have the correct stop info
// for this thread and we will continually send qThreadStopInfo packets
// down to the remote GDB server, so we need to keep our own notion
// of the stop ID that m_actual_stop_info_sp is valid for (even if it
// contains nothing). We use m_thread_stop_reason_stop_id for this below.
m_thread_stop_reason_stop_id = process_stop_id;
m_actual_stop_info_sp.reset();
if (process_sp)
{
OperatingSystem *os = process_sp->GetOperatingSystem ();
if (os)
m_actual_stop_info_sp = os->CreateThreadStopReason (this);
{
SetStopInfo (os->CreateThreadStopReason (this));
return true;
}
}
}
return m_actual_stop_info_sp;
return false;
}
void
@ -309,4 +134,7 @@ ThreadMemory::RefreshStateAfterStop()
{
if (m_backing_thread_sp)
return m_backing_thread_sp->RefreshStateAfterStop();
if (m_reg_context_sp)
m_reg_context_sp->InvalidateAllRegisters();
}

View File

@ -39,8 +39,8 @@ public:
virtual lldb::RegisterContextSP
CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
virtual lldb::StopInfoSP
GetPrivateStopReason ();
virtual bool
CalculateStopInfo ();
virtual const char *
GetInfo ()

View File

@ -1770,7 +1770,7 @@ ProcessGDBRemote::DoDestroy ()
for (size_t i = 0; i < num_threads; i++)
{
ThreadSP thread_sp = threads.GetThreadAtIndex(i);
StopInfoSP stop_info_sp = thread_sp->GetPrivateStopReason();
StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
StopReason reason = eStopReasonInvalid;
if (stop_info_sp)
reason = stop_info_sp->GetStopReason();
@ -1805,7 +1805,7 @@ ProcessGDBRemote::DoDestroy ()
for (size_t i = 0; i < num_threads; i++)
{
ThreadSP thread_sp = threads.GetThreadAtIndex(i);
StopInfoSP stop_info_sp = thread_sp->GetPrivateStopReason();
StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
StopReason reason = eStopReasonInvalid;
if (stop_info_sp)
reason = stop_info_sp->GetStopReason();

View File

@ -197,56 +197,18 @@ ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &respons
return gdb_reg_ctx->PrivateSetRegisterValue (reg, response);
}
lldb::StopInfoSP
ThreadGDBRemote::GetPrivateStopReason ()
bool
ThreadGDBRemote::CalculateStopInfo ()
{
ProcessSP process_sp (GetProcess());
if (process_sp)
{
const uint32_t process_stop_id = process_sp->GetStopID();
if (m_thread_stop_reason_stop_id == process_stop_id)
{
// Our stop info is up to date even if it is empty...
return m_actual_stop_info_sp;
}
if (m_actual_stop_info_sp && m_actual_stop_info_sp->IsValid())
{
// The stop info is up to date, reset it so everything updates
SetStopInfo (m_actual_stop_info_sp);
}
else
{
if (IsStillAtLastBreakpointHit())
{
SetStopInfo(m_actual_stop_info_sp);
}
else
{
// If GetGDBProcess().SetThreadStopInfo() doesn't find a stop reason
// for this thread, then m_actual_stop_info_sp will not ever contain
// a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
// check will never be able to tell us if we have the correct stop info
// for this thread and we will continually send qThreadStopInfo packets
// down to the remote GDB server, so we need to keep our own notion
// of the stop ID that m_actual_stop_info_sp is valid for (even if it
// contains nothing). We use m_thread_stop_reason_stop_id for this below.
m_actual_stop_info_sp.reset();
StringExtractorGDBRemote stop_packet;
ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
if (gdb_process->GetGDBRemote().GetThreadStopInfo(GetProtocolID(), stop_packet))
{
gdb_process->SetThreadStopInfo (stop_packet);
}
else
{
SetStopInfo (StopInfoSP());
}
}
}
StringExtractorGDBRemote stop_packet;
ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
if (gdb_process->GetGDBRemote().GetThreadStopInfo(GetProtocolID(), stop_packet))
return gdb_process->SetThreadStopInfo (stop_packet) == eStateStopped;
}
return m_actual_stop_info_sp;
return false;
}

View File

@ -98,8 +98,8 @@ protected:
void
SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id);
virtual lldb::StopInfoSP
GetPrivateStopReason ();
virtual bool
CalculateStopInfo ();
};

View File

@ -117,39 +117,16 @@ ThreadMachCore::CreateRegisterContextForFrame (StackFrame *frame)
return reg_ctx_sp;
}
lldb::StopInfoSP
ThreadMachCore::GetPrivateStopReason ()
bool
ThreadMachCore::CalculateStopInfo ()
{
ProcessSP process_sp (GetProcess());
if (process_sp)
{
const uint32_t process_stop_id = process_sp->GetStopID();
if (m_thread_stop_reason_stop_id != process_stop_id ||
(m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
{
if (IsStillAtLastBreakpointHit())
return m_actual_stop_info_sp;
// TODO: can we query the initial state of the thread here?
// For now I am just going to pretend that a SIGSTOP happened.
SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
// If GetKDPProcess().SetThreadStopInfo() doesn't find a stop reason
// for this thread, then m_actual_stop_info_sp will not ever contain
// a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
// check will never be able to tell us if we have the correct stop info
// for this thread and we will continually send qThreadStopInfo packets
// down to the remote KDP server, so we need to keep our own notion
// of the stop ID that m_actual_stop_info_sp is valid for (even if it
// contains nothing). We use m_thread_stop_reason_stop_id for this below.
// m_thread_stop_reason_stop_id = process_stop_id;
// m_actual_stop_info_sp.reset();
}
SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
return true;
}
return m_actual_stop_info_sp;
return false;
}

View File

@ -79,11 +79,10 @@ protected:
lldb::addr_t m_thread_dispatch_qaddr;
lldb::RegisterContextSP m_thread_reg_ctx_sp;
//------------------------------------------------------------------
// Member variables.
// Protected member functions.
//------------------------------------------------------------------
virtual lldb::StopInfoSP
GetPrivateStopReason ();
virtual bool
CalculateStopInfo ();
};
#endif // liblldb_ThreadMachCore_h_

View File

@ -243,9 +243,9 @@ Thread::Thread (Process &process, lldb::tid_t tid) :
UserID (tid),
Broadcaster(&process.GetTarget().GetDebugger(), Thread::GetStaticBroadcasterClass().AsCString()),
m_process_wp (process.shared_from_this()),
m_actual_stop_info_sp (),
m_stop_info_sp (),
m_stop_info_stop_id (0),
m_index_id (process.GetNextThreadIndexID(tid)),
m_protocol_tid (tid),
m_reg_context_sp (),
m_state (eStateUnloaded),
m_state_mutex (Mutex::eMutexTypeRecursive),
@ -259,7 +259,6 @@ Thread::Thread (Process &process, lldb::tid_t tid) :
m_temporary_resume_state (eStateRunning),
m_unwinder_ap (),
m_destroy_called (false),
m_thread_stop_reason_stop_id (0),
m_override_should_notify (eLazyBoolCalculate)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
@ -283,11 +282,17 @@ Thread::~Thread()
void
Thread::DestroyThread ()
{
// Tell any plans on the plan stack that the thread is being destroyed since
// any active plans that have a thread go away in the middle of might need
// to do cleanup.
for (auto plan : m_plan_stack)
plan->ThreadDestroyed();
m_destroy_called = true;
m_plan_stack.clear();
m_discarded_plan_stack.clear();
m_completed_plan_stack.clear();
m_actual_stop_info_sp.reset();
m_stop_info_sp.reset();
m_reg_context_sp.reset();
m_unwinder_ap.reset();
Mutex::Locker locker(m_frame_mutex);
@ -366,19 +371,58 @@ Thread::GetStopInfo ()
}
else
{
if ((m_thread_stop_reason_stop_id == stop_id) || // Stop info is valid, just return what we have (even if empty)
(m_actual_stop_info_sp && m_actual_stop_info_sp->IsValid())) // Stop info is valid, just return what we have
if ((m_stop_info_stop_id == stop_id) || // Stop info is valid, just return what we have (even if empty)
(m_stop_info_sp && m_stop_info_sp->IsValid())) // Stop info is valid, just return what we have
{
return m_actual_stop_info_sp;
return m_stop_info_sp;
}
else
{
GetPrivateStopReason ();
return m_actual_stop_info_sp;
GetPrivateStopInfo ();
return m_stop_info_sp;
}
}
}
lldb::StopInfoSP
Thread::GetPrivateStopInfo ()
{
ProcessSP process_sp (GetProcess());
if (process_sp)
{
ProcessSP process_sp (GetProcess());
if (process_sp)
{
const uint32_t process_stop_id = process_sp->GetStopID();
if (m_stop_info_stop_id != process_stop_id)
{
if (m_stop_info_sp)
{
if (m_stop_info_sp->IsValid())
{
SetStopInfo (m_stop_info_sp);
}
else
{
if (IsStillAtLastBreakpointHit())
SetStopInfo(m_stop_info_sp);
else
m_stop_info_sp.reset();
}
}
if (!m_stop_info_sp)
{
if (CalculateStopInfo() == false)
SetStopInfo (StopInfoSP());
}
}
}
}
return m_stop_info_sp;
}
lldb::StopReason
Thread::GetStopReason()
{
@ -393,20 +437,20 @@ Thread::GetStopReason()
void
Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp)
{
m_actual_stop_info_sp = stop_info_sp;
if (m_actual_stop_info_sp)
m_stop_info_sp = stop_info_sp;
if (m_stop_info_sp)
{
m_actual_stop_info_sp->MakeStopInfoValid();
m_stop_info_sp->MakeStopInfoValid();
// If we are overriding the ShouldReportStop, do that here:
if (m_override_should_notify != eLazyBoolCalculate)
m_actual_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes);
m_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes);
}
ProcessSP process_sp (GetProcess());
if (process_sp)
m_thread_stop_reason_stop_id = process_sp->GetStopID();
m_stop_info_stop_id = process_sp->GetStopID();
else
m_thread_stop_reason_stop_id = UINT32_MAX;
m_stop_info_stop_id = UINT32_MAX;
}
void
@ -417,8 +461,8 @@ Thread::SetShouldReportStop (Vote vote)
else
{
m_override_should_notify = (vote == eVoteYes ? eLazyBoolYes : eLazyBoolNo);
if (m_actual_stop_info_sp)
m_actual_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes);
if (m_stop_info_sp)
m_stop_info_sp->OverrideShouldNotify (m_override_should_notify == eLazyBoolYes);
}
}
@ -433,7 +477,7 @@ Thread::SetStopInfoToNothing()
bool
Thread::ThreadStoppedForAReason (void)
{
return (bool) GetPrivateStopReason ();
return (bool) GetPrivateStopInfo ();
}
bool
@ -554,18 +598,22 @@ Thread::ShouldResume (StateType resume_state)
m_temporary_resume_state = resume_state;
// Make sure m_actual_stop_info_sp is valid
GetPrivateStopReason();
lldb::ThreadSP backing_thread_sp (GetBackingThread ());
if (backing_thread_sp)
backing_thread_sp->m_temporary_resume_state = resume_state;
// Make sure m_stop_info_sp is valid
GetPrivateStopInfo();
// This is a little dubious, but we are trying to limit how often we actually fetch stop info from
// the target, 'cause that slows down single stepping. So assume that if we got to the point where
// we're about to resume, and we haven't yet had to fetch the stop reason, then it doesn't need to know
// about the fact that we are resuming...
const uint32_t process_stop_id = GetProcess()->GetStopID();
if (m_thread_stop_reason_stop_id == process_stop_id &&
(m_actual_stop_info_sp && m_actual_stop_info_sp->IsValid()))
if (m_stop_info_stop_id == process_stop_id &&
(m_stop_info_sp && m_stop_info_sp->IsValid()))
{
StopInfo *stop_info = GetPrivateStopReason().get();
StopInfo *stop_info = GetPrivateStopInfo().get();
if (stop_info)
stop_info->WillResume (resume_state);
}
@ -590,7 +638,7 @@ Thread::ShouldResume (StateType resume_state)
if (need_to_resume && resume_state != eStateSuspended)
{
m_actual_stop_info_sp.reset();
m_stop_info_sp.reset();
}
}
@ -676,7 +724,7 @@ Thread::ShouldStop (Event* event_ptr)
// First query the stop info's ShouldStopSynchronous. This handles "synchronous" stop reasons, for example the breakpoint
// command on internal breakpoints. If a synchronous stop reason says we should not stop, then we don't have to
// do any more work on this stop.
StopInfoSP private_stop_info (GetPrivateStopReason());
StopInfoSP private_stop_info (GetPrivateStopInfo());
if (private_stop_info && private_stop_info->ShouldStopSynchronous(event_ptr) == false)
{
if (log)
@ -1906,10 +1954,10 @@ Thread::IsStillAtLastBreakpointHit ()
// If we are currently stopped at a breakpoint, always return that stopinfo and don't reset it.
// This allows threads to maintain their breakpoint stopinfo, such as when thread-stepping in
// multithreaded programs.
if (m_actual_stop_info_sp) {
StopReason stop_reason = m_actual_stop_info_sp->GetStopReason();
if (m_stop_info_sp) {
StopReason stop_reason = m_stop_info_sp->GetStopReason();
if (stop_reason == lldb::eStopReasonBreakpoint) {
uint64_t value = m_actual_stop_info_sp->GetValue();
uint64_t value = m_stop_info_sp->GetValue();
lldb::RegisterContextSP reg_ctx_sp (GetRegisterContext());
if (reg_ctx_sp)
{

View File

@ -505,6 +505,8 @@ ThreadList::WillResume ()
if ((*pos)->GetResumeState() != eStateSuspended &&
(*pos)->GetCurrentPlan()->StopOthers())
{
if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread())
continue;
wants_solo_run = true;
break;
}
@ -535,6 +537,8 @@ ThreadList::WillResume ()
if ((*pos)->GetResumeState() != eStateSuspended
&& (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers()))
{
if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread())
continue;
(*pos)->SetupForResume ();
}
}
@ -546,7 +550,6 @@ ThreadList::WillResume ()
run_me_only_list.SetStopID(m_process->GetStopID());
ThreadSP immediate_thread_sp;
bool run_only_current_thread = false;
for (pos = m_threads.begin(); pos != end; ++pos)
@ -555,6 +558,9 @@ ThreadList::WillResume ()
if (thread_sp->GetResumeState() != eStateSuspended &&
thread_sp->GetCurrentPlan()->StopOthers())
{
if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread())
continue;
// You can't say "stop others" and also want yourself to be suspended.
assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
@ -573,18 +579,7 @@ ThreadList::WillResume ()
bool need_to_resume = true;
if (immediate_thread_sp)
{
for (pos = m_threads.begin(); pos != end; ++pos)
{
ThreadSP thread_sp(*pos);
if (thread_sp.get() == immediate_thread_sp.get())
thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState());
else
thread_sp->ShouldResume (eStateSuspended);
}
}
else if (run_me_only_list.GetSize (false) == 0)
if (run_me_only_list.GetSize (false) == 0)
{
// Everybody runs as they wish:
for (pos = m_threads.begin(); pos != end; ++pos)

View File

@ -34,7 +34,8 @@ ThreadPlanStepOverBreakpoint::ThreadPlanStepOverBreakpoint (Thread &thread) :
// first in the thread plan stack when stepping
// over a breakpoint
m_breakpoint_addr (LLDB_INVALID_ADDRESS),
m_auto_continue(false)
m_auto_continue(false),
m_reenabled_breakpoint_site (false)
{
m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC();
@ -105,9 +106,7 @@ ThreadPlanStepOverBreakpoint::DoWillResume (StateType resume_state, bool current
bool
ThreadPlanStepOverBreakpoint::WillStop ()
{
BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
if (bp_site_sp)
m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
ReenableBreakpointSite ();
return true;
}
@ -128,14 +127,31 @@ ThreadPlanStepOverBreakpoint::MischiefManaged ()
if (log)
log->Printf("Completed step over breakpoint plan.");
// Otherwise, re-enable the breakpoint we were stepping over, and we're done.
BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
if (bp_site_sp)
m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
ReenableBreakpointSite ();
ThreadPlan::MischiefManaged ();
return true;
}
}
void
ThreadPlanStepOverBreakpoint::ReenableBreakpointSite ()
{
if (!m_reenabled_breakpoint_site)
{
m_reenabled_breakpoint_site = true;
BreakpointSiteSP bp_site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress (m_breakpoint_addr));
if (bp_site_sp)
{
m_thread.GetProcess()->EnableBreakpointSite (bp_site_sp.get());
}
}
}
void
ThreadPlanStepOverBreakpoint::ThreadDestroyed ()
{
ReenableBreakpointSite ();
}
void
ThreadPlanStepOverBreakpoint::SetAutoContinue (bool do_it)
{