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