/* Multi-process/thread control for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010
+ 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
#include "annotate.h"
#include "cli/cli-decode.h"
-/* Definition of struct thread_info exported to gdbthread.h */
+/* Definition of struct thread_info exported to gdbthread.h. */
-/* Prototypes for exported functions. */
+/* Prototypes for exported functions. */
void _initialize_thread (void);
-/* Prototypes for local functions. */
+/* Prototypes for local functions. */
static struct thread_info *thread_list = NULL;
static int highest_thread_num;
if (ptid_equal (tp->ptid, ptid))
return 1;
- return 0; /* Never heard of 'im */
+ return 0; /* Never heard of 'im. */
}
/* Finds the first thread of the inferior given by PID. If PID is -1,
}
/* Print a list of thread ids currently known, and the total number of
- threads. To be used from within catch_errors. */
+ threads. To be used from within catch_errors. */
static int
do_captured_list_thread_ids (struct ui_out *uiout, void *arg)
{
}
/* Official gdblib interface function to get a list of thread ids and
- the total number. */
+ the total number. */
enum gdb_rc
gdb_list_thread_ids (struct ui_out *uiout, char **error_message)
{
return GDB_RC_OK;
}
-/* Return true if TP is an active thread. */
+/* Return true if TP is an active thread. */
static int
thread_alive (struct thread_info *tp)
{
/* Prints the list of threads and their details on UIOUT.
This is a version of 'info_thread_command' suitable for
- use from MI.
+ use from MI.
If REQUESTED_THREAD is not -1, it's the GDB id of the thread
that should be printed. Otherwise, all threads are
- printed.
+ printed.
If PID is not -1, only print threads from the process PID.
- Otherwise, threads from all attached PIDs are printed.
+ Otherwise, threads from all attached PIDs are printed.
If both REQUESTED_THREAD and PID are not -1, then the thread
is printed if it belongs to the specified process. Otherwise,
an error is raised. */
/* We'll be switching threads temporarily. */
old_chain = make_cleanup_restore_current_thread ();
- make_cleanup_ui_out_list_begin_end (uiout, "threads");
+ /* For backward compatibility, we make a list for MI. A table is
+ preferable for the CLI, though, because it shows table
+ headers. */
+ if (ui_out_is_mi_like_p (uiout))
+ make_cleanup_ui_out_list_begin_end (uiout, "threads");
+ else
+ {
+ int n_threads = 0;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ {
+ if (requested_thread != -1 && tp->num != requested_thread)
+ continue;
+
+ if (pid != -1 && PIDGET (tp->ptid) != pid)
+ continue;
+
+ if (tp->state_ == THREAD_EXITED)
+ continue;
+
+ ++n_threads;
+ }
+
+ if (n_threads == 0)
+ {
+ if (requested_thread == -1)
+ ui_out_message (uiout, 0, _("No threads.\n"));
+ else
+ ui_out_message (uiout, 0, _("No thread %d.\n"), requested_thread);
+ do_cleanups (old_chain);
+ return;
+ }
+
+ make_cleanup_ui_out_table_begin_end (uiout, 5, n_threads, "threads");
+
+ ui_out_table_header (uiout, 1, ui_left, "current", "");
+ ui_out_table_header (uiout, 4, ui_left, "id", "Id");
+ ui_out_table_header (uiout, 17, ui_left, "target-id", "Target Id");
+ ui_out_table_header (uiout, 1, ui_noalign, "details", "");
+ ui_out_table_header (uiout, 1, ui_left, "frame", "Frame");
+ ui_out_table_body (uiout);
+ }
+
for (tp = thread_list; tp; tp = tp->next)
{
struct cleanup *chain2;
chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
- if (ptid_equal (tp->ptid, current_ptid))
- ui_out_text (uiout, "* ");
+ if (ui_out_is_mi_like_p (uiout))
+ {
+ /* Compatibility. */
+ if (ptid_equal (tp->ptid, current_ptid))
+ ui_out_text (uiout, "* ");
+ else
+ ui_out_text (uiout, " ");
+ }
else
- ui_out_text (uiout, " ");
+ {
+ if (ptid_equal (tp->ptid, current_ptid))
+ ui_out_field_string (uiout, "current", "*");
+ else
+ ui_out_field_skip (uiout, "current");
+ }
ui_out_field_int (uiout, "id", tp->num);
- ui_out_text (uiout, " ");
ui_out_field_string (uiout, "target-id", target_pid_to_str (tp->ptid));
extra_info = target_extra_thread_info (tp);
ui_out_field_string (uiout, "details", extra_info);
ui_out_text (uiout, ")");
}
- ui_out_text (uiout, " ");
+ else if (! ui_out_is_mi_like_p (uiout))
+ ui_out_field_skip (uiout, "details");
if (tp->state_ == THREAD_RUNNING)
ui_out_text (uiout, "(running)\n");
print_thread_info (uiout, -1, -1);
}
-/* Switch from one thread to another. */
+/* Switch from one thread to another. */
void
switch_to_thread (ptid_t ptid)
/* Warn the user. */
if (frame_level > 0 && !ui_out_is_mi_like_p (uiout))
{
- warning (_("\
-Couldn't restore frame #%d in current thread, at reparsed frame #0\n"),
+ warning (_("Couldn't restore frame #%d in "
+ "current thread, at reparsed frame #0\n"),
frame_level);
/* For MI, we should probably have a notification about
current frame change. But this error is not very
thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4
thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9
- thread apply all p x/i $pc Apply x/i $pc cmd to all threads
- */
+ thread apply all p x/i $pc Apply x/i $pc cmd to all threads. */
static void
thread_apply_all_command (char *cmd, int from_tty)
old_chain = make_cleanup_restore_current_thread ();
/* Save a copy of the command in case it is clobbered by
- execute_command */
+ execute_command. */
saved_cmd = xstrdup (cmd);
make_cleanup (xfree, saved_cmd);
for (tp = thread_list; tp; tp = tp->next)
printf_filtered (_("\nThread %d (%s):\n"),
tp->num, target_pid_to_str (inferior_ptid));
execute_command (cmd, from_tty);
- strcpy (cmd, saved_cmd); /* Restore exact command used previously */
+ strcpy (cmd, saved_cmd); /* Restore exact command used
+ previously. */
}
do_cleanups (old_chain);
error (_("Please specify a command following the thread ID list"));
/* Save a copy of the command in case it is clobbered by
- execute_command */
+ execute_command. */
saved_cmd = xstrdup (cmd);
old_chain = make_cleanup (xfree, saved_cmd);
while (tidlist < cmd)
while (*tidlist == ' ' || *tidlist == '\t')
tidlist++;
- if (*tidlist == '-') /* Got a range of IDs? */
+ if (*tidlist == '-') /* Got a range of IDs? */
{
tidlist++; /* Skip the - */
end = strtol (tidlist, &p, 10);
show_print_thread_events (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("\
-Printing of thread events is %s.\n"),
+ fprintf_filtered (file,
+ _("Printing of thread events is %s.\n"),
value);
}
if (tp->state_ == THREAD_RUNNING)
ui_out_text (uiout, "(running)\n");
else
- print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
+ {
+ ui_out_text (uiout, "\n");
+ print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
+ }
/* Since the current thread may have changed, see if there is any
exited thread we can now delete. */