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