f14b41fc041c6c873d5dcefe263ec5ab072a6049
[deliverable/binutils-gdb.git] / gdb / thread.c
1 /* Multi-process/thread control for GDB, the GNU debugger.
2 Copyright 1986, 1987, 1988, 1993
3
4 Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
5 Free Software Foundation, Inc.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 #include "defs.h"
24 #include "symtab.h"
25 #include "frame.h"
26 #include "inferior.h"
27 #include "environ.h"
28 #include "value.h"
29 #include "target.h"
30 #include "thread.h"
31 #include "command.h"
32
33 #include <sys/types.h>
34 #include <signal.h>
35
36 /*#include "lynxos-core.h"*/
37
38 struct thread_info
39 {
40 struct thread_info *next;
41 int pid; /* Actual process id */
42 int num; /* Convenient handle */
43 };
44
45 static struct thread_info *thread_list = NULL;
46 static int highest_thread_num;
47
48 static void thread_command PARAMS ((char * tidstr, int from_tty));
49
50 static void prune_threads PARAMS ((void));
51
52 static void thread_switch PARAMS ((int pid));
53
54 static struct thread_info * find_thread_id PARAMS ((int num));
55
56 void
57 init_thread_list ()
58 {
59 struct thread_info *tp, *tpnext;
60
61 if (!thread_list)
62 return;
63
64 for (tp = thread_list; tp; tp = tpnext)
65 {
66 tpnext = tp->next;
67 free (tp);
68 }
69
70 thread_list = NULL;
71 highest_thread_num = 0;
72 }
73
74 void
75 add_thread (pid)
76 int pid;
77 {
78 struct thread_info *tp;
79
80 tp = (struct thread_info *) xmalloc (sizeof (struct thread_info));
81
82 tp->pid = pid;
83 tp->num = ++highest_thread_num;
84 tp->next = thread_list;
85 thread_list = tp;
86 }
87
88 static struct thread_info *
89 find_thread_id (num)
90 int num;
91 {
92 struct thread_info *tp;
93
94 for (tp = thread_list; tp; tp = tp->next)
95 if (tp->num == num)
96 return tp;
97
98 return NULL;
99 }
100
101 int
102 valid_thread_id (num)
103 int num;
104 {
105 struct thread_info *tp;
106
107 for (tp = thread_list; tp; tp = tp->next)
108 if (tp->num == num)
109 return 1;
110
111 return 0;
112 }
113
114 int
115 pid_to_thread_id (pid)
116 int pid;
117 {
118 struct thread_info *tp;
119
120 for (tp = thread_list; tp; tp = tp->next)
121 if (tp->pid == pid)
122 return tp->num;
123
124 return 0;
125 }
126
127 int
128 in_thread_list (pid)
129 int pid;
130 {
131 struct thread_info *tp;
132
133 for (tp = thread_list; tp; tp = tp->next)
134 if (tp->pid == pid)
135 return 1;
136
137 return 0; /* Never heard of 'im */
138 }
139
140 static void
141 prune_threads ()
142 {
143 struct thread_info *tp, *tpprev;
144
145 tpprev = 0;
146
147 for (tp = thread_list; tp; tp = tp->next)
148 if (tp->pid == -1)
149 {
150 if (tpprev)
151 tpprev->next = tp->next;
152 else
153 thread_list = NULL;
154
155 free (tp);
156 }
157 else
158 tpprev = tp;
159 }
160
161 /* Print information about currently known threads */
162
163 static void
164 info_threads_command (arg, from_tty)
165 char *arg;
166 int from_tty;
167 {
168 struct thread_info *tp;
169 int current_pid = inferior_pid;
170
171 for (tp = thread_list; tp; tp = tp->next)
172 {
173 if (target_has_execution
174 && kill (tp->pid, 0) == -1)
175 {
176 tp->pid = -1; /* Mark it as dead */
177 continue;
178 }
179
180 if (tp->pid == current_pid)
181 printf_filtered ("* ");
182 else
183 printf_filtered (" ");
184
185 printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
186
187 thread_switch (tp->pid);
188 print_stack_frame (selected_frame, -1, 0);
189 }
190
191 thread_switch (current_pid);
192 prune_threads ();
193 }
194
195 /* Switch from one thread to another. */
196
197 static void
198 thread_switch (pid)
199 int pid;
200 {
201 if (pid == inferior_pid)
202 return;
203
204 inferior_pid = pid;
205 flush_cached_frames ();
206 registers_changed ();
207 stop_pc = read_pc();
208 set_current_frame (create_new_frame (read_fp (), stop_pc));
209 stop_frame_address = FRAME_FP (get_current_frame ());
210 select_frame (get_current_frame (), 0);
211 }
212
213 static void
214 thread_command (tidstr, from_tty)
215 char *tidstr;
216 int from_tty;
217 {
218 int num;
219 struct thread_info *tp;
220
221 if (!tidstr)
222 error ("Please specify a thread ID. Use the \"info threads\" command to\n\
223 see the IDs of currently known threads.");
224
225
226 num = atoi (tidstr);
227
228 tp = find_thread_id (num);
229
230 if (!tp)
231 error ("Thread ID %d not known. Use the \"info threads\" command to\n\
232 see the IDs of currently known threads.", num);
233
234 thread_switch (tp->pid);
235
236 printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid));
237 print_stack_frame (selected_frame, selected_frame_level, 1);
238 }
239
240 void
241 _initialize_thread ()
242 {
243 add_info ("threads", info_threads_command,
244 "IDs of currently known threads.");
245 add_com ("thread", class_info, thread_command,
246 "Use this command to switch between threads.\n\
247 The new thread ID must be currently known.");
248 }
This page took 0.03371 seconds and 4 git commands to generate.