virtual void
ClearStackFrames ();
+ virtual bool
+ SetBackingThread (const lldb::ThreadSP &thread_sp)
+ {
+ return false;
+ }
+
+ virtual void
+ ClearBackingThread ()
+ {
+ // Subclasses can use this function if a thread is actually backed by
+ // another thread. This is currently used for the OperatingSystem plug-ins
+ // where they might have a thread that is in memory, yet its registers
+ // are available through the lldb_private::Thread subclass for the current
+ // lldb_private::Process class. Since each time the process stops the backing
+ // threads for memory threads can change, we need a way to clear the backing
+ // thread for all memory threads each time we stop.
+ }
+
void
DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx);
if (log)
log->Printf ("OperatingSystemPython::UpdateThreadList() fetching thread data from python for pid %" PRIu64, m_process->GetID());
+ // The threads that are in "new_thread_list" upon entry are the threads from the
+ // lldb_private::Process subclass, no memory threads will be in this list.
+
auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure threads_list stays alive
PythonList threads_list(m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp));
if (threads_list)
{
+ ThreadList core_thread_list(new_thread_list);
+
+ threads_list.Dump(); // REMOVE THIS
+
+ uint32_t i;
const uint32_t num_threads = threads_list.GetSize();
- for (uint32_t i=0; i<num_threads; ++i)
+ for (i=0; i<num_threads; ++i)
+ {
+ PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
+ if (thread_dict)
+ {
+ 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, &old_thread_list, NULL));
+ ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, NULL));
if (thread_sp)
new_thread_list.AddThread(thread_sp);
}
}
ThreadSP
-OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict, ThreadList *old_thread_list_ptr, bool *did_create_ptr)
+OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict,
+ ThreadList &core_thread_list,
+ ThreadList &old_thread_list,
+ bool *did_create_ptr)
{
ThreadSP thread_sp;
if (thread_dict)
const tid_t tid = thread_dict.GetItemForKeyAsInteger (tid_pystr, LLDB_INVALID_THREAD_ID);
if (tid != LLDB_INVALID_THREAD_ID)
{
+ PythonString core_pystr("core");
PythonString name_pystr("name");
PythonString queue_pystr("queue");
PythonString state_pystr("state");
PythonString stop_reason_pystr("stop_reason");
PythonString reg_data_addr_pystr ("register_data_addr");
+ const uint32_t core_number = thread_dict.GetItemForKeyAsInteger (core_pystr, UINT32_MAX);
const addr_t reg_data_addr = thread_dict.GetItemForKeyAsInteger (reg_data_addr_pystr, LLDB_INVALID_ADDRESS);
const char *name = thread_dict.GetItemForKeyAsString (name_pystr);
const char *queue = thread_dict.GetItemForKeyAsString (queue_pystr);
//const char *state = thread_dict.GetItemForKeyAsString (state_pystr);
//const char *stop_reason = thread_dict.GetItemForKeyAsString (stop_reason_pystr);
- if (old_thread_list_ptr)
- thread_sp = old_thread_list_ptr->FindThreadByID (tid, false);
+ thread_sp = old_thread_list.FindThreadByID (tid, false);
if (!thread_sp)
{
if (did_create_ptr)
name,
queue,
reg_data_addr));
+
+ }
+
+ if (core_number < core_thread_list.GetSize(false))
+ {
+ thread_sp->SetBackingThread(core_thread_list.GetThreadAtIndex(core_number, false));
}
}
}
PythonDictionary thread_info_dict (m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context));
if (thread_info_dict)
{
+ ThreadList core_threads(m_process);
ThreadList &thread_list = m_process->GetThreadList();
bool did_create = false;
- ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_info_dict, &thread_list, &did_create));
+ ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_info_dict, core_threads, thread_list, &did_create));
if (did_create)
thread_list.AddThread(thread_sp);
return thread_sp;
lldb::ThreadSP
CreateThreadFromThreadInfo (lldb_private::PythonDictionary &thread_dict,
- lldb_private::ThreadList *old_thread_list_ptr,
+ lldb_private::ThreadList &core_thread_list,
+ lldb_private::ThreadList &old_thread_list,
bool *did_create_ptr);
DynamicRegisterInfo *
}
}
}
- else if (m_unwinder_ap.get())
- reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+ else
+ {
+ Unwind *unwinder = GetUnwinder ();
+ if (unwinder)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
+ }
return reg_ctx_sp;
}
tid_t tid,
const ValueObjectSP &thread_info_valobj_sp) :
Thread (process, tid),
+ m_backing_thread_sp (),
m_thread_info_valobj_sp (thread_info_valobj_sp),
m_name(),
m_queue()
const char *queue,
lldb::addr_t register_data_addr) :
Thread (process, tid),
+ m_backing_thread_sp (),
m_thread_info_valobj_sp (),
m_name(),
m_queue(),
RegisterContextSP
ThreadMemory::GetRegisterContext ()
{
+ if (m_backing_thread_sp)
+ return m_backing_thread_sp->GetRegisterContext();
+
if (!m_reg_context_sp)
{
ProcessSP process_sp (GetProcess());
RegisterContextSP
ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame)
{
+ if (m_backing_thread_sp)
+ return m_backing_thread_sp->CreateRegisterContextForFrame(frame);
+
RegisterContextSP reg_ctx_sp;
uint32_t concrete_frame_idx = 0;
{
reg_ctx_sp = GetRegisterContext ();
}
- else if (m_unwinder_ap.get())
+ else
{
- reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+ Unwind *unwinder = GetUnwinder ();
+ if (unwinder)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
}
return reg_ctx_sp;
}
lldb::StopInfoSP
ThreadMemory::GetPrivateStopReason ()
{
+ if (m_backing_thread_sp)
+ return m_backing_thread_sp->GetPrivateStopReason();
+
ProcessSP process_sp (GetProcess());
if (process_sp)
void
ThreadMemory::RefreshStateAfterStop()
{
+ if (m_backing_thread_sp)
+ return m_backing_thread_sp->RefreshStateAfterStop();
+
+
// Don't fetch the registers by calling Thread::GetRegisterContext() below.
// We might not have fetched any registers yet and we don't want to fetch
// the registers just to call invalidate on them...
//------------------------------------------------------------------
// lldb_private::Thread methods
//------------------------------------------------------------------
- virtual void
- RefreshStateAfterStop();
-
virtual lldb::RegisterContextSP
GetRegisterContext ();
GetPrivateStopReason ();
virtual const char *
+ GetInfo ()
+ {
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->GetInfo();
+ return NULL;
+ }
+
+ virtual const char *
GetName ()
{
- return m_name.c_str();
+ if (!m_name.empty())
+ return m_name.c_str();
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->GetName();
+ return NULL;
}
virtual const char *
GetQueueName ()
{
- return m_queue.c_str();
+ if (!m_queue.empty())
+ return m_queue.c_str();
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->GetQueueName();
+ return NULL;
}
virtual bool
WillResume (lldb::StateType resume_state);
+ virtual void
+ DidResume ()
+ {
+ if (m_backing_thread_sp)
+ m_backing_thread_sp->DidResume();
+ }
+
+ virtual void
+ RefreshStateAfterStop();
+
lldb::ValueObjectSP &
GetValueObject ()
{
return m_thread_info_valobj_sp;
}
+
+ virtual void
+ ClearBackingThread ()
+ {
+ m_backing_thread_sp.reset();
+ }
+
+ virtual bool
+ SetBackingThread (const lldb::ThreadSP &thread_sp)
+ {
+ m_backing_thread_sp = thread_sp;
+ return (bool)thread_sp;
+ }
protected:
//------------------------------------------------------------------
// For ThreadMemory and subclasses
//------------------------------------------------------------------
+ // If this memory thread is actually represented by a thread from the
+ // lldb_private::Process subclass, then fill in the thread here and
+ // all APIs will be routed through this thread object. If m_backing_thread_sp
+ // is empty, then this thread is simply in memory with no representation
+ // through the process plug-in.
+ lldb::ThreadSP m_backing_thread_sp;
lldb::ValueObjectSP m_thread_info_valobj_sp;
std::string m_name;
std::string m_queue;
reg_ctx_sp.reset (new GDBRemoteRegisterContext (*this, concrete_frame_idx, gdb_process->m_register_info, read_all_registers_at_once));
}
}
- else if (m_unwinder_ap.get())
- reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+ else
+ {
+ Unwind *unwinder = GetUnwinder ();
+ if (unwinder)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
+ }
return reg_ctx_sp;
}
}
reg_ctx_sp = m_thread_reg_ctx_sp;
}
- else if (m_unwinder_ap.get())
+ else
{
- reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+ Unwind *unwinder = GetUnwinder ();
+ if (unwinder)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
}
return reg_ctx_sp;
}
{
OperatingSystem *os = GetOperatingSystem ();
if (os)
+ {
+ // Clear any old backing threads where memory threads might have been
+ // backed by actual threads from the lldb_private::Process subclass
+ size_t num_old_threads = m_thread_list.GetSize(false);
+ for (size_t i=0; i<num_old_threads; ++i)
+ m_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread();
+
+ // Now let the OperatingSystem plug-in update the thread list
os->UpdateThreadList (m_thread_list, new_thread_list);
+ }
m_thread_list.Update (new_thread_list);
m_thread_list.SetStopID (stop_id);
}
// if we need to
if (m_frames.empty())
{
- m_thread.GetRegisterContext();
- assert (m_thread.m_reg_context_sp.get());
-
- const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
- // There shouldn't be any way not to get the frame info for frame 0.
- // But if the unwinder can't make one, lets make one by hand with the
- // SP as the CFA and see if that gets any further.
- if (!success)
+ RegisterContextSP reg_ctx_sp (m_thread.GetRegisterContext());
+
+ if (reg_ctx_sp)
{
- cfa = m_thread.GetRegisterContext()->GetSP();
- pc = m_thread.GetRegisterContext()->GetPC();
+
+ const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+ // There shouldn't be any way not to get the frame info for frame 0.
+ // But if the unwinder can't make one, lets make one by hand with the
+ // SP as the CFA and see if that gets any further.
+ if (!success)
+ {
+ cfa = reg_ctx_sp->GetSP();
+ pc = reg_ctx_sp->GetPC();
+ }
+
+ unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(),
+ m_frames.size(),
+ idx,
+ reg_ctx_sp,
+ cfa,
+ pc,
+ NULL));
+ m_frames.push_back (unwind_frame_sp);
}
-
- unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(),
- m_frames.size(),
- idx,
- m_thread.m_reg_context_sp,
- cfa,
- pc,
- NULL));
- m_frames.push_back (unwind_frame_sp);
}
else
{