Add "set remote multiprocess-extensions-packet" command
[deliverable/binutils-gdb.git] / gdb / gdbserver / inferiors.c
CommitLineData
ce3a066d 1/* Inferior process information for the remote server for GDB.
32d0add0 2 Copyright (C) 2002-2015 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{
bca929d3 108 struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
0d62e5e8
DJ
109
110 memset (new_thread, 0, sizeof (*new_thread));
111
112 new_thread->entry.id = thread_id;
8336d594 113 new_thread->last_resume_kind = resume_continue;
fc7238bb 114 new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
0d62e5e8 115
ecc6f45c 116 add_inferior_to_list (&all_threads, &new_thread->entry);
255e7678 117
0bfdf32f
GB
118 if (current_thread == NULL)
119 current_thread = new_thread;
ce3a066d 120
0d62e5e8 121 new_thread->target_data = target_data;
f7667f0d
DE
122
123 return new_thread;
a06660f7
DJ
124}
125
95954743 126ptid_t
a06660f7
DJ
127thread_to_gdb_id (struct thread_info *thread)
128{
95954743 129 return thread->entry.id;
a06660f7
DJ
130}
131
649ebbca
DE
132/* Wrapper around get_first_inferior to return a struct thread_info *. */
133
dae5f5cf 134struct thread_info *
649ebbca 135get_first_thread (void)
a06660f7 136{
649ebbca
DE
137 return (struct thread_info *) get_first_inferior (&all_threads);
138}
a06660f7 139
649ebbca
DE
140struct thread_info *
141find_thread_ptid (ptid_t ptid)
142{
143 return (struct thread_info *) find_inferior_id (&all_threads, ptid);
dae5f5cf
DJ
144}
145
95954743
PA
146ptid_t
147gdb_id_to_thread_id (ptid_t gdb_id)
dae5f5cf 148{
e09875d4 149 struct thread_info *thread = find_thread_ptid (gdb_id);
dae5f5cf 150
95954743 151 return thread ? thread->entry.id : null_ptid;
0d62e5e8 152}
c04a1aa8 153
0d62e5e8
DJ
154static void
155free_one_thread (struct inferior_list_entry *inf)
156{
157 struct thread_info *thread = get_thread (inf);
158 free_register_cache (inferior_regcache_data (thread));
159 free (thread);
160}
161
162void
163remove_thread (struct thread_info *thread)
164{
9accd112
MM
165 if (thread->btrace != NULL)
166 target_disable_btrace (thread->btrace);
167
465a859e 168 discard_queued_stop_replies (ptid_of (thread));
0d62e5e8
DJ
169 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
170 free_one_thread (&thread->entry);
ce3a066d
DJ
171}
172
649ebbca
DE
173/* Return a pointer to the first inferior in LIST, or NULL if there isn't one.
174 This is for cases where the caller needs a thread, but doesn't care
175 which one. */
176
177struct inferior_list_entry *
178get_first_inferior (struct inferior_list *list)
179{
3b8361aa
DE
180 if (list->head != NULL)
181 return list->head;
649ebbca
DE
182 return NULL;
183}
184
0718675c
JB
185/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
186 returns non-zero. If no entry is found then return NULL. */
187
0d62e5e8
DJ
188struct inferior_list_entry *
189find_inferior (struct inferior_list *list,
190 int (*func) (struct inferior_list_entry *, void *), void *arg)
191{
192 struct inferior_list_entry *inf = list->head;
ce3a066d 193
0d62e5e8 194 while (inf != NULL)
ce3a066d 195 {
a07b2135
PA
196 struct inferior_list_entry *next;
197
198 next = inf->next;
0d62e5e8
DJ
199 if ((*func) (inf, arg))
200 return inf;
a07b2135 201 inf = next;
0d62e5e8 202 }
611cb4a5 203
0d62e5e8
DJ
204 return NULL;
205}
611cb4a5 206
0d62e5e8 207struct inferior_list_entry *
95954743 208find_inferior_id (struct inferior_list *list, ptid_t id)
0d62e5e8
DJ
209{
210 struct inferior_list_entry *inf = list->head;
211
212 while (inf != NULL)
213 {
95954743 214 if (ptid_equal (inf->id, id))
0d62e5e8
DJ
215 return inf;
216 inf = inf->next;
ce3a066d
DJ
217 }
218
0d62e5e8 219 return NULL;
ce3a066d 220}
611cb4a5
DJ
221
222void *
0d62e5e8 223inferior_target_data (struct thread_info *inferior)
611cb4a5
DJ
224{
225 return inferior->target_data;
226}
227
228void
0d62e5e8 229set_inferior_target_data (struct thread_info *inferior, void *data)
611cb4a5
DJ
230{
231 inferior->target_data = data;
232}
c04a1aa8 233
a44892be 234struct regcache *
0d62e5e8 235inferior_regcache_data (struct thread_info *inferior)
c04a1aa8
DJ
236{
237 return inferior->regcache_data;
238}
239
240void
a44892be 241set_inferior_regcache_data (struct thread_info *inferior, struct regcache *data)
c04a1aa8
DJ
242{
243 inferior->regcache_data = data;
244}
255e7678 245
649ebbca
DE
246/* Return true if LIST has exactly one entry. */
247
248int
249one_inferior_p (struct inferior_list *list)
250{
251 return list->head != NULL && list->head == list->tail;
252}
253
254/* Reset head,tail of LIST, assuming all entries have already been freed. */
255
256void
257clear_inferior_list (struct inferior_list *list)
258{
259 list->head = NULL;
260 list->tail = NULL;
261}
255e7678
DJ
262
263void
264clear_inferiors (void)
265{
266 for_each_inferior (&all_threads, free_one_thread);
649ebbca 267 clear_inferior_list (&all_threads);
bf4c19f7
YQ
268
269 clear_dlls ();
7284e1be 270
0bfdf32f 271 current_thread = NULL;
255e7678 272}
24a09b5f 273
95954743
PA
274struct process_info *
275add_process (int pid, int attached)
276{
277 struct process_info *process;
278
279 process = xcalloc (1, sizeof (*process));
280
80894984 281 process->entry.id = pid_to_ptid (pid);
95954743
PA
282 process->attached = attached;
283
80894984 284 add_inferior_to_list (&all_processes, &process->entry);
95954743
PA
285
286 return process;
287}
288
5091eb23
DE
289/* Remove a process from the common process list and free the memory
290 allocated for it.
291 The caller is responsible for freeing private data first. */
292
95954743
PA
293void
294remove_process (struct process_info *process)
295{
296 clear_symbol_cache (&process->symbol_cache);
297 free_all_breakpoints (process);
80894984 298 remove_inferior (&all_processes, &process->entry);
5091eb23 299 free (process);
95954743
PA
300}
301
302struct process_info *
303find_process_pid (int pid)
304{
305 return (struct process_info *)
306 find_inferior_id (&all_processes, pid_to_ptid (pid));
307}
308
9f767825
DE
309/* Return non-zero if INF, a struct process_info, was started by us,
310 i.e. not attached to. */
311
312static int
313started_inferior_callback (struct inferior_list_entry *entry, void *args)
314{
315 struct process_info *process = (struct process_info *) entry;
316
317 return ! process->attached;
318}
319
320/* Return non-zero if there are any inferiors that we have created
321 (as opposed to attached-to). */
322
323int
324have_started_inferiors_p (void)
325{
326 return (find_inferior (&all_processes, started_inferior_callback, NULL)
327 != NULL);
328}
329
330/* Return non-zero if INF, a struct process_info, was attached to. */
331
332static int
333attached_inferior_callback (struct inferior_list_entry *entry, void *args)
334{
335 struct process_info *process = (struct process_info *) entry;
336
337 return process->attached;
338}
339
340/* Return non-zero if there are any inferiors that we have attached to. */
341
342int
343have_attached_inferiors_p (void)
344{
345 return (find_inferior (&all_processes, attached_inferior_callback, NULL)
346 != NULL);
347}
348
7fe519cb 349struct process_info *
95954743
PA
350get_thread_process (struct thread_info *thread)
351{
352 int pid = ptid_get_pid (thread->entry.id);
353 return find_process_pid (pid);
354}
355
356struct process_info *
357current_process (void)
358{
0bfdf32f
GB
359 gdb_assert (current_thread != NULL);
360 return get_thread_process (current_thread);
95954743 361}
This page took 1.492682 seconds and 4 git commands to generate.