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