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