OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [thread.c] - Blame information for rev 311

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* Multi-process/thread control for GDB, the GNU debugger.
2
 
3
   Copyright (C) 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4
   2000, 2001, 2002, 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
5
 
6
   Contributed by Lynx Real-Time Systems, Inc.  Los Gatos, CA.
7
 
8
   This file is part of GDB.
9
 
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 3 of the License, or
13
   (at your option) any later version.
14
 
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.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
#include "defs.h"
24
#include "symtab.h"
25
#include "frame.h"
26
#include "inferior.h"
27
#include "environ.h"
28
#include "value.h"
29
#include "target.h"
30
#include "gdbthread.h"
31
#include "exceptions.h"
32
#include "command.h"
33
#include "gdbcmd.h"
34
#include "regcache.h"
35
#include "gdb.h"
36
#include "gdb_string.h"
37
 
38
#include <ctype.h>
39
#include <sys/types.h>
40
#include <signal.h>
41
#include "ui-out.h"
42
 
43
/* Definition of struct thread_info exported to gdbthread.h */
44
 
45
/* Prototypes for exported functions. */
46
 
47
void _initialize_thread (void);
48
 
49
/* Prototypes for local functions. */
50
 
51
static struct thread_info *thread_list = NULL;
52
static int highest_thread_num;
53
 
54
static struct thread_info *find_thread_id (int num);
55
 
56
static void thread_command (char *tidstr, int from_tty);
57
static void thread_apply_all_command (char *, int);
58
static int thread_alive (struct thread_info *);
59
static void info_threads_command (char *, int);
60
static void thread_apply_command (char *, int);
61
static void restore_current_thread (ptid_t);
62
static void prune_threads (void);
63
static struct cleanup *make_cleanup_restore_current_thread (ptid_t,
64
                                                            struct frame_id);
65
 
66
void
67
delete_step_resume_breakpoint (void *arg)
68
{
69
  struct breakpoint **breakpointp = (struct breakpoint **) arg;
70
  struct thread_info *tp;
71
 
72
  if (*breakpointp != NULL)
73
    {
74
      delete_breakpoint (*breakpointp);
75
      for (tp = thread_list; tp; tp = tp->next)
76
        if (tp->step_resume_breakpoint == *breakpointp)
77
          tp->step_resume_breakpoint = NULL;
78
 
79
      *breakpointp = NULL;
80
    }
81
}
82
 
83
static void
84
free_thread (struct thread_info *tp)
85
{
86
  /* NOTE: this will take care of any left-over step_resume breakpoints,
87
     but not any user-specified thread-specific breakpoints.  We can not
88
     delete the breakpoint straight-off, because the inferior might not
89
     be stopped at the moment.  */
90
  if (tp->step_resume_breakpoint)
91
    tp->step_resume_breakpoint->disposition = disp_del_at_next_stop;
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)
96
    xfree (tp->private);
97
 
98
  xfree (tp);
99
}
100
 
101
void
102
init_thread_list (void)
103
{
104
  struct thread_info *tp, *tpnext;
105
 
106
  highest_thread_num = 0;
107
  if (!thread_list)
108
    return;
109
 
110
  for (tp = thread_list; tp; tp = tpnext)
111
    {
112
      tpnext = tp->next;
113
      free_thread (tp);
114
    }
115
 
116
  thread_list = NULL;
117
}
118
 
119
struct thread_info *
120
add_thread_silent (ptid_t ptid)
121
{
122
  struct thread_info *tp;
123
 
124
  tp = (struct thread_info *) xmalloc (sizeof (*tp));
125
  memset (tp, 0, sizeof (*tp));
126
  tp->ptid = ptid;
127
  tp->num = ++highest_thread_num;
128
  tp->next = thread_list;
129
  thread_list = tp;
130
  return tp;
131
}
132
 
133
struct thread_info *
134
add_thread (ptid_t ptid)
135
{
136
  struct thread_info *result = add_thread_silent (ptid);
137
 
138
  if (print_thread_events)
139
    printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
140
 
141
  return result;
142
}
143
 
144
void
145
delete_thread (ptid_t ptid)
146
{
147
  struct thread_info *tp, *tpprev;
148
 
149
  tpprev = NULL;
150
 
151
  for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
152
    if (ptid_equal (tp->ptid, ptid))
153
      break;
154
 
155
  if (!tp)
156
    return;
157
 
158
  if (tpprev)
159
    tpprev->next = tp->next;
160
  else
161
    thread_list = tp->next;
162
 
163
  free_thread (tp);
164
}
165
 
166
static struct thread_info *
167
find_thread_id (int num)
168
{
169
  struct thread_info *tp;
170
 
171
  for (tp = thread_list; tp; tp = tp->next)
172
    if (tp->num == num)
173
      return tp;
174
 
175
  return NULL;
176
}
177
 
178
/* Find a thread_info by matching PTID.  */
179
struct thread_info *
180
find_thread_pid (ptid_t ptid)
181
{
182
  struct thread_info *tp;
183
 
184
  for (tp = thread_list; tp; tp = tp->next)
185
    if (ptid_equal (tp->ptid, ptid))
186
      return tp;
187
 
188
  return NULL;
189
}
190
 
191
/*
192
 * Thread iterator function.
193
 *
194
 * Calls a callback function once for each thread, so long as
195
 * the callback function returns false.  If the callback function
196
 * returns true, the iteration will end and the current thread
197
 * will be returned.  This can be useful for implementing a
198
 * search for a thread with arbitrary attributes, or for applying
199
 * some operation to every thread.
200
 *
201
 * FIXME: some of the existing functionality, such as
202
 * "Thread apply all", might be rewritten using this functionality.
203
 */
204
 
205
struct thread_info *
206
iterate_over_threads (int (*callback) (struct thread_info *, void *),
207
                      void *data)
208
{
209
  struct thread_info *tp;
210
 
211
  for (tp = thread_list; tp; tp = tp->next)
212
    if ((*callback) (tp, data))
213
      return tp;
214
 
215
  return NULL;
216
}
217
 
218
int
219
valid_thread_id (int num)
220
{
221
  struct thread_info *tp;
222
 
223
  for (tp = thread_list; tp; tp = tp->next)
224
    if (tp->num == num)
225
      return 1;
226
 
227
  return 0;
228
}
229
 
230
int
231
pid_to_thread_id (ptid_t ptid)
232
{
233
  struct thread_info *tp;
234
 
235
  for (tp = thread_list; tp; tp = tp->next)
236
    if (ptid_equal (tp->ptid, ptid))
237
      return tp->num;
238
 
239
  return 0;
240
}
241
 
242
ptid_t
243
thread_id_to_pid (int num)
244
{
245
  struct thread_info *thread = find_thread_id (num);
246
  if (thread)
247
    return thread->ptid;
248
  else
249
    return pid_to_ptid (-1);
250
}
251
 
252
int
253
in_thread_list (ptid_t ptid)
254
{
255
  struct thread_info *tp;
256
 
257
  for (tp = thread_list; tp; tp = tp->next)
258
    if (ptid_equal (tp->ptid, ptid))
259
      return 1;
260
 
261
  return 0;                      /* Never heard of 'im */
262
}
263
 
264
/* Print a list of thread ids currently known, and the total number of
265
   threads. To be used from within catch_errors. */
266
static int
267
do_captured_list_thread_ids (struct ui_out *uiout, void *arg)
268
{
269
  struct thread_info *tp;
270
  int num = 0;
271
  struct cleanup *cleanup_chain;
272
 
273
  prune_threads ();
274
  target_find_new_threads ();
275
 
276
  cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "thread-ids");
277
 
278
  for (tp = thread_list; tp; tp = tp->next)
279
    {
280
      num++;
281
      ui_out_field_int (uiout, "thread-id", tp->num);
282
    }
283
 
284
  do_cleanups (cleanup_chain);
285
  ui_out_field_int (uiout, "number-of-threads", num);
286
  return GDB_RC_OK;
287
}
288
 
289
/* Official gdblib interface function to get a list of thread ids and
290
   the total number. */
291
enum gdb_rc
292
gdb_list_thread_ids (struct ui_out *uiout, char **error_message)
293
{
294
  if (catch_exceptions_with_msg (uiout, do_captured_list_thread_ids, NULL,
295
                                 error_message, RETURN_MASK_ALL) < 0)
296
    return GDB_RC_FAIL;
297
  return GDB_RC_OK;
298
}
299
 
300
/* Load infrun state for the thread PID.  */
301
 
302
void
303
load_infrun_state (ptid_t ptid,
304
                   CORE_ADDR *prev_pc,
305
                   int *trap_expected,
306
                   struct breakpoint **step_resume_breakpoint,
307
                   CORE_ADDR *step_range_start,
308
                   CORE_ADDR *step_range_end,
309
                   struct frame_id *step_frame_id,
310
                   int *handling_longjmp,
311
                   int *stepping_over_breakpoint,
312
                   int *stepping_through_solib_after_catch,
313
                   bpstat *stepping_through_solib_catchpoints,
314
                   int *current_line,
315
                   struct symtab **current_symtab)
316
{
317
  struct thread_info *tp;
318
 
319
  /* If we can't find the thread, then we're debugging a single threaded
320
     process.  No need to do anything in that case.  */
321
  tp = find_thread_id (pid_to_thread_id (ptid));
322
  if (tp == NULL)
323
    return;
324
 
325
  *prev_pc = tp->prev_pc;
326
  *trap_expected = tp->trap_expected;
327
  *step_resume_breakpoint = tp->step_resume_breakpoint;
328
  *step_range_start = tp->step_range_start;
329
  *step_range_end = tp->step_range_end;
330
  *step_frame_id = tp->step_frame_id;
331
  *handling_longjmp = tp->handling_longjmp;
332
  *stepping_over_breakpoint = tp->stepping_over_breakpoint;
333
  *stepping_through_solib_after_catch =
334
    tp->stepping_through_solib_after_catch;
335
  *stepping_through_solib_catchpoints =
336
    tp->stepping_through_solib_catchpoints;
337
  *current_line = tp->current_line;
338
  *current_symtab = tp->current_symtab;
339
}
340
 
341
/* Save infrun state for the thread PID.  */
342
 
343
void
344
save_infrun_state (ptid_t ptid,
345
                   CORE_ADDR prev_pc,
346
                   int trap_expected,
347
                   struct breakpoint *step_resume_breakpoint,
348
                   CORE_ADDR step_range_start,
349
                   CORE_ADDR step_range_end,
350
                   const struct frame_id *step_frame_id,
351
                   int handling_longjmp,
352
                   int stepping_over_breakpoint,
353
                   int stepping_through_solib_after_catch,
354
                   bpstat stepping_through_solib_catchpoints,
355
                   int current_line,
356
                   struct symtab *current_symtab)
357
{
358
  struct thread_info *tp;
359
 
360
  /* If we can't find the thread, then we're debugging a single-threaded
361
     process.  Nothing to do in that case.  */
362
  tp = find_thread_id (pid_to_thread_id (ptid));
363
  if (tp == NULL)
364
    return;
365
 
366
  tp->prev_pc = prev_pc;
367
  tp->trap_expected = trap_expected;
368
  tp->step_resume_breakpoint = step_resume_breakpoint;
369
  tp->step_range_start = step_range_start;
370
  tp->step_range_end = step_range_end;
371
  tp->step_frame_id = (*step_frame_id);
372
  tp->handling_longjmp = handling_longjmp;
373
  tp->stepping_over_breakpoint = stepping_over_breakpoint;
374
  tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
375
  tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;
376
  tp->current_line = current_line;
377
  tp->current_symtab = current_symtab;
378
}
379
 
380
/* Return true if TP is an active thread. */
381
static int
382
thread_alive (struct thread_info *tp)
383
{
384
  if (PIDGET (tp->ptid) == -1)
385
    return 0;
386
  if (!target_thread_alive (tp->ptid))
387
    {
388
      tp->ptid = pid_to_ptid (-1);      /* Mark it as dead */
389
      return 0;
390
    }
391
  return 1;
392
}
393
 
394
static void
395
prune_threads (void)
396
{
397
  struct thread_info *tp, *next;
398
 
399
  for (tp = thread_list; tp; tp = next)
400
    {
401
      next = tp->next;
402
      if (!thread_alive (tp))
403
        delete_thread (tp->ptid);
404
    }
405
}
406
 
407
/* Print information about currently known threads
408
 
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
 
414
static void
415
info_threads_command (char *arg, int from_tty)
416
{
417
  struct thread_info *tp;
418
  ptid_t current_ptid;
419
  struct frame_info *cur_frame;
420
  struct cleanup *old_chain;
421
  struct frame_id saved_frame_id;
422
  char *extra_info;
423
 
424
  /* Backup current thread and selected frame.  */
425
  saved_frame_id = get_frame_id (get_selected_frame (NULL));
426
  old_chain = make_cleanup_restore_current_thread (inferior_ptid, saved_frame_id);
427
 
428
  prune_threads ();
429
  target_find_new_threads ();
430
  current_ptid = inferior_ptid;
431
  for (tp = thread_list; tp; tp = tp->next)
432
    {
433
      if (ptid_equal (tp->ptid, current_ptid))
434
        printf_filtered ("* ");
435
      else
436
        printf_filtered ("  ");
437
 
438
      printf_filtered ("%d %s", tp->num, target_tid_to_str (tp->ptid));
439
 
440
      extra_info = target_extra_thread_info (tp);
441
      if (extra_info)
442
        printf_filtered (" (%s)", extra_info);
443
      puts_filtered ("  ");
444
      /* That switch put us at the top of the stack (leaf frame).  */
445
      switch_to_thread (tp->ptid);
446
      print_stack_frame (get_selected_frame (NULL), 0, LOCATION);
447
    }
448
 
449
  /* Restores the current thread and the frame selected before
450
     the "info threads" command.  */
451
  do_cleanups (old_chain);
452
 
453
  /*  If case we were not able to find the original frame, print the
454
      new selected frame.  */
455
  if (frame_find_by_id (saved_frame_id) == NULL)
456
    {
457
      warning (_("Couldn't restore frame in current thread, at frame 0"));
458
      print_stack_frame (get_selected_frame (NULL), 0, LOCATION);
459
    }
460
}
461
 
462
/* Switch from one thread to another. */
463
 
464
void
465
switch_to_thread (ptid_t ptid)
466
{
467
  if (ptid_equal (ptid, inferior_ptid))
468
    return;
469
 
470
  inferior_ptid = ptid;
471
  reinit_frame_cache ();
472
  registers_changed ();
473
  stop_pc = read_pc ();
474
}
475
 
476
static void
477
restore_current_thread (ptid_t ptid)
478
{
479
  if (!ptid_equal (ptid, inferior_ptid))
480
    {
481
      switch_to_thread (ptid);
482
    }
483
}
484
 
485
static void
486
restore_selected_frame (struct frame_id a_frame_id)
487
{
488
  struct frame_info *selected_frame_info = NULL;
489
 
490
  if (frame_id_eq (a_frame_id, null_frame_id))
491
    return;
492
 
493
  if ((selected_frame_info = frame_find_by_id (a_frame_id)) != NULL)
494
    {
495
      select_frame (selected_frame_info);
496
    }
497
}
498
 
499
struct current_thread_cleanup
500
{
501
  ptid_t inferior_ptid;
502
  struct frame_id selected_frame_id;
503
};
504
 
505
static void
506
do_restore_current_thread_cleanup (void *arg)
507
{
508
  struct current_thread_cleanup *old = arg;
509
  restore_current_thread (old->inferior_ptid);
510
  restore_selected_frame (old->selected_frame_id);
511
  xfree (old);
512
}
513
 
514
static struct cleanup *
515
make_cleanup_restore_current_thread (ptid_t inferior_ptid,
516
                                     struct frame_id a_frame_id)
517
{
518
  struct current_thread_cleanup *old
519
    = xmalloc (sizeof (struct current_thread_cleanup));
520
  old->inferior_ptid = inferior_ptid;
521
  old->selected_frame_id = a_frame_id;
522
  return make_cleanup (do_restore_current_thread_cleanup, old);
523
}
524
 
525
/* Apply a GDB command to a list of threads.  List syntax is a whitespace
526
   seperated list of numbers, or ranges, or the keyword `all'.  Ranges consist
527
   of two numbers seperated by a hyphen.  Examples:
528
 
529
   thread apply 1 2 7 4 backtrace       Apply backtrace cmd to threads 1,2,7,4
530
   thread apply 2-7 9 p foo(1)  Apply p foo(1) cmd to threads 2->7 & 9
531
   thread apply all p x/i $pc   Apply x/i $pc cmd to all threads
532
 */
533
 
534
static void
535
thread_apply_all_command (char *cmd, int from_tty)
536
{
537
  struct thread_info *tp;
538
  struct cleanup *old_chain;
539
  struct cleanup *saved_cmd_cleanup_chain;
540
  char *saved_cmd;
541
  struct frame_id saved_frame_id;
542
  ptid_t current_ptid;
543
  int thread_has_changed = 0;
544
 
545
  if (cmd == NULL || *cmd == '\000')
546
    error (_("Please specify a command following the thread ID list"));
547
 
548
  current_ptid = inferior_ptid;
549
  saved_frame_id = get_frame_id (get_selected_frame (NULL));
550
  old_chain = make_cleanup_restore_current_thread (inferior_ptid, saved_frame_id);
551
 
552
  /* It is safe to update the thread list now, before
553
     traversing it for "thread apply all".  MVS */
554
  target_find_new_threads ();
555
 
556
  /* Save a copy of the command in case it is clobbered by
557
     execute_command */
558
  saved_cmd = xstrdup (cmd);
559
  saved_cmd_cleanup_chain = make_cleanup (xfree, (void *) saved_cmd);
560
  for (tp = thread_list; tp; tp = tp->next)
561
    if (thread_alive (tp))
562
      {
563
        switch_to_thread (tp->ptid);
564
        printf_filtered (_("\nThread %d (%s):\n"),
565
                         tp->num, target_tid_to_str (inferior_ptid));
566
        execute_command (cmd, from_tty);
567
        strcpy (cmd, saved_cmd);        /* Restore exact command used previously */
568
      }
569
 
570
  if (!ptid_equal (current_ptid, inferior_ptid))
571
    thread_has_changed = 1;
572
 
573
  do_cleanups (saved_cmd_cleanup_chain);
574
  do_cleanups (old_chain);
575
  /* Print stack frame only if we changed thread.  */
576
  if (thread_has_changed)
577
    print_stack_frame (get_current_frame (), 1, SRC_LINE);
578
 
579
}
580
 
581
static void
582
thread_apply_command (char *tidlist, int from_tty)
583
{
584
  char *cmd;
585
  char *p;
586
  struct cleanup *old_chain;
587
  struct cleanup *saved_cmd_cleanup_chain;
588
  char *saved_cmd;
589
  struct frame_id saved_frame_id;
590
  ptid_t current_ptid;
591
  int thread_has_changed = 0;
592
 
593
  if (tidlist == NULL || *tidlist == '\000')
594
    error (_("Please specify a thread ID list"));
595
 
596
  for (cmd = tidlist; *cmd != '\000' && !isalpha (*cmd); cmd++);
597
 
598
  if (*cmd == '\000')
599
    error (_("Please specify a command following the thread ID list"));
600
 
601
  current_ptid = inferior_ptid;
602
  saved_frame_id = get_frame_id (get_selected_frame (NULL));
603
  old_chain = make_cleanup_restore_current_thread (inferior_ptid, saved_frame_id);
604
 
605
  /* Save a copy of the command in case it is clobbered by
606
     execute_command */
607
  saved_cmd = xstrdup (cmd);
608
  saved_cmd_cleanup_chain = make_cleanup (xfree, (void *) saved_cmd);
609
  while (tidlist < cmd)
610
    {
611
      struct thread_info *tp;
612
      int start, end;
613
 
614
      start = strtol (tidlist, &p, 10);
615
      if (p == tidlist)
616
        error (_("Error parsing %s"), tidlist);
617
      tidlist = p;
618
 
619
      while (*tidlist == ' ' || *tidlist == '\t')
620
        tidlist++;
621
 
622
      if (*tidlist == '-')      /* Got a range of IDs? */
623
        {
624
          tidlist++;            /* Skip the - */
625
          end = strtol (tidlist, &p, 10);
626
          if (p == tidlist)
627
            error (_("Error parsing %s"), tidlist);
628
          tidlist = p;
629
 
630
          while (*tidlist == ' ' || *tidlist == '\t')
631
            tidlist++;
632
        }
633
      else
634
        end = start;
635
 
636
      for (; start <= end; start++)
637
        {
638
          tp = find_thread_id (start);
639
 
640
          if (!tp)
641
            warning (_("Unknown thread %d."), start);
642
          else if (!thread_alive (tp))
643
            warning (_("Thread %d has terminated."), start);
644
          else
645
            {
646
              switch_to_thread (tp->ptid);
647
              printf_filtered (_("\nThread %d (%s):\n"), tp->num,
648
                               target_tid_to_str (inferior_ptid));
649
              execute_command (cmd, from_tty);
650
              strcpy (cmd, saved_cmd);  /* Restore exact command used previously */
651
            }
652
        }
653
    }
654
 
655
  if (!ptid_equal (current_ptid, inferior_ptid))
656
    thread_has_changed = 1;
657
 
658
  do_cleanups (saved_cmd_cleanup_chain);
659
  do_cleanups (old_chain);
660
  /* Print stack frame only if we changed thread.  */
661
  if (thread_has_changed)
662
    print_stack_frame (get_current_frame (), 1, SRC_LINE);
663
}
664
 
665
/* Switch to the specified thread.  Will dispatch off to thread_apply_command
666
   if prefix of arg is `apply'.  */
667
 
668
static void
669
thread_command (char *tidstr, int from_tty)
670
{
671
  if (!tidstr)
672
    {
673
      /* Don't generate an error, just say which thread is current. */
674
      if (target_has_stack)
675
        printf_filtered (_("[Current thread is %d (%s)]\n"),
676
                         pid_to_thread_id (inferior_ptid),
677
                         target_tid_to_str (inferior_ptid));
678
      else
679
        error (_("No stack."));
680
      return;
681
    }
682
 
683
  gdb_thread_select (uiout, tidstr, NULL);
684
}
685
 
686
/* Print notices when new threads are attached and detached.  */
687
int print_thread_events = 1;
688
static void
689
show_print_thread_events (struct ui_file *file, int from_tty,
690
                          struct cmd_list_element *c, const char *value)
691
{
692
  fprintf_filtered (file, _("\
693
Printing of thread events is %s.\n"),
694
                    value);
695
}
696
 
697
static int
698
do_captured_thread_select (struct ui_out *uiout, void *tidstr)
699
{
700
  int num;
701
  struct thread_info *tp;
702
 
703
  num = value_as_long (parse_and_eval (tidstr));
704
 
705
  tp = find_thread_id (num);
706
 
707
  if (!tp)
708
    error (_("Thread ID %d not known."), num);
709
 
710
  if (!thread_alive (tp))
711
    error (_("Thread ID %d has terminated."), num);
712
 
713
  switch_to_thread (tp->ptid);
714
 
715
  ui_out_text (uiout, "[Switching to thread ");
716
  ui_out_field_int (uiout, "new-thread-id", pid_to_thread_id (inferior_ptid));
717
  ui_out_text (uiout, " (");
718
  ui_out_text (uiout, target_tid_to_str (inferior_ptid));
719
  ui_out_text (uiout, ")]");
720
 
721
  print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
722
  return GDB_RC_OK;
723
}
724
 
725
enum gdb_rc
726
gdb_thread_select (struct ui_out *uiout, char *tidstr, char **error_message)
727
{
728
  if (catch_exceptions_with_msg (uiout, do_captured_thread_select, tidstr,
729
                                 error_message, RETURN_MASK_ALL) < 0)
730
    return GDB_RC_FAIL;
731
  return GDB_RC_OK;
732
}
733
 
734
/* Commands with a prefix of `thread'.  */
735
struct cmd_list_element *thread_cmd_list = NULL;
736
 
737
void
738
_initialize_thread (void)
739
{
740
  static struct cmd_list_element *thread_apply_list = NULL;
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\
747
The new thread ID must be currently known."),
748
                  &thread_cmd_list, "thread ", 1, &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, "thread apply ", 1, &thread_cmd_list);
753
 
754
  add_cmd ("all", class_run, thread_apply_all_command,
755
           _("Apply a command to all threads."), &thread_apply_list);
756
 
757
  if (!xdb_commands)
758
    add_com_alias ("t", "thread", class_run, 1);
759
 
760
  add_setshow_boolean_cmd ("thread-events", no_class,
761
         &print_thread_events, _("\
762
Set printing of thread events (e.g., thread start and exit)."), _("\
763
Show printing of thread events (e.g., thread start and exit)."), NULL,
764
         NULL,
765
         show_print_thread_events,
766
         &setprintlist, &showprintlist);
767
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.