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