CARP: *BREAKPOINT*
[deliverable/binutils-gdb.git] / gdb / thread.c
CommitLineData
da0baf42 1/* Multi-process/thread control for GDB, the GNU debugger.
87feff9d 2 Copyright 1986, 1987, 1988, 1993, 1998
da0baf42
SG
3
4 Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
5 Free Software Foundation, Inc.
6
7This file is part of GDB.
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
6c9638b4 21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
25286543
SG
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"
fdfa3315 30#include "gdbthread.h"
46c28185 31#include "command.h"
89ce0c8f 32#include "gdbcmd.h"
25286543 33
89ce0c8f 34#include <ctype.h>
25286543
SG
35#include <sys/types.h>
36#include <signal.h>
37
38/*#include "lynxos-core.h"*/
39
40struct thread_info
41{
42 struct thread_info *next;
43 int pid; /* Actual process id */
44 int num; /* Convenient handle */
88a294b1
JL
45 CORE_ADDR prev_pc; /* State from wait_for_inferior */
46 CORE_ADDR prev_func_start;
47 char *prev_func_name;
48 struct breakpoint *step_resume_breakpoint;
49 struct breakpoint *through_sigtramp_breakpoint;
50 CORE_ADDR step_range_start;
51 CORE_ADDR step_range_end;
52 CORE_ADDR step_frame_address;
53 int trap_expected;
54 int handling_longjmp;
55 int another_trap;
25286543
SG
56};
57
25286543 58
9ee59844
JM
59
60static struct target_thread_vector *target_thread_functions;
61
62int
63target_find_new_threads ()
64{
65 int retval = 0;
66 if (target_thread_functions &&
67 target_thread_functions->find_new_threads)
68 retval = (*(target_thread_functions->find_new_threads)) ();
69 return retval; /* no support */
70}
71
72
73int
74target_get_thread_info PARAMS ((
75 gdb_threadref * ref,
76 int selection, /* FIXME: Selection */
77 struct gdb_ext_thread_info * info));
78
79int
80target_get_thread_info (ref, selection, info)
81
82 gdb_threadref *ref;
83 int selection;
84 /* FIXME: Selection */
85 struct gdb_ext_thread_info *info;
86
87{
88 int retval = 0;
89 if (target_thread_functions
90 && target_thread_functions->get_thread_info)
91 retval = (*(target_thread_functions->get_thread_info)) (ref, selection, info);
92 return retval;
93}
94
95
96/* It is possible that these bind and unbinf functions implement a
97 stack the interface allows it, but its not implemented that way
98 */
99
100
101void
102bind_target_thread_vector (vec)
103 struct target_thread_vector *vec;
104{
105 target_thread_functions = vec;
106}
879c0417 107/* Prototypes for exported functions. */
25286543 108
9ee59844
JM
109struct target_thread_vector *
110unbind_target_thread_vector ()
111{
112 struct target_thread_vector *retval;
113 retval = target_thread_functions;
114 target_thread_functions = 0;
115 return retval;
116} /* unbind_target_thread-vector */
117
879c0417 118void _initialize_thread PARAMS ((void));
25286543 119
9ee59844 120
879c0417 121/* Prototypes for local functions. */
9ee59844
JM
122/* If the host has threads, the host machine definition may
123 set this macro. But, for remote thread debugging, it gets more
124 complex and setting macros does not bind to the various target
125 dependent methods well. So, we use the vector target_thread_functions
126 */
127#if !defined(FIND_NEW_THREADS)
128#define FIND_NEW_THREADS target_find_new_threads
129#endif
130
131static struct thread_info *thread_list = NULL;
132static int highest_thread_num;
133
134static void
135thread_command PARAMS ((char * tidstr, int from_tty));
136static void
137prune_threads PARAMS ((void));
138
139static void
140switch_to_thread PARAMS ((int pid));
141
142static struct thread_info *
143find_thread_id PARAMS ((int num));
25286543 144
9ee59844
JM
145static void
146info_threads_command PARAMS ((char *, int));
b607efe7 147
9ee59844
JM
148static void
149restore_current_thread PARAMS ((int));
b607efe7 150
9ee59844
JM
151static void
152thread_apply_all_command PARAMS ((char *, int));
b607efe7 153
9ee59844
JM
154static void
155thread_apply_command PARAMS ((char *, int));
b607efe7 156
879c0417 157static void info_threads_command PARAMS ((char *, int));
de43d7d0 158
879c0417
JM
159static void restore_current_thread PARAMS ((int));
160
161static void thread_apply_all_command PARAMS ((char *, int));
162
163static void thread_apply_command PARAMS ((char *, int));
164
165static int thread_alive PARAMS ((struct thread_info *));
87feff9d 166
25286543
SG
167void
168init_thread_list ()
169{
170 struct thread_info *tp, *tpnext;
171
172 if (!thread_list)
173 return;
174
175 for (tp = thread_list; tp; tp = tpnext)
176 {
177 tpnext = tp->next;
178 free (tp);
179 }
180
181 thread_list = NULL;
182 highest_thread_num = 0;
183}
184
185void
186add_thread (pid)
187 int pid;
188{
189 struct thread_info *tp;
190
3082244d 191 tp = (struct thread_info *) xmalloc (sizeof (struct thread_info));
25286543
SG
192
193 tp->pid = pid;
194 tp->num = ++highest_thread_num;
88a294b1
JL
195 tp->prev_pc = 0;
196 tp->prev_func_start = 0;
197 tp->prev_func_name = NULL;
198 tp->step_range_start = 0;
199 tp->step_range_end = 0;
200 tp->step_frame_address =0;
201 tp->step_resume_breakpoint = 0;
202 tp->through_sigtramp_breakpoint = 0;
203 tp->handling_longjmp = 0;
204 tp->trap_expected = 0;
205 tp->another_trap = 0;
25286543
SG
206 tp->next = thread_list;
207 thread_list = tp;
208}
209
3780c337
MS
210void
211delete_thread (pid)
212 int pid;
213{
214 struct thread_info *tp, *tpprev;
215
216 tpprev = NULL;
217
218 for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
219 if (tp->pid == pid)
220 break;
221
222 if (!tp)
223 return;
224
225 if (tpprev)
226 tpprev->next = tp->next;
227 else
228 thread_list = tp->next;
229
230 free (tp);
231
232 return;
233}
234
25286543
SG
235static struct thread_info *
236find_thread_id (num)
237 int num;
238{
239 struct thread_info *tp;
240
241 for (tp = thread_list; tp; tp = tp->next)
242 if (tp->num == num)
243 return tp;
244
245 return NULL;
246}
247
de43d7d0
SG
248int
249valid_thread_id (num)
250 int num;
251{
252 struct thread_info *tp;
253
254 for (tp = thread_list; tp; tp = tp->next)
255 if (tp->num == num)
256 return 1;
257
258 return 0;
259}
260
261int
262pid_to_thread_id (pid)
263 int pid;
264{
265 struct thread_info *tp;
266
267 for (tp = thread_list; tp; tp = tp->next)
268 if (tp->pid == pid)
269 return tp->num;
270
271 return 0;
272}
273
c889a1eb
MS
274int
275thread_id_to_pid (num)
276 int num;
277{
278 struct thread_info *thread = find_thread_id (num);
279 if (thread)
280 return thread->pid;
281 else
282 return -1;
283}
284
25286543
SG
285int
286in_thread_list (pid)
287 int pid;
288{
289 struct thread_info *tp;
290
291 for (tp = thread_list; tp; tp = tp->next)
292 if (tp->pid == pid)
293 return 1;
294
295 return 0; /* Never heard of 'im */
296}
297
88a294b1
JL
298/* Load infrun state for the thread PID. */
299
300void load_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
301 trap_expected, step_resume_breakpoint,
302 through_sigtramp_breakpoint, step_range_start,
303 step_range_end, step_frame_address,
304 handling_longjmp, another_trap)
305 int pid;
306 CORE_ADDR *prev_pc;
307 CORE_ADDR *prev_func_start;
308 char **prev_func_name;
309 int *trap_expected;
310 struct breakpoint **step_resume_breakpoint;
311 struct breakpoint **through_sigtramp_breakpoint;
312 CORE_ADDR *step_range_start;
313 CORE_ADDR *step_range_end;
314 CORE_ADDR *step_frame_address;
315 int *handling_longjmp;
316 int *another_trap;
317{
318 struct thread_info *tp;
319
320 /* If we can't find the thread, then we're debugging a single threaded
321 process. No need to do anything in that case. */
322 tp = find_thread_id (pid_to_thread_id (pid));
323 if (tp == NULL)
324 return;
325
326 *prev_pc = tp->prev_pc;
327 *prev_func_start = tp->prev_func_start;
328 *prev_func_name = tp->prev_func_name;
329 *step_resume_breakpoint = tp->step_resume_breakpoint;
330 *step_range_start = tp->step_range_start;
331 *step_range_end = tp->step_range_end;
332 *step_frame_address = tp->step_frame_address;
333 *through_sigtramp_breakpoint = tp->through_sigtramp_breakpoint;
334 *handling_longjmp = tp->handling_longjmp;
335 *trap_expected = tp->trap_expected;
336 *another_trap = tp->another_trap;
337}
338
339/* Save infrun state for the thread PID. */
340
341void save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
342 trap_expected, step_resume_breakpoint,
343 through_sigtramp_breakpoint, step_range_start,
344 step_range_end, step_frame_address,
345 handling_longjmp, another_trap)
346 int pid;
347 CORE_ADDR prev_pc;
348 CORE_ADDR prev_func_start;
349 char *prev_func_name;
350 int trap_expected;
351 struct breakpoint *step_resume_breakpoint;
352 struct breakpoint *through_sigtramp_breakpoint;
353 CORE_ADDR step_range_start;
354 CORE_ADDR step_range_end;
355 CORE_ADDR step_frame_address;
356 int handling_longjmp;
357 int another_trap;
358{
359 struct thread_info *tp;
360
361 /* If we can't find the thread, then we're debugging a single-threaded
362 process. Nothing to do in that case. */
363 tp = find_thread_id (pid_to_thread_id (pid));
364 if (tp == NULL)
365 return;
366
367 tp->prev_pc = prev_pc;
368 tp->prev_func_start = prev_func_start;
369 tp->prev_func_name = prev_func_name;
370 tp->step_resume_breakpoint = step_resume_breakpoint;
371 tp->step_range_start = step_range_start;
372 tp->step_range_end = step_range_end;
373 tp->step_frame_address = step_frame_address;
374 tp->through_sigtramp_breakpoint = through_sigtramp_breakpoint;
375 tp->handling_longjmp = handling_longjmp;
376 tp->trap_expected = trap_expected;
377 tp->another_trap = another_trap;
378}
379
2847920a
MS
380/* Return true if TP is an active thread. */
381static int
382thread_alive (tp)
383 struct thread_info *tp;
384{
385 if (tp->pid == -1)
386 return 0;
387 if (! target_thread_alive (tp->pid))
388 {
389 tp->pid = -1; /* Mark it as dead */
390 return 0;
391 }
392 return 1;
393}
394
25286543
SG
395static void
396prune_threads ()
397{
2847920a 398 struct thread_info *tp, *tpprev, *next;
25286543
SG
399
400 tpprev = 0;
2847920a
MS
401 for (tp = thread_list; tp; tp = next)
402 {
403 next = tp->next;
404 if (!thread_alive (tp))
405 {
406 if (tpprev)
407 tpprev->next = next;
408 else
409 thread_list = next;
410 free (tp);
411 }
412 else
413 tpprev = tp;
414 }
25286543
SG
415}
416
417/* Print information about currently known threads */
418
419static void
420info_threads_command (arg, from_tty)
421 char *arg;
422 int from_tty;
423{
424 struct thread_info *tp;
425 int current_pid = inferior_pid;
426
4cc1b3f7
JK
427 /* Avoid coredumps which would happen if we tried to access a NULL
428 selected_frame. */
429 if (!target_has_stack) error ("No stack.");
430
2847920a 431 prune_threads ();
02227894
DT
432#if defined(FIND_NEW_THREADS)
433 FIND_NEW_THREADS ();
434#endif
435
25286543
SG
436 for (tp = thread_list; tp; tp = tp->next)
437 {
25286543
SG
438 if (tp->pid == current_pid)
439 printf_filtered ("* ");
440 else
441 printf_filtered (" ");
442
443 printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
444
c889a1eb 445 switch_to_thread (tp->pid);
3780c337
MS
446 if (selected_frame)
447 print_stack_frame (selected_frame, -1, 0);
448 else
449 printf_filtered ("[No stack.]\n");
25286543
SG
450 }
451
c889a1eb 452 switch_to_thread (current_pid);
25286543
SG
453}
454
455/* Switch from one thread to another. */
456
3082244d 457static void
c889a1eb 458switch_to_thread (pid)
25286543
SG
459 int pid;
460{
461 if (pid == inferior_pid)
462 return;
463
464 inferior_pid = pid;
25286543
SG
465 flush_cached_frames ();
466 registers_changed ();
467 stop_pc = read_pc();
25286543
SG
468 select_frame (get_current_frame (), 0);
469}
470
5090e82c
SG
471static void
472restore_current_thread (pid)
473 int pid;
474{
475 if (pid != inferior_pid)
c889a1eb 476 switch_to_thread (pid);
5090e82c
SG
477}
478
479/* Apply a GDB command to a list of threads. List syntax is a whitespace
480 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist
481 of two numbers seperated by a hyphen. Examples:
482
483 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4
484 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9
485 thread apply all p x/i $pc Apply x/i $pc cmd to all threads
486*/
487
488static void
489thread_apply_all_command (cmd, from_tty)
490 char *cmd;
491 int from_tty;
492{
493 struct thread_info *tp;
494 struct cleanup *old_chain;
495
496 if (cmd == NULL || *cmd == '\000')
497 error ("Please specify a command following the thread ID list");
498
ad3b8c4a
JM
499 old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
500 (void *) inferior_pid);
5090e82c
SG
501
502 for (tp = thread_list; tp; tp = tp->next)
2847920a
MS
503 if (thread_alive (tp))
504 {
505 switch_to_thread (tp->pid);
506 printf_filtered ("\nThread %d (%s):\n", tp->num,
507 target_pid_to_str (inferior_pid));
508 execute_command (cmd, from_tty);
509 }
5090e82c
SG
510}
511
512static void
513thread_apply_command (tidlist, from_tty)
514 char *tidlist;
515 int from_tty;
516{
517 char *cmd;
518 char *p;
519 struct cleanup *old_chain;
520
521 if (tidlist == NULL || *tidlist == '\000')
522 error ("Please specify a thread ID list");
523
524 for (cmd = tidlist; *cmd != '\000' && !isalpha(*cmd); cmd++);
525
526 if (*cmd == '\000')
527 error ("Please specify a command following the thread ID list");
528
ad3b8c4a
JM
529 old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
530 (void *) inferior_pid);
5090e82c
SG
531
532 while (tidlist < cmd)
533 {
534 struct thread_info *tp;
535 int start, end;
536
537 start = strtol (tidlist, &p, 10);
538 if (p == tidlist)
539 error ("Error parsing %s", tidlist);
540 tidlist = p;
541
542 while (*tidlist == ' ' || *tidlist == '\t')
543 tidlist++;
544
545 if (*tidlist == '-') /* Got a range of IDs? */
546 {
547 tidlist++; /* Skip the - */
548 end = strtol (tidlist, &p, 10);
549 if (p == tidlist)
550 error ("Error parsing %s", tidlist);
551 tidlist = p;
552
553 while (*tidlist == ' ' || *tidlist == '\t')
554 tidlist++;
555 }
556 else
557 end = start;
558
559 for (; start <= end; start++)
560 {
561 tp = find_thread_id (start);
562
563 if (!tp)
2847920a
MS
564 warning ("Unknown thread %d.", start);
565 else if (!thread_alive (tp))
566 warning ("Thread %d has terminated.", start);
567 else
5090e82c 568 {
2847920a
MS
569 switch_to_thread (tp->pid);
570 printf_filtered ("\nThread %d (%s):\n", tp->num,
571 target_pid_to_str (inferior_pid));
572 execute_command (cmd, from_tty);
5090e82c 573 }
5090e82c
SG
574 }
575 }
576}
577
578/* Switch to the specified thread. Will dispatch off to thread_apply_command
579 if prefix of arg is `apply'. */
580
25286543
SG
581static void
582thread_command (tidstr, from_tty)
583 char *tidstr;
584 int from_tty;
585{
586 int num;
587 struct thread_info *tp;
588
589 if (!tidstr)
590 error ("Please specify a thread ID. Use the \"info threads\" command to\n\
591see the IDs of currently known threads.");
592
25286543
SG
593 num = atoi (tidstr);
594
595 tp = find_thread_id (num);
596
597 if (!tp)
598 error ("Thread ID %d not known. Use the \"info threads\" command to\n\
599see the IDs of currently known threads.", num);
2847920a
MS
600
601 if (!thread_alive (tp))
602 error ("Thread ID %d has terminated.\n", num);
25286543 603
c889a1eb 604 switch_to_thread (tp->pid);
4ff5d55a
MH
605 if (context_hook)
606 context_hook (num);
25286543
SG
607 printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid));
608 print_stack_frame (selected_frame, selected_frame_level, 1);
609}
610
c889a1eb
MS
611/* Commands with a prefix of `thread'. */
612struct cmd_list_element *thread_cmd_list = NULL;
613
25286543
SG
614void
615_initialize_thread ()
616{
5090e82c
SG
617 static struct cmd_list_element *thread_apply_list = NULL;
618 extern struct cmd_list_element *cmdlist;
619
25286543
SG
620 add_info ("threads", info_threads_command,
621 "IDs of currently known threads.");
5090e82c
SG
622
623 add_prefix_cmd ("thread", class_run, thread_command,
624 "Use this command to switch between threads.\n\
625The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1,
626 &cmdlist);
627
628 add_prefix_cmd ("apply", class_run, thread_apply_command,
629 "Apply a command to a list of threads.",
630 &thread_apply_list, "apply ", 1, &thread_cmd_list);
631
632 add_cmd ("all", class_run, thread_apply_all_command,
633 "Apply a command to all threads.",
634 &thread_apply_list);
635
636 add_com_alias ("t", "thread", class_run, 1);
25286543 637}
This page took 0.302017 seconds and 4 git commands to generate.