This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA] Implement -thread-info.


On Friday 14 March 2008 18:11:15 Daniel Jacobowitz wrote:
> On Fri, Mar 14, 2008 at 11:07:32AM -0400, Daniel Jacobowitz wrote:

> > ? ? ? ?/* That switch put us at the top of the stack (leaf frame). ?*/
> > ? ? ? ?switch_to_thread (tp->ptid);
> > ? ? ? ?print_stack_frame (get_selected_frame (NULL), 0, LOCATION);
>
> I think Nick was right about printing the frame level. ?It's not
> necessarily going to be zero in the future. ?For instance, GDB might
> automatically select the nearest user frame if you stop when a C++
> exception is thrown, like we already do for Ada; and then we could
> teach GDB not to lose the selected frame whenever it switches threads.
> That wants doing anyway.

Ok, I've enabled printing of stack level.

> > > I have realized that while the patch is mostly about MI, it also
> > > touches generic code -- thread.c. Is that part of patch (attached again
> > > for convenience) OK?
> 
> Oh, one other thing.  I went back to look at Denis's patches.  He made
> -thread-info without an argument describe the current thread only.
> Doesn't that seem useful, especially before we get notifications
> completely hammered out?  I do not see any other MI command that
> reports the current thread.
> 
> So that would mean we needed -thread-list-all-threads back again.

Hmm, I'd rather not. Currently, the current thread is reported by 
*stopped, and is not supposed to randomly change -- because the
target is fully stopped while frontend talks with gdb. Therefore,
using -thread-info as a roundabout way to get the current thread
does not really give you anything.

For non-stop mode, I have long and evil plans that I'll post soon,
but they don't require this either.

I attach the patch revised per your comments. How does it look?

- Volodya
From b8e58feeae705971a9f927a7f0df3220df6f5523 Mon Sep 17 00:00:00 2001
From: Vladimir Prus <vladimir@codesourcery.com>
Date: Sun, 17 Feb 2008 18:16:02 +0300
Subject: [RFA] Implement -thread-info.
To: gdb-patches@sources.redhat.com
X-KMail-Transport: CodeSourcery
X-KMail-Identity: 901867920

	* gdbthread.h (print_thread_info): Declare.

	* thread.c (print_thread_info): New, extracted
	from info_threads_command and adjusted to
	work for CLI and MI.
	(info_threads_command): Use print_thread_info.
        * Makefile.in: Update dependencies.

	* mi/mi-cmds.c (mi_cmds): Specify a handler
	for -thread-info.
	* mi/mi-cmds.h (mi_cmd_thread_info): Declare.
	* mi/mi-main.c (mi_cmd_thread_info): New.
	(mi_cmd_list_features): Include 'thread-info'.

	doc/
	* gdb.texinfo (Thread Commands): Document
	-thread-info.  Remove -thread-list-all-threads.
---
 gdb/Makefile.in     |    2 +-
 gdb/doc/gdb.texinfo |   37 ++++++++++++------------
 gdb/gdbthread.h     |    4 ++
 gdb/mi/mi-cmds.c    |    3 +-
 gdb/mi/mi-cmds.h    |    1 +
 gdb/mi/mi-main.c    |   19 ++++++++++++
 gdb/thread.c        |   77 ++++++++++++++++++++++++++++++++++++++++----------
 7 files changed, 106 insertions(+), 37 deletions(-)

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 2ba51b1..75f4991 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -793,7 +793,7 @@ gdb_stabs_h = gdb-stabs.h
 gdb_stat_h = gdb_stat.h
 gdb_string_h = gdb_string.h
 gdb_thread_db_h = gdb_thread_db.h
-gdbthread_h = gdbthread.h $(breakpoint_h) $(frame_h)
+gdbthread_h = gdbthread.h $(breakpoint_h) $(frame_h) $(ui_out_h)
 gdbtypes_h = gdbtypes.h $(hashtab_h)
 gdb_vfork_h = gdb_vfork.h
 gdb_wait_h = gdb_wait.h
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index dbc9efc..98cf7a5 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18924,34 +18924,33 @@ The corresponding @value{GDBN} command is @samp{pwd}.
 @subsubheading Synopsis
 
 @smallexample
- -thread-info
+ -thread-info [ @var{thread-id} ]
 @end smallexample
 
+Reports information about either a specific thread, if 
+the @var{thread-id} parameter is present, or about all
+threads.  When printing information about all threads,
+also reports the current thread.
+
 @subsubheading @value{GDBN} Command
 
-No equivalent.
+The @samp{info thread} command prints the same information
+about all threads.
 
 @subsubheading Example
-N.A.
-
-
-@subheading The @code{-thread-list-all-threads} Command
-@findex -thread-list-all-threads
-
-@subsubheading Synopsis
 
 @smallexample
- -thread-list-all-threads
+-thread-info
+^done,threads=[
+@{id="2",target-id="Thread 0xb7e14b90 (LWP 21257)",
+   frame=@{addr="0xffffe410",func="__kernel_vsyscall",args=[]@},
+@{id="1",target-id="Thread 0xb7e156b0 (LWP 21254)",
+   frame=@{addr="0x0804891f",func="foo",args=[@{name="i",value="10"@}],
+           file="/tmp/a.c",fullname="/tmp/a.c",line="158"@}@}],
+current-thread-id="1"
+(gdb)
 @end smallexample
 
-@subsubheading @value{GDBN} Command
-
-The equivalent @value{GDBN} command is @samp{info threads}.
-
-@subsubheading Example
-N.A.
-
-
 @subheading The @code{-thread-list-ids} Command
 @findex -thread-list-ids
 
@@ -21845,6 +21844,8 @@ The current list of features is:
 @item
 @samp{pending-breakpoints}---indicates presence of the @code{-f}
 option to the @code{-break-insert} command.
+@item
+@samp{thread-info}---indicates presence of the @code{-thread-info} command.
 
 @end itemize
 
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index a1e4efe..5ca329e 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -32,6 +32,8 @@ struct symtab;
 /* For struct frame_id.  */
 #include "frame.h"
 
+#include "ui-out.h"
+
 struct thread_info
 {
   struct thread_info *next;
@@ -152,4 +154,6 @@ extern struct cmd_list_element *thread_cmd_list;
    `set print thread-events'.  */
 extern int print_thread_events;
 
+extern void print_thread_info (struct ui_out *uiout, int thread);
+
 #endif /* GDBTHREAD_H */
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index c651694..89c6376 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -130,8 +130,7 @@ struct mi_cmd mi_cmds[] =
   { "target-list-current-targets", { NULL, 0 }, NULL, NULL },
   { "target-list-parameters", { NULL, 0 }, NULL, NULL },
   { "target-select", { NULL, 0 }, mi_cmd_target_select},
-  { "thread-info", { NULL, 0 }, NULL, NULL },
-  { "thread-list-all-threads", { NULL, 0 }, NULL, NULL },
+  { "thread-info", { NULL, 0 }, NULL, mi_cmd_thread_info },
   { "thread-list-ids", { NULL, 0 }, 0, mi_cmd_thread_list_ids},
   { "thread-select", { NULL, 0 }, 0, mi_cmd_thread_select},
   { "trace-actions", { NULL, 0 }, NULL, NULL },
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index 2d0393b..6a033e5 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -105,6 +105,7 @@ extern mi_cmd_argv_ftype mi_cmd_target_file_get;
 extern mi_cmd_argv_ftype mi_cmd_target_file_put;
 extern mi_cmd_argv_ftype mi_cmd_target_file_delete;
 extern mi_cmd_args_ftype mi_cmd_target_select;
+extern mi_cmd_argv_ftype mi_cmd_thread_info;
 extern mi_cmd_argv_ftype mi_cmd_thread_list_ids;
 extern mi_cmd_argv_ftype mi_cmd_thread_select;
 extern mi_cmd_argv_ftype mi_cmd_var_assign;
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 41e12d2..cea8503 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -277,6 +277,24 @@ mi_cmd_thread_list_ids (char *command, char **argv, int argc)
 }
 
 enum mi_cmd_result
+mi_cmd_thread_info (char *command, char **argv, int argc)
+{
+  int thread = -1;
+  
+  if (argc != 0 && argc != 1)
+    {
+      mi_error_message = xstrprintf ("Invalid MI command");
+      return MI_CMD_ERROR;
+    }
+
+  if (argc == 1)
+    thread = atoi (argv[0]);
+
+  print_thread_info (uiout, thread);
+  return MI_CMD_DONE;
+}
+
+enum mi_cmd_result
 mi_cmd_data_list_register_names (char *command, char **argv, int argc)
 {
   int regnum, numregs;
@@ -1055,6 +1073,7 @@ mi_cmd_list_features (char *command, char **argv, int argc)
 
       ui_out_field_string (uiout, NULL, "frozen-varobjs");
       ui_out_field_string (uiout, NULL, "pending-breakpoints");
+      ui_out_field_string (uiout, NULL, "thread-info");
       
       do_cleanups (cleanup);
 
diff --git a/gdb/thread.c b/gdb/thread.c
index 4aae4b6..e1ff672 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -416,15 +416,14 @@ prune_threads (void)
     }
 }
 
-/* Print information about currently known threads 
-
- * Note: this has the drawback that it _really_ switches
- *       threads, which frees the frame cache.  A no-side
- *       effects info-threads command would be nicer.
- */
-
-static void
-info_threads_command (char *arg, int from_tty)
+/* Prints the list of threads and their details on UIOUT.
+   This is a version of 'info_thread_command' suitable for
+   use from MI.  
+   If REQESTED_THREAD is not -1, it's the GDB id of the thread
+   that should be printed.  Otherwise, all threads are
+   printed.  */
+void
+print_thread_info (struct ui_out *uiout, int requested_thread)
 {
   struct thread_info *tp;
   ptid_t current_ptid;
@@ -432,45 +431,91 @@ info_threads_command (char *arg, int from_tty)
   struct cleanup *old_chain;
   struct frame_id saved_frame_id;
   char *extra_info;
+  int current_thread = -1;
 
   /* Backup current thread and selected frame.  */
   saved_frame_id = get_frame_id (get_selected_frame (NULL));
   old_chain = make_cleanup_restore_current_thread (inferior_ptid, saved_frame_id);
 
+  make_cleanup_ui_out_list_begin_end (uiout, "threads");
+
   prune_threads ();
   target_find_new_threads ();
   current_ptid = inferior_ptid;
   for (tp = thread_list; tp; tp = tp->next)
     {
+      struct cleanup *chain2;
+
+      if (requested_thread != -1 && tp->num != requested_thread)
+	continue;
+
+      chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+
       if (ptid_equal (tp->ptid, current_ptid))
-	printf_filtered ("* ");
+	{
+	  current_thread = tp->num;
+	  ui_out_text (uiout, "* ");
+	}
       else
-	printf_filtered ("  ");
+	ui_out_text (uiout, "  ");
 
-      printf_filtered ("%d %s", tp->num, target_tid_to_str (tp->ptid));
+      ui_out_field_int (uiout, "id", tp->num);
+      ui_out_text (uiout, " ");
+      ui_out_field_string (uiout, "target-id", target_tid_to_str (tp->ptid));
 
       extra_info = target_extra_thread_info (tp);
       if (extra_info)
-	printf_filtered (" (%s)", extra_info);
-      puts_filtered ("  ");
+	{
+	  ui_out_text (uiout, " (");
+	  ui_out_field_string (uiout, "details", extra_info);
+	  ui_out_text (uiout, ")");
+	}
+      ui_out_text (uiout, "  ");
       /* That switch put us at the top of the stack (leaf frame).  */
       switch_to_thread (tp->ptid);
-      print_stack_frame (get_selected_frame (NULL), 0, LOCATION);
+      print_stack_frame (get_selected_frame (NULL), 1, LOCATION);
+
+      do_cleanups (chain2);
     }
 
   /* Restores the current thread and the frame selected before
      the "info threads" command.  */
   do_cleanups (old_chain);
 
+  if (requested_thread == -1)
+    {
+      gdb_assert (current_thread != -1);
+      if (ui_out_is_mi_like_p (uiout))
+	ui_out_field_int (uiout, "current-thread-id", current_thread);
+    }
+
   /*  If case we were not able to find the original frame, print the
       new selected frame.  */
   if (frame_find_by_id (saved_frame_id) == NULL)
     {
       warning (_("Couldn't restore frame in current thread, at frame 0"));
-      print_stack_frame (get_selected_frame (NULL), 0, LOCATION);
+      /* For MI, we should probably have a notification about
+	 current frame change.  But this error is not very likely, so
+	 don't bother for now.  */
+      if (!ui_out_is_mi_like_p (uiout))
+	print_stack_frame (get_selected_frame (NULL), 0, LOCATION);
     }
 }
 
+
+/* Print information about currently known threads 
+
+ * Note: this has the drawback that it _really_ switches
+ *       threads, which frees the frame cache.  A no-side
+ *       effects info-threads command would be nicer.
+ */
+
+static void
+info_threads_command (char *arg, int from_tty)
+{
+  print_thread_info (uiout, -1);
+}
+
 /* Switch from one thread to another. */
 
 void
-- 
1.5.3.5


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]