gdbserver: Reset current_thread when the thread is removed.
[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{
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
95954743
PA
165ptid_t
166gdb_id_to_thread_id (ptid_t gdb_id)
dae5f5cf 167{
e09875d4 168 struct thread_info *thread = find_thread_ptid (gdb_id);
dae5f5cf 169
95954743 170 return thread ? thread->entry.id : null_ptid;
0d62e5e8 171}
c04a1aa8 172
0d62e5e8
DJ
173static void
174free_one_thread (struct inferior_list_entry *inf)
175{
176 struct thread_info *thread = get_thread (inf);
177 free_register_cache (inferior_regcache_data (thread));
178 free (thread);
179}
180
181void
182remove_thread (struct thread_info *thread)
183{
9accd112
MM
184 if (thread->btrace != NULL)
185 target_disable_btrace (thread->btrace);
186
465a859e 187 discard_queued_stop_replies (ptid_of (thread));
0d62e5e8
DJ
188 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
189 free_one_thread (&thread->entry);
96e7a1eb
AR
190 if (current_thread == thread)
191 current_thread = NULL;
ce3a066d
DJ
192}
193
649ebbca
DE
194/* Return a pointer to the first inferior in LIST, or NULL if there isn't one.
195 This is for cases where the caller needs a thread, but doesn't care
196 which one. */
197
198struct inferior_list_entry *
199get_first_inferior (struct inferior_list *list)
200{
3b8361aa
DE
201 if (list->head != NULL)
202 return list->head;
649ebbca
DE
203 return NULL;
204}
205
0718675c
JB
206/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
207 returns non-zero. If no entry is found then return NULL. */
208
0d62e5e8
DJ
209struct inferior_list_entry *
210find_inferior (struct inferior_list *list,
211 int (*func) (struct inferior_list_entry *, void *), void *arg)
212{
213 struct inferior_list_entry *inf = list->head;
ce3a066d 214
0d62e5e8 215 while (inf != NULL)
ce3a066d 216 {
a07b2135
PA
217 struct inferior_list_entry *next;
218
219 next = inf->next;
0d62e5e8
DJ
220 if ((*func) (inf, arg))
221 return inf;
a07b2135 222 inf = next;
0d62e5e8 223 }
611cb4a5 224
0d62e5e8
DJ
225 return NULL;
226}
611cb4a5 227
0d62e5e8 228struct inferior_list_entry *
95954743 229find_inferior_id (struct inferior_list *list, ptid_t id)
0d62e5e8
DJ
230{
231 struct inferior_list_entry *inf = list->head;
232
233 while (inf != NULL)
234 {
95954743 235 if (ptid_equal (inf->id, id))
0d62e5e8
DJ
236 return inf;
237 inf = inf->next;
ce3a066d
DJ
238 }
239
0d62e5e8 240 return NULL;
ce3a066d 241}
611cb4a5
DJ
242
243void *
0d62e5e8 244inferior_target_data (struct thread_info *inferior)
611cb4a5
DJ
245{
246 return inferior->target_data;
247}
248
249void
0d62e5e8 250set_inferior_target_data (struct thread_info *inferior, void *data)
611cb4a5
DJ
251{
252 inferior->target_data = data;
253}
c04a1aa8 254
a44892be 255struct regcache *
0d62e5e8 256inferior_regcache_data (struct thread_info *inferior)
c04a1aa8
DJ
257{
258 return inferior->regcache_data;
259}
260
261void
a44892be 262set_inferior_regcache_data (struct thread_info *inferior, struct regcache *data)
c04a1aa8
DJ
263{
264 inferior->regcache_data = data;
265}
255e7678 266
649ebbca
DE
267/* Return true if LIST has exactly one entry. */
268
269int
270one_inferior_p (struct inferior_list *list)
271{
272 return list->head != NULL && list->head == list->tail;
273}
274
275/* Reset head,tail of LIST, assuming all entries have already been freed. */
276
277void
278clear_inferior_list (struct inferior_list *list)
279{
280 list->head = NULL;
281 list->tail = NULL;
282}
255e7678
DJ
283
284void
285clear_inferiors (void)
286{
287 for_each_inferior (&all_threads, free_one_thread);
649ebbca 288 clear_inferior_list (&all_threads);
bf4c19f7
YQ
289
290 clear_dlls ();
7284e1be 291
0bfdf32f 292 current_thread = NULL;
255e7678 293}
24a09b5f 294
95954743
PA
295struct process_info *
296add_process (int pid, int attached)
297{
8d749320 298 struct process_info *process = XCNEW (struct process_info);
95954743 299
80894984 300 process->entry.id = pid_to_ptid (pid);
95954743
PA
301 process->attached = attached;
302
80894984 303 add_inferior_to_list (&all_processes, &process->entry);
95954743
PA
304
305 return process;
306}
307
5091eb23
DE
308/* Remove a process from the common process list and free the memory
309 allocated for it.
310 The caller is responsible for freeing private data first. */
311
95954743
PA
312void
313remove_process (struct process_info *process)
314{
315 clear_symbol_cache (&process->symbol_cache);
316 free_all_breakpoints (process);
96e7a1eb 317 gdb_assert (find_thread_process (process) == NULL);
80894984 318 remove_inferior (&all_processes, &process->entry);
5091eb23 319 free (process);
95954743
PA
320}
321
322struct process_info *
323find_process_pid (int pid)
324{
325 return (struct process_info *)
326 find_inferior_id (&all_processes, pid_to_ptid (pid));
327}
328
3d40fbb5
PA
329/* Wrapper around get_first_inferior to return a struct process_info *. */
330
331struct process_info *
332get_first_process (void)
333{
334 return (struct process_info *) get_first_inferior (&all_processes);
335}
336
9f767825
DE
337/* Return non-zero if INF, a struct process_info, was started by us,
338 i.e. not attached to. */
339
340static int
341started_inferior_callback (struct inferior_list_entry *entry, void *args)
342{
343 struct process_info *process = (struct process_info *) entry;
344
345 return ! process->attached;
346}
347
348/* Return non-zero if there are any inferiors that we have created
349 (as opposed to attached-to). */
350
351int
352have_started_inferiors_p (void)
353{
354 return (find_inferior (&all_processes, started_inferior_callback, NULL)
355 != NULL);
356}
357
358/* Return non-zero if INF, a struct process_info, was attached to. */
359
360static int
361attached_inferior_callback (struct inferior_list_entry *entry, void *args)
362{
363 struct process_info *process = (struct process_info *) entry;
364
365 return process->attached;
366}
367
368/* Return non-zero if there are any inferiors that we have attached to. */
369
370int
371have_attached_inferiors_p (void)
372{
373 return (find_inferior (&all_processes, attached_inferior_callback, NULL)
374 != NULL);
375}
376
7fe519cb 377struct process_info *
95954743
PA
378get_thread_process (struct thread_info *thread)
379{
380 int pid = ptid_get_pid (thread->entry.id);
381 return find_process_pid (pid);
382}
383
384struct process_info *
385current_process (void)
386{
0bfdf32f
GB
387 gdb_assert (current_thread != NULL);
388 return get_thread_process (current_thread);
95954743 389}
This page took 1.474484 seconds and 4 git commands to generate.