mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-30 21:44:19 +08:00
9213a6d79a
Make find_thread_ptid (the overload that takes a process_stratum_target) a method of process_stratum_target. Change-Id: Ib190a925a83c6b93e9c585dc7c6ab65efbdd8629 Reviewed-By: Tom Tromey <tom@tromey.com>
189 lines
4.3 KiB
C
189 lines
4.3 KiB
C
/* Thread iterators and ranges for GDB, the GNU debugger.
|
|
|
|
Copyright (C) 2018-2023 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include "defs.h"
|
|
#include "gdbthread.h"
|
|
#include "inferior.h"
|
|
|
|
/* See thread-iter.h. */
|
|
|
|
all_threads_iterator::all_threads_iterator (begin_t)
|
|
{
|
|
/* Advance M_INF/M_THR to the first thread's position. */
|
|
|
|
for (inferior &inf : inferior_list)
|
|
{
|
|
auto thr_iter = inf.thread_list.begin ();
|
|
if (thr_iter != inf.thread_list.end ())
|
|
{
|
|
m_inf = &inf;
|
|
m_thr = &*thr_iter;
|
|
return;
|
|
}
|
|
}
|
|
m_inf = nullptr;
|
|
m_thr = nullptr;
|
|
}
|
|
|
|
/* See thread-iter.h. */
|
|
|
|
void
|
|
all_threads_iterator::advance ()
|
|
{
|
|
intrusive_list<inferior>::iterator inf_iter (m_inf);
|
|
intrusive_list<thread_info>::iterator thr_iter (m_thr);
|
|
|
|
/* The loop below is written in the natural way as-if we'd always
|
|
start at the beginning of the inferior list. This fast forwards
|
|
the algorithm to the actual current position. */
|
|
goto start;
|
|
|
|
for (; inf_iter != inferior_list.end (); ++inf_iter)
|
|
{
|
|
m_inf = &*inf_iter;
|
|
thr_iter = m_inf->thread_list.begin ();
|
|
while (thr_iter != m_inf->thread_list.end ())
|
|
{
|
|
m_thr = &*thr_iter;
|
|
return;
|
|
start:
|
|
++thr_iter;
|
|
}
|
|
}
|
|
|
|
m_thr = nullptr;
|
|
}
|
|
|
|
/* See thread-iter.h. */
|
|
|
|
bool
|
|
all_matching_threads_iterator::m_inf_matches ()
|
|
{
|
|
return (m_filter_target == nullptr
|
|
|| m_filter_target == m_inf->process_target ());
|
|
}
|
|
|
|
/* See thread-iter.h. */
|
|
|
|
all_matching_threads_iterator::all_matching_threads_iterator
|
|
(process_stratum_target *filter_target, ptid_t filter_ptid)
|
|
: m_filter_target (filter_target)
|
|
{
|
|
if (filter_ptid == minus_one_ptid)
|
|
{
|
|
/* Iterate on all threads of all inferiors, possibly filtering on
|
|
FILTER_TARGET. */
|
|
m_mode = mode::ALL_THREADS;
|
|
|
|
/* Seek the first thread of the first matching inferior. */
|
|
for (inferior &inf : inferior_list)
|
|
{
|
|
m_inf = &inf;
|
|
|
|
if (!m_inf_matches ()
|
|
|| inf.thread_list.empty ())
|
|
continue;
|
|
|
|
m_thr = &inf.thread_list.front ();
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gdb_assert (filter_target != nullptr);
|
|
|
|
if (filter_ptid.is_pid ())
|
|
{
|
|
/* Iterate on all threads of the given inferior. */
|
|
m_mode = mode::ALL_THREADS_OF_INFERIOR;
|
|
|
|
m_inf = find_inferior_pid (filter_target, filter_ptid.pid ());
|
|
if (m_inf != nullptr)
|
|
m_thr = &m_inf->thread_list.front ();
|
|
}
|
|
else
|
|
{
|
|
/* Iterate on a single thread. */
|
|
m_mode = mode::SINGLE_THREAD;
|
|
|
|
m_thr = filter_target->find_thread (filter_ptid);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* See thread-iter.h. */
|
|
|
|
void
|
|
all_matching_threads_iterator::advance ()
|
|
{
|
|
switch (m_mode)
|
|
{
|
|
case mode::ALL_THREADS:
|
|
{
|
|
intrusive_list<inferior>::iterator inf_iter (m_inf);
|
|
intrusive_list<thread_info>::iterator thr_iter
|
|
= m_inf->thread_list.iterator_to (*m_thr);
|
|
|
|
/* The loop below is written in the natural way as-if we'd always
|
|
start at the beginning of the inferior list. This fast forwards
|
|
the algorithm to the actual current position. */
|
|
goto start;
|
|
|
|
for (; inf_iter != inferior_list.end (); ++inf_iter)
|
|
{
|
|
m_inf = &*inf_iter;
|
|
|
|
if (!m_inf_matches ())
|
|
continue;
|
|
|
|
thr_iter = m_inf->thread_list.begin ();
|
|
while (thr_iter != m_inf->thread_list.end ())
|
|
{
|
|
m_thr = &*thr_iter;
|
|
return;
|
|
|
|
start:
|
|
++thr_iter;
|
|
}
|
|
}
|
|
}
|
|
m_thr = nullptr;
|
|
break;
|
|
|
|
case mode::ALL_THREADS_OF_INFERIOR:
|
|
{
|
|
intrusive_list<thread_info>::iterator thr_iter
|
|
= m_inf->thread_list.iterator_to (*m_thr);
|
|
++thr_iter;
|
|
if (thr_iter != m_inf->thread_list.end ())
|
|
m_thr = &*thr_iter;
|
|
else
|
|
m_thr = nullptr;
|
|
break;
|
|
}
|
|
|
|
case mode::SINGLE_THREAD:
|
|
m_thr = nullptr;
|
|
break;
|
|
|
|
default:
|
|
gdb_assert_not_reached ("invalid mode value");
|
|
}
|
|
}
|