* inferiors.c (change_inferior_id): Add comment.
[deliverable/binutils-gdb.git] / gdb / gdbserver / inferiors.c
1 /* Inferior process information for the remote server for GDB.
2 Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
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
10 the Free Software Foundation; either version 2 of the License, or
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
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23 #include <stdlib.h>
24
25 #include "server.h"
26
27 struct thread_info
28 {
29 struct inferior_list_entry entry;
30 void *target_data;
31 void *regcache_data;
32 unsigned int gdb_id;
33 };
34
35 struct inferior_list all_threads;
36
37 struct thread_info *current_inferior;
38
39 #define get_thread(inf) ((struct thread_info *)(inf))
40
41 void
42 add_inferior_to_list (struct inferior_list *list,
43 struct inferior_list_entry *new_inferior)
44 {
45 new_inferior->next = NULL;
46 if (list->tail != NULL)
47 list->tail->next = new_inferior;
48 else
49 list->head = new_inferior;
50 list->tail = new_inferior;
51 }
52
53 void
54 for_each_inferior (struct inferior_list *list,
55 void (*action) (struct inferior_list_entry *))
56 {
57 struct inferior_list_entry *cur = list->head, *next;
58
59 while (cur != NULL)
60 {
61 next = cur->next;
62 (*action) (cur);
63 cur = next;
64 }
65 }
66
67 /* When debugging a single-threaded program, the threads list (such as
68 it is) is indexed by PID. When debugging a multi-threaded program,
69 we index by TID. This ugly routine replaces the
70 first-debugged-thread's PID with its TID. */
71
72 void
73 change_inferior_id (struct inferior_list *list,
74 unsigned long new_id)
75 {
76 if (list->head != list->tail)
77 error ("tried to change thread ID after multiple threads are created");
78
79 list->head->id = new_id;
80 }
81
82 void
83 remove_inferior (struct inferior_list *list,
84 struct inferior_list_entry *entry)
85 {
86 struct inferior_list_entry **cur;
87
88 if (list->head == entry)
89 {
90 list->head = entry->next;
91 if (list->tail == entry)
92 list->tail = list->head;
93 return;
94 }
95
96 cur = &list->head;
97 while (*cur && (*cur)->next != entry)
98 cur = &(*cur)->next;
99
100 if (*cur == NULL)
101 return;
102
103 (*cur)->next = entry->next;
104
105 if (list->tail == entry)
106 list->tail = *cur;
107 }
108
109 void
110 add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
111 {
112 struct thread_info *new_thread
113 = (struct thread_info *) malloc (sizeof (*new_thread));
114
115 memset (new_thread, 0, sizeof (*new_thread));
116
117 new_thread->entry.id = thread_id;
118
119 add_inferior_to_list (&all_threads, & new_thread->entry);
120
121 if (current_inferior == NULL)
122 current_inferior = new_thread;
123
124 new_thread->target_data = target_data;
125 set_inferior_regcache_data (new_thread, new_register_cache ());
126 new_thread->gdb_id = gdb_id;
127 }
128
129 unsigned int
130 thread_id_to_gdb_id (unsigned long thread_id)
131 {
132 struct inferior_list_entry *inf = all_threads.head;
133
134 while (inf != NULL)
135 {
136 struct thread_info *thread = get_thread (inf);
137 if (inf->id == thread_id)
138 return thread->gdb_id;
139 inf = inf->next;
140 }
141
142 return 0;
143 }
144
145 unsigned int
146 thread_to_gdb_id (struct thread_info *thread)
147 {
148 return thread->gdb_id;
149 }
150
151 struct thread_info *
152 gdb_id_to_thread (unsigned int gdb_id)
153 {
154 struct inferior_list_entry *inf = all_threads.head;
155
156 while (inf != NULL)
157 {
158 struct thread_info *thread = get_thread (inf);
159 if (thread->gdb_id == gdb_id)
160 return thread;
161 inf = inf->next;
162 }
163
164 return NULL;
165 }
166
167 unsigned long
168 gdb_id_to_thread_id (unsigned int gdb_id)
169 {
170 struct thread_info *thread = gdb_id_to_thread (gdb_id);
171
172 return thread ? thread->entry.id : 0;
173 }
174
175 static void
176 free_one_thread (struct inferior_list_entry *inf)
177 {
178 struct thread_info *thread = get_thread (inf);
179 free_register_cache (inferior_regcache_data (thread));
180 free (thread);
181 }
182
183 void
184 remove_thread (struct thread_info *thread)
185 {
186 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
187 free_one_thread (&thread->entry);
188 }
189
190 void
191 clear_inferiors (void)
192 {
193 for_each_inferior (&all_threads, free_one_thread);
194
195 all_threads.head = all_threads.tail = NULL;
196 }
197
198 struct inferior_list_entry *
199 find_inferior (struct inferior_list *list,
200 int (*func) (struct inferior_list_entry *, void *), void *arg)
201 {
202 struct inferior_list_entry *inf = list->head;
203
204 while (inf != NULL)
205 {
206 if ((*func) (inf, arg))
207 return inf;
208 inf = inf->next;
209 }
210
211 return NULL;
212 }
213
214 struct inferior_list_entry *
215 find_inferior_id (struct inferior_list *list, unsigned long id)
216 {
217 struct inferior_list_entry *inf = list->head;
218
219 while (inf != NULL)
220 {
221 if (inf->id == id)
222 return inf;
223 inf = inf->next;
224 }
225
226 return NULL;
227 }
228
229 void *
230 inferior_target_data (struct thread_info *inferior)
231 {
232 return inferior->target_data;
233 }
234
235 void
236 set_inferior_target_data (struct thread_info *inferior, void *data)
237 {
238 inferior->target_data = data;
239 }
240
241 void *
242 inferior_regcache_data (struct thread_info *inferior)
243 {
244 return inferior->regcache_data;
245 }
246
247 void
248 set_inferior_regcache_data (struct thread_info *inferior, void *data)
249 {
250 inferior->regcache_data = data;
251 }
This page took 0.048835 seconds and 4 git commands to generate.