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