gdbserver: Rename some functions, thread -> inferior
[deliverable/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
95954743 25struct inferior_list all_processes;
0d62e5e8
DJ
26struct inferior_list all_threads;
27
0bfdf32f 28struct thread_info *current_thread;
0d62e5e8
DJ
29
30#define get_thread(inf) ((struct thread_info *)(inf))
31
32void
33add_inferior_to_list (struct inferior_list *list,
34 struct inferior_list_entry *new_inferior)
35{
36 new_inferior->next = NULL;
37 if (list->tail != NULL)
38 list->tail->next = new_inferior;
39 else
40 list->head = new_inferior;
41 list->tail = new_inferior;
42}
43
9f767825
DE
44/* Invoke ACTION for each inferior in LIST. */
45
0d62e5e8
DJ
46void
47for_each_inferior (struct inferior_list *list,
48 void (*action) (struct inferior_list_entry *))
49{
50 struct inferior_list_entry *cur = list->head, *next;
51
52 while (cur != NULL)
53 {
54 next = cur->next;
55 (*action) (cur);
56 cur = next;
57 }
58}
ce3a066d 59
649ebbca
DE
60/* Invoke ACTION for each inferior in LIST, passing DATA to ACTION. */
61
62void
63for_each_inferior_with_data (struct inferior_list *list,
64 void (*action) (struct inferior_list_entry *,
65 void *),
66 void *data)
67{
68 struct inferior_list_entry *cur = list->head, *next;
69
70 while (cur != NULL)
71 {
72 next = cur->next;
73 (*action) (cur, data);
74 cur = next;
75 }
76}
77
0d62e5e8
DJ
78void
79remove_inferior (struct inferior_list *list,
80 struct inferior_list_entry *entry)
81{
82 struct inferior_list_entry **cur;
ce3a066d 83
0d62e5e8
DJ
84 if (list->head == entry)
85 {
86 list->head = entry->next;
87 if (list->tail == entry)
88 list->tail = list->head;
89 return;
90 }
91
92 cur = &list->head;
93 while (*cur && (*cur)->next != entry)
94 cur = &(*cur)->next;
95
96 if (*cur == NULL)
97 return;
ce3a066d 98
0d62e5e8
DJ
99 (*cur)->next = entry->next;
100
101 if (list->tail == entry)
102 list->tail = *cur;
103}
104
f7667f0d 105struct thread_info *
95954743 106add_thread (ptid_t thread_id, void *target_data)
0d62e5e8 107{
8d749320 108 struct thread_info *new_thread = XCNEW (struct thread_info);
0d62e5e8
DJ
109
110 new_thread->entry.id = thread_id;
8336d594 111 new_thread->last_resume_kind = resume_continue;
fc7238bb 112 new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
0d62e5e8 113
ecc6f45c 114 add_inferior_to_list (&all_threads, &new_thread->entry);
255e7678 115
0bfdf32f
GB
116 if (current_thread == NULL)
117 current_thread = new_thread;
ce3a066d 118
0d62e5e8 119 new_thread->target_data = target_data;
f7667f0d
DE
120
121 return new_thread;
a06660f7
DJ
122}
123
95954743 124ptid_t
a06660f7
DJ
125thread_to_gdb_id (struct thread_info *thread)
126{
95954743 127 return thread->entry.id;
a06660f7
DJ
128}
129
649ebbca
DE
130/* Wrapper around get_first_inferior to return a struct thread_info *. */
131
dae5f5cf 132struct thread_info *
649ebbca 133get_first_thread (void)
a06660f7 134{
649ebbca
DE
135 return (struct thread_info *) get_first_inferior (&all_threads);
136}
a06660f7 137
649ebbca
DE
138struct thread_info *
139find_thread_ptid (ptid_t ptid)
140{
141 return (struct thread_info *) find_inferior_id (&all_threads, ptid);
dae5f5cf
DJ
142}
143
96e7a1eb
AR
144/* Predicate function for matching thread entry's pid to the given
145 pid value passed by address in ARGS. */
146
147static int
148thread_pid_matches_callback (struct inferior_list_entry *entry, void *args)
149{
150 return (ptid_get_pid (entry->id) == *(pid_t *)args);
151}
152
153/* Find a thread associated with the given PROCESS, or NULL if no
154 such thread exists. */
155
156static struct thread_info *
157find_thread_process (const struct process_info *const process)
158{
159 pid_t pid = ptid_get_pid (ptid_of (process));
160
161 return (struct thread_info *)
162 find_inferior (&all_threads, thread_pid_matches_callback, &pid);
163}
164
34c65914
PA
165/* Helper for find_any_thread_of_pid. Returns true if a thread
166 matches a PID. */
167
168static int
169thread_of_pid (struct inferior_list_entry *entry, void *pid_p)
170{
171 int pid = *(int *) pid_p;
172
173 return (ptid_get_pid (entry->id) == pid);
174}
175
176/* See gdbthread.h. */
177
178struct thread_info *
179find_any_thread_of_pid (int pid)
180{
181 struct inferior_list_entry *entry;
182
183 entry = find_inferior (&all_threads, thread_of_pid, &pid);
184
185 return (struct thread_info *) entry;
186}
187
95954743
PA
188ptid_t
189gdb_id_to_thread_id (ptid_t gdb_id)
dae5f5cf 190{
e09875d4 191 struct thread_info *thread = find_thread_ptid (gdb_id);
dae5f5cf 192
95954743 193 return thread ? thread->entry.id : null_ptid;
0d62e5e8 194}
c04a1aa8 195
0d62e5e8
DJ
196static void
197free_one_thread (struct inferior_list_entry *inf)
198{
199 struct thread_info *thread = get_thread (inf);
6afd337d 200 free_register_cache (thread_regcache_data (thread));
0d62e5e8
DJ
201 free (thread);
202}
203
204void
205remove_thread (struct thread_info *thread)
206{
9accd112
MM
207 if (thread->btrace != NULL)
208 target_disable_btrace (thread->btrace);
209
465a859e 210 discard_queued_stop_replies (ptid_of (thread));
0d62e5e8
DJ
211 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
212 free_one_thread (&thread->entry);
96e7a1eb
AR
213 if (current_thread == thread)
214 current_thread = NULL;
ce3a066d
DJ
215}
216
649ebbca
DE
217/* Return a pointer to the first inferior in LIST, or NULL if there isn't one.
218 This is for cases where the caller needs a thread, but doesn't care
219 which one. */
220
221struct inferior_list_entry *
222get_first_inferior (struct inferior_list *list)
223{
3b8361aa
DE
224 if (list->head != NULL)
225 return list->head;
649ebbca
DE
226 return NULL;
227}
228
0718675c
JB
229/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
230 returns non-zero. If no entry is found then return NULL. */
231
0d62e5e8
DJ
232struct inferior_list_entry *
233find_inferior (struct inferior_list *list,
234 int (*func) (struct inferior_list_entry *, void *), void *arg)
235{
236 struct inferior_list_entry *inf = list->head;
ce3a066d 237
0d62e5e8 238 while (inf != NULL)
ce3a066d 239 {
a07b2135
PA
240 struct inferior_list_entry *next;
241
242 next = inf->next;
0d62e5e8
DJ
243 if ((*func) (inf, arg))
244 return inf;
a07b2135 245 inf = next;
0d62e5e8 246 }
611cb4a5 247
0d62e5e8
DJ
248 return NULL;
249}
611cb4a5 250
89342618
YQ
251/* Find the random inferior_list_entry E in LIST for which FUNC (E, ARG)
252 returns non-zero. If no entry is found then return NULL. */
253
254struct inferior_list_entry *
255find_inferior_in_random (struct inferior_list *list,
256 int (*func) (struct inferior_list_entry *, void *),
257 void *arg)
258{
259 struct inferior_list_entry *inf = list->head;
260 int count = 0;
261 int random_selector;
262
263 /* First count how many interesting entries we have. */
264 while (inf != NULL)
265 {
266 struct inferior_list_entry *next;
267
268 next = inf->next;
269 if ((*func) (inf, arg))
270 count++;
271 inf = next;
272 }
273
274 if (count == 0)
275 return NULL;
276
277 /* Now randomly pick an entry out of those. */
278 random_selector = (int)
279 ((count * (double) rand ()) / (RAND_MAX + 1.0));
280
281 inf = list->head;
282 while (inf != NULL)
283 {
284 struct inferior_list_entry *next;
285
286 next = inf->next;
287 if ((*func) (inf, arg) && (random_selector-- == 0))
288 return inf;
289 inf = next;
290 }
291
292 gdb_assert_not_reached ("failed to find an inferior in random.");
293 return NULL;
294}
295
0d62e5e8 296struct inferior_list_entry *
95954743 297find_inferior_id (struct inferior_list *list, ptid_t id)
0d62e5e8
DJ
298{
299 struct inferior_list_entry *inf = list->head;
300
301 while (inf != NULL)
302 {
95954743 303 if (ptid_equal (inf->id, id))
0d62e5e8
DJ
304 return inf;
305 inf = inf->next;
ce3a066d
DJ
306 }
307
0d62e5e8 308 return NULL;
ce3a066d 309}
611cb4a5
DJ
310
311void *
6afd337d 312thread_target_data (struct thread_info *thread)
611cb4a5 313{
6afd337d 314 return thread->target_data;
611cb4a5
DJ
315}
316
a44892be 317struct regcache *
6afd337d 318thread_regcache_data (struct thread_info *thread)
c04a1aa8 319{
6afd337d 320 return thread->regcache_data;
c04a1aa8
DJ
321}
322
323void
6afd337d 324set_thread_regcache_data (struct thread_info *thread, struct regcache *data)
c04a1aa8 325{
6afd337d 326 thread->regcache_data = data;
c04a1aa8 327}
255e7678 328
649ebbca
DE
329/* Return true if LIST has exactly one entry. */
330
331int
332one_inferior_p (struct inferior_list *list)
333{
334 return list->head != NULL && list->head == list->tail;
335}
336
337/* Reset head,tail of LIST, assuming all entries have already been freed. */
338
339void
340clear_inferior_list (struct inferior_list *list)
341{
342 list->head = NULL;
343 list->tail = NULL;
344}
255e7678
DJ
345
346void
347clear_inferiors (void)
348{
349 for_each_inferior (&all_threads, free_one_thread);
649ebbca 350 clear_inferior_list (&all_threads);
bf4c19f7
YQ
351
352 clear_dlls ();
7284e1be 353
0bfdf32f 354 current_thread = NULL;
255e7678 355}
24a09b5f 356
95954743
PA
357struct process_info *
358add_process (int pid, int attached)
359{
8d749320 360 struct process_info *process = XCNEW (struct process_info);
95954743 361
80894984 362 process->entry.id = pid_to_ptid (pid);
95954743
PA
363 process->attached = attached;
364
80894984 365 add_inferior_to_list (&all_processes, &process->entry);
95954743
PA
366
367 return process;
368}
369
5091eb23
DE
370/* Remove a process from the common process list and free the memory
371 allocated for it.
372 The caller is responsible for freeing private data first. */
373
95954743
PA
374void
375remove_process (struct process_info *process)
376{
377 clear_symbol_cache (&process->symbol_cache);
378 free_all_breakpoints (process);
96e7a1eb 379 gdb_assert (find_thread_process (process) == NULL);
80894984 380 remove_inferior (&all_processes, &process->entry);
82075af2 381 VEC_free (int, process->syscalls_to_catch);
5091eb23 382 free (process);
95954743
PA
383}
384
385struct process_info *
386find_process_pid (int pid)
387{
388 return (struct process_info *)
389 find_inferior_id (&all_processes, pid_to_ptid (pid));
390}
391
3d40fbb5
PA
392/* Wrapper around get_first_inferior to return a struct process_info *. */
393
394struct process_info *
395get_first_process (void)
396{
397 return (struct process_info *) get_first_inferior (&all_processes);
398}
399
9f767825
DE
400/* Return non-zero if INF, a struct process_info, was started by us,
401 i.e. not attached to. */
402
403static int
404started_inferior_callback (struct inferior_list_entry *entry, void *args)
405{
406 struct process_info *process = (struct process_info *) entry;
407
408 return ! process->attached;
409}
410
411/* Return non-zero if there are any inferiors that we have created
412 (as opposed to attached-to). */
413
414int
415have_started_inferiors_p (void)
416{
417 return (find_inferior (&all_processes, started_inferior_callback, NULL)
418 != NULL);
419}
420
421/* Return non-zero if INF, a struct process_info, was attached to. */
422
423static int
424attached_inferior_callback (struct inferior_list_entry *entry, void *args)
425{
426 struct process_info *process = (struct process_info *) entry;
427
428 return process->attached;
429}
430
431/* Return non-zero if there are any inferiors that we have attached to. */
432
433int
434have_attached_inferiors_p (void)
435{
436 return (find_inferior (&all_processes, attached_inferior_callback, NULL)
437 != NULL);
438}
439
7fe519cb 440struct process_info *
63c40ec7 441get_thread_process (const struct thread_info *thread)
95954743
PA
442{
443 int pid = ptid_get_pid (thread->entry.id);
444 return find_process_pid (pid);
445}
446
447struct process_info *
448current_process (void)
449{
0bfdf32f
GB
450 gdb_assert (current_thread != NULL);
451 return get_thread_process (current_thread);
95954743 452}
984a2c04
YQ
453
454static void
455do_restore_current_thread_cleanup (void *arg)
456{
457 current_thread = (struct thread_info *) arg;
458}
459
460struct cleanup *
461make_cleanup_restore_current_thread (void)
462{
463 return make_cleanup (do_restore_current_thread_cleanup, current_thread);
464}
043a4934
SDJ
465
466/* See common/common-gdbthread.h. */
467
468void
469switch_to_thread (ptid_t ptid)
470{
471 if (!ptid_equal (ptid, minus_one_ptid))
472 current_thread = find_thread_ptid (ptid);
473}
This page took 1.104712 seconds and 4 git commands to generate.