Sun Aug 1 22:58:18 1993 Stu Grossman (grossman at cygnus.com)
[deliverable/binutils-gdb.git] / gdb / thread.c
1 /* for separate threads within the inferior process, for GDB.
2 Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
3
4 GDB is distributed in the hope that it will be useful, but WITHOUT ANY
5 WARRANTY. No author or distributor accepts responsibility to anyone
6 for the consequences of using it or for whether it serves any
7 particular purpose or works at all, unless he says so in writing.
8 Refer to the GDB General Public License for full details.
9
10 Everyone is granted permission to copy, modify and redistribute GDB,
11 but only under the conditions described in the GDB General Public
12 License. A copy of this license is supposed to have been given to you
13 along with GDB so you can know your rights and responsibilities. It
14 should be in a file named COPYING. Among other things, the copyright
15 notice and this notice must be preserved on all copies.
16
17 In other words, go ahead and share GDB, but don't try to stop
18 anyone else from sharing it farther. Help stamp out software hoarding!
19 */
20
21 #include "defs.h"
22 #include "symtab.h"
23 #include "frame.h"
24 #include "inferior.h"
25 #include "environ.h"
26 #include "value.h"
27 #include "target.h"
28 #include "thread.h"
29
30 #include <sys/types.h>
31 #include <signal.h>
32
33 /*#include "lynxos-core.h"*/
34
35 struct thread_info
36 {
37 struct thread_info *next;
38 int pid; /* Actual process id */
39 int num; /* Convenient handle */
40 };
41
42 static struct thread_info *thread_list = NULL;
43 static int highest_thread_num;
44
45 static void thread_info PARAMS ((void));
46
47 static void thread_command PARAMS ((char * tidstr, int from_tty));
48
49 static void prune_threads PARAMS ((void));
50
51 static void thread_switch PARAMS ((int pid));
52
53 void
54 init_thread_list ()
55 {
56 struct thread_info *tp, *tpnext;
57
58 if (!thread_list)
59 return;
60
61 for (tp = thread_list; tp; tp = tpnext)
62 {
63 tpnext = tp->next;
64 free (tp);
65 }
66
67 thread_list = NULL;
68 highest_thread_num = 0;
69 }
70
71 void
72 add_thread (pid)
73 int pid;
74 {
75 struct thread_info *tp;
76
77 tp = xmalloc (sizeof (struct thread_info));
78
79 tp->pid = pid;
80 tp->num = ++highest_thread_num;
81 tp->next = thread_list;
82 thread_list = tp;
83 }
84
85 static struct thread_info *
86 find_thread_id (num)
87 int num;
88 {
89 struct thread_info *tp;
90
91 for (tp = thread_list; tp; tp = tp->next)
92 if (tp->num == num)
93 return tp;
94
95 return NULL;
96 }
97
98 int
99 in_thread_list (pid)
100 int pid;
101 {
102 struct thread_info *tp;
103
104 for (tp = thread_list; tp; tp = tp->next)
105 if (tp->pid == pid)
106 return 1;
107
108 return 0; /* Never heard of 'im */
109 }
110
111 #if 0
112 void
113 bfd_get_core_threads (abfd)
114 bfd *abfd;
115 {
116 int i;
117
118 inferior_pid = BUILDPID (inferior_pid, core_thread (abfd)->pid);
119 for (i = 0; i < core_pss (abfd).threadcnt; i++)
120 add_thread (core_thread (abfd)[i].pid);
121 }
122 #endif
123
124 static void
125 prune_threads ()
126 {
127 struct thread_info *tp, *tpprev;
128
129 tpprev = 0;
130
131 for (tp = thread_list; tp; tp = tp->next)
132 if (tp->pid == -1)
133 {
134 if (tpprev)
135 tpprev->next = tp->next;
136 else
137 thread_list = NULL;
138
139 free (tp);
140 }
141 else
142 tpprev = tp;
143 }
144
145 /* Print information about currently known threads */
146
147 static void
148 info_threads_command (arg, from_tty)
149 char *arg;
150 int from_tty;
151 {
152 struct thread_info *tp;
153 int current_pid = inferior_pid;
154
155 for (tp = thread_list; tp; tp = tp->next)
156 {
157 if (target_has_execution
158 && kill (tp->pid, 0) == -1)
159 {
160 tp->pid == -1; /* Mark it as dead */
161 continue;
162 }
163
164 if (tp->pid == current_pid)
165 printf_filtered ("* ");
166 else
167 printf_filtered (" ");
168
169 printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
170
171 thread_switch (tp->pid);
172 print_stack_frame (selected_frame, -1, 0);
173 }
174
175 thread_switch (current_pid);
176 prune_threads ();
177 }
178
179 /* Switch from one thread to another. */
180
181 void
182 thread_switch (pid)
183 int pid;
184 {
185 if (pid == inferior_pid)
186 return;
187
188 inferior_pid = pid;
189 pc_changed = 0;
190 flush_cached_frames ();
191 registers_changed ();
192 stop_pc = read_pc();
193 set_current_frame (create_new_frame (read_fp (), stop_pc));
194 stop_frame_address = FRAME_FP (get_current_frame ());
195 select_frame (get_current_frame (), 0);
196 }
197
198 static void
199 thread_command (tidstr, from_tty)
200 char *tidstr;
201 int from_tty;
202 {
203 int num;
204 struct thread_info *tp;
205
206 if (!tidstr)
207 error ("Please specify a thread ID. Use the \"info threads\" command to\n\
208 see the IDs of currently known threads.");
209
210
211 num = atoi (tidstr);
212
213 tp = find_thread_id (num);
214
215 if (!tp)
216 error ("Thread ID %d not known. Use the \"info threads\" command to\n\
217 see the IDs of currently known threads.", num);
218
219 thread_switch (tp->pid);
220
221 printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid));
222 print_stack_frame (selected_frame, selected_frame_level, 1);
223 }
224
225 void
226 _initialize_thread ()
227 {
228 add_info ("threads", info_threads_command,
229 "IDs of currently known threads.");
230 add_com ("thread", class_info, thread_command,
231 "Use this command to switch between threads.\n\
232 The new thread ID must be currently known.");
233 }
This page took 0.03369 seconds and 4 git commands to generate.