xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/thread-iter.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17f2ac410Schristos /* Thread iterators and ranges for GDB, the GNU debugger.
27f2ac410Schristos 
3*6881a400Schristos    Copyright (C) 2018-2023 Free Software Foundation, Inc.
47f2ac410Schristos 
57f2ac410Schristos    This file is part of GDB.
67f2ac410Schristos 
77f2ac410Schristos    This program is free software; you can redistribute it and/or modify
87f2ac410Schristos    it under the terms of the GNU General Public License as published by
97f2ac410Schristos    the Free Software Foundation; either version 3 of the License, or
107f2ac410Schristos    (at your option) any later version.
117f2ac410Schristos 
127f2ac410Schristos    This program is distributed in the hope that it will be useful,
137f2ac410Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
147f2ac410Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157f2ac410Schristos    GNU General Public License for more details.
167f2ac410Schristos 
177f2ac410Schristos    You should have received a copy of the GNU General Public License
187f2ac410Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
197f2ac410Schristos 
207f2ac410Schristos #include "defs.h"
217f2ac410Schristos #include "gdbthread.h"
227f2ac410Schristos #include "inferior.h"
237f2ac410Schristos 
247f2ac410Schristos /* See thread-iter.h.  */
257f2ac410Schristos 
267f2ac410Schristos all_threads_iterator::all_threads_iterator (begin_t)
277f2ac410Schristos {
287f2ac410Schristos   /* Advance M_INF/M_THR to the first thread's position.  */
29*6881a400Schristos 
30*6881a400Schristos   for (inferior &inf : inferior_list)
31*6881a400Schristos     {
32*6881a400Schristos       auto thr_iter = inf.thread_list.begin ();
33*6881a400Schristos       if (thr_iter != inf.thread_list.end ())
34*6881a400Schristos 	{
35*6881a400Schristos 	  m_inf = &inf;
36*6881a400Schristos 	  m_thr = &*thr_iter;
377f2ac410Schristos 	  return;
387f2ac410Schristos 	}
39*6881a400Schristos     }
40*6881a400Schristos   m_inf = nullptr;
41*6881a400Schristos   m_thr = nullptr;
42*6881a400Schristos }
437f2ac410Schristos 
447f2ac410Schristos /* See thread-iter.h.  */
457f2ac410Schristos 
467f2ac410Schristos void
477f2ac410Schristos all_threads_iterator::advance ()
487f2ac410Schristos {
49*6881a400Schristos   intrusive_list<inferior>::iterator inf_iter (m_inf);
50*6881a400Schristos   intrusive_list<thread_info>::iterator thr_iter (m_thr);
51*6881a400Schristos 
527f2ac410Schristos   /* The loop below is written in the natural way as-if we'd always
537f2ac410Schristos      start at the beginning of the inferior list.  This fast forwards
547f2ac410Schristos      the algorithm to the actual current position.  */
557f2ac410Schristos   goto start;
567f2ac410Schristos 
57*6881a400Schristos   for (; inf_iter != inferior_list.end (); ++inf_iter)
587f2ac410Schristos     {
59*6881a400Schristos       m_inf = &*inf_iter;
60*6881a400Schristos       thr_iter = m_inf->thread_list.begin ();
61*6881a400Schristos       while (thr_iter != m_inf->thread_list.end ())
627f2ac410Schristos 	{
63*6881a400Schristos 	  m_thr = &*thr_iter;
647f2ac410Schristos 	  return;
657f2ac410Schristos 	start:
66*6881a400Schristos 	  ++thr_iter;
677f2ac410Schristos 	}
687f2ac410Schristos     }
69*6881a400Schristos 
70*6881a400Schristos   m_thr = nullptr;
717f2ac410Schristos }
727f2ac410Schristos 
737f2ac410Schristos /* See thread-iter.h.  */
747f2ac410Schristos 
757f2ac410Schristos bool
767f2ac410Schristos all_matching_threads_iterator::m_inf_matches ()
777f2ac410Schristos {
78*6881a400Schristos   return (m_filter_target == nullptr
79*6881a400Schristos 	  || m_filter_target == m_inf->process_target ());
807f2ac410Schristos }
817f2ac410Schristos 
827f2ac410Schristos /* See thread-iter.h.  */
837f2ac410Schristos 
847f2ac410Schristos all_matching_threads_iterator::all_matching_threads_iterator
857d62b00eSchristos   (process_stratum_target *filter_target, ptid_t filter_ptid)
86*6881a400Schristos   : m_filter_target (filter_target)
877f2ac410Schristos {
88*6881a400Schristos   if (filter_ptid == minus_one_ptid)
89*6881a400Schristos     {
90*6881a400Schristos       /* Iterate on all threads of all inferiors, possibly filtering on
91*6881a400Schristos          FILTER_TARGET.  */
92*6881a400Schristos       m_mode = mode::ALL_THREADS;
937d62b00eSchristos 
94*6881a400Schristos       /* Seek the first thread of the first matching inferior.  */
95*6881a400Schristos       for (inferior &inf : inferior_list)
96*6881a400Schristos 	{
97*6881a400Schristos 	  m_inf = &inf;
98*6881a400Schristos 
99*6881a400Schristos 	  if (!m_inf_matches ()
100*6881a400Schristos 	      || inf.thread_list.empty ())
101*6881a400Schristos 	    continue;
102*6881a400Schristos 
103*6881a400Schristos 	  m_thr = &inf.thread_list.front ();
1047f2ac410Schristos 	  return;
1057f2ac410Schristos 	}
106*6881a400Schristos     }
107*6881a400Schristos   else
108*6881a400Schristos     {
109*6881a400Schristos       gdb_assert (filter_target != nullptr);
110*6881a400Schristos 
111*6881a400Schristos       if (filter_ptid.is_pid ())
112*6881a400Schristos 	{
113*6881a400Schristos 	  /* Iterate on all threads of the given inferior.  */
114*6881a400Schristos 	  m_mode = mode::ALL_THREADS_OF_INFERIOR;
115*6881a400Schristos 
116*6881a400Schristos 	  m_inf = find_inferior_pid (filter_target, filter_ptid.pid ());
117*6881a400Schristos 	  if (m_inf != nullptr)
118*6881a400Schristos 	    m_thr = &m_inf->thread_list.front ();
119*6881a400Schristos 	}
120*6881a400Schristos       else
121*6881a400Schristos 	{
122*6881a400Schristos 	  /* Iterate on a single thread.  */
123*6881a400Schristos 	  m_mode = mode::SINGLE_THREAD;
124*6881a400Schristos 
125*6881a400Schristos 	  m_thr = find_thread_ptid (filter_target, filter_ptid);
126*6881a400Schristos 	}
127*6881a400Schristos     }
128*6881a400Schristos }
1297f2ac410Schristos 
1307f2ac410Schristos /* See thread-iter.h.  */
1317f2ac410Schristos 
1327f2ac410Schristos void
1337f2ac410Schristos all_matching_threads_iterator::advance ()
1347f2ac410Schristos {
135*6881a400Schristos   switch (m_mode)
136*6881a400Schristos     {
137*6881a400Schristos     case mode::ALL_THREADS:
138*6881a400Schristos       {
139*6881a400Schristos 	intrusive_list<inferior>::iterator inf_iter (m_inf);
140*6881a400Schristos 	intrusive_list<thread_info>::iterator thr_iter
141*6881a400Schristos 	  = m_inf->thread_list.iterator_to (*m_thr);
142*6881a400Schristos 
1437f2ac410Schristos 	/* The loop below is written in the natural way as-if we'd always
1447f2ac410Schristos 	   start at the beginning of the inferior list.  This fast forwards
1457f2ac410Schristos 	   the algorithm to the actual current position.  */
1467f2ac410Schristos 	goto start;
1477f2ac410Schristos 
148*6881a400Schristos 	for (; inf_iter != inferior_list.end (); ++inf_iter)
1497f2ac410Schristos 	  {
150*6881a400Schristos 	    m_inf = &*inf_iter;
151*6881a400Schristos 
152*6881a400Schristos 	    if (!m_inf_matches ())
153*6881a400Schristos 	      continue;
154*6881a400Schristos 
155*6881a400Schristos 	    thr_iter = m_inf->thread_list.begin ();
156*6881a400Schristos 	    while (thr_iter != m_inf->thread_list.end ())
1577f2ac410Schristos 	      {
158*6881a400Schristos 		m_thr = &*thr_iter;
1597f2ac410Schristos 		return;
160*6881a400Schristos 
1617f2ac410Schristos 	      start:
162*6881a400Schristos 		++thr_iter;
1637f2ac410Schristos 	      }
1647f2ac410Schristos 	  }
1657f2ac410Schristos       }
166*6881a400Schristos       m_thr = nullptr;
167*6881a400Schristos       break;
168*6881a400Schristos 
169*6881a400Schristos     case mode::ALL_THREADS_OF_INFERIOR:
170*6881a400Schristos       {
171*6881a400Schristos 	intrusive_list<thread_info>::iterator thr_iter
172*6881a400Schristos 	  = m_inf->thread_list.iterator_to (*m_thr);
173*6881a400Schristos 	++thr_iter;
174*6881a400Schristos 	if (thr_iter != m_inf->thread_list.end ())
175*6881a400Schristos 	  m_thr = &*thr_iter;
176*6881a400Schristos 	else
177*6881a400Schristos 	  m_thr = nullptr;
178*6881a400Schristos 	break;
179*6881a400Schristos       }
180*6881a400Schristos 
181*6881a400Schristos     case mode::SINGLE_THREAD:
182*6881a400Schristos       m_thr = nullptr;
183*6881a400Schristos       break;
184*6881a400Schristos 
185*6881a400Schristos     default:
186*6881a400Schristos       gdb_assert_not_reached ("invalid mode value");
187*6881a400Schristos     }
188*6881a400Schristos }
189