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