| /* Thread iterators and ranges for GDB, the GNU debugger. | 
 |  | 
 |    Copyright (C) 2018-2024 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"); | 
 |     } | 
 | } |