Fri Aug 2 15:53:50 2002 Andrew Cagney <cagney@redhat.com>
[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
f8e42d24 265 ui_out_tuple_begin (uiout, "thread-ids");
8b93c638
JM
266
267 for (tp = thread_list; tp; tp = tp->next)
268 {
269 num++;
270 ui_out_field_int (uiout, "thread-id", tp->num);
271 }
272
f8e42d24 273 ui_out_tuple_end (uiout);
8b93c638
JM
274 ui_out_field_int (uiout, "number-of-threads", num);
275 return GDB_RC_OK;
276}
277
278/* Official gdblib interface function to get a list of thread ids and
279 the total number. */
280enum gdb_rc
2b65245e 281gdb_list_thread_ids (struct ui_out *uiout)
8b93c638 282{
2b65245e
AC
283 return catch_exceptions (uiout, do_captured_list_thread_ids, NULL,
284 NULL, RETURN_MASK_ALL);
8b93c638 285}
c906108c
SS
286
287/* Load infrun state for the thread PID. */
288
c5aa993b 289void
6c0d3f6a
MS
290load_infrun_state (ptid_t ptid,
291 CORE_ADDR *prev_pc,
292 CORE_ADDR *prev_func_start,
293 char **prev_func_name,
294 int *trap_expected,
fba45db2
KB
295 struct breakpoint **step_resume_breakpoint,
296 struct breakpoint **through_sigtramp_breakpoint,
6c0d3f6a
MS
297 CORE_ADDR *step_range_start,
298 CORE_ADDR *step_range_end,
299 CORE_ADDR *step_frame_address,
300 int *handling_longjmp,
301 int *another_trap,
302 int *stepping_through_solib_after_catch,
fba45db2 303 bpstat *stepping_through_solib_catchpoints,
6c0d3f6a
MS
304 int *stepping_through_sigtramp,
305 int *current_line,
306 struct symtab **current_symtab,
307 CORE_ADDR *step_sp)
c906108c
SS
308{
309 struct thread_info *tp;
310
311 /* If we can't find the thread, then we're debugging a single threaded
312 process. No need to do anything in that case. */
39f77062 313 tp = find_thread_id (pid_to_thread_id (ptid));
c906108c
SS
314 if (tp == NULL)
315 return;
316
317 *prev_pc = tp->prev_pc;
318 *prev_func_start = tp->prev_func_start;
319 *prev_func_name = tp->prev_func_name;
6c0d3f6a 320 *trap_expected = tp->trap_expected;
c906108c 321 *step_resume_breakpoint = tp->step_resume_breakpoint;
6c0d3f6a 322 *through_sigtramp_breakpoint = tp->through_sigtramp_breakpoint;
c906108c
SS
323 *step_range_start = tp->step_range_start;
324 *step_range_end = tp->step_range_end;
325 *step_frame_address = tp->step_frame_address;
c906108c 326 *handling_longjmp = tp->handling_longjmp;
c906108c
SS
327 *another_trap = tp->another_trap;
328 *stepping_through_solib_after_catch = tp->stepping_through_solib_after_catch;
329 *stepping_through_solib_catchpoints = tp->stepping_through_solib_catchpoints;
330 *stepping_through_sigtramp = tp->stepping_through_sigtramp;
6c0d3f6a
MS
331 *current_line = tp->current_line;
332 *current_symtab = tp->current_symtab;
333 *step_sp = tp->step_sp;
c906108c
SS
334}
335
336/* Save infrun state for the thread PID. */
337
c5aa993b 338void
6c0d3f6a
MS
339save_infrun_state (ptid_t ptid,
340 CORE_ADDR prev_pc,
341 CORE_ADDR prev_func_start,
342 char *prev_func_name,
343 int trap_expected,
fba45db2
KB
344 struct breakpoint *step_resume_breakpoint,
345 struct breakpoint *through_sigtramp_breakpoint,
6c0d3f6a
MS
346 CORE_ADDR step_range_start,
347 CORE_ADDR step_range_end,
348 CORE_ADDR step_frame_address,
349 int handling_longjmp,
350 int another_trap,
351 int stepping_through_solib_after_catch,
fba45db2 352 bpstat stepping_through_solib_catchpoints,
6c0d3f6a
MS
353 int stepping_through_sigtramp,
354 int current_line,
355 struct symtab *current_symtab,
356 CORE_ADDR step_sp)
c906108c
SS
357{
358 struct thread_info *tp;
359
360 /* If we can't find the thread, then we're debugging a single-threaded
361 process. Nothing to do in that case. */
39f77062 362 tp = find_thread_id (pid_to_thread_id (ptid));
c906108c
SS
363 if (tp == NULL)
364 return;
365
366 tp->prev_pc = prev_pc;
367 tp->prev_func_start = prev_func_start;
368 tp->prev_func_name = prev_func_name;
6c0d3f6a 369 tp->trap_expected = trap_expected;
c906108c 370 tp->step_resume_breakpoint = step_resume_breakpoint;
6c0d3f6a 371 tp->through_sigtramp_breakpoint = through_sigtramp_breakpoint;
c906108c
SS
372 tp->step_range_start = step_range_start;
373 tp->step_range_end = step_range_end;
374 tp->step_frame_address = step_frame_address;
c906108c 375 tp->handling_longjmp = handling_longjmp;
c906108c
SS
376 tp->another_trap = another_trap;
377 tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
378 tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;
379 tp->stepping_through_sigtramp = stepping_through_sigtramp;
6c0d3f6a
MS
380 tp->current_line = current_line;
381 tp->current_symtab = current_symtab;
382 tp->step_sp = step_sp;
c906108c
SS
383}
384
385/* Return true if TP is an active thread. */
386static int
fba45db2 387thread_alive (struct thread_info *tp)
c906108c 388{
39f77062 389 if (PIDGET (tp->ptid) == -1)
c906108c 390 return 0;
39f77062 391 if (!target_thread_alive (tp->ptid))
c906108c 392 {
39f77062 393 tp->ptid = pid_to_ptid (-1); /* Mark it as dead */
c906108c
SS
394 return 0;
395 }
396 return 1;
397}
398
399static void
fba45db2 400prune_threads (void)
c906108c 401{
d4f3574e 402 struct thread_info *tp, *next;
c906108c 403
c906108c
SS
404 for (tp = thread_list; tp; tp = next)
405 {
406 next = tp->next;
407 if (!thread_alive (tp))
39f77062 408 delete_thread (tp->ptid);
c906108c
SS
409 }
410}
411
412/* Print information about currently known threads
c5aa993b 413
c906108c
SS
414 * Note: this has the drawback that it _really_ switches
415 * threads, which frees the frame cache. A no-side
416 * effects info-threads command would be nicer.
417 */
418
419static void
fba45db2 420info_threads_command (char *arg, int from_tty)
c906108c
SS
421{
422 struct thread_info *tp;
39f77062 423 ptid_t current_ptid;
c5aa993b 424 struct frame_info *cur_frame;
b31da25e 425 int saved_frame_level = frame_relative_level (selected_frame);
c5aa993b 426 int counter;
0d06e24b 427 char *extra_info;
c906108c
SS
428
429 /* Avoid coredumps which would happen if we tried to access a NULL
430 selected_frame. */
c5aa993b
JM
431 if (!target_has_stack)
432 error ("No stack.");
c906108c
SS
433
434 prune_threads ();
b83266a0 435 target_find_new_threads ();
39f77062 436 current_ptid = inferior_ptid;
c906108c
SS
437 for (tp = thread_list; tp; tp = tp->next)
438 {
39f77062 439 if (ptid_equal (tp->ptid, current_ptid))
c906108c
SS
440 printf_filtered ("* ");
441 else
442 printf_filtered (" ");
443
444#ifdef HPUXHPPA
39f77062 445 printf_filtered ("%d %s", tp->num, target_tid_to_str (tp->ptid));
c906108c 446#else
39f77062 447 printf_filtered ("%d %s", tp->num, target_pid_to_str (tp->ptid));
c906108c 448#endif
0d06e24b
JM
449
450 extra_info = target_extra_thread_info (tp);
451 if (extra_info)
452 printf_filtered (" (%s)", extra_info);
453 puts_filtered (" ");
454
39f77062 455 switch_to_thread (tp->ptid);
c906108c
SS
456 if (selected_frame)
457 print_only_stack_frame (selected_frame, -1, 0);
458 else
459 printf_filtered ("[No stack.]\n");
460 }
461
39f77062 462 switch_to_thread (current_ptid);
c906108c
SS
463
464 /* Code below copied from "up_silently_base" in "stack.c".
465 * It restores the frame set by the user before the "info threads"
466 * command. We have finished the info-threads display by switching
467 * back to the current thread. That switch has put us at the top
468 * of the stack (leaf frame).
469 */
c5aa993b
JM
470 counter = saved_frame_level;
471 cur_frame = find_relative_frame (selected_frame, &counter);
c906108c
SS
472 if (counter != 0)
473 {
474 /* Ooops, can't restore, tell user where we are. */
475 warning ("Couldn't restore frame in current thread, at frame 0");
476 print_stack_frame (selected_frame, -1, 0);
477 }
478 else
479 {
0f7d239c 480 select_frame (cur_frame);
c906108c
SS
481 }
482
483 /* re-show current frame. */
c5aa993b 484 show_stack_frame (cur_frame);
c906108c
SS
485}
486
487/* Switch from one thread to another. */
488
489static void
39f77062 490switch_to_thread (ptid_t ptid)
c906108c 491{
39f77062 492 if (ptid_equal (ptid, inferior_ptid))
c906108c
SS
493 return;
494
39f77062 495 inferior_ptid = ptid;
c906108c
SS
496 flush_cached_frames ();
497 registers_changed ();
c5aa993b 498 stop_pc = read_pc ();
0f7d239c 499 select_frame (get_current_frame ());
c906108c
SS
500}
501
502static void
39f77062 503restore_current_thread (ptid_t ptid)
c906108c 504{
39f77062 505 if (! ptid_equal (ptid, inferior_ptid))
c906108c 506 {
39f77062 507 switch_to_thread (ptid);
c5aa993b 508 print_stack_frame (get_current_frame (), 0, -1);
c906108c
SS
509 }
510}
511
6ecce94d
AC
512struct current_thread_cleanup
513{
39f77062 514 ptid_t inferior_ptid;
6ecce94d
AC
515};
516
517static void
518do_restore_current_thread_cleanup (void *arg)
519{
520 struct current_thread_cleanup *old = arg;
39f77062 521 restore_current_thread (old->inferior_ptid);
b8c9b27d 522 xfree (old);
6ecce94d
AC
523}
524
525static struct cleanup *
39f77062 526make_cleanup_restore_current_thread (ptid_t inferior_ptid)
6ecce94d
AC
527{
528 struct current_thread_cleanup *old
529 = xmalloc (sizeof (struct current_thread_cleanup));
39f77062 530 old->inferior_ptid = inferior_ptid;
6ecce94d
AC
531 return make_cleanup (do_restore_current_thread_cleanup, old);
532}
533
c906108c
SS
534/* Apply a GDB command to a list of threads. List syntax is a whitespace
535 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist
536 of two numbers seperated by a hyphen. Examples:
537
c5aa993b
JM
538 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4
539 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9
540 thread apply all p x/i $pc Apply x/i $pc cmd to all threads
541 */
c906108c
SS
542
543static void
fba45db2 544thread_apply_all_command (char *cmd, int from_tty)
c906108c
SS
545{
546 struct thread_info *tp;
547 struct cleanup *old_chain;
e35ce267
CF
548 struct cleanup *saved_cmd_cleanup_chain;
549 char *saved_cmd;
c906108c
SS
550
551 if (cmd == NULL || *cmd == '\000')
552 error ("Please specify a command following the thread ID list");
553
39f77062 554 old_chain = make_cleanup_restore_current_thread (inferior_ptid);
c906108c 555
e9d196c5
MS
556 /* It is safe to update the thread list now, before
557 traversing it for "thread apply all". MVS */
558 target_find_new_threads ();
559
e35ce267
CF
560 /* Save a copy of the command in case it is clobbered by
561 execute_command */
5b616ba1 562 saved_cmd = xstrdup (cmd);
b8c9b27d 563 saved_cmd_cleanup_chain = make_cleanup (xfree, (void *) saved_cmd);
c906108c
SS
564 for (tp = thread_list; tp; tp = tp->next)
565 if (thread_alive (tp))
566 {
39f77062 567 switch_to_thread (tp->ptid);
c906108c
SS
568#ifdef HPUXHPPA
569 printf_filtered ("\nThread %d (%s):\n",
570 tp->num,
39f77062 571 target_tid_to_str (inferior_ptid));
c906108c
SS
572#else
573 printf_filtered ("\nThread %d (%s):\n", tp->num,
39f77062 574 target_pid_to_str (inferior_ptid));
c906108c
SS
575#endif
576 execute_command (cmd, from_tty);
e35ce267 577 strcpy (cmd, saved_cmd); /* Restore exact command used previously */
c906108c 578 }
6ecce94d 579
e35ce267 580 do_cleanups (saved_cmd_cleanup_chain);
6ecce94d 581 do_cleanups (old_chain);
c906108c
SS
582}
583
584static void
fba45db2 585thread_apply_command (char *tidlist, int from_tty)
c906108c
SS
586{
587 char *cmd;
588 char *p;
589 struct cleanup *old_chain;
e35ce267
CF
590 struct cleanup *saved_cmd_cleanup_chain;
591 char *saved_cmd;
c906108c
SS
592
593 if (tidlist == NULL || *tidlist == '\000')
594 error ("Please specify a thread ID list");
595
c5aa993b 596 for (cmd = tidlist; *cmd != '\000' && !isalpha (*cmd); cmd++);
c906108c
SS
597
598 if (*cmd == '\000')
599 error ("Please specify a command following the thread ID list");
600
39f77062 601 old_chain = make_cleanup_restore_current_thread (inferior_ptid);
c906108c 602
e35ce267
CF
603 /* Save a copy of the command in case it is clobbered by
604 execute_command */
5b616ba1 605 saved_cmd = xstrdup (cmd);
b8c9b27d 606 saved_cmd_cleanup_chain = make_cleanup (xfree, (void *) saved_cmd);
c906108c
SS
607 while (tidlist < cmd)
608 {
609 struct thread_info *tp;
610 int start, end;
611
612 start = strtol (tidlist, &p, 10);
613 if (p == tidlist)
614 error ("Error parsing %s", tidlist);
615 tidlist = p;
616
617 while (*tidlist == ' ' || *tidlist == '\t')
618 tidlist++;
619
620 if (*tidlist == '-') /* Got a range of IDs? */
621 {
c5aa993b 622 tidlist++; /* Skip the - */
c906108c
SS
623 end = strtol (tidlist, &p, 10);
624 if (p == tidlist)
625 error ("Error parsing %s", tidlist);
626 tidlist = p;
627
628 while (*tidlist == ' ' || *tidlist == '\t')
629 tidlist++;
630 }
631 else
632 end = start;
633
634 for (; start <= end; start++)
635 {
636 tp = find_thread_id (start);
637
638 if (!tp)
639 warning ("Unknown thread %d.", start);
640 else if (!thread_alive (tp))
641 warning ("Thread %d has terminated.", start);
642 else
643 {
39f77062 644 switch_to_thread (tp->ptid);
c906108c
SS
645#ifdef HPUXHPPA
646 printf_filtered ("\nThread %d (%s):\n", tp->num,
39f77062 647 target_tid_to_str (inferior_ptid));
c906108c
SS
648#else
649 printf_filtered ("\nThread %d (%s):\n", tp->num,
39f77062 650 target_pid_to_str (inferior_ptid));
c906108c
SS
651#endif
652 execute_command (cmd, from_tty);
e35ce267 653 strcpy (cmd, saved_cmd); /* Restore exact command used previously */
c906108c
SS
654 }
655 }
656 }
6ecce94d 657
e35ce267 658 do_cleanups (saved_cmd_cleanup_chain);
6ecce94d 659 do_cleanups (old_chain);
c906108c
SS
660}
661
662/* Switch to the specified thread. Will dispatch off to thread_apply_command
663 if prefix of arg is `apply'. */
664
665static void
fba45db2 666thread_command (char *tidstr, int from_tty)
c906108c 667{
c906108c
SS
668 if (!tidstr)
669 {
670 /* Don't generate an error, just say which thread is current. */
671 if (target_has_stack)
672 printf_filtered ("[Current thread is %d (%s)]\n",
39f77062 673 pid_to_thread_id (inferior_ptid),
c906108c 674#if defined(HPUXHPPA)
39f77062 675 target_tid_to_str (inferior_ptid)
c906108c 676#else
39f77062 677 target_pid_to_str (inferior_ptid)
c906108c 678#endif
c5aa993b 679 );
c906108c
SS
680 else
681 error ("No stack.");
682 return;
683 }
c5394b80 684
2b65245e 685 gdb_thread_select (uiout, tidstr);
c5394b80
JM
686}
687
688static int
2b65245e
AC
689do_captured_thread_select (struct ui_out *uiout,
690 void *tidstr)
c5394b80
JM
691{
692 int num;
693 struct thread_info *tp;
694
81490ea1 695 num = value_as_long (parse_and_eval (tidstr));
c906108c
SS
696
697 tp = find_thread_id (num);
698
8b93c638
JM
699 if (!tp)
700 error ("Thread ID %d not known.", num);
c906108c
SS
701
702 if (!thread_alive (tp))
703 error ("Thread ID %d has terminated.\n", num);
704
39f77062 705 switch_to_thread (tp->ptid);
c906108c 706
8b93c638 707 ui_out_text (uiout, "[Switching to thread ");
39f77062 708 ui_out_field_int (uiout, "new-thread-id", pid_to_thread_id (inferior_ptid));
8b93c638
JM
709 ui_out_text (uiout, " (");
710#if defined(HPUXHPPA)
39f77062 711 ui_out_text (uiout, target_tid_to_str (inferior_ptid));
8b93c638 712#else
39f77062 713 ui_out_text (uiout, target_pid_to_str (inferior_ptid));
8b93c638
JM
714#endif
715 ui_out_text (uiout, ")]");
c5394b80 716
b31da25e 717 print_stack_frame (selected_frame, frame_relative_level (selected_frame), 1);
c5394b80
JM
718 return GDB_RC_OK;
719}
720
721enum gdb_rc
2b65245e
AC
722gdb_thread_select (struct ui_out *uiout,
723 char *tidstr)
c5394b80 724{
2b65245e
AC
725 return catch_exceptions (uiout, do_captured_thread_select, tidstr,
726 NULL, RETURN_MASK_ALL);
c906108c
SS
727}
728
729/* Commands with a prefix of `thread'. */
730struct cmd_list_element *thread_cmd_list = NULL;
731
732void
fba45db2 733_initialize_thread (void)
c906108c
SS
734{
735 static struct cmd_list_element *thread_apply_list = NULL;
c906108c
SS
736
737 add_info ("threads", info_threads_command,
738 "IDs of currently known threads.");
739
740 add_prefix_cmd ("thread", class_run, thread_command,
741 "Use this command to switch between threads.\n\
742The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1,
743 &cmdlist);
744
745 add_prefix_cmd ("apply", class_run, thread_apply_command,
746 "Apply a command to a list of threads.",
747 &thread_apply_list, "apply ", 1, &thread_cmd_list);
748
749 add_cmd ("all", class_run, thread_apply_all_command,
750 "Apply a command to all threads.",
751 &thread_apply_list);
752
753 if (!xdb_commands)
754 add_com_alias ("t", "thread", class_run, 1);
755}
This page took 0.353207 seconds and 4 git commands to generate.