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