]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/thread-iter.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / gdb / thread-iter.c
1 /* Thread iterators and ranges for GDB, the GNU debugger.
2
3 Copyright (C) 2018-2024 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "gdbthread.h"
21 #include "inferior.h"
22
23 /* See thread-iter.h. */
24
25 all_threads_iterator::all_threads_iterator (begin_t)
26 {
27 /* Advance M_INF/M_THR to the first thread's position. */
28
29 for (inferior &inf : inferior_list)
30 {
31 auto thr_iter = inf.thread_list.begin ();
32 if (thr_iter != inf.thread_list.end ())
33 {
34 m_inf = &inf;
35 m_thr = &*thr_iter;
36 return;
37 }
38 }
39 m_inf = nullptr;
40 m_thr = nullptr;
41 }
42
43 /* See thread-iter.h. */
44
45 void
46 all_threads_iterator::advance ()
47 {
48 intrusive_list<inferior>::iterator inf_iter (m_inf);
49 intrusive_list<thread_info>::iterator thr_iter (m_thr);
50
51 /* The loop below is written in the natural way as-if we'd always
52 start at the beginning of the inferior list. This fast forwards
53 the algorithm to the actual current position. */
54 goto start;
55
56 for (; inf_iter != inferior_list.end (); ++inf_iter)
57 {
58 m_inf = &*inf_iter;
59 thr_iter = m_inf->thread_list.begin ();
60 while (thr_iter != m_inf->thread_list.end ())
61 {
62 m_thr = &*thr_iter;
63 return;
64 start:
65 ++thr_iter;
66 }
67 }
68
69 m_thr = nullptr;
70 }
71
72 /* See thread-iter.h. */
73
74 bool
75 all_matching_threads_iterator::m_inf_matches ()
76 {
77 return (m_filter_target == nullptr
78 || m_filter_target == m_inf->process_target ());
79 }
80
81 /* See thread-iter.h. */
82
83 all_matching_threads_iterator::all_matching_threads_iterator
84 (process_stratum_target *filter_target, ptid_t filter_ptid)
85 : m_filter_target (filter_target)
86 {
87 if (filter_ptid == minus_one_ptid)
88 {
89 /* Iterate on all threads of all inferiors, possibly filtering on
90 FILTER_TARGET. */
91 m_mode = mode::ALL_THREADS;
92
93 /* Seek the first thread of the first matching inferior. */
94 for (inferior &inf : inferior_list)
95 {
96 m_inf = &inf;
97
98 if (!m_inf_matches ()
99 || inf.thread_list.empty ())
100 continue;
101
102 m_thr = &inf.thread_list.front ();
103 return;
104 }
105 }
106 else
107 {
108 gdb_assert (filter_target != nullptr);
109
110 if (filter_ptid.is_pid ())
111 {
112 /* Iterate on all threads of the given inferior. */
113 m_mode = mode::ALL_THREADS_OF_INFERIOR;
114
115 m_inf = find_inferior_pid (filter_target, filter_ptid.pid ());
116 if (m_inf != nullptr)
117 m_thr = &m_inf->thread_list.front ();
118 }
119 else
120 {
121 /* Iterate on a single thread. */
122 m_mode = mode::SINGLE_THREAD;
123
124 m_thr = filter_target->find_thread (filter_ptid);
125 }
126 }
127 }
128
129 /* See thread-iter.h. */
130
131 void
132 all_matching_threads_iterator::advance ()
133 {
134 switch (m_mode)
135 {
136 case mode::ALL_THREADS:
137 {
138 intrusive_list<inferior>::iterator inf_iter (m_inf);
139 intrusive_list<thread_info>::iterator thr_iter
140 = m_inf->thread_list.iterator_to (*m_thr);
141
142 /* The loop below is written in the natural way as-if we'd always
143 start at the beginning of the inferior list. This fast forwards
144 the algorithm to the actual current position. */
145 goto start;
146
147 for (; inf_iter != inferior_list.end (); ++inf_iter)
148 {
149 m_inf = &*inf_iter;
150
151 if (!m_inf_matches ())
152 continue;
153
154 thr_iter = m_inf->thread_list.begin ();
155 while (thr_iter != m_inf->thread_list.end ())
156 {
157 m_thr = &*thr_iter;
158 return;
159
160 start:
161 ++thr_iter;
162 }
163 }
164 }
165 m_thr = nullptr;
166 break;
167
168 case mode::ALL_THREADS_OF_INFERIOR:
169 {
170 intrusive_list<thread_info>::iterator thr_iter
171 = m_inf->thread_list.iterator_to (*m_thr);
172 ++thr_iter;
173 if (thr_iter != m_inf->thread_list.end ())
174 m_thr = &*thr_iter;
175 else
176 m_thr = nullptr;
177 break;
178 }
179
180 case mode::SINGLE_THREAD:
181 m_thr = nullptr;
182 break;
183
184 default:
185 gdb_assert_not_reached ("invalid mode value");
186 }
187 }