diff options
author | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2017-04-02 17:24:58 +0000 |
commit | 60b571e49a90d38697b3aca23020d9da42fc7d7f (patch) | |
tree | 99351324c24d6cb146b6285b6caffa4d26fce188 /contrib/llvm/tools/lldb/source/Target/ThreadList.cpp | |
parent | bea1b22c7a9bce1dfdd73e6e5b65bc4752215180 (diff) | |
download | FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.zip FreeBSD-src-60b571e49a90d38697b3aca23020d9da42fc7d7f.tar.gz |
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release:
MFC r309142 (by emaste):
Add WITH_LLD_AS_LD build knob
If set it installs LLD as /usr/bin/ld. LLD (as of version 3.9) is not
capable of linking the world and kernel, but can self-host and link many
substantial applications. GNU ld continues to be used for the world and
kernel build, regardless of how this knob is set.
It is on by default for arm64, and off for all other CPU architectures.
Sponsored by: The FreeBSD Foundation
MFC r310840:
Reapply 310775, now it also builds correctly if lldb is disabled:
Move llvm-objdump from CLANG_EXTRAS to installed by default
We currently install three tools from binutils 2.17.50: as, ld, and
objdump. Work is underway to migrate to a permissively-licensed
tool-chain, with one goal being the retirement of binutils 2.17.50.
LLVM's llvm-objdump is intended to be compatible with GNU objdump
although it is currently missing some options and may have formatting
differences. Enable it by default for testing and further investigation.
It may later be changed to install as /usr/bin/objdump, it becomes a
fully viable replacement.
Reviewed by: emaste
Differential Revision: https://reviews.freebsd.org/D8879
MFC r312855 (by emaste):
Rename LLD_AS_LD to LLD_IS_LD, for consistency with CLANG_IS_CC
Reported by: Dan McGregor <dan.mcgregor usask.ca>
MFC r313559 | glebius | 2017-02-10 18:34:48 +0100 (Fri, 10 Feb 2017) | 5 lines
Don't check struct rtentry on FreeBSD, it is an internal kernel structure.
On other systems it may be API structure for SIOCADDRT/SIOCDELRT.
Reviewed by: emaste, dim
MFC r314152 (by jkim):
Remove an assembler flag, which is redundant since r309124. The upstream
took care of it by introducing a macro NO_EXEC_STACK_DIRECTIVE.
http://llvm.org/viewvc/llvm-project?rev=273500&view=rev
Reviewed by: dim
MFC r314564:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
4.0.0 (branches/release_40 296509). The release will follow soon.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Also note that as of 4.0.0, lld should be able to link the base system
on amd64 and aarch64. See the WITH_LLD_IS_LLD setting in src.conf(5).
Though please be aware that this is work in progress.
Release notes for llvm, clang and lld will be available here:
<http://releases.llvm.org/4.0.0/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/4.0.0/tools/lld/docs/ReleaseNotes.html>
Thanks to Ed Maste, Jan Beich, Antoine Brodin and Eric Fiselier for
their help.
Relnotes: yes
Exp-run: antoine
PR: 215969, 216008
MFC r314708:
For now, revert r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
This commit is the cause of excessive compile times on skein_block.c
(and possibly other files) during kernel builds on amd64.
We never saw the problematic behavior described in this upstream commit,
so for now it is better to revert it. An upstream bug has been filed
here: https://bugs.llvm.org/show_bug.cgi?id=32142
Reported by: mjg
MFC r314795:
Reapply r287232 from upstream llvm trunk (by Daniil Fukalov):
[SCEV] limit recursion depth of CompareSCEVComplexity
Summary:
CompareSCEVComplexity goes too deep (50+ on a quite a big unrolled
loop) and runs almost infinite time.
Added cache of "equal" SCEV pairs to earlier cutoff of further
estimation. Recursion depth limit was also introduced as a parameter.
Reviewers: sanjoy
Subscribers: mzolotukhin, tstellarAMD, llvm-commits
Differential Revision: https://reviews.llvm.org/D26389
Pull in r296992 from upstream llvm trunk (by Sanjoy Das):
[SCEV] Decrease the recursion threshold for CompareValueComplexity
Fixes PR32142.
r287232 accidentally increased the recursion threshold for
CompareValueComplexity from 2 to 32. This change reverses that
change by introducing a separate flag for CompareValueComplexity's
threshold.
The latter revision fixes the excessive compile times for skein_block.c.
MFC r314907 | mmel | 2017-03-08 12:40:27 +0100 (Wed, 08 Mar 2017) | 7 lines
Unbreak ARMv6 world.
The new compiler_rt library imported with clang 4.0.0 have several fatal
issues (non-functional __udivsi3 for example) with ARM specific instrict
functions. As temporary workaround, until upstream solve these problems,
disable all thumb[1][2] related feature.
MFC r315016:
Update clang, llvm, lld, lldb, compiler-rt and libc++ to 4.0.0 release.
We were already very close to the last release candidate, so this is a
pretty minor update.
Relnotes: yes
MFC r316005:
Revert r314907, and pull in r298713 from upstream compiler-rt trunk (by
Weiming Zhao):
builtins: Select correct code fragments when compiling for Thumb1/Thum2/ARM ISA.
Summary:
Value of __ARM_ARCH_ISA_THUMB isn't based on the actual compilation
mode (-mthumb, -marm), it reflect's capability of given CPU.
Due to this:
- use __tbumb__ and __thumb2__ insteand of __ARM_ARCH_ISA_THUMB
- use '.thumb' directive consistently in all affected files
- decorate all thumb functions using
DEFINE_COMPILERRT_THUMB_FUNCTION()
---------
Note: This patch doesn't fix broken Thumb1 variant of __udivsi3 !
Reviewers: weimingz, rengolin, compnerd
Subscribers: aemerson, dim
Differential Revision: https://reviews.llvm.org/D30938
Discussed with: mmel
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/ThreadList.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Target/ThreadList.cpp | 1357 |
1 files changed, 625 insertions, 732 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp index 23e9f78..1e47451 100644 --- a/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp +++ b/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp @@ -17,856 +17,749 @@ // Project includes #include "lldb/Core/Log.h" #include "lldb/Core/State.h" +#include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" -#include "lldb/Target/ThreadList.h" #include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadList.h" #include "lldb/Target/ThreadPlan.h" -#include "lldb/Target/Process.h" #include "lldb/Utility/ConvertEnum.h" #include "lldb/Utility/LLDBAssert.h" using namespace lldb; using namespace lldb_private; -ThreadList::ThreadList (Process *process) : - ThreadCollection(), - m_process (process), - m_stop_id (0), - m_selected_tid (LLDB_INVALID_THREAD_ID) -{ -} - -ThreadList::ThreadList (const ThreadList &rhs) : - ThreadCollection(), - m_process (rhs.m_process), - m_stop_id (rhs.m_stop_id), - m_selected_tid () -{ - // Use the assignment operator since it uses the mutex - *this = rhs; -} - -const ThreadList& -ThreadList::operator = (const ThreadList& rhs) -{ - if (this != &rhs) - { - // Lock both mutexes to make sure neither side changes anyone on us - // while the assignment occurs - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - - m_process = rhs.m_process; - m_stop_id = rhs.m_stop_id; - m_threads = rhs.m_threads; - m_selected_tid = rhs.m_selected_tid; - } - return *this; +ThreadList::ThreadList(Process *process) + : ThreadCollection(), m_process(process), m_stop_id(0), + m_selected_tid(LLDB_INVALID_THREAD_ID) {} + +ThreadList::ThreadList(const ThreadList &rhs) + : ThreadCollection(), m_process(rhs.m_process), m_stop_id(rhs.m_stop_id), + m_selected_tid() { + // Use the assignment operator since it uses the mutex + *this = rhs; } +const ThreadList &ThreadList::operator=(const ThreadList &rhs) { + if (this != &rhs) { + // Lock both mutexes to make sure neither side changes anyone on us + // while the assignment occurs + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + std::lock_guard<std::recursive_mutex> rhs_guard(rhs.GetMutex()); -ThreadList::~ThreadList() -{ - // Clear the thread list. Clear will take the mutex lock - // which will ensure that if anyone is using the list - // they won't get it removed while using it. - Clear(); + m_process = rhs.m_process; + m_stop_id = rhs.m_stop_id; + m_threads = rhs.m_threads; + m_selected_tid = rhs.m_selected_tid; + } + return *this; } -lldb::ThreadSP -ThreadList::GetExpressionExecutionThread() -{ - if (m_expression_tid_stack.empty()) - return GetSelectedThread(); - ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back()); - if (expr_thread_sp) - return expr_thread_sp; - else - return GetSelectedThread(); +ThreadList::~ThreadList() { + // Clear the thread list. Clear will take the mutex lock + // which will ensure that if anyone is using the list + // they won't get it removed while using it. + Clear(); } -void -ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) -{ - m_expression_tid_stack.push_back(tid); +lldb::ThreadSP ThreadList::GetExpressionExecutionThread() { + if (m_expression_tid_stack.empty()) + return GetSelectedThread(); + ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back()); + if (expr_thread_sp) + return expr_thread_sp; + else + return GetSelectedThread(); } - -void -ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) -{ - assert(m_expression_tid_stack.back() == tid); - m_expression_tid_stack.pop_back(); + +void ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) { + m_expression_tid_stack.push_back(tid); } -uint32_t -ThreadList::GetStopID () const -{ - return m_stop_id; +void ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) { + assert(m_expression_tid_stack.back() == tid); + m_expression_tid_stack.pop_back(); } -void -ThreadList::SetStopID (uint32_t stop_id) -{ - m_stop_id = stop_id; +uint32_t ThreadList::GetStopID() const { return m_stop_id; } + +void ThreadList::SetStopID(uint32_t stop_id) { m_stop_id = stop_id; } + +uint32_t ThreadList::GetSize(bool can_update) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + + if (can_update) + m_process->UpdateThreadListIfNeeded(); + return m_threads.size(); } -uint32_t -ThreadList::GetSize (bool can_update) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); +ThreadSP ThreadList::GetThreadAtIndex(uint32_t idx, bool can_update) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); - if (can_update) - m_process->UpdateThreadListIfNeeded(); - return m_threads.size(); + if (can_update) + m_process->UpdateThreadListIfNeeded(); + + ThreadSP thread_sp; + if (idx < m_threads.size()) + thread_sp = m_threads[idx]; + return thread_sp; } -ThreadSP -ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); +ThreadSP ThreadList::FindThreadByID(lldb::tid_t tid, bool can_update) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); - if (can_update) - m_process->UpdateThreadListIfNeeded(); + if (can_update) + m_process->UpdateThreadListIfNeeded(); - ThreadSP thread_sp; - if (idx < m_threads.size()) - thread_sp = m_threads[idx]; - return thread_sp; + ThreadSP thread_sp; + uint32_t idx = 0; + const uint32_t num_threads = m_threads.size(); + for (idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->GetID() == tid) { + thread_sp = m_threads[idx]; + break; + } + } + return thread_sp; } -ThreadSP -ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); +ThreadSP ThreadList::FindThreadByProtocolID(lldb::tid_t tid, bool can_update) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); - if (can_update) - m_process->UpdateThreadListIfNeeded(); + if (can_update) + m_process->UpdateThreadListIfNeeded(); - ThreadSP thread_sp; - uint32_t idx = 0; - const uint32_t num_threads = m_threads.size(); - for (idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->GetID() == tid) - { - thread_sp = m_threads[idx]; - break; - } + ThreadSP thread_sp; + uint32_t idx = 0; + const uint32_t num_threads = m_threads.size(); + for (idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->GetProtocolID() == tid) { + thread_sp = m_threads[idx]; + break; } - return thread_sp; + } + return thread_sp; } -ThreadSP -ThreadList::FindThreadByProtocolID (lldb::tid_t tid, bool can_update) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); +ThreadSP ThreadList::RemoveThreadByID(lldb::tid_t tid, bool can_update) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); - if (can_update) - m_process->UpdateThreadListIfNeeded(); - - ThreadSP thread_sp; - uint32_t idx = 0; - const uint32_t num_threads = m_threads.size(); - for (idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->GetProtocolID() == tid) - { - thread_sp = m_threads[idx]; - break; - } + if (can_update) + m_process->UpdateThreadListIfNeeded(); + + ThreadSP thread_sp; + uint32_t idx = 0; + const uint32_t num_threads = m_threads.size(); + for (idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->GetID() == tid) { + thread_sp = m_threads[idx]; + m_threads.erase(m_threads.begin() + idx); + break; } - return thread_sp; + } + return thread_sp; } +ThreadSP ThreadList::RemoveThreadByProtocolID(lldb::tid_t tid, + bool can_update) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); -ThreadSP -ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); + if (can_update) + m_process->UpdateThreadListIfNeeded(); - if (can_update) - m_process->UpdateThreadListIfNeeded(); - - ThreadSP thread_sp; - uint32_t idx = 0; - const uint32_t num_threads = m_threads.size(); - for (idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->GetID() == tid) - { - thread_sp = m_threads[idx]; - m_threads.erase(m_threads.begin()+idx); - break; - } + ThreadSP thread_sp; + uint32_t idx = 0; + const uint32_t num_threads = m_threads.size(); + for (idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->GetProtocolID() == tid) { + thread_sp = m_threads[idx]; + m_threads.erase(m_threads.begin() + idx); + break; } - return thread_sp; + } + return thread_sp; } -ThreadSP -ThreadList::RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update) -{ +ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) { + ThreadSP thread_sp; + if (thread_ptr) { std::lock_guard<std::recursive_mutex> guard(GetMutex()); - if (can_update) - m_process->UpdateThreadListIfNeeded(); - - ThreadSP thread_sp; uint32_t idx = 0; const uint32_t num_threads = m_threads.size(); - for (idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->GetProtocolID() == tid) - { - thread_sp = m_threads[idx]; - m_threads.erase(m_threads.begin()+idx); - break; - } + for (idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx].get() == thread_ptr) { + thread_sp = m_threads[idx]; + break; + } } - return thread_sp; -} - -ThreadSP -ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr) -{ - ThreadSP thread_sp; - if (thread_ptr) - { - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - - uint32_t idx = 0; - const uint32_t num_threads = m_threads.size(); - for (idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx].get() == thread_ptr) - { - thread_sp = m_threads[idx]; - break; - } - } + } + return thread_sp; +} + +ThreadSP ThreadList::FindThreadByIndexID(uint32_t index_id, bool can_update) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + + if (can_update) + m_process->UpdateThreadListIfNeeded(); + + ThreadSP thread_sp; + const uint32_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->GetIndexID() == index_id) { + thread_sp = m_threads[idx]; + break; } - return thread_sp; + } + return thread_sp; } +bool ThreadList::ShouldStop(Event *event_ptr) { + // Running events should never stop, obviously... + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); -ThreadSP -ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); + // The ShouldStop method of the threads can do a whole lot of work, + // figuring out whether the thread plan conditions are met. So we don't want + // to keep the ThreadList locked the whole time we are doing this. + // FIXME: It is possible that running code could cause new threads + // to be created. If that happens, we will miss asking them whether + // they should stop. This is not a big deal since we haven't had + // a chance to hang any interesting operations on those threads yet. - if (can_update) - m_process->UpdateThreadListIfNeeded(); + collection threads_copy; + { + // Scope for locker + std::lock_guard<std::recursive_mutex> guard(GetMutex()); - ThreadSP thread_sp; - const uint32_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->GetIndexID() == index_id) - { - thread_sp = m_threads[idx]; - break; - } + m_process->UpdateThreadListIfNeeded(); + for (lldb::ThreadSP thread_sp : m_threads) { + // This is an optimization... If we didn't let a thread run in between + // the previous stop and this + // one, we shouldn't have to consult it for ShouldStop. So just leave it + // off the list we are going to + // inspect. + // On Linux, if a thread-specific conditional breakpoint was hit, it won't + // necessarily be the thread + // that hit the breakpoint itself that evaluates the conditional + // expression, so the thread that hit + // the breakpoint could still be asked to stop, even though it hasn't been + // allowed to run since the + // previous stop. + if (thread_sp->GetTemporaryResumeState() != eStateSuspended || + thread_sp->IsStillAtLastBreakpointHit()) + threads_copy.push_back(thread_sp); } - return thread_sp; -} - -bool -ThreadList::ShouldStop (Event *event_ptr) -{ - // Running events should never stop, obviously... - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - - // The ShouldStop method of the threads can do a whole lot of work, - // figuring out whether the thread plan conditions are met. So we don't want - // to keep the ThreadList locked the whole time we are doing this. - // FIXME: It is possible that running code could cause new threads - // to be created. If that happens, we will miss asking them whether - // they should stop. This is not a big deal since we haven't had - // a chance to hang any interesting operations on those threads yet. - - collection threads_copy; - { - // Scope for locker - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - - m_process->UpdateThreadListIfNeeded(); - for (lldb::ThreadSP thread_sp : m_threads) - { - // This is an optimization... If we didn't let a thread run in between the previous stop and this - // one, we shouldn't have to consult it for ShouldStop. So just leave it off the list we are going to - // inspect. - // On Linux, if a thread-specific conditional breakpoint was hit, it won't necessarily be the thread - // that hit the breakpoint itself that evaluates the conditional expression, so the thread that hit - // the breakpoint could still be asked to stop, even though it hasn't been allowed to run since the - // previous stop. - if (thread_sp->GetTemporaryResumeState () != eStateSuspended || thread_sp->IsStillAtLastBreakpointHit()) - threads_copy.push_back(thread_sp); - } - // It is possible the threads we were allowing to run all exited and then maybe the user interrupted - // or something, then fall back on looking at all threads: + // It is possible the threads we were allowing to run all exited and then + // maybe the user interrupted + // or something, then fall back on looking at all threads: - if (threads_copy.size() == 0) - threads_copy = m_threads; - } + if (threads_copy.size() == 0) + threads_copy = m_threads; + } + + collection::iterator pos, end = threads_copy.end(); - collection::iterator pos, end = threads_copy.end(); + if (log) { + log->PutCString(""); + log->Printf("ThreadList::%s: %" PRIu64 " threads, %" PRIu64 + " unsuspended threads", + __FUNCTION__, (uint64_t)m_threads.size(), + (uint64_t)threads_copy.size()); + } + bool did_anybody_stop_for_a_reason = false; + + // If the event is an Interrupt event, then we're going to stop no matter + // what. Otherwise, presume we won't stop. + bool should_stop = false; + if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) { if (log) - { - log->PutCString(""); - log->Printf ("ThreadList::%s: %" PRIu64 " threads, %" PRIu64 " unsuspended threads", - __FUNCTION__, - (uint64_t)m_threads.size(), - (uint64_t)threads_copy.size()); - } + log->Printf( + "ThreadList::%s handling interrupt event, should stop set to true", + __FUNCTION__); + + should_stop = true; + } + + // Now we run through all the threads and get their stop info's. We want to + // make sure to do this first before + // we start running the ShouldStop, because one thread's ShouldStop could + // destroy information (like deleting a + // thread specific breakpoint another thread had stopped at) which could lead + // us to compute the StopInfo incorrectly. + // We don't need to use it here, we just want to make sure it gets computed. + + for (pos = threads_copy.begin(); pos != end; ++pos) { + ThreadSP thread_sp(*pos); + thread_sp->GetStopInfo(); + } + + for (pos = threads_copy.begin(); pos != end; ++pos) { + ThreadSP thread_sp(*pos); + + // We should never get a stop for which no thread had a stop reason, but + // sometimes we do see this - + // for instance when we first connect to a remote stub. In that case we + // should stop, since we can't figure out + // the right thing to do and stopping gives the user control over what to do + // in this instance. + // + // Note, this causes a problem when you have a thread specific breakpoint, + // and a bunch of threads hit the breakpoint, + // but not the thread which we are waiting for. All the threads that are + // not "supposed" to hit the breakpoint + // are marked as having no stop reason, which is right, they should not show + // a stop reason. But that triggers this + // code and causes us to stop seemingly for no reason. + // + // Since the only way we ever saw this error was on first attach, I'm only + // going to trigger set did_anybody_stop_for_a_reason + // to true unless this is the first stop. + // + // If this becomes a problem, we'll have to have another StopReason like + // "StopInfoHidden" which will look invalid + // everywhere but at this check. + + if (thread_sp->GetProcess()->GetStopID() > 1) + did_anybody_stop_for_a_reason = true; + else + did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); - bool did_anybody_stop_for_a_reason = false; - - // If the event is an Interrupt event, then we're going to stop no matter what. Otherwise, presume we won't stop. - bool should_stop = false; - if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) - { - if (log) - log->Printf("ThreadList::%s handling interrupt event, should stop set to true", __FUNCTION__); - - should_stop = true; - } - - // Now we run through all the threads and get their stop info's. We want to make sure to do this first before - // we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a - // thread specific breakpoint another thread had stopped at) which could lead us to compute the StopInfo incorrectly. - // We don't need to use it here, we just want to make sure it gets computed. - - for (pos = threads_copy.begin(); pos != end; ++pos) - { - ThreadSP thread_sp(*pos); - thread_sp->GetStopInfo(); - } - - for (pos = threads_copy.begin(); pos != end; ++pos) - { - ThreadSP thread_sp(*pos); - - // We should never get a stop for which no thread had a stop reason, but sometimes we do see this - - // for instance when we first connect to a remote stub. In that case we should stop, since we can't figure out - // the right thing to do and stopping gives the user control over what to do in this instance. - // - // Note, this causes a problem when you have a thread specific breakpoint, and a bunch of threads hit the breakpoint, - // but not the thread which we are waiting for. All the threads that are not "supposed" to hit the breakpoint - // are marked as having no stop reason, which is right, they should not show a stop reason. But that triggers this - // code and causes us to stop seemingly for no reason. - // - // Since the only way we ever saw this error was on first attach, I'm only going to trigger set did_anybody_stop_for_a_reason - // to true unless this is the first stop. - // - // If this becomes a problem, we'll have to have another StopReason like "StopInfoHidden" which will look invalid - // everywhere but at this check. - - if (thread_sp->GetProcess()->GetStopID() > 1) - did_anybody_stop_for_a_reason = true; - else - did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); - - const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); - if (thread_should_stop) - should_stop |= true; - } + const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); + if (thread_should_stop) + should_stop |= true; + } - if (!should_stop && !did_anybody_stop_for_a_reason) - { - should_stop = true; - if (log) - log->Printf ("ThreadList::%s we stopped but no threads had a stop reason, overriding should_stop and stopping.", __FUNCTION__); - } - + if (!should_stop && !did_anybody_stop_for_a_reason) { + should_stop = true; if (log) - log->Printf ("ThreadList::%s overall should_stop = %i", __FUNCTION__, should_stop); - - if (should_stop) - { - for (pos = threads_copy.begin(); pos != end; ++pos) - { - ThreadSP thread_sp(*pos); - thread_sp->WillStop (); - } + log->Printf("ThreadList::%s we stopped but no threads had a stop reason, " + "overriding should_stop and stopping.", + __FUNCTION__); + } + + if (log) + log->Printf("ThreadList::%s overall should_stop = %i", __FUNCTION__, + should_stop); + + if (should_stop) { + for (pos = threads_copy.begin(); pos != end; ++pos) { + ThreadSP thread_sp(*pos); + thread_sp->WillStop(); } + } - return should_stop; + return should_stop; } -Vote -ThreadList::ShouldReportStop (Event *event_ptr) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); +Vote ThreadList::ShouldReportStop(Event *event_ptr) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); - Vote result = eVoteNoOpinion; - m_process->UpdateThreadListIfNeeded(); - collection::iterator pos, end = m_threads.end(); + Vote result = eVoteNoOpinion; + m_process->UpdateThreadListIfNeeded(); + collection::iterator pos, end = m_threads.end(); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf ("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); - - // Run through the threads and ask whether we should report this event. - // For stopping, a YES vote wins over everything. A NO vote wins over NO opinion. - for (pos = m_threads.begin(); pos != end; ++pos) - { - ThreadSP thread_sp(*pos); - const Vote vote = thread_sp->ShouldReportStop (event_ptr); - switch (vote) - { - case eVoteNoOpinion: - continue; - - case eVoteYes: - result = eVoteYes; - break; - - case eVoteNo: - if (result == eVoteNoOpinion) - { - result = eVoteNo; - } - else - { - if (log) - log->Printf ("ThreadList::%s thread 0x%4.4" PRIx64 ": voted %s, but lost out because result was %s", - __FUNCTION__, - thread_sp->GetID (), - GetVoteAsCString (vote), - GetVoteAsCString (result)); - } - break; - } + if (log) + log->Printf("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, + (uint64_t)m_threads.size()); + + // Run through the threads and ask whether we should report this event. + // For stopping, a YES vote wins over everything. A NO vote wins over NO + // opinion. + for (pos = m_threads.begin(); pos != end; ++pos) { + ThreadSP thread_sp(*pos); + const Vote vote = thread_sp->ShouldReportStop(event_ptr); + switch (vote) { + case eVoteNoOpinion: + continue; + + case eVoteYes: + result = eVoteYes; + break; + + case eVoteNo: + if (result == eVoteNoOpinion) { + result = eVoteNo; + } else { + if (log) + log->Printf("ThreadList::%s thread 0x%4.4" PRIx64 + ": voted %s, but lost out because result was %s", + __FUNCTION__, thread_sp->GetID(), GetVoteAsCString(vote), + GetVoteAsCString(result)); + } + break; } - if (log) - log->Printf ("ThreadList::%s returning %s", __FUNCTION__, GetVoteAsCString (result)); - return result; + } + if (log) + log->Printf("ThreadList::%s returning %s", __FUNCTION__, + GetVoteAsCString(result)); + return result; } -void -ThreadList::SetShouldReportStop (Vote vote) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); +void ThreadList::SetShouldReportStop(Vote vote) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); - m_process->UpdateThreadListIfNeeded(); - collection::iterator pos, end = m_threads.end(); - for (pos = m_threads.begin(); pos != end; ++pos) - { - ThreadSP thread_sp(*pos); - thread_sp->SetShouldReportStop (vote); - } + m_process->UpdateThreadListIfNeeded(); + collection::iterator pos, end = m_threads.end(); + for (pos = m_threads.begin(); pos != end; ++pos) { + ThreadSP thread_sp(*pos); + thread_sp->SetShouldReportStop(vote); + } } -Vote -ThreadList::ShouldReportRun (Event *event_ptr) -{ +Vote ThreadList::ShouldReportRun(Event *event_ptr) { - std::lock_guard<std::recursive_mutex> guard(GetMutex()); + std::lock_guard<std::recursive_mutex> guard(GetMutex()); - Vote result = eVoteNoOpinion; - m_process->UpdateThreadListIfNeeded(); - collection::iterator pos, end = m_threads.end(); - - // Run through the threads and ask whether we should report this event. - // The rule is NO vote wins over everything, a YES vote wins over no opinion. - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - - for (pos = m_threads.begin(); pos != end; ++pos) - { - if ((*pos)->GetResumeState () != eStateSuspended) - { - switch ((*pos)->ShouldReportRun (event_ptr)) - { - case eVoteNoOpinion: - continue; - case eVoteYes: - if (result == eVoteNoOpinion) - result = eVoteYes; - break; - case eVoteNo: - if (log) - log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.", - (*pos)->GetIndexID(), - (*pos)->GetID()); - result = eVoteNo; - break; - } - } + Vote result = eVoteNoOpinion; + m_process->UpdateThreadListIfNeeded(); + collection::iterator pos, end = m_threads.end(); + + // Run through the threads and ask whether we should report this event. + // The rule is NO vote wins over everything, a YES vote wins over no opinion. + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + + for (pos = m_threads.begin(); pos != end; ++pos) { + if ((*pos)->GetResumeState() != eStateSuspended) { + switch ((*pos)->ShouldReportRun(event_ptr)) { + case eVoteNoOpinion: + continue; + case eVoteYes: + if (result == eVoteNoOpinion) + result = eVoteYes; + break; + case eVoteNo: + if (log) + log->Printf("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 + ") says don't report.", + (*pos)->GetIndexID(), (*pos)->GetID()); + result = eVoteNo; + break; + } } - return result; + } + return result; } -void -ThreadList::Clear() -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - m_stop_id = 0; - m_threads.clear(); - m_selected_tid = LLDB_INVALID_THREAD_ID; +void ThreadList::Clear() { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + m_stop_id = 0; + m_threads.clear(); + m_selected_tid = LLDB_INVALID_THREAD_ID; } -void -ThreadList::Destroy() -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - const uint32_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - m_threads[idx]->DestroyThread(); - } +void ThreadList::Destroy() { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + const uint32_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) { + m_threads[idx]->DestroyThread(); + } } -void -ThreadList::RefreshStateAfterStop () -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); +void ThreadList::RefreshStateAfterStop() { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); - m_process->UpdateThreadListIfNeeded(); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log && log->GetVerbose()) - log->Printf ("Turning off notification of new threads while single stepping a thread."); + m_process->UpdateThreadListIfNeeded(); - collection::iterator pos, end = m_threads.end(); - for (pos = m_threads.begin(); pos != end; ++pos) - (*pos)->RefreshStateAfterStop (); -} + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log && log->GetVerbose()) + log->Printf("Turning off notification of new threads while single stepping " + "a thread."); -void -ThreadList::DiscardThreadPlans () -{ - // You don't need to update the thread list here, because only threads - // that you currently know about have any thread plans. - std::lock_guard<std::recursive_mutex> guard(GetMutex()); + collection::iterator pos, end = m_threads.end(); + for (pos = m_threads.begin(); pos != end; ++pos) + (*pos)->RefreshStateAfterStop(); +} - collection::iterator pos, end = m_threads.end(); - for (pos = m_threads.begin(); pos != end; ++pos) - (*pos)->DiscardThreadPlans (true); +void ThreadList::DiscardThreadPlans() { + // You don't need to update the thread list here, because only threads + // that you currently know about have any thread plans. + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + collection::iterator pos, end = m_threads.end(); + for (pos = m_threads.begin(); pos != end; ++pos) + (*pos)->DiscardThreadPlans(true); } -bool -ThreadList::WillResume () -{ - // Run through the threads and perform their momentary actions. - // But we only do this for threads that are running, user suspended - // threads stay where they are. +bool ThreadList::WillResume() { + // Run through the threads and perform their momentary actions. + // But we only do this for threads that are running, user suspended + // threads stay where they are. - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - m_process->UpdateThreadListIfNeeded(); + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + m_process->UpdateThreadListIfNeeded(); - collection::iterator pos, end = m_threads.end(); - - // See if any thread wants to run stopping others. If it does, then we won't - // setup the other threads for resume, since they aren't going to get a chance - // to run. This is necessary because the SetupForResume might add "StopOthers" - // plans which would then get to be part of the who-gets-to-run negotiation, but - // they're coming in after the fact, and the threads that are already set up should - // take priority. - - bool wants_solo_run = false; - - for (pos = m_threads.begin(); pos != end; ++pos) - { - lldbassert((*pos)->GetCurrentPlan() && "thread should not have null thread plan"); - if ((*pos)->GetResumeState() != eStateSuspended && - (*pos)->GetCurrentPlan()->StopOthers()) - { - if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) - continue; - wants_solo_run = true; - break; - } - } - - if (wants_solo_run) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log && log->GetVerbose()) - log->Printf ("Turning on notification of new threads while single stepping a thread."); - m_process->StartNoticingNewThreads(); - } - else - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log && log->GetVerbose()) - log->Printf ("Turning off notification of new threads while single stepping a thread."); - m_process->StopNoticingNewThreads(); - } - - // Give all the threads that are likely to run a last chance to set up their state before we - // negotiate who is actually going to get a chance to run... - // Don't set to resume suspended threads, and if any thread wanted to stop others, only - // call setup on the threads that request StopOthers... - - for (pos = m_threads.begin(); pos != end; ++pos) - { - if ((*pos)->GetResumeState() != eStateSuspended - && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) - { - if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) - continue; - (*pos)->SetupForResume (); - } - } + collection::iterator pos, end = m_threads.end(); - // Now go through the threads and see if any thread wants to run just itself. - // if so then pick one and run it. - - ThreadList run_me_only_list (m_process); - - run_me_only_list.SetStopID(m_process->GetStopID()); - - bool run_only_current_thread = false; - - for (pos = m_threads.begin(); pos != end; ++pos) - { - ThreadSP thread_sp(*pos); - 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); - - if (thread_sp == GetSelectedThread()) - { - // If the currently selected thread wants to run on its own, always let it. - run_only_current_thread = true; - run_me_only_list.Clear(); - run_me_only_list.AddThread (thread_sp); - break; - } - - run_me_only_list.AddThread (thread_sp); - } + // See if any thread wants to run stopping others. If it does, then we won't + // setup the other threads for resume, since they aren't going to get a chance + // to run. This is necessary because the SetupForResume might add + // "StopOthers" + // plans which would then get to be part of the who-gets-to-run negotiation, + // but + // they're coming in after the fact, and the threads that are already set up + // should + // take priority. + + bool wants_solo_run = false; + for (pos = m_threads.begin(); pos != end; ++pos) { + lldbassert((*pos)->GetCurrentPlan() && + "thread should not have null thread plan"); + if ((*pos)->GetResumeState() != eStateSuspended && + (*pos)->GetCurrentPlan()->StopOthers()) { + if ((*pos)->IsOperatingSystemPluginThread() && + !(*pos)->GetBackingThread()) + continue; + wants_solo_run = true; + break; } + } - bool need_to_resume = true; - - if (run_me_only_list.GetSize (false) == 0) - { - // Everybody runs as they wish: - for (pos = m_threads.begin(); pos != end; ++pos) - { - ThreadSP thread_sp(*pos); - StateType run_state; - if (thread_sp->GetResumeState() != eStateSuspended) - run_state = thread_sp->GetCurrentPlan()->RunState(); - else - run_state = eStateSuspended; - if (!thread_sp->ShouldResume(run_state)) - need_to_resume = false; - } + if (wants_solo_run) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log && log->GetVerbose()) + log->Printf("Turning on notification of new threads while single " + "stepping a thread."); + m_process->StartNoticingNewThreads(); + } else { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log && log->GetVerbose()) + log->Printf("Turning off notification of new threads while single " + "stepping a thread."); + m_process->StopNoticingNewThreads(); + } + + // Give all the threads that are likely to run a last chance to set up their + // state before we + // negotiate who is actually going to get a chance to run... + // Don't set to resume suspended threads, and if any thread wanted to stop + // others, only + // call setup on the threads that request StopOthers... + + for (pos = m_threads.begin(); pos != end; ++pos) { + if ((*pos)->GetResumeState() != eStateSuspended && + (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) { + if ((*pos)->IsOperatingSystemPluginThread() && + !(*pos)->GetBackingThread()) + continue; + (*pos)->SetupForResume(); } - else - { - ThreadSP thread_to_run; + } - if (run_only_current_thread) - { - thread_to_run = GetSelectedThread(); - } - else if (run_me_only_list.GetSize (false) == 1) - { - thread_to_run = run_me_only_list.GetThreadAtIndex (0); - } - else - { - int random_thread = (int) - ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0)); - thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread); - } + // Now go through the threads and see if any thread wants to run just itself. + // if so then pick one and run it. - for (pos = m_threads.begin(); pos != end; ++pos) - { - ThreadSP thread_sp(*pos); - if (thread_sp == thread_to_run) - { - if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) - need_to_resume = false; - } - else - thread_sp->ShouldResume (eStateSuspended); - } - } + ThreadList run_me_only_list(m_process); - return need_to_resume; -} + run_me_only_list.SetStopID(m_process->GetStopID()); -void -ThreadList::DidResume () -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - collection::iterator pos, end = m_threads.end(); - for (pos = m_threads.begin(); pos != end; ++pos) - { - // Don't clear out threads that aren't going to get a chance to run, rather - // leave their state for the next time around. - ThreadSP thread_sp(*pos); - if (thread_sp->GetResumeState() != eStateSuspended) - thread_sp->DidResume (); - } -} + bool run_only_current_thread = false; -void -ThreadList::DidStop () -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - collection::iterator pos, end = m_threads.end(); - for (pos = m_threads.begin(); pos != end; ++pos) - { - // Notify threads that the process just stopped. - // Note, this currently assumes that all threads in the list - // stop when the process stops. In the future we will want to support - // a debugging model where some threads continue to run while others - // are stopped. We either need to handle that somehow here or - // create a special thread list containing only threads which will - // stop in the code that calls this method (currently - // Process::SetPrivateState). - ThreadSP thread_sp(*pos); - if (StateIsRunningState(thread_sp->GetState())) - thread_sp->DidStop (); + for (pos = m_threads.begin(); pos != end; ++pos) { + ThreadSP thread_sp(*pos); + 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); + + if (thread_sp == GetSelectedThread()) { + // If the currently selected thread wants to run on its own, always let + // it. + run_only_current_thread = true; + run_me_only_list.Clear(); + run_me_only_list.AddThread(thread_sp); + break; + } + + run_me_only_list.AddThread(thread_sp); + } + } + + bool need_to_resume = true; + + if (run_me_only_list.GetSize(false) == 0) { + // Everybody runs as they wish: + for (pos = m_threads.begin(); pos != end; ++pos) { + ThreadSP thread_sp(*pos); + StateType run_state; + if (thread_sp->GetResumeState() != eStateSuspended) + run_state = thread_sp->GetCurrentPlan()->RunState(); + else + run_state = eStateSuspended; + if (!thread_sp->ShouldResume(run_state)) + need_to_resume = false; + } + } else { + ThreadSP thread_to_run; + + if (run_only_current_thread) { + thread_to_run = GetSelectedThread(); + } else if (run_me_only_list.GetSize(false) == 1) { + thread_to_run = run_me_only_list.GetThreadAtIndex(0); + } else { + int random_thread = + (int)((run_me_only_list.GetSize(false) * (double)rand()) / + (RAND_MAX + 1.0)); + thread_to_run = run_me_only_list.GetThreadAtIndex(random_thread); } -} -ThreadSP -ThreadList::GetSelectedThread () -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - ThreadSP thread_sp = FindThreadByID(m_selected_tid); - if (!thread_sp.get()) - { - if (m_threads.size() == 0) - return thread_sp; - m_selected_tid = m_threads[0]->GetID(); - thread_sp = m_threads[0]; + for (pos = m_threads.begin(); pos != end; ++pos) { + ThreadSP thread_sp(*pos); + if (thread_sp == thread_to_run) { + if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) + need_to_resume = false; + } else + thread_sp->ShouldResume(eStateSuspended); } - return thread_sp; + } + + return need_to_resume; +} + +void ThreadList::DidResume() { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + collection::iterator pos, end = m_threads.end(); + for (pos = m_threads.begin(); pos != end; ++pos) { + // Don't clear out threads that aren't going to get a chance to run, rather + // leave their state for the next time around. + ThreadSP thread_sp(*pos); + if (thread_sp->GetResumeState() != eStateSuspended) + thread_sp->DidResume(); + } +} + +void ThreadList::DidStop() { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + collection::iterator pos, end = m_threads.end(); + for (pos = m_threads.begin(); pos != end; ++pos) { + // Notify threads that the process just stopped. + // Note, this currently assumes that all threads in the list + // stop when the process stops. In the future we will want to support + // a debugging model where some threads continue to run while others + // are stopped. We either need to handle that somehow here or + // create a special thread list containing only threads which will + // stop in the code that calls this method (currently + // Process::SetPrivateState). + ThreadSP thread_sp(*pos); + if (StateIsRunningState(thread_sp->GetState())) + thread_sp->DidStop(); + } +} + +ThreadSP ThreadList::GetSelectedThread() { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + ThreadSP thread_sp = FindThreadByID(m_selected_tid); + if (!thread_sp.get()) { + if (m_threads.size() == 0) + return thread_sp; + m_selected_tid = m_threads[0]->GetID(); + thread_sp = m_threads[0]; + } + return thread_sp; +} + +bool ThreadList::SetSelectedThreadByID(lldb::tid_t tid, bool notify) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + ThreadSP selected_thread_sp(FindThreadByID(tid)); + if (selected_thread_sp) { + m_selected_tid = tid; + selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); + } else + m_selected_tid = LLDB_INVALID_THREAD_ID; + + if (notify) + NotifySelectedThreadChanged(m_selected_tid); + + return m_selected_tid != LLDB_INVALID_THREAD_ID; } -bool -ThreadList::SetSelectedThreadByID (lldb::tid_t tid, bool notify) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - ThreadSP selected_thread_sp(FindThreadByID(tid)); - if (selected_thread_sp) - { - m_selected_tid = tid; - selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); - } - else - m_selected_tid = LLDB_INVALID_THREAD_ID; +bool ThreadList::SetSelectedThreadByIndexID(uint32_t index_id, bool notify) { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + ThreadSP selected_thread_sp(FindThreadByIndexID(index_id)); + if (selected_thread_sp.get()) { + m_selected_tid = selected_thread_sp->GetID(); + selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); + } else + m_selected_tid = LLDB_INVALID_THREAD_ID; + + if (notify) + NotifySelectedThreadChanged(m_selected_tid); - if (notify) - NotifySelectedThreadChanged(m_selected_tid); - - return m_selected_tid != LLDB_INVALID_THREAD_ID; + return m_selected_tid != LLDB_INVALID_THREAD_ID; } -bool -ThreadList::SetSelectedThreadByIndexID (uint32_t index_id, bool notify) -{ - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - ThreadSP selected_thread_sp (FindThreadByIndexID(index_id)); - if (selected_thread_sp.get()) - { - m_selected_tid = selected_thread_sp->GetID(); - selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); - } - else - m_selected_tid = LLDB_INVALID_THREAD_ID; - - if (notify) - NotifySelectedThreadChanged(m_selected_tid); - - return m_selected_tid != LLDB_INVALID_THREAD_ID; -} - -void -ThreadList::NotifySelectedThreadChanged (lldb::tid_t tid) -{ - ThreadSP selected_thread_sp (FindThreadByID(tid)); - if (selected_thread_sp->EventTypeHasListeners(Thread::eBroadcastBitThreadSelected)) - selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected, - new Thread::ThreadEventData(selected_thread_sp)); -} - -void -ThreadList::Update (ThreadList &rhs) -{ - if (this != &rhs) - { - // Lock both mutexes to make sure neither side changes anyone on us - // while the assignment occurs - std::lock_guard<std::recursive_mutex> guard(GetMutex()); - - m_process = rhs.m_process; - m_stop_id = rhs.m_stop_id; - m_threads.swap(rhs.m_threads); - m_selected_tid = rhs.m_selected_tid; - - - // Now we look for threads that we are done with and - // make sure to clear them up as much as possible so - // anyone with a shared pointer will still have a reference, - // but the thread won't be of much use. Using std::weak_ptr - // for all backward references (such as a thread to a process) - // will eventually solve this issue for us, but for now, we - // need to work around the issue - collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); - for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) - { - const lldb::tid_t tid = (*rhs_pos)->GetID(); - bool thread_is_alive = false; - const uint32_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - ThreadSP backing_thread = m_threads[idx]->GetBackingThread(); - if (m_threads[idx]->GetID() == tid || (backing_thread && backing_thread->GetID() == tid)) - { - thread_is_alive = true; - break; - } - } - if (!thread_is_alive) - (*rhs_pos)->DestroyThread(); - } - } +void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) { + ThreadSP selected_thread_sp(FindThreadByID(tid)); + if (selected_thread_sp->EventTypeHasListeners( + Thread::eBroadcastBitThreadSelected)) + selected_thread_sp->BroadcastEvent( + Thread::eBroadcastBitThreadSelected, + new Thread::ThreadEventData(selected_thread_sp)); } -void -ThreadList::Flush () -{ +void ThreadList::Update(ThreadList &rhs) { + if (this != &rhs) { + // Lock both mutexes to make sure neither side changes anyone on us + // while the assignment occurs std::lock_guard<std::recursive_mutex> guard(GetMutex()); - collection::iterator pos, end = m_threads.end(); - for (pos = m_threads.begin(); pos != end; ++pos) - (*pos)->Flush (); -} - -std::recursive_mutex & -ThreadList::GetMutex() -{ - return m_process->m_thread_mutex; -} - -ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher (lldb::ThreadSP thread_sp) : - m_thread_list(nullptr), - m_tid(LLDB_INVALID_THREAD_ID) -{ - if (thread_sp) - { - m_tid = thread_sp->GetID(); - m_thread_list = &thread_sp->GetProcess()->GetThreadList(); - m_thread_list->PushExpressionExecutionThread(m_tid); + + m_process = rhs.m_process; + m_stop_id = rhs.m_stop_id; + m_threads.swap(rhs.m_threads); + m_selected_tid = rhs.m_selected_tid; + + // Now we look for threads that we are done with and + // make sure to clear them up as much as possible so + // anyone with a shared pointer will still have a reference, + // but the thread won't be of much use. Using std::weak_ptr + // for all backward references (such as a thread to a process) + // will eventually solve this issue for us, but for now, we + // need to work around the issue + collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); + for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) { + const lldb::tid_t tid = (*rhs_pos)->GetID(); + bool thread_is_alive = false; + const uint32_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) { + ThreadSP backing_thread = m_threads[idx]->GetBackingThread(); + if (m_threads[idx]->GetID() == tid || + (backing_thread && backing_thread->GetID() == tid)) { + thread_is_alive = true; + break; + } + } + if (!thread_is_alive) + (*rhs_pos)->DestroyThread(); } + } } +void ThreadList::Flush() { + std::lock_guard<std::recursive_mutex> guard(GetMutex()); + collection::iterator pos, end = m_threads.end(); + for (pos = m_threads.begin(); pos != end; ++pos) + (*pos)->Flush(); +} + +std::recursive_mutex &ThreadList::GetMutex() const { + return m_process->m_thread_mutex; +} +ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher( + lldb::ThreadSP thread_sp) + : m_thread_list(nullptr), m_tid(LLDB_INVALID_THREAD_ID) { + if (thread_sp) { + m_tid = thread_sp->GetID(); + m_thread_list = &thread_sp->GetProcess()->GetThreadList(); + m_thread_list->PushExpressionExecutionThread(m_tid); + } +} |