]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/thread.c
import gdb-1999-07-07 post reformat
[thirdparty/binutils-gdb.git] / gdb / thread.c
CommitLineData
c906108c
SS
1/* Multi-process/thread control for GDB, the GNU debugger.
2 Copyright 1986, 1987, 1988, 1993, 1998
3
4 Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
5 Free Software Foundation, Inc.
6
c5aa993b 7 This file is part of GDB.
c906108c 8
c5aa993b
JM
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.
c906108c 13
c5aa993b
JM
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.
c906108c 18
c5aa993b
JM
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., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
c906108c
SS
23
24#include "defs.h"
25#include "symtab.h"
26#include "frame.h"
27#include "inferior.h"
28#include "environ.h"
29#include "value.h"
30#include "target.h"
31#include "gdbthread.h"
32#include "command.h"
33#include "gdbcmd.h"
34
35#include <ctype.h>
36#include <sys/types.h>
37#include <signal.h>
38
c5aa993b 39/*#include "lynxos-core.h" */
c906108c
SS
40
41struct thread_info
c5aa993b
JM
42 {
43 struct thread_info *next;
44 int pid; /* Actual process id */
45 int num; /* Convenient handle */
46 CORE_ADDR prev_pc; /* State from wait_for_inferior */
47 CORE_ADDR prev_func_start;
48 char *prev_func_name;
49 struct breakpoint *step_resume_breakpoint;
50 struct breakpoint *through_sigtramp_breakpoint;
51 CORE_ADDR step_range_start;
52 CORE_ADDR step_range_end;
53 CORE_ADDR step_frame_address;
54 int trap_expected;
55 int handling_longjmp;
56 int another_trap;
57
58 /* This is set TRUE when a catchpoint of a shared library event
59 triggers. Since we don't wish to leave the inferior in the
60 solib hook when we report the event, we step the inferior
61 back to user code before stopping and reporting the event.
c906108c 62 */
c5aa993b 63 int stepping_through_solib_after_catch;
c906108c 64
c5aa993b
JM
65 /* When stepping_through_solib_after_catch is TRUE, this is a
66 list of the catchpoints that should be reported as triggering
67 when we finally do stop stepping.
c906108c 68 */
c5aa993b 69 bpstat stepping_through_solib_catchpoints;
c906108c 70
c5aa993b
JM
71 /* This is set to TRUE when this thread is in a signal handler
72 trampoline and we're single-stepping through it */
73 int stepping_through_sigtramp;
c906108c 74
c5aa993b 75 };
c906108c
SS
76
77/* Prototypes for exported functions. */
78
79void _initialize_thread PARAMS ((void));
80
81/* Prototypes for local functions. */
82
c906108c
SS
83static struct thread_info *thread_list = NULL;
84static int highest_thread_num;
85
c5aa993b 86static struct thread_info *find_thread_id PARAMS ((int num));
c906108c 87
c5aa993b 88static void thread_command PARAMS ((char *tidstr, int from_tty));
c906108c 89static void thread_apply_all_command PARAMS ((char *, int));
c5aa993b 90static int thread_alive PARAMS ((struct thread_info *));
c906108c
SS
91static void info_threads_command PARAMS ((char *, int));
92static void thread_apply_command PARAMS ((char *, int));
93static void restore_current_thread PARAMS ((int));
94static void switch_to_thread PARAMS ((int pid));
95static void prune_threads PARAMS ((void));
c906108c
SS
96
97void
98init_thread_list ()
99{
100 struct thread_info *tp, *tpnext;
101
102 if (!thread_list)
103 return;
104
105 for (tp = thread_list; tp; tp = tpnext)
106 {
107 tpnext = tp->next;
108 free (tp);
109 }
110
111 thread_list = NULL;
112 highest_thread_num = 0;
113}
114
115void
116add_thread (pid)
117 int pid;
118{
119 struct thread_info *tp;
120
121 tp = (struct thread_info *) xmalloc (sizeof (struct thread_info));
122
123 tp->pid = pid;
124 tp->num = ++highest_thread_num;
125 tp->prev_pc = 0;
126 tp->prev_func_start = 0;
127 tp->prev_func_name = NULL;
128 tp->step_range_start = 0;
129 tp->step_range_end = 0;
c5aa993b 130 tp->step_frame_address = 0;
c906108c
SS
131 tp->step_resume_breakpoint = 0;
132 tp->through_sigtramp_breakpoint = 0;
133 tp->handling_longjmp = 0;
134 tp->trap_expected = 0;
135 tp->another_trap = 0;
136 tp->stepping_through_solib_after_catch = 0;
137 tp->stepping_through_solib_catchpoints = NULL;
138 tp->stepping_through_sigtramp = 0;
139 tp->next = thread_list;
140 thread_list = tp;
141}
142
143void
144delete_thread (pid)
145 int pid;
146{
147 struct thread_info *tp, *tpprev;
148
149 tpprev = NULL;
150
151 for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
152 if (tp->pid == pid)
153 break;
154
155 if (!tp)
156 return;
157
158 if (tpprev)
159 tpprev->next = tp->next;
160 else
161 thread_list = tp->next;
162
163 free (tp);
164
165 return;
166}
167
168static struct thread_info *
169find_thread_id (num)
c5aa993b 170 int num;
c906108c
SS
171{
172 struct thread_info *tp;
173
174 for (tp = thread_list; tp; tp = tp->next)
175 if (tp->num == num)
176 return tp;
177
178 return NULL;
179}
180
181int
182valid_thread_id (num)
c5aa993b 183 int num;
c906108c
SS
184{
185 struct thread_info *tp;
186
187 for (tp = thread_list; tp; tp = tp->next)
188 if (tp->num == num)
189 return 1;
190
191 return 0;
192}
193
194int
195pid_to_thread_id (pid)
c5aa993b 196 int pid;
c906108c
SS
197{
198 struct thread_info *tp;
199
200 for (tp = thread_list; tp; tp = tp->next)
201 if (tp->pid == pid)
202 return tp->num;
203
204 return 0;
205}
206
207int
208thread_id_to_pid (num)
c5aa993b 209 int num;
c906108c
SS
210{
211 struct thread_info *thread = find_thread_id (num);
212 if (thread)
213 return thread->pid;
214 else
215 return -1;
216}
217
218int
219in_thread_list (pid)
c5aa993b 220 int pid;
c906108c
SS
221{
222 struct thread_info *tp;
223
224 for (tp = thread_list; tp; tp = tp->next)
225 if (tp->pid == pid)
226 return 1;
227
228 return 0; /* Never heard of 'im */
229}
230
231/* Load infrun state for the thread PID. */
232
c5aa993b
JM
233void
234load_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
235 trap_expected, step_resume_breakpoint,
236 through_sigtramp_breakpoint, step_range_start,
237 step_range_end, step_frame_address,
238 handling_longjmp, another_trap,
239 stepping_through_solib_after_catch,
240 stepping_through_solib_catchpoints,
241 stepping_through_sigtramp)
c906108c
SS
242 int pid;
243 CORE_ADDR *prev_pc;
244 CORE_ADDR *prev_func_start;
245 char **prev_func_name;
246 int *trap_expected;
247 struct breakpoint **step_resume_breakpoint;
248 struct breakpoint **through_sigtramp_breakpoint;
249 CORE_ADDR *step_range_start;
250 CORE_ADDR *step_range_end;
251 CORE_ADDR *step_frame_address;
252 int *handling_longjmp;
253 int *another_trap;
c5aa993b
JM
254 int *stepping_through_solib_after_catch;
255 bpstat *stepping_through_solib_catchpoints;
256 int *stepping_through_sigtramp;
c906108c
SS
257{
258 struct thread_info *tp;
259
260 /* If we can't find the thread, then we're debugging a single threaded
261 process. No need to do anything in that case. */
262 tp = find_thread_id (pid_to_thread_id (pid));
263 if (tp == NULL)
264 return;
265
266 *prev_pc = tp->prev_pc;
267 *prev_func_start = tp->prev_func_start;
268 *prev_func_name = tp->prev_func_name;
269 *step_resume_breakpoint = tp->step_resume_breakpoint;
270 *step_range_start = tp->step_range_start;
271 *step_range_end = tp->step_range_end;
272 *step_frame_address = tp->step_frame_address;
273 *through_sigtramp_breakpoint = tp->through_sigtramp_breakpoint;
274 *handling_longjmp = tp->handling_longjmp;
275 *trap_expected = tp->trap_expected;
276 *another_trap = tp->another_trap;
277 *stepping_through_solib_after_catch = tp->stepping_through_solib_after_catch;
278 *stepping_through_solib_catchpoints = tp->stepping_through_solib_catchpoints;
279 *stepping_through_sigtramp = tp->stepping_through_sigtramp;
280}
281
282/* Save infrun state for the thread PID. */
283
c5aa993b
JM
284void
285save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
286 trap_expected, step_resume_breakpoint,
287 through_sigtramp_breakpoint, step_range_start,
288 step_range_end, step_frame_address,
289 handling_longjmp, another_trap,
290 stepping_through_solib_after_catch,
291 stepping_through_solib_catchpoints,
292 stepping_through_sigtramp)
c906108c
SS
293 int pid;
294 CORE_ADDR prev_pc;
295 CORE_ADDR prev_func_start;
296 char *prev_func_name;
297 int trap_expected;
298 struct breakpoint *step_resume_breakpoint;
299 struct breakpoint *through_sigtramp_breakpoint;
300 CORE_ADDR step_range_start;
301 CORE_ADDR step_range_end;
302 CORE_ADDR step_frame_address;
303 int handling_longjmp;
304 int another_trap;
c5aa993b
JM
305 int stepping_through_solib_after_catch;
306 bpstat stepping_through_solib_catchpoints;
307 int stepping_through_sigtramp;
c906108c
SS
308{
309 struct thread_info *tp;
310
311 /* If we can't find the thread, then we're debugging a single-threaded
312 process. Nothing to do in that case. */
313 tp = find_thread_id (pid_to_thread_id (pid));
314 if (tp == NULL)
315 return;
316
317 tp->prev_pc = prev_pc;
318 tp->prev_func_start = prev_func_start;
319 tp->prev_func_name = prev_func_name;
320 tp->step_resume_breakpoint = step_resume_breakpoint;
321 tp->step_range_start = step_range_start;
322 tp->step_range_end = step_range_end;
323 tp->step_frame_address = step_frame_address;
324 tp->through_sigtramp_breakpoint = through_sigtramp_breakpoint;
325 tp->handling_longjmp = handling_longjmp;
326 tp->trap_expected = trap_expected;
327 tp->another_trap = another_trap;
328 tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
329 tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;
330 tp->stepping_through_sigtramp = stepping_through_sigtramp;
331}
332
333/* Return true if TP is an active thread. */
334static int
335thread_alive (tp)
336 struct thread_info *tp;
337{
338 if (tp->pid == -1)
339 return 0;
c5aa993b 340 if (!target_thread_alive (tp->pid))
c906108c 341 {
c5aa993b 342 tp->pid = -1; /* Mark it as dead */
c906108c
SS
343 return 0;
344 }
345 return 1;
346}
347
348static void
349prune_threads ()
350{
351 struct thread_info *tp, *tpprev, *next;
352
353 tpprev = 0;
354 for (tp = thread_list; tp; tp = next)
355 {
356 next = tp->next;
357 if (!thread_alive (tp))
358 {
359 if (tpprev)
360 tpprev->next = next;
361 else
c5aa993b 362 thread_list = next;
c906108c
SS
363 free (tp);
364 }
365 else
366 tpprev = tp;
367 }
368}
369
370/* Print information about currently known threads
c5aa993b 371
c906108c
SS
372 * Note: this has the drawback that it _really_ switches
373 * threads, which frees the frame cache. A no-side
374 * effects info-threads command would be nicer.
375 */
376
377static void
378info_threads_command (arg, from_tty)
379 char *arg;
380 int from_tty;
381{
382 struct thread_info *tp;
c5aa993b
JM
383 int current_pid;
384 struct frame_info *cur_frame;
385 int saved_frame_level = selected_frame_level;
386 int counter;
c906108c
SS
387
388 /* Avoid coredumps which would happen if we tried to access a NULL
389 selected_frame. */
c5aa993b
JM
390 if (!target_has_stack)
391 error ("No stack.");
c906108c
SS
392
393 prune_threads ();
b83266a0 394 target_find_new_threads ();
c906108c
SS
395 current_pid = inferior_pid;
396 for (tp = thread_list; tp; tp = tp->next)
397 {
398 if (tp->pid == current_pid)
399 printf_filtered ("* ");
400 else
401 printf_filtered (" ");
402
403#ifdef HPUXHPPA
404 printf_filtered ("%d %s ", tp->num, target_tid_to_str (tp->pid));
405#else
406 printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
407#endif
408 switch_to_thread (tp->pid);
409 if (selected_frame)
410 print_only_stack_frame (selected_frame, -1, 0);
411 else
412 printf_filtered ("[No stack.]\n");
413 }
414
415 switch_to_thread (current_pid);
416
417 /* Code below copied from "up_silently_base" in "stack.c".
418 * It restores the frame set by the user before the "info threads"
419 * command. We have finished the info-threads display by switching
420 * back to the current thread. That switch has put us at the top
421 * of the stack (leaf frame).
422 */
c5aa993b
JM
423 counter = saved_frame_level;
424 cur_frame = find_relative_frame (selected_frame, &counter);
c906108c
SS
425 if (counter != 0)
426 {
427 /* Ooops, can't restore, tell user where we are. */
428 warning ("Couldn't restore frame in current thread, at frame 0");
429 print_stack_frame (selected_frame, -1, 0);
430 }
431 else
432 {
c5aa993b 433 select_frame (cur_frame, saved_frame_level);
c906108c
SS
434 }
435
436 /* re-show current frame. */
c5aa993b 437 show_stack_frame (cur_frame);
c906108c
SS
438}
439
440/* Switch from one thread to another. */
441
442static void
443switch_to_thread (pid)
444 int pid;
445{
446 if (pid == inferior_pid)
447 return;
448
449 inferior_pid = pid;
450 flush_cached_frames ();
451 registers_changed ();
c5aa993b 452 stop_pc = read_pc ();
c906108c
SS
453 select_frame (get_current_frame (), 0);
454}
455
456static void
457restore_current_thread (pid)
458 int pid;
459{
c5aa993b 460 if (pid != inferior_pid)
c906108c
SS
461 {
462 switch_to_thread (pid);
c5aa993b 463 print_stack_frame (get_current_frame (), 0, -1);
c906108c
SS
464 }
465}
466
467/* Apply a GDB command to a list of threads. List syntax is a whitespace
468 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist
469 of two numbers seperated by a hyphen. Examples:
470
c5aa993b
JM
471 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4
472 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9
473 thread apply all p x/i $pc Apply x/i $pc cmd to all threads
474 */
c906108c
SS
475
476static void
477thread_apply_all_command (cmd, from_tty)
478 char *cmd;
479 int from_tty;
480{
481 struct thread_info *tp;
482 struct cleanup *old_chain;
483
484 if (cmd == NULL || *cmd == '\000')
485 error ("Please specify a command following the thread ID list");
486
c5aa993b 487 old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
c906108c
SS
488 (void *) inferior_pid);
489
490 for (tp = thread_list; tp; tp = tp->next)
491 if (thread_alive (tp))
492 {
493 switch_to_thread (tp->pid);
494#ifdef HPUXHPPA
495 printf_filtered ("\nThread %d (%s):\n",
496 tp->num,
497 target_tid_to_str (inferior_pid));
498#else
499 printf_filtered ("\nThread %d (%s):\n", tp->num,
500 target_pid_to_str (inferior_pid));
501#endif
502 execute_command (cmd, from_tty);
503 }
504}
505
506static void
507thread_apply_command (tidlist, from_tty)
508 char *tidlist;
509 int from_tty;
510{
511 char *cmd;
512 char *p;
513 struct cleanup *old_chain;
514
515 if (tidlist == NULL || *tidlist == '\000')
516 error ("Please specify a thread ID list");
517
c5aa993b 518 for (cmd = tidlist; *cmd != '\000' && !isalpha (*cmd); cmd++);
c906108c
SS
519
520 if (*cmd == '\000')
521 error ("Please specify a command following the thread ID list");
522
c5aa993b 523 old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
c906108c
SS
524 (void *) inferior_pid);
525
526 while (tidlist < cmd)
527 {
528 struct thread_info *tp;
529 int start, end;
530
531 start = strtol (tidlist, &p, 10);
532 if (p == tidlist)
533 error ("Error parsing %s", tidlist);
534 tidlist = p;
535
536 while (*tidlist == ' ' || *tidlist == '\t')
537 tidlist++;
538
539 if (*tidlist == '-') /* Got a range of IDs? */
540 {
c5aa993b 541 tidlist++; /* Skip the - */
c906108c
SS
542 end = strtol (tidlist, &p, 10);
543 if (p == tidlist)
544 error ("Error parsing %s", tidlist);
545 tidlist = p;
546
547 while (*tidlist == ' ' || *tidlist == '\t')
548 tidlist++;
549 }
550 else
551 end = start;
552
553 for (; start <= end; start++)
554 {
555 tp = find_thread_id (start);
556
557 if (!tp)
558 warning ("Unknown thread %d.", start);
559 else if (!thread_alive (tp))
560 warning ("Thread %d has terminated.", start);
561 else
562 {
563 switch_to_thread (tp->pid);
564#ifdef HPUXHPPA
565 printf_filtered ("\nThread %d (%s):\n", tp->num,
566 target_tid_to_str (inferior_pid));
567#else
568 printf_filtered ("\nThread %d (%s):\n", tp->num,
569 target_pid_to_str (inferior_pid));
570#endif
571 execute_command (cmd, from_tty);
572 }
573 }
574 }
575}
576
577/* Switch to the specified thread. Will dispatch off to thread_apply_command
578 if prefix of arg is `apply'. */
579
580static void
581thread_command (tidstr, from_tty)
582 char *tidstr;
583 int from_tty;
584{
585 int num;
586 struct thread_info *tp;
587
588 if (!tidstr)
589 {
590 /* Don't generate an error, just say which thread is current. */
591 if (target_has_stack)
592 printf_filtered ("[Current thread is %d (%s)]\n",
c5aa993b 593 pid_to_thread_id (inferior_pid),
c906108c 594#if defined(HPUXHPPA)
c5aa993b 595 target_tid_to_str (inferior_pid)
c906108c 596#else
c5aa993b 597 target_pid_to_str (inferior_pid)
c906108c 598#endif
c5aa993b 599 );
c906108c
SS
600 else
601 error ("No stack.");
602 return;
603 }
604 num = atoi (tidstr);
605
606 tp = find_thread_id (num);
607
608 if (!tp)
609 error ("Thread ID %d not known. Use the \"info threads\" command to\n\
610see the IDs of currently known threads.", num);
611
612 if (!thread_alive (tp))
613 error ("Thread ID %d has terminated.\n", num);
614
615 switch_to_thread (tp->pid);
616
617 if (context_hook)
618 context_hook (num);
619
620 printf_filtered ("[Switching to thread %d (%s)]\n",
621 pid_to_thread_id (inferior_pid),
622#if defined(HPUXHPPA)
623 target_tid_to_str (inferior_pid)
624#else
625 target_pid_to_str (inferior_pid)
626#endif
c5aa993b 627 );
c906108c
SS
628 print_stack_frame (selected_frame, selected_frame_level, 1);
629}
630
631/* Commands with a prefix of `thread'. */
632struct cmd_list_element *thread_cmd_list = NULL;
633
634void
635_initialize_thread ()
636{
637 static struct cmd_list_element *thread_apply_list = NULL;
c906108c
SS
638
639 add_info ("threads", info_threads_command,
640 "IDs of currently known threads.");
641
642 add_prefix_cmd ("thread", class_run, thread_command,
643 "Use this command to switch between threads.\n\
644The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1,
645 &cmdlist);
646
647 add_prefix_cmd ("apply", class_run, thread_apply_command,
648 "Apply a command to a list of threads.",
649 &thread_apply_list, "apply ", 1, &thread_cmd_list);
650
651 add_cmd ("all", class_run, thread_apply_all_command,
652 "Apply a command to all threads.",
653 &thread_apply_list);
654
655 if (!xdb_commands)
656 add_com_alias ("t", "thread", class_run, 1);
657}