Simplify .section in dw2-icycle.S
[deliverable/binutils-gdb.git] / gdb / gdbserver / inferiors.c
CommitLineData
ce3a066d 1/* Inferior process information for the remote server for GDB.
ecd75fc8 2 Copyright (C) 2002-2014 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
DJ
20
21#include <stdlib.h>
22
23#include "server.h"
623b6bdf 24#include "gdbthread.h"
799cdc37 25#include "dll.h"
ce3a066d 26
95954743 27struct inferior_list all_processes;
0d62e5e8
DJ
28struct inferior_list all_threads;
29
30struct thread_info *current_inferior;
31
32#define get_thread(inf) ((struct thread_info *)(inf))
33
34void
35add_inferior_to_list (struct inferior_list *list,
36 struct inferior_list_entry *new_inferior)
37{
38 new_inferior->next = NULL;
39 if (list->tail != NULL)
40 list->tail->next = new_inferior;
41 else
42 list->head = new_inferior;
43 list->tail = new_inferior;
44}
45
9f767825
DE
46/* Invoke ACTION for each inferior in LIST. */
47
0d62e5e8
DJ
48void
49for_each_inferior (struct inferior_list *list,
50 void (*action) (struct inferior_list_entry *))
51{
52 struct inferior_list_entry *cur = list->head, *next;
53
54 while (cur != NULL)
55 {
56 next = cur->next;
57 (*action) (cur);
58 cur = next;
59 }
60}
ce3a066d 61
649ebbca
DE
62/* Invoke ACTION for each inferior in LIST, passing DATA to ACTION. */
63
64void
65for_each_inferior_with_data (struct inferior_list *list,
66 void (*action) (struct inferior_list_entry *,
67 void *),
68 void *data)
69{
70 struct inferior_list_entry *cur = list->head, *next;
71
72 while (cur != NULL)
73 {
74 next = cur->next;
75 (*action) (cur, data);
76 cur = next;
77 }
78}
79
0d62e5e8
DJ
80void
81remove_inferior (struct inferior_list *list,
82 struct inferior_list_entry *entry)
83{
84 struct inferior_list_entry **cur;
ce3a066d 85
0d62e5e8
DJ
86 if (list->head == entry)
87 {
88 list->head = entry->next;
89 if (list->tail == entry)
90 list->tail = list->head;
91 return;
92 }
93
94 cur = &list->head;
95 while (*cur && (*cur)->next != entry)
96 cur = &(*cur)->next;
97
98 if (*cur == NULL)
99 return;
ce3a066d 100
0d62e5e8
DJ
101 (*cur)->next = entry->next;
102
103 if (list->tail == entry)
104 list->tail = *cur;
105}
106
f7667f0d 107struct thread_info *
95954743 108add_thread (ptid_t thread_id, void *target_data)
0d62e5e8 109{
bca929d3 110 struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
0d62e5e8
DJ
111
112 memset (new_thread, 0, sizeof (*new_thread));
113
114 new_thread->entry.id = thread_id;
8336d594 115 new_thread->last_resume_kind = resume_continue;
fc7238bb 116 new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
0d62e5e8 117
ecc6f45c 118 add_inferior_to_list (&all_threads, &new_thread->entry);
255e7678 119
ce3a066d 120 if (current_inferior == NULL)
0d62e5e8 121 current_inferior = new_thread;
ce3a066d 122
0d62e5e8 123 new_thread->target_data = target_data;
f7667f0d
DE
124
125 return new_thread;
a06660f7
DJ
126}
127
95954743 128ptid_t
a06660f7
DJ
129thread_to_gdb_id (struct thread_info *thread)
130{
95954743 131 return thread->entry.id;
a06660f7
DJ
132}
133
649ebbca
DE
134/* Wrapper around get_first_inferior to return a struct thread_info *. */
135
dae5f5cf 136struct thread_info *
649ebbca 137get_first_thread (void)
a06660f7 138{
649ebbca
DE
139 return (struct thread_info *) get_first_inferior (&all_threads);
140}
a06660f7 141
649ebbca
DE
142struct thread_info *
143find_thread_ptid (ptid_t ptid)
144{
145 return (struct thread_info *) find_inferior_id (&all_threads, ptid);
dae5f5cf
DJ
146}
147
95954743
PA
148ptid_t
149gdb_id_to_thread_id (ptid_t gdb_id)
dae5f5cf 150{
e09875d4 151 struct thread_info *thread = find_thread_ptid (gdb_id);
dae5f5cf 152
95954743 153 return thread ? thread->entry.id : null_ptid;
0d62e5e8 154}
c04a1aa8 155
0d62e5e8
DJ
156static void
157free_one_thread (struct inferior_list_entry *inf)
158{
159 struct thread_info *thread = get_thread (inf);
160 free_register_cache (inferior_regcache_data (thread));
161 free (thread);
162}
163
164void
165remove_thread (struct thread_info *thread)
166{
9accd112
MM
167 if (thread->btrace != NULL)
168 target_disable_btrace (thread->btrace);
169
0d62e5e8
DJ
170 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
171 free_one_thread (&thread->entry);
ce3a066d
DJ
172}
173
649ebbca
DE
174/* Return a pointer to the first inferior in LIST, or NULL if there isn't one.
175 This is for cases where the caller needs a thread, but doesn't care
176 which one. */
177
178struct inferior_list_entry *
179get_first_inferior (struct inferior_list *list)
180{
181 if (all_threads.head != NULL)
182 return all_threads.head;
183 return NULL;
184}
185
0718675c
JB
186/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
187 returns non-zero. If no entry is found then return NULL. */
188
0d62e5e8
DJ
189struct inferior_list_entry *
190find_inferior (struct inferior_list *list,
191 int (*func) (struct inferior_list_entry *, void *), void *arg)
192{
193 struct inferior_list_entry *inf = list->head;
ce3a066d 194
0d62e5e8 195 while (inf != NULL)
ce3a066d 196 {
a07b2135
PA
197 struct inferior_list_entry *next;
198
199 next = inf->next;
0d62e5e8
DJ
200 if ((*func) (inf, arg))
201 return inf;
a07b2135 202 inf = next;
0d62e5e8 203 }
611cb4a5 204
0d62e5e8
DJ
205 return NULL;
206}
611cb4a5 207
0d62e5e8 208struct inferior_list_entry *
95954743 209find_inferior_id (struct inferior_list *list, ptid_t id)
0d62e5e8
DJ
210{
211 struct inferior_list_entry *inf = list->head;
212
213 while (inf != NULL)
214 {
95954743 215 if (ptid_equal (inf->id, id))
0d62e5e8
DJ
216 return inf;
217 inf = inf->next;
ce3a066d
DJ
218 }
219
0d62e5e8 220 return NULL;
ce3a066d 221}
611cb4a5
DJ
222
223void *
0d62e5e8 224inferior_target_data (struct thread_info *inferior)
611cb4a5
DJ
225{
226 return inferior->target_data;
227}
228
229void
0d62e5e8 230set_inferior_target_data (struct thread_info *inferior, void *data)
611cb4a5
DJ
231{
232 inferior->target_data = data;
233}
c04a1aa8
DJ
234
235void *
0d62e5e8 236inferior_regcache_data (struct thread_info *inferior)
c04a1aa8
DJ
237{
238 return inferior->regcache_data;
239}
240
241void
0d62e5e8 242set_inferior_regcache_data (struct thread_info *inferior, void *data)
c04a1aa8
DJ
243{
244 inferior->regcache_data = data;
245}
255e7678 246
649ebbca
DE
247/* Return true if LIST has exactly one entry. */
248
249int
250one_inferior_p (struct inferior_list *list)
251{
252 return list->head != NULL && list->head == list->tail;
253}
254
255/* Reset head,tail of LIST, assuming all entries have already been freed. */
256
257void
258clear_inferior_list (struct inferior_list *list)
259{
260 list->head = NULL;
261 list->tail = NULL;
262}
255e7678
DJ
263
264void
265clear_inferiors (void)
266{
267 for_each_inferior (&all_threads, free_one_thread);
649ebbca 268 clear_inferior_list (&all_threads);
bf4c19f7
YQ
269
270 clear_dlls ();
7284e1be
UW
271
272 current_inferior = NULL;
255e7678 273}
24a09b5f 274
95954743
PA
275struct process_info *
276add_process (int pid, int attached)
277{
278 struct process_info *process;
279
280 process = xcalloc (1, sizeof (*process));
281
80894984 282 process->entry.id = pid_to_ptid (pid);
95954743
PA
283 process->attached = attached;
284
80894984 285 add_inferior_to_list (&all_processes, &process->entry);
95954743
PA
286
287 return process;
288}
289
5091eb23
DE
290/* Remove a process from the common process list and free the memory
291 allocated for it.
292 The caller is responsible for freeing private data first. */
293
95954743
PA
294void
295remove_process (struct process_info *process)
296{
297 clear_symbol_cache (&process->symbol_cache);
298 free_all_breakpoints (process);
80894984 299 remove_inferior (&all_processes, &process->entry);
5091eb23 300 free (process);
95954743
PA
301}
302
303struct process_info *
304find_process_pid (int pid)
305{
306 return (struct process_info *)
307 find_inferior_id (&all_processes, pid_to_ptid (pid));
308}
309
9f767825
DE
310/* Return non-zero if INF, a struct process_info, was started by us,
311 i.e. not attached to. */
312
313static int
314started_inferior_callback (struct inferior_list_entry *entry, void *args)
315{
316 struct process_info *process = (struct process_info *) entry;
317
318 return ! process->attached;
319}
320
321/* Return non-zero if there are any inferiors that we have created
322 (as opposed to attached-to). */
323
324int
325have_started_inferiors_p (void)
326{
327 return (find_inferior (&all_processes, started_inferior_callback, NULL)
328 != NULL);
329}
330
331/* Return non-zero if INF, a struct process_info, was attached to. */
332
333static int
334attached_inferior_callback (struct inferior_list_entry *entry, void *args)
335{
336 struct process_info *process = (struct process_info *) entry;
337
338 return process->attached;
339}
340
341/* Return non-zero if there are any inferiors that we have attached to. */
342
343int
344have_attached_inferiors_p (void)
345{
346 return (find_inferior (&all_processes, attached_inferior_callback, NULL)
347 != NULL);
348}
349
7fe519cb 350struct process_info *
95954743
PA
351get_thread_process (struct thread_info *thread)
352{
353 int pid = ptid_get_pid (thread->entry.id);
354 return find_process_pid (pid);
355}
356
357struct process_info *
358current_process (void)
359{
360 if (current_inferior == NULL)
361 fatal ("Current inferior requested, but current_inferior is NULL\n");
362
363 return get_thread_process (current_inferior);
364}
This page took 0.884019 seconds and 4 git commands to generate.