]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/thread.c
Fix whitespace problem in my most recent entry.
[thirdparty/binutils-gdb.git] / gdb / thread.c
CommitLineData
c906108c 1/* Multi-process/thread control for GDB, the GNU debugger.
5b616ba1 2 Copyright 1986, 1987, 1988, 1993, 1998, 1999, 2000, 2001
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"
4e052eda 34#include "regcache.h"
c906108c
SS
35
36#include <ctype.h>
37#include <sys/types.h>
38#include <signal.h>
8b93c638
JM
39#ifdef UI_OUT
40#include "ui-out.h"
41#endif
c906108c 42
c5aa993b 43/*#include "lynxos-core.h" */
c906108c 44
0d06e24b 45/* Definition of struct thread_info exported to gdbthread.h */
c906108c
SS
46
47/* Prototypes for exported functions. */
48
a14ed312 49void _initialize_thread (void);
c906108c
SS
50
51/* Prototypes for local functions. */
52
c906108c
SS
53static struct thread_info *thread_list = NULL;
54static int highest_thread_num;
55
a14ed312 56static struct thread_info *find_thread_id (int num);
c906108c 57
a14ed312
KB
58static void thread_command (char *tidstr, int from_tty);
59static void thread_apply_all_command (char *, int);
60static int thread_alive (struct thread_info *);
61static void info_threads_command (char *, int);
62static void thread_apply_command (char *, int);
63static void restore_current_thread (int);
64static void switch_to_thread (int pid);
65static void prune_threads (void);
c906108c 66
7c952b6d
ND
67static void
68free_thread (struct thread_info *tp)
69{
70 /* NOTE: this will take care of any left-over step_resume breakpoints,
71 but not any user-specified thread-specific breakpoints. */
72 if (tp->step_resume_breakpoint)
73 delete_breakpoint (tp->step_resume_breakpoint);
74
75 /* FIXME: do I ever need to call the back-end to give it a
76 chance at this private data before deleting the thread? */
77 if (tp->private)
b8c9b27d 78 xfree (tp->private);
7c952b6d 79
b8c9b27d 80 xfree (tp);
7c952b6d
ND
81}
82
c906108c 83void
fba45db2 84init_thread_list (void)
c906108c
SS
85{
86 struct thread_info *tp, *tpnext;
87
7c952b6d 88 highest_thread_num = 0;
c906108c
SS
89 if (!thread_list)
90 return;
91
92 for (tp = thread_list; tp; tp = tpnext)
93 {
94 tpnext = tp->next;
7c952b6d 95 free_thread (tp);
c906108c
SS
96 }
97
98 thread_list = NULL;
c906108c
SS
99}
100
0d06e24b
JM
101/* add_thread now returns a pointer to the new thread_info,
102 so that back_ends can initialize their private data. */
103
104struct thread_info *
fba45db2 105add_thread (int pid)
c906108c
SS
106{
107 struct thread_info *tp;
108
109 tp = (struct thread_info *) xmalloc (sizeof (struct thread_info));
110
111 tp->pid = pid;
112 tp->num = ++highest_thread_num;
113 tp->prev_pc = 0;
114 tp->prev_func_start = 0;
115 tp->prev_func_name = NULL;
116 tp->step_range_start = 0;
117 tp->step_range_end = 0;
c5aa993b 118 tp->step_frame_address = 0;
c906108c
SS
119 tp->step_resume_breakpoint = 0;
120 tp->through_sigtramp_breakpoint = 0;
121 tp->handling_longjmp = 0;
122 tp->trap_expected = 0;
123 tp->another_trap = 0;
124 tp->stepping_through_solib_after_catch = 0;
125 tp->stepping_through_solib_catchpoints = NULL;
126 tp->stepping_through_sigtramp = 0;
127 tp->next = thread_list;
c5394b80 128 tp->private = NULL;
c906108c 129 thread_list = tp;
0d06e24b 130 return tp;
c906108c
SS
131}
132
133void
fba45db2 134delete_thread (int pid)
c906108c
SS
135{
136 struct thread_info *tp, *tpprev;
137
138 tpprev = NULL;
139
140 for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
141 if (tp->pid == pid)
142 break;
143
144 if (!tp)
145 return;
146
147 if (tpprev)
148 tpprev->next = tp->next;
149 else
150 thread_list = tp->next;
151
7c952b6d 152 free_thread (tp);
c906108c
SS
153}
154
155static struct thread_info *
fba45db2 156find_thread_id (int num)
c906108c
SS
157{
158 struct thread_info *tp;
159
160 for (tp = thread_list; tp; tp = tp->next)
161 if (tp->num == num)
162 return tp;
163
164 return NULL;
165}
166
0d06e24b
JM
167/* Find a thread_info by matching 'pid'. */
168struct thread_info *
fba45db2 169find_thread_pid (int pid)
0d06e24b
JM
170{
171 struct thread_info *tp;
172
173 for (tp = thread_list; tp; tp = tp->next)
174 if (tp->pid == pid)
175 return tp;
176
177 return NULL;
178}
179
180/*
181 * Thread iterator function.
182 *
183 * Calls a callback function once for each thread, so long as
184 * the callback function returns false. If the callback function
185 * returns true, the iteration will end and the current thread
186 * will be returned. This can be useful for implementing a
187 * search for a thread with arbitrary attributes, or for applying
188 * some operation to every thread.
189 *
190 * FIXME: some of the existing functionality, such as
191 * "Thread apply all", might be rewritten using this functionality.
192 */
193
194struct thread_info *
fd118b61
KB
195iterate_over_threads (int (*callback) (struct thread_info *, void *),
196 void *data)
0d06e24b
JM
197{
198 struct thread_info *tp;
199
200 for (tp = thread_list; tp; tp = tp->next)
201 if ((*callback) (tp, data))
202 return tp;
203
204 return NULL;
205}
206
c906108c 207int
fba45db2 208valid_thread_id (int num)
c906108c
SS
209{
210 struct thread_info *tp;
211
212 for (tp = thread_list; tp; tp = tp->next)
213 if (tp->num == num)
214 return 1;
215
216 return 0;
217}
218
219int
fba45db2 220pid_to_thread_id (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 tp->num;
227
228 return 0;
229}
230
231int
fba45db2 232thread_id_to_pid (int num)
c906108c
SS
233{
234 struct thread_info *thread = find_thread_id (num);
235 if (thread)
236 return thread->pid;
237 else
238 return -1;
239}
240
241int
fba45db2 242in_thread_list (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}
8b93c638
JM
252#ifdef UI_OUT
253/* Print a list of thread ids currently known, and the total number of
254 threads. To be used from within catch_errors. */
255static int
256do_captured_list_thread_ids (void *arg)
257{
258 struct thread_info *tp;
259 int num = 0;
260
261 ui_out_list_begin (uiout, "thread-ids");
262
263 for (tp = thread_list; tp; tp = tp->next)
264 {
265 num++;
266 ui_out_field_int (uiout, "thread-id", tp->num);
267 }
268
269 ui_out_list_end (uiout);
270 ui_out_field_int (uiout, "number-of-threads", num);
271 return GDB_RC_OK;
272}
273
274/* Official gdblib interface function to get a list of thread ids and
275 the total number. */
276enum gdb_rc
277gdb_list_thread_ids (/* output object */)
278{
279 return catch_errors (do_captured_list_thread_ids, NULL,
280 NULL, RETURN_MASK_ALL);
281}
282#endif
c906108c
SS
283
284/* Load infrun state for the thread PID. */
285
c5aa993b 286void
fba45db2
KB
287load_infrun_state (int pid, CORE_ADDR *prev_pc, CORE_ADDR *prev_func_start,
288 char **prev_func_name, int *trap_expected,
289 struct breakpoint **step_resume_breakpoint,
290 struct breakpoint **through_sigtramp_breakpoint,
291 CORE_ADDR *step_range_start, CORE_ADDR *step_range_end,
292 CORE_ADDR *step_frame_address, int *handling_longjmp,
293 int *another_trap, int *stepping_through_solib_after_catch,
294 bpstat *stepping_through_solib_catchpoints,
295 int *stepping_through_sigtramp)
c906108c
SS
296{
297 struct thread_info *tp;
298
299 /* If we can't find the thread, then we're debugging a single threaded
300 process. No need to do anything in that case. */
301 tp = find_thread_id (pid_to_thread_id (pid));
302 if (tp == NULL)
303 return;
304
305 *prev_pc = tp->prev_pc;
306 *prev_func_start = tp->prev_func_start;
307 *prev_func_name = tp->prev_func_name;
308 *step_resume_breakpoint = tp->step_resume_breakpoint;
309 *step_range_start = tp->step_range_start;
310 *step_range_end = tp->step_range_end;
311 *step_frame_address = tp->step_frame_address;
312 *through_sigtramp_breakpoint = tp->through_sigtramp_breakpoint;
313 *handling_longjmp = tp->handling_longjmp;
314 *trap_expected = tp->trap_expected;
315 *another_trap = tp->another_trap;
316 *stepping_through_solib_after_catch = tp->stepping_through_solib_after_catch;
317 *stepping_through_solib_catchpoints = tp->stepping_through_solib_catchpoints;
318 *stepping_through_sigtramp = tp->stepping_through_sigtramp;
319}
320
321/* Save infrun state for the thread PID. */
322
c5aa993b 323void
fba45db2
KB
324save_infrun_state (int pid, CORE_ADDR prev_pc, CORE_ADDR prev_func_start,
325 char *prev_func_name, int trap_expected,
326 struct breakpoint *step_resume_breakpoint,
327 struct breakpoint *through_sigtramp_breakpoint,
328 CORE_ADDR step_range_start, CORE_ADDR step_range_end,
329 CORE_ADDR step_frame_address, int handling_longjmp,
330 int another_trap, int stepping_through_solib_after_catch,
331 bpstat stepping_through_solib_catchpoints,
332 int stepping_through_sigtramp)
c906108c
SS
333{
334 struct thread_info *tp;
335
336 /* If we can't find the thread, then we're debugging a single-threaded
337 process. Nothing to do in that case. */
338 tp = find_thread_id (pid_to_thread_id (pid));
339 if (tp == NULL)
340 return;
341
342 tp->prev_pc = prev_pc;
343 tp->prev_func_start = prev_func_start;
344 tp->prev_func_name = prev_func_name;
345 tp->step_resume_breakpoint = step_resume_breakpoint;
346 tp->step_range_start = step_range_start;
347 tp->step_range_end = step_range_end;
348 tp->step_frame_address = step_frame_address;
349 tp->through_sigtramp_breakpoint = through_sigtramp_breakpoint;
350 tp->handling_longjmp = handling_longjmp;
351 tp->trap_expected = trap_expected;
352 tp->another_trap = another_trap;
353 tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
354 tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;
355 tp->stepping_through_sigtramp = stepping_through_sigtramp;
356}
357
358/* Return true if TP is an active thread. */
359static int
fba45db2 360thread_alive (struct thread_info *tp)
c906108c
SS
361{
362 if (tp->pid == -1)
363 return 0;
c5aa993b 364 if (!target_thread_alive (tp->pid))
c906108c 365 {
c5aa993b 366 tp->pid = -1; /* Mark it as dead */
c906108c
SS
367 return 0;
368 }
369 return 1;
370}
371
372static void
fba45db2 373prune_threads (void)
c906108c 374{
d4f3574e 375 struct thread_info *tp, *next;
c906108c 376
c906108c
SS
377 for (tp = thread_list; tp; tp = next)
378 {
379 next = tp->next;
380 if (!thread_alive (tp))
53a5351d 381 delete_thread (tp->pid);
c906108c
SS
382 }
383}
384
385/* Print information about currently known threads
c5aa993b 386
c906108c
SS
387 * Note: this has the drawback that it _really_ switches
388 * threads, which frees the frame cache. A no-side
389 * effects info-threads command would be nicer.
390 */
391
392static void
fba45db2 393info_threads_command (char *arg, int from_tty)
c906108c
SS
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
fba45db2 463switch_to_thread (int pid)
c906108c
SS
464{
465 if (pid == inferior_pid)
466 return;
467
468 inferior_pid = pid;
469 flush_cached_frames ();
470 registers_changed ();
c5aa993b 471 stop_pc = read_pc ();
c906108c
SS
472 select_frame (get_current_frame (), 0);
473}
474
475static void
fba45db2 476restore_current_thread (int pid)
c906108c 477{
c5aa993b 478 if (pid != inferior_pid)
c906108c
SS
479 {
480 switch_to_thread (pid);
c5aa993b 481 print_stack_frame (get_current_frame (), 0, -1);
c906108c
SS
482 }
483}
484
6ecce94d
AC
485struct current_thread_cleanup
486{
487 int inferior_pid;
488};
489
490static void
491do_restore_current_thread_cleanup (void *arg)
492{
493 struct current_thread_cleanup *old = arg;
494 restore_current_thread (old->inferior_pid);
b8c9b27d 495 xfree (old);
6ecce94d
AC
496}
497
498static struct cleanup *
499make_cleanup_restore_current_thread (int inferior_pid)
500{
501 struct current_thread_cleanup *old
502 = xmalloc (sizeof (struct current_thread_cleanup));
503 old->inferior_pid = inferior_pid;
504 return make_cleanup (do_restore_current_thread_cleanup, old);
505}
506
c906108c
SS
507/* Apply a GDB command to a list of threads. List syntax is a whitespace
508 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist
509 of two numbers seperated by a hyphen. Examples:
510
c5aa993b
JM
511 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4
512 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9
513 thread apply all p x/i $pc Apply x/i $pc cmd to all threads
514 */
c906108c
SS
515
516static void
fba45db2 517thread_apply_all_command (char *cmd, int from_tty)
c906108c
SS
518{
519 struct thread_info *tp;
520 struct cleanup *old_chain;
e35ce267
CF
521 struct cleanup *saved_cmd_cleanup_chain;
522 char *saved_cmd;
c906108c
SS
523
524 if (cmd == NULL || *cmd == '\000')
525 error ("Please specify a command following the thread ID list");
526
6ecce94d 527 old_chain = make_cleanup_restore_current_thread (inferior_pid);
c906108c 528
e9d196c5
MS
529 /* It is safe to update the thread list now, before
530 traversing it for "thread apply all". MVS */
531 target_find_new_threads ();
532
e35ce267
CF
533 /* Save a copy of the command in case it is clobbered by
534 execute_command */
5b616ba1 535 saved_cmd = xstrdup (cmd);
b8c9b27d 536 saved_cmd_cleanup_chain = make_cleanup (xfree, (void *) saved_cmd);
c906108c
SS
537 for (tp = thread_list; tp; tp = tp->next)
538 if (thread_alive (tp))
539 {
540 switch_to_thread (tp->pid);
541#ifdef HPUXHPPA
542 printf_filtered ("\nThread %d (%s):\n",
543 tp->num,
544 target_tid_to_str (inferior_pid));
545#else
546 printf_filtered ("\nThread %d (%s):\n", tp->num,
547 target_pid_to_str (inferior_pid));
548#endif
549 execute_command (cmd, from_tty);
e35ce267 550 strcpy (cmd, saved_cmd); /* Restore exact command used previously */
c906108c 551 }
6ecce94d 552
e35ce267 553 do_cleanups (saved_cmd_cleanup_chain);
6ecce94d 554 do_cleanups (old_chain);
c906108c
SS
555}
556
557static void
fba45db2 558thread_apply_command (char *tidlist, int from_tty)
c906108c
SS
559{
560 char *cmd;
561 char *p;
562 struct cleanup *old_chain;
e35ce267
CF
563 struct cleanup *saved_cmd_cleanup_chain;
564 char *saved_cmd;
c906108c
SS
565
566 if (tidlist == NULL || *tidlist == '\000')
567 error ("Please specify a thread ID list");
568
c5aa993b 569 for (cmd = tidlist; *cmd != '\000' && !isalpha (*cmd); cmd++);
c906108c
SS
570
571 if (*cmd == '\000')
572 error ("Please specify a command following the thread ID list");
573
6ecce94d 574 old_chain = make_cleanup_restore_current_thread (inferior_pid);
c906108c 575
e35ce267
CF
576 /* Save a copy of the command in case it is clobbered by
577 execute_command */
5b616ba1 578 saved_cmd = xstrdup (cmd);
b8c9b27d 579 saved_cmd_cleanup_chain = make_cleanup (xfree, (void *) saved_cmd);
c906108c
SS
580 while (tidlist < cmd)
581 {
582 struct thread_info *tp;
583 int start, end;
584
585 start = strtol (tidlist, &p, 10);
586 if (p == tidlist)
587 error ("Error parsing %s", tidlist);
588 tidlist = p;
589
590 while (*tidlist == ' ' || *tidlist == '\t')
591 tidlist++;
592
593 if (*tidlist == '-') /* Got a range of IDs? */
594 {
c5aa993b 595 tidlist++; /* Skip the - */
c906108c
SS
596 end = strtol (tidlist, &p, 10);
597 if (p == tidlist)
598 error ("Error parsing %s", tidlist);
599 tidlist = p;
600
601 while (*tidlist == ' ' || *tidlist == '\t')
602 tidlist++;
603 }
604 else
605 end = start;
606
607 for (; start <= end; start++)
608 {
609 tp = find_thread_id (start);
610
611 if (!tp)
612 warning ("Unknown thread %d.", start);
613 else if (!thread_alive (tp))
614 warning ("Thread %d has terminated.", start);
615 else
616 {
617 switch_to_thread (tp->pid);
618#ifdef HPUXHPPA
619 printf_filtered ("\nThread %d (%s):\n", tp->num,
620 target_tid_to_str (inferior_pid));
621#else
622 printf_filtered ("\nThread %d (%s):\n", tp->num,
623 target_pid_to_str (inferior_pid));
624#endif
625 execute_command (cmd, from_tty);
e35ce267 626 strcpy (cmd, saved_cmd); /* Restore exact command used previously */
c906108c
SS
627 }
628 }
629 }
6ecce94d 630
e35ce267 631 do_cleanups (saved_cmd_cleanup_chain);
6ecce94d 632 do_cleanups (old_chain);
c906108c
SS
633}
634
635/* Switch to the specified thread. Will dispatch off to thread_apply_command
636 if prefix of arg is `apply'. */
637
638static void
fba45db2 639thread_command (char *tidstr, int from_tty)
c906108c 640{
c906108c
SS
641 if (!tidstr)
642 {
643 /* Don't generate an error, just say which thread is current. */
644 if (target_has_stack)
645 printf_filtered ("[Current thread is %d (%s)]\n",
c5aa993b 646 pid_to_thread_id (inferior_pid),
c906108c 647#if defined(HPUXHPPA)
c5aa993b 648 target_tid_to_str (inferior_pid)
c906108c 649#else
c5aa993b 650 target_pid_to_str (inferior_pid)
c906108c 651#endif
c5aa993b 652 );
c906108c
SS
653 else
654 error ("No stack.");
655 return;
656 }
c5394b80
JM
657
658 gdb_thread_select (tidstr);
659}
660
661static int
662do_captured_thread_select (void *tidstr)
663{
664 int num;
665 struct thread_info *tp;
666
667 num = atoi ((char *)tidstr);
c906108c
SS
668
669 tp = find_thread_id (num);
670
8b93c638
JM
671#ifdef UI_OUT
672 if (!tp)
673 error ("Thread ID %d not known.", num);
674#else
c906108c
SS
675 if (!tp)
676 error ("Thread ID %d not known. Use the \"info threads\" command to\n\
677see the IDs of currently known threads.", num);
8b93c638 678#endif
c906108c
SS
679
680 if (!thread_alive (tp))
681 error ("Thread ID %d has terminated.\n", num);
682
683 switch_to_thread (tp->pid);
684
8b93c638
JM
685#ifdef UI_OUT
686 ui_out_text (uiout, "[Switching to thread ");
687 ui_out_field_int (uiout, "new-thread-id", pid_to_thread_id (inferior_pid));
688 ui_out_text (uiout, " (");
689#if defined(HPUXHPPA)
690 ui_out_text (uiout, target_tid_to_str (inferior_pid));
691#else
692 ui_out_text (uiout, target_pid_to_str (inferior_pid));
693#endif
694 ui_out_text (uiout, ")]");
695#else /* UI_OUT */
c906108c
SS
696 printf_filtered ("[Switching to thread %d (%s)]\n",
697 pid_to_thread_id (inferior_pid),
698#if defined(HPUXHPPA)
699 target_tid_to_str (inferior_pid)
700#else
701 target_pid_to_str (inferior_pid)
702#endif
c5aa993b 703 );
8b93c638 704#endif /* UI_OUT */
c5394b80 705
c906108c 706 print_stack_frame (selected_frame, selected_frame_level, 1);
c5394b80
JM
707 return GDB_RC_OK;
708}
709
710enum gdb_rc
711gdb_thread_select (char *tidstr)
712{
713 return catch_errors (do_captured_thread_select, tidstr,
714 NULL, RETURN_MASK_ALL);
c906108c
SS
715}
716
717/* Commands with a prefix of `thread'. */
718struct cmd_list_element *thread_cmd_list = NULL;
719
720void
fba45db2 721_initialize_thread (void)
c906108c
SS
722{
723 static struct cmd_list_element *thread_apply_list = NULL;
c906108c
SS
724
725 add_info ("threads", info_threads_command,
726 "IDs of currently known threads.");
727
728 add_prefix_cmd ("thread", class_run, thread_command,
729 "Use this command to switch between threads.\n\
730The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1,
731 &cmdlist);
732
733 add_prefix_cmd ("apply", class_run, thread_apply_command,
734 "Apply a command to a list of threads.",
735 &thread_apply_list, "apply ", 1, &thread_cmd_list);
736
737 add_cmd ("all", class_run, thread_apply_all_command,
738 "Apply a command to all threads.",
739 &thread_apply_list);
740
741 if (!xdb_commands)
742 add_com_alias ("t", "thread", class_run, 1);
743}