summaryrefslogtreecommitdiff
path: root/source/Target/ThreadList.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Target/ThreadList.cpp')
-rw-r--r--source/Target/ThreadList.cpp162
1 files changed, 80 insertions, 82 deletions
diff --git a/source/Target/ThreadList.cpp b/source/Target/ThreadList.cpp
index 4cf8f9061a898..ee57a401f7420 100644
--- a/source/Target/ThreadList.cpp
+++ b/source/Target/ThreadList.cpp
@@ -40,8 +40,8 @@ ThreadList::ThreadList(const ThreadList &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
+ // 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());
@@ -54,9 +54,8 @@ const ThreadList &ThreadList::operator=(const ThreadList &rhs) {
}
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 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();
}
@@ -195,6 +194,20 @@ ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) {
return thread_sp;
}
+ThreadSP ThreadList::GetBackingThread(const ThreadSP &real_thread) {
+ 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]->GetBackingThread() == real_thread) {
+ 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());
@@ -217,13 +230,13 @@ bool ThreadList::ShouldStop(Event *event_ptr) {
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.
+ // 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.
+ // 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;
{
@@ -233,25 +246,21 @@ bool ThreadList::ShouldStop(Event *event_ptr) {
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.
+ // 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:
+ // maybe the user interrupted or something, then fall back on looking at
+ // all threads:
if (threads_copy.size() == 0)
threads_copy = m_threads;
@@ -282,12 +291,11 @@ bool ThreadList::ShouldStop(Event *event_ptr) {
}
// 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.
+ // 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);
@@ -298,27 +306,24 @@ bool ThreadList::ShouldStop(Event *event_ptr) {
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.
+ // 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.
+ // 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.
+ // 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.
+ // "StopInfoHidden" which will look invalid everywhere but at this check.
if (thread_sp->GetProcess()->GetStopID() > 1)
did_anybody_stop_for_a_reason = true;
@@ -365,8 +370,8 @@ Vote ThreadList::ShouldReportStop(Event *event_ptr) {
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
+ // 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);
@@ -413,8 +418,8 @@ Vote ThreadList::ShouldReportRun(Event *event_ptr) {
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.
+ // 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));
@@ -471,8 +476,8 @@ void ThreadList::RefreshStateAfterStop() {
}
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.
+ // 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();
@@ -481,9 +486,9 @@ void ThreadList::DiscardThreadPlans() {
}
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.
+ // 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();
@@ -491,14 +496,11 @@ bool ThreadList::WillResume() {
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.
+ // 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;
@@ -530,11 +532,9 @@ bool ThreadList::WillResume() {
}
// 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...
+ // 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...
+ // others, only call setup on the threads that request StopOthers...
for (pos = m_threads.begin(); pos != end; ++pos) {
if ((*pos)->GetResumeState() != eStateSuspended &&
@@ -636,13 +636,12 @@ 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
+ // 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()))
@@ -703,8 +702,8 @@ void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) {
void ThreadList::Update(ThreadList &rhs) {
if (this != &rhs) {
- // Lock both mutexes to make sure neither side changes anyone on us
- // while the assignment occurs
+ // 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;
@@ -712,13 +711,12 @@ void ThreadList::Update(ThreadList &rhs) {
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
+ // 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();