]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/inferiors.c
Add overloads of for_each_thread/find_thread that filter on pid
[thirdparty/binutils-gdb.git] / gdb / gdbserver / inferiors.c
CommitLineData
ce3a066d 1/* Inferior process information for the remote server for GDB.
61baf725 2 Copyright (C) 2002-2017 Free Software Foundation, Inc.
ce3a066d
DJ
3
4 Contributed by MontaVista Software.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
ce3a066d
DJ
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
ce3a066d 20
ce3a066d 21#include "server.h"
623b6bdf 22#include "gdbthread.h"
799cdc37 23#include "dll.h"
ce3a066d 24
9179355e 25std::list<process_info *> all_processes;
9c80ecd6 26std::list<thread_info *> all_threads;
0d62e5e8 27
0bfdf32f 28struct thread_info *current_thread;
0d62e5e8 29
d092c5a2
SDJ
30/* The current working directory used to start the inferior. */
31static const char *current_inferior_cwd = NULL;
32
9c80ecd6
SM
33thread_info *
34find_inferior (std::list<thread_info *> *thread_list,
35 int (*func) (thread_info *, void *),
36 void *arg)
0d62e5e8 37{
9c80ecd6 38 gdb_assert (thread_list == &all_threads);
0d62e5e8 39
9c80ecd6
SM
40 return find_thread ([&] (thread_info *thread) {
41 return func (thread, arg);
42 });
43}
9f767825 44
9c80ecd6
SM
45thread_info *
46find_inferior_id (std::list<thread_info *> *thread_list, ptid_t id)
0d62e5e8 47{
9c80ecd6 48 gdb_assert (thread_list == &all_threads);
ce3a066d 49
9c80ecd6
SM
50 return find_thread ([&] (thread_info *thread) {
51 return thread->id == id;
52 });
53}
649ebbca 54
9c80ecd6
SM
55thread_info *
56find_inferior_in_random (std::list<thread_info *> *thread_list,
57 int (*func) (thread_info *, void *),
58 void *arg)
649ebbca 59{
9c80ecd6
SM
60 gdb_assert (thread_list == &all_threads);
61
62 return find_thread_in_random ([&] (thread_info *thread) {
63 return func (thread, arg);
64 });
649ebbca
DE
65}
66
0d62e5e8 67void
9c80ecd6
SM
68for_each_inferior (std::list<thread_info *> *thread_list,
69 void (*action) (thread_info *))
0d62e5e8 70{
9c80ecd6 71 gdb_assert (thread_list == &all_threads);
0d62e5e8 72
9c80ecd6
SM
73 for_each_thread ([&] (thread_info *thread) {
74 action (thread);
75 });
76}
ce3a066d 77
9c80ecd6
SM
78void
79for_each_inferior_with_data (std::list<thread_info *> *thread_list,
80 void (*action) (thread_info *, void *),
81 void *data)
82{
83 gdb_assert (thread_list == &all_threads);
0d62e5e8 84
9c80ecd6
SM
85 for_each_thread ([&] (thread_info *thread) {
86 action (thread, data);
87 });
0d62e5e8
DJ
88}
89
f7667f0d 90struct thread_info *
95954743 91add_thread (ptid_t thread_id, void *target_data)
0d62e5e8 92{
8d749320 93 struct thread_info *new_thread = XCNEW (struct thread_info);
0d62e5e8 94
9c80ecd6 95 new_thread->id = thread_id;
8336d594 96 new_thread->last_resume_kind = resume_continue;
fc7238bb 97 new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
0d62e5e8 98
9c80ecd6 99 all_threads.push_back (new_thread);
255e7678 100
0bfdf32f
GB
101 if (current_thread == NULL)
102 current_thread = new_thread;
ce3a066d 103
0d62e5e8 104 new_thread->target_data = target_data;
f7667f0d
DE
105
106 return new_thread;
a06660f7
DJ
107}
108
9c80ecd6 109/* See gdbthread.h. */
649ebbca 110
dae5f5cf 111struct thread_info *
649ebbca 112get_first_thread (void)
a06660f7 113{
9c80ecd6
SM
114 if (!all_threads.empty ())
115 return all_threads.front ();
116 else
117 return NULL;
649ebbca 118}
a06660f7 119
649ebbca
DE
120struct thread_info *
121find_thread_ptid (ptid_t ptid)
122{
123 return (struct thread_info *) find_inferior_id (&all_threads, ptid);
dae5f5cf
DJ
124}
125
96e7a1eb
AR
126/* Find a thread associated with the given PROCESS, or NULL if no
127 such thread exists. */
128
129static struct thread_info *
130find_thread_process (const struct process_info *const process)
131{
9179355e 132 return find_any_thread_of_pid (process->pid);
96e7a1eb
AR
133}
134
34c65914
PA
135/* See gdbthread.h. */
136
137struct thread_info *
138find_any_thread_of_pid (int pid)
139{
4d3bb80e
SM
140 return find_thread (pid, [] (thread_info *thread) {
141 return true;
142 });
34c65914
PA
143}
144
0d62e5e8 145static void
9c80ecd6 146free_one_thread (thread_info *thread)
0d62e5e8 147{
6afd337d 148 free_register_cache (thread_regcache_data (thread));
0d62e5e8
DJ
149 free (thread);
150}
151
152void
153remove_thread (struct thread_info *thread)
154{
9accd112
MM
155 if (thread->btrace != NULL)
156 target_disable_btrace (thread->btrace);
157
465a859e 158 discard_queued_stop_replies (ptid_of (thread));
9c80ecd6
SM
159 all_threads.remove (thread);
160 free_one_thread (thread);
96e7a1eb
AR
161 if (current_thread == thread)
162 current_thread = NULL;
ce3a066d
DJ
163}
164
611cb4a5 165void *
6afd337d 166thread_target_data (struct thread_info *thread)
611cb4a5 167{
6afd337d 168 return thread->target_data;
611cb4a5
DJ
169}
170
a44892be 171struct regcache *
6afd337d 172thread_regcache_data (struct thread_info *thread)
c04a1aa8 173{
6afd337d 174 return thread->regcache_data;
c04a1aa8
DJ
175}
176
177void
6afd337d 178set_thread_regcache_data (struct thread_info *thread, struct regcache *data)
c04a1aa8 179{
6afd337d 180 thread->regcache_data = data;
c04a1aa8 181}
255e7678 182
255e7678
DJ
183void
184clear_inferiors (void)
185{
186 for_each_inferior (&all_threads, free_one_thread);
9c80ecd6 187 all_threads.clear ();
bf4c19f7
YQ
188
189 clear_dlls ();
7284e1be 190
0bfdf32f 191 current_thread = NULL;
255e7678 192}
24a09b5f 193
95954743
PA
194struct process_info *
195add_process (int pid, int attached)
196{
8d749320 197 struct process_info *process = XCNEW (struct process_info);
95954743 198
9179355e 199 process->pid = pid;
95954743
PA
200 process->attached = attached;
201
9179355e 202 all_processes.push_back (process);
95954743
PA
203
204 return process;
205}
206
5091eb23
DE
207/* Remove a process from the common process list and free the memory
208 allocated for it.
209 The caller is responsible for freeing private data first. */
210
95954743
PA
211void
212remove_process (struct process_info *process)
213{
214 clear_symbol_cache (&process->symbol_cache);
215 free_all_breakpoints (process);
96e7a1eb 216 gdb_assert (find_thread_process (process) == NULL);
9179355e 217 all_processes.remove (process);
82075af2 218 VEC_free (int, process->syscalls_to_catch);
5091eb23 219 free (process);
95954743
PA
220}
221
9179355e 222process_info *
95954743
PA
223find_process_pid (int pid)
224{
9179355e
SM
225 return find_process ([&] (process_info *process) {
226 return process->pid == pid;
227 });
95954743
PA
228}
229
9179355e 230/* Get the first process in the process list, or NULL if the list is empty. */
3d40fbb5 231
9179355e 232process_info *
3d40fbb5
PA
233get_first_process (void)
234{
9179355e
SM
235 if (!all_processes.empty ())
236 return all_processes.front ();
237 else
238 return NULL;
9f767825
DE
239}
240
241/* Return non-zero if there are any inferiors that we have created
242 (as opposed to attached-to). */
243
244int
245have_started_inferiors_p (void)
246{
9179355e
SM
247 return find_process ([] (process_info *process) {
248 return !process->attached;
249 }) != NULL;
9f767825
DE
250}
251
252/* Return non-zero if there are any inferiors that we have attached to. */
253
254int
255have_attached_inferiors_p (void)
256{
9179355e
SM
257 return find_process ([] (process_info *process) {
258 return process->attached;
259 }) != NULL;
9f767825
DE
260}
261
7fe519cb 262struct process_info *
63c40ec7 263get_thread_process (const struct thread_info *thread)
95954743 264{
9c80ecd6 265 return find_process_pid (thread->id.pid ());
95954743
PA
266}
267
268struct process_info *
269current_process (void)
270{
0bfdf32f
GB
271 gdb_assert (current_thread != NULL);
272 return get_thread_process (current_thread);
95954743 273}
984a2c04
YQ
274
275static void
276do_restore_current_thread_cleanup (void *arg)
277{
278 current_thread = (struct thread_info *) arg;
279}
280
281struct cleanup *
282make_cleanup_restore_current_thread (void)
283{
284 return make_cleanup (do_restore_current_thread_cleanup, current_thread);
285}
043a4934
SDJ
286
287/* See common/common-gdbthread.h. */
288
289void
290switch_to_thread (ptid_t ptid)
291{
75352e28
SDJ
292 gdb_assert (ptid != minus_one_ptid);
293 current_thread = find_thread_ptid (ptid);
043a4934 294}
d092c5a2
SDJ
295
296/* See common/common-inferior.h. */
297
298const char *
299get_inferior_cwd ()
300{
301 return current_inferior_cwd;
302}
bc3b087d
SDJ
303
304/* See common/common-inferior.h. */
305
306void
307set_inferior_cwd (const char *cwd)
308{
309 xfree ((void *) current_inferior_cwd);
310 if (cwd != NULL)
311 current_inferior_cwd = xstrdup (cwd);
312 else
313 current_inferior_cwd = NULL;
314}