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