2001-06-01 Michael Snyder <msnyder@redhat.com>
[deliverable/binutils-gdb.git] / gdb / thread.c
CommitLineData
c906108c 1/* Multi-process/thread control for GDB, the GNU debugger.
b6ba6518
KB
2 Copyright 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000, 2001
c906108c 4 Free Software Foundation, Inc.
b6ba6518
KB
5 Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
6
c906108c 7
c5aa993b 8 This file is part of GDB.
c906108c 9
c5aa993b
JM
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
c906108c 14
c5aa993b
JM
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
c906108c 19
c5aa993b
JM
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
c906108c
SS
24
25#include "defs.h"
26#include "symtab.h"
27#include "frame.h"
28#include "inferior.h"
29#include "environ.h"
30#include "value.h"
31#include "target.h"
32#include "gdbthread.h"
33#include "command.h"
34#include "gdbcmd.h"
4e052eda 35#include "regcache.h"
c906108c
SS
36
37#include <ctype.h>
38#include <sys/types.h>
39#include <signal.h>
8b93c638
JM
40#ifdef UI_OUT
41#include "ui-out.h"
42#endif
c906108c 43
c5aa993b 44/*#include "lynxos-core.h" */
c906108c 45
0d06e24b 46/* Definition of struct thread_info exported to gdbthread.h */
c906108c
SS
47
48/* Prototypes for exported functions. */
49
a14ed312 50void _initialize_thread (void);
c906108c
SS
51
52/* Prototypes for local functions. */
53
c906108c
SS
54static struct thread_info *thread_list = NULL;
55static int highest_thread_num;
56
a14ed312 57static struct thread_info *find_thread_id (int num);
c906108c 58
a14ed312
KB
59static void thread_command (char *tidstr, int from_tty);
60static void thread_apply_all_command (char *, int);
61static int thread_alive (struct thread_info *);
62static void info_threads_command (char *, int);
63static void thread_apply_command (char *, int);
39f77062
KB
64static void restore_current_thread (ptid_t);
65static void switch_to_thread (ptid_t ptid);
a14ed312 66static void prune_threads (void);
c906108c 67
8601f500
MS
68void
69delete_step_resume_breakpoint (void *arg)
70{
71 struct breakpoint **breakpointp = (struct breakpoint **) arg;
72 struct thread_info *tp;
73
74 if (*breakpointp != NULL)
75 {
76 delete_breakpoint (*breakpointp);
77 for (tp = thread_list; tp; tp = tp->next)
78 if (tp->step_resume_breakpoint == *breakpointp)
79 tp->step_resume_breakpoint = NULL;
80
81 *breakpointp = NULL;
82 }
83}
84
7c952b6d
ND
85static void
86free_thread (struct thread_info *tp)
87{
88 /* NOTE: this will take care of any left-over step_resume breakpoints,
89 but not any user-specified thread-specific breakpoints. */
90 if (tp->step_resume_breakpoint)
91 delete_breakpoint (tp->step_resume_breakpoint);
92
93 /* FIXME: do I ever need to call the back-end to give it a
94 chance at this private data before deleting the thread? */
95 if (tp->private)
b8c9b27d 96 xfree (tp->private);
7c952b6d 97
b8c9b27d 98 xfree (tp);
7c952b6d
ND
99}
100
c906108c 101void
fba45db2 102init_thread_list (void)
c906108c
SS
103{
104 struct thread_info *tp, *tpnext;
105
7c952b6d 106 highest_thread_num = 0;
c906108c
SS
107 if (!thread_list)
108 return;
109
110 for (tp = thread_list; tp; tp = tpnext)
111 {
112 tpnext = tp->next;
7c952b6d 113 free_thread (tp);
c906108c
SS
114 }
115
116 thread_list = NULL;
c906108c
SS
117}
118
0d06e24b
JM
119/* add_thread now returns a pointer to the new thread_info,
120 so that back_ends can initialize their private data. */
121
122struct thread_info *
39f77062 123add_thread (ptid_t ptid)
c906108c
SS
124{
125 struct thread_info *tp;
126
127 tp = (struct thread_info *) xmalloc (sizeof (struct thread_info));
128
39f77062 129 tp->ptid = ptid;
c906108c
SS
130 tp->num = ++highest_thread_num;
131 tp->prev_pc = 0;
132 tp->prev_func_start = 0;
133 tp->prev_func_name = NULL;
134 tp->step_range_start = 0;
135 tp->step_range_end = 0;
c5aa993b 136 tp->step_frame_address = 0;
c906108c
SS
137 tp->step_resume_breakpoint = 0;
138 tp->through_sigtramp_breakpoint = 0;
139 tp->handling_longjmp = 0;
140 tp->trap_expected = 0;
141 tp->another_trap = 0;
142 tp->stepping_through_solib_after_catch = 0;
143 tp->stepping_through_solib_catchpoints = NULL;
144 tp->stepping_through_sigtramp = 0;
145 tp->next = thread_list;
c5394b80 146 tp->private = NULL;
c906108c 147 thread_list = tp;
0d06e24b 148 return tp;
c906108c
SS
149}
150
151void
39f77062 152delete_thread (ptid_t ptid)
c906108c
SS
153{
154 struct thread_info *tp, *tpprev;
155
156 tpprev = NULL;
157
158 for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
39f77062 159 if (ptid_equal (tp->ptid, ptid))
c906108c
SS
160 break;
161
162 if (!tp)
163 return;
164
165 if (tpprev)
166 tpprev->next = tp->next;
167 else
168 thread_list = tp->next;
169
7c952b6d 170 free_thread (tp);
c906108c
SS
171}
172
173static struct thread_info *
fba45db2 174find_thread_id (int num)
c906108c
SS
175{
176 struct thread_info *tp;
177
178 for (tp = thread_list; tp; tp = tp->next)
179 if (tp->num == num)
180 return tp;
181
182 return NULL;
183}
184
39f77062 185/* Find a thread_info by matching PTID. */
0d06e24b 186struct thread_info *
39f77062 187find_thread_pid (ptid_t ptid)
0d06e24b
JM
188{
189 struct thread_info *tp;
190
191 for (tp = thread_list; tp; tp = tp->next)
39f77062 192 if (ptid_equal (tp->ptid, ptid))
0d06e24b
JM
193 return tp;
194
195 return NULL;
196}
197
198/*
199 * Thread iterator function.
200 *
201 * Calls a callback function once for each thread, so long as
202 * the callback function returns false. If the callback function
203 * returns true, the iteration will end and the current thread
204 * will be returned. This can be useful for implementing a
205 * search for a thread with arbitrary attributes, or for applying
206 * some operation to every thread.
207 *
208 * FIXME: some of the existing functionality, such as
209 * "Thread apply all", might be rewritten using this functionality.
210 */
211
212struct thread_info *
fd118b61
KB
213iterate_over_threads (int (*callback) (struct thread_info *, void *),
214 void *data)
0d06e24b
JM
215{
216 struct thread_info *tp;
217
218 for (tp = thread_list; tp; tp = tp->next)
219 if ((*callback) (tp, data))
220 return tp;
221
222 return NULL;
223}
224
c906108c 225int
fba45db2 226valid_thread_id (int num)
c906108c
SS
227{
228 struct thread_info *tp;
229
230 for (tp = thread_list; tp; tp = tp->next)
231 if (tp->num == num)
232 return 1;
233
234 return 0;
235}
236
237int
39f77062 238pid_to_thread_id (ptid_t ptid)
c906108c
SS
239{
240 struct thread_info *tp;
241
242 for (tp = thread_list; tp; tp = tp->next)
39f77062 243 if (ptid_equal (tp->ptid, ptid))
c906108c
SS
244 return tp->num;
245
246 return 0;
247}
248
39f77062 249ptid_t
fba45db2 250thread_id_to_pid (int num)
c906108c
SS
251{
252 struct thread_info *thread = find_thread_id (num);
253 if (thread)
39f77062 254 return thread->ptid;
c906108c 255 else
39f77062 256 return pid_to_ptid (-1);
c906108c
SS
257}
258
259int
39f77062 260in_thread_list (ptid_t ptid)
c906108c
SS
261{
262 struct thread_info *tp;
263
264 for (tp = thread_list; tp; tp = tp->next)
39f77062 265 if (ptid_equal (tp->ptid, ptid))
c906108c
SS
266 return 1;
267
268 return 0; /* Never heard of 'im */
269}
8b93c638
JM
270#ifdef UI_OUT
271/* Print a list of thread ids currently known, and the total number of
272 threads. To be used from within catch_errors. */
273static int
274do_captured_list_thread_ids (void *arg)
275{
276 struct thread_info *tp;
277 int num = 0;
278
f8e42d24 279 ui_out_tuple_begin (uiout, "thread-ids");
8b93c638
JM
280
281 for (tp = thread_list; tp; tp = tp->next)
282 {
283 num++;
284 ui_out_field_int (uiout, "thread-id", tp->num);
285 }
286
f8e42d24 287 ui_out_tuple_end (uiout);
8b93c638
JM
288 ui_out_field_int (uiout, "number-of-threads", num);
289 return GDB_RC_OK;
290}
291
292/* Official gdblib interface function to get a list of thread ids and
293 the total number. */
294enum gdb_rc
295gdb_list_thread_ids (/* output object */)
296{
297 return catch_errors (do_captured_list_thread_ids, NULL,
298 NULL, RETURN_MASK_ALL);
299}
300#endif
c906108c
SS
301
302/* Load infrun state for the thread PID. */
303
c5aa993b 304void
39f77062 305load_infrun_state (ptid_t ptid, CORE_ADDR *prev_pc, CORE_ADDR *prev_func_start,
fba45db2
KB
306 char **prev_func_name, int *trap_expected,
307 struct breakpoint **step_resume_breakpoint,
308 struct breakpoint **through_sigtramp_breakpoint,
309 CORE_ADDR *step_range_start, CORE_ADDR *step_range_end,
310 CORE_ADDR *step_frame_address, int *handling_longjmp,
311 int *another_trap, int *stepping_through_solib_after_catch,
312 bpstat *stepping_through_solib_catchpoints,
313 int *stepping_through_sigtramp)
c906108c
SS
314{
315 struct thread_info *tp;
316
317 /* If we can't find the thread, then we're debugging a single threaded
318 process. No need to do anything in that case. */
39f77062 319 tp = find_thread_id (pid_to_thread_id (ptid));
c906108c
SS
320 if (tp == NULL)
321 return;
322
323 *prev_pc = tp->prev_pc;
324 *prev_func_start = tp->prev_func_start;
325 *prev_func_name = tp->prev_func_name;
326 *step_resume_breakpoint = tp->step_resume_breakpoint;
327 *step_range_start = tp->step_range_start;
328 *step_range_end = tp->step_range_end;
329 *step_frame_address = tp->step_frame_address;
330 *through_sigtramp_breakpoint = tp->through_sigtramp_breakpoint;
331 *handling_longjmp = tp->handling_longjmp;
332 *trap_expected = tp->trap_expected;
333 *another_trap = tp->another_trap;
334 *stepping_through_solib_after_catch = tp->stepping_through_solib_after_catch;
335 *stepping_through_solib_catchpoints = tp->stepping_through_solib_catchpoints;
336 *stepping_through_sigtramp = tp->stepping_through_sigtramp;
337}
338
339/* Save infrun state for the thread PID. */
340
c5aa993b 341void
39f77062 342save_infrun_state (ptid_t ptid, CORE_ADDR prev_pc, CORE_ADDR prev_func_start,
fba45db2
KB
343 char *prev_func_name, int trap_expected,
344 struct breakpoint *step_resume_breakpoint,
345 struct breakpoint *through_sigtramp_breakpoint,
346 CORE_ADDR step_range_start, CORE_ADDR step_range_end,
347 CORE_ADDR step_frame_address, int handling_longjmp,
348 int another_trap, int stepping_through_solib_after_catch,
349 bpstat stepping_through_solib_catchpoints,
350 int stepping_through_sigtramp)
c906108c
SS
351{
352 struct thread_info *tp;
353
354 /* If we can't find the thread, then we're debugging a single-threaded
355 process. Nothing to do in that case. */
39f77062 356 tp = find_thread_id (pid_to_thread_id (ptid));
c906108c
SS
357 if (tp == NULL)
358 return;
359
360 tp->prev_pc = prev_pc;
361 tp->prev_func_start = prev_func_start;
362 tp->prev_func_name = prev_func_name;
363 tp->step_resume_breakpoint = step_resume_breakpoint;
364 tp->step_range_start = step_range_start;
365 tp->step_range_end = step_range_end;
366 tp->step_frame_address = step_frame_address;
367 tp->through_sigtramp_breakpoint = through_sigtramp_breakpoint;
368 tp->handling_longjmp = handling_longjmp;
369 tp->trap_expected = trap_expected;
370 tp->another_trap = another_trap;
371 tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
372 tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;
373 tp->stepping_through_sigtramp = stepping_through_sigtramp;
374}
375
376/* Return true if TP is an active thread. */
377static int
fba45db2 378thread_alive (struct thread_info *tp)
c906108c 379{
39f77062 380 if (PIDGET (tp->ptid) == -1)
c906108c 381 return 0;
39f77062 382 if (!target_thread_alive (tp->ptid))
c906108c 383 {
39f77062 384 tp->ptid = pid_to_ptid (-1); /* Mark it as dead */
c906108c
SS
385 return 0;
386 }
387 return 1;
388}
389
390static void
fba45db2 391prune_threads (void)
c906108c 392{
d4f3574e 393 struct thread_info *tp, *next;
c906108c 394
c906108c
SS
395 for (tp = thread_list; tp; tp = next)
396 {
397 next = tp->next;
398 if (!thread_alive (tp))
39f77062 399 delete_thread (tp->ptid);
c906108c
SS
400 }
401}
402
403/* Print information about currently known threads
c5aa993b 404
c906108c
SS
405 * Note: this has the drawback that it _really_ switches
406 * threads, which frees the frame cache. A no-side
407 * effects info-threads command would be nicer.
408 */
409
410static void
fba45db2 411info_threads_command (char *arg, int from_tty)
c906108c
SS
412{
413 struct thread_info *tp;
39f77062 414 ptid_t current_ptid;
c5aa993b
JM
415 struct frame_info *cur_frame;
416 int saved_frame_level = selected_frame_level;
417 int counter;
0d06e24b 418 char *extra_info;
c906108c
SS
419
420 /* Avoid coredumps which would happen if we tried to access a NULL
421 selected_frame. */
c5aa993b
JM
422 if (!target_has_stack)
423 error ("No stack.");
c906108c
SS
424
425 prune_threads ();
b83266a0 426 target_find_new_threads ();
39f77062 427 current_ptid = inferior_ptid;
c906108c
SS
428 for (tp = thread_list; tp; tp = tp->next)
429 {
39f77062 430 if (ptid_equal (tp->ptid, current_ptid))
c906108c
SS
431 printf_filtered ("* ");
432 else
433 printf_filtered (" ");
434
435#ifdef HPUXHPPA
39f77062 436 printf_filtered ("%d %s", tp->num, target_tid_to_str (tp->ptid));
c906108c 437#else
39f77062 438 printf_filtered ("%d %s", tp->num, target_pid_to_str (tp->ptid));
c906108c 439#endif
0d06e24b
JM
440
441 extra_info = target_extra_thread_info (tp);
442 if (extra_info)
443 printf_filtered (" (%s)", extra_info);
444 puts_filtered (" ");
445
39f77062 446 switch_to_thread (tp->ptid);
c906108c
SS
447 if (selected_frame)
448 print_only_stack_frame (selected_frame, -1, 0);
449 else
450 printf_filtered ("[No stack.]\n");
451 }
452
39f77062 453 switch_to_thread (current_ptid);
c906108c
SS
454
455 /* Code below copied from "up_silently_base" in "stack.c".
456 * It restores the frame set by the user before the "info threads"
457 * command. We have finished the info-threads display by switching
458 * back to the current thread. That switch has put us at the top
459 * of the stack (leaf frame).
460 */
c5aa993b
JM
461 counter = saved_frame_level;
462 cur_frame = find_relative_frame (selected_frame, &counter);
c906108c
SS
463 if (counter != 0)
464 {
465 /* Ooops, can't restore, tell user where we are. */
466 warning ("Couldn't restore frame in current thread, at frame 0");
467 print_stack_frame (selected_frame, -1, 0);
468 }
469 else
470 {
c5aa993b 471 select_frame (cur_frame, saved_frame_level);
c906108c
SS
472 }
473
474 /* re-show current frame. */
c5aa993b 475 show_stack_frame (cur_frame);
c906108c
SS
476}
477
478/* Switch from one thread to another. */
479
480static void
39f77062 481switch_to_thread (ptid_t ptid)
c906108c 482{
39f77062 483 if (ptid_equal (ptid, inferior_ptid))
c906108c
SS
484 return;
485
39f77062 486 inferior_ptid = ptid;
c906108c
SS
487 flush_cached_frames ();
488 registers_changed ();
c5aa993b 489 stop_pc = read_pc ();
c906108c
SS
490 select_frame (get_current_frame (), 0);
491}
492
493static void
39f77062 494restore_current_thread (ptid_t ptid)
c906108c 495{
39f77062 496 if (! ptid_equal (ptid, inferior_ptid))
c906108c 497 {
39f77062 498 switch_to_thread (ptid);
c5aa993b 499 print_stack_frame (get_current_frame (), 0, -1);
c906108c
SS
500 }
501}
502
6ecce94d
AC
503struct current_thread_cleanup
504{
39f77062 505 ptid_t inferior_ptid;
6ecce94d
AC
506};
507
508static void
509do_restore_current_thread_cleanup (void *arg)
510{
511 struct current_thread_cleanup *old = arg;
39f77062 512 restore_current_thread (old->inferior_ptid);
b8c9b27d 513 xfree (old);
6ecce94d
AC
514}
515
516static struct cleanup *
39f77062 517make_cleanup_restore_current_thread (ptid_t inferior_ptid)
6ecce94d
AC
518{
519 struct current_thread_cleanup *old
520 = xmalloc (sizeof (struct current_thread_cleanup));
39f77062 521 old->inferior_ptid = inferior_ptid;
6ecce94d
AC
522 return make_cleanup (do_restore_current_thread_cleanup, old);
523}
524
c906108c
SS
525/* Apply a GDB command to a list of threads. List syntax is a whitespace
526 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist
527 of two numbers seperated by a hyphen. Examples:
528
c5aa993b
JM
529 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4
530 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9
531 thread apply all p x/i $pc Apply x/i $pc cmd to all threads
532 */
c906108c
SS
533
534static void
fba45db2 535thread_apply_all_command (char *cmd, int from_tty)
c906108c
SS
536{
537 struct thread_info *tp;
538 struct cleanup *old_chain;
e35ce267
CF
539 struct cleanup *saved_cmd_cleanup_chain;
540 char *saved_cmd;
c906108c
SS
541
542 if (cmd == NULL || *cmd == '\000')
543 error ("Please specify a command following the thread ID list");
544
39f77062 545 old_chain = make_cleanup_restore_current_thread (inferior_ptid);
c906108c 546
e9d196c5
MS
547 /* It is safe to update the thread list now, before
548 traversing it for "thread apply all". MVS */
549 target_find_new_threads ();
550
e35ce267
CF
551 /* Save a copy of the command in case it is clobbered by
552 execute_command */
5b616ba1 553 saved_cmd = xstrdup (cmd);
b8c9b27d 554 saved_cmd_cleanup_chain = make_cleanup (xfree, (void *) saved_cmd);
c906108c
SS
555 for (tp = thread_list; tp; tp = tp->next)
556 if (thread_alive (tp))
557 {
39f77062 558 switch_to_thread (tp->ptid);
c906108c
SS
559#ifdef HPUXHPPA
560 printf_filtered ("\nThread %d (%s):\n",
561 tp->num,
39f77062 562 target_tid_to_str (inferior_ptid));
c906108c
SS
563#else
564 printf_filtered ("\nThread %d (%s):\n", tp->num,
39f77062 565 target_pid_to_str (inferior_ptid));
c906108c
SS
566#endif
567 execute_command (cmd, from_tty);
e35ce267 568 strcpy (cmd, saved_cmd); /* Restore exact command used previously */
c906108c 569 }
6ecce94d 570
e35ce267 571 do_cleanups (saved_cmd_cleanup_chain);
6ecce94d 572 do_cleanups (old_chain);
c906108c
SS
573}
574
575static void
fba45db2 576thread_apply_command (char *tidlist, int from_tty)
c906108c
SS
577{
578 char *cmd;
579 char *p;
580 struct cleanup *old_chain;
e35ce267
CF
581 struct cleanup *saved_cmd_cleanup_chain;
582 char *saved_cmd;
c906108c
SS
583
584 if (tidlist == NULL || *tidlist == '\000')
585 error ("Please specify a thread ID list");
586
c5aa993b 587 for (cmd = tidlist; *cmd != '\000' && !isalpha (*cmd); cmd++);
c906108c
SS
588
589 if (*cmd == '\000')
590 error ("Please specify a command following the thread ID list");
591
39f77062 592 old_chain = make_cleanup_restore_current_thread (inferior_ptid);
c906108c 593
e35ce267
CF
594 /* Save a copy of the command in case it is clobbered by
595 execute_command */
5b616ba1 596 saved_cmd = xstrdup (cmd);
b8c9b27d 597 saved_cmd_cleanup_chain = make_cleanup (xfree, (void *) saved_cmd);
c906108c
SS
598 while (tidlist < cmd)
599 {
600 struct thread_info *tp;
601 int start, end;
602
603 start = strtol (tidlist, &p, 10);
604 if (p == tidlist)
605 error ("Error parsing %s", tidlist);
606 tidlist = p;
607
608 while (*tidlist == ' ' || *tidlist == '\t')
609 tidlist++;
610
611 if (*tidlist == '-') /* Got a range of IDs? */
612 {
c5aa993b 613 tidlist++; /* Skip the - */
c906108c
SS
614 end = strtol (tidlist, &p, 10);
615 if (p == tidlist)
616 error ("Error parsing %s", tidlist);
617 tidlist = p;
618
619 while (*tidlist == ' ' || *tidlist == '\t')
620 tidlist++;
621 }
622 else
623 end = start;
624
625 for (; start <= end; start++)
626 {
627 tp = find_thread_id (start);
628
629 if (!tp)
630 warning ("Unknown thread %d.", start);
631 else if (!thread_alive (tp))
632 warning ("Thread %d has terminated.", start);
633 else
634 {
39f77062 635 switch_to_thread (tp->ptid);
c906108c
SS
636#ifdef HPUXHPPA
637 printf_filtered ("\nThread %d (%s):\n", tp->num,
39f77062 638 target_tid_to_str (inferior_ptid));
c906108c
SS
639#else
640 printf_filtered ("\nThread %d (%s):\n", tp->num,
39f77062 641 target_pid_to_str (inferior_ptid));
c906108c
SS
642#endif
643 execute_command (cmd, from_tty);
e35ce267 644 strcpy (cmd, saved_cmd); /* Restore exact command used previously */
c906108c
SS
645 }
646 }
647 }
6ecce94d 648
e35ce267 649 do_cleanups (saved_cmd_cleanup_chain);
6ecce94d 650 do_cleanups (old_chain);
c906108c
SS
651}
652
653/* Switch to the specified thread. Will dispatch off to thread_apply_command
654 if prefix of arg is `apply'. */
655
656static void
fba45db2 657thread_command (char *tidstr, int from_tty)
c906108c 658{
c906108c
SS
659 if (!tidstr)
660 {
661 /* Don't generate an error, just say which thread is current. */
662 if (target_has_stack)
663 printf_filtered ("[Current thread is %d (%s)]\n",
39f77062 664 pid_to_thread_id (inferior_ptid),
c906108c 665#if defined(HPUXHPPA)
39f77062 666 target_tid_to_str (inferior_ptid)
c906108c 667#else
39f77062 668 target_pid_to_str (inferior_ptid)
c906108c 669#endif
c5aa993b 670 );
c906108c
SS
671 else
672 error ("No stack.");
673 return;
674 }
c5394b80
JM
675
676 gdb_thread_select (tidstr);
677}
678
679static int
680do_captured_thread_select (void *tidstr)
681{
682 int num;
683 struct thread_info *tp;
684
81490ea1 685 num = value_as_long (parse_and_eval (tidstr));
c906108c
SS
686
687 tp = find_thread_id (num);
688
8b93c638
JM
689#ifdef UI_OUT
690 if (!tp)
691 error ("Thread ID %d not known.", num);
692#else
c906108c
SS
693 if (!tp)
694 error ("Thread ID %d not known. Use the \"info threads\" command to\n\
695see the IDs of currently known threads.", num);
8b93c638 696#endif
c906108c
SS
697
698 if (!thread_alive (tp))
699 error ("Thread ID %d has terminated.\n", num);
700
39f77062 701 switch_to_thread (tp->ptid);
c906108c 702
8b93c638
JM
703#ifdef UI_OUT
704 ui_out_text (uiout, "[Switching to thread ");
39f77062 705 ui_out_field_int (uiout, "new-thread-id", pid_to_thread_id (inferior_ptid));
8b93c638
JM
706 ui_out_text (uiout, " (");
707#if defined(HPUXHPPA)
39f77062 708 ui_out_text (uiout, target_tid_to_str (inferior_ptid));
8b93c638 709#else
39f77062 710 ui_out_text (uiout, target_pid_to_str (inferior_ptid));
8b93c638
JM
711#endif
712 ui_out_text (uiout, ")]");
713#else /* UI_OUT */
c906108c 714 printf_filtered ("[Switching to thread %d (%s)]\n",
39f77062 715 pid_to_thread_id (inferior_ptid),
c906108c 716#if defined(HPUXHPPA)
39f77062 717 target_tid_to_str (inferior_ptid)
c906108c 718#else
39f77062 719 target_pid_to_str (inferior_ptid)
c906108c 720#endif
c5aa993b 721 );
8b93c638 722#endif /* UI_OUT */
c5394b80 723
c906108c 724 print_stack_frame (selected_frame, selected_frame_level, 1);
c5394b80
JM
725 return GDB_RC_OK;
726}
727
728enum gdb_rc
729gdb_thread_select (char *tidstr)
730{
731 return catch_errors (do_captured_thread_select, tidstr,
732 NULL, RETURN_MASK_ALL);
c906108c
SS
733}
734
735/* Commands with a prefix of `thread'. */
736struct cmd_list_element *thread_cmd_list = NULL;
737
738void
fba45db2 739_initialize_thread (void)
c906108c
SS
740{
741 static struct cmd_list_element *thread_apply_list = NULL;
c906108c
SS
742
743 add_info ("threads", info_threads_command,
744 "IDs of currently known threads.");
745
746 add_prefix_cmd ("thread", class_run, thread_command,
747 "Use this command to switch between threads.\n\
748The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1,
749 &cmdlist);
750
751 add_prefix_cmd ("apply", class_run, thread_apply_command,
752 "Apply a command to a list of threads.",
753 &thread_apply_list, "apply ", 1, &thread_cmd_list);
754
755 add_cmd ("all", class_run, thread_apply_all_command,
756 "Apply a command to all threads.",
757 &thread_apply_list);
758
759 if (!xdb_commands)
760 add_com_alias ("t", "thread", class_run, 1);
761}
This page took 0.177279 seconds and 4 git commands to generate.