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