From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28820 invoked by alias); 14 Mar 2008 17:04:31 -0000 Received: (qmail 27645 invoked by uid 22791); 14 Mar 2008 17:04:28 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 14 Mar 2008 17:03:47 +0000 Received: (qmail 16352 invoked from network); 14 Mar 2008 17:03:45 -0000 Received: from unknown (HELO localhost) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 14 Mar 2008 17:03:45 -0000 From: Vladimir Prus To: gdb-patches@sources.redhat.com Subject: Re: [RFA] Implement -thread-info. Date: Fri, 14 Mar 2008 17:04:00 -0000 User-Agent: KMail/1.9.6 (enterprise 0.20070907.709405) References: <200802171833.26673.vladimir@codesourcery.com> <20080314150732.GA19288@caradoc.them.org> <20080314151115.GB19288@caradoc.them.org> In-Reply-To: <20080314151115.GB19288@caradoc.them.org> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_0/q2HUIt52z5O4O" Message-Id: <200803142003.48178.vladimir@codesourcery.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-03/txt/msg00179.txt.bz2 --Boundary-00=_0/q2HUIt52z5O4O Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Content-length: 1812 On Friday 14 March 2008 18:11:15 Daniel Jacobowitz wrote: > On Fri, Mar 14, 2008 at 11:07:32AM -0400, Daniel Jacobowitz wrote: > > =A0 =A0 =A0 =A0/* That switch put us at the top of the stack (leaf fram= e). =A0*/ > > =A0 =A0 =A0 =A0switch_to_thread (tp->ptid); > > =A0 =A0 =A0 =A0print_stack_frame (get_selected_frame (NULL), 0, LOCATIO= N); > > I think Nick was right about printing the frame level. =A0It's not > necessarily going to be zero in the future. =A0For 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 aga= in > > > for convenience) OK? >=20 > 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. >=20 > So that would mean we needed -thread-list-all-threads back again. Hmm, I'd rather not. Currently, the current thread is reported by=20 *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 --Boundary-00=_0/q2HUIt52z5O4O Content-Type: text/x-diff; charset="iso-8859-1"; name="0001-Implement-thread-info.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-Implement-thread-info.patch" Content-length: 10300 =46rom b8e58feeae705971a9f927a7f0df3220df6f5523 Mon Sep 17 00:00:00 2001 From: Vladimir Prus 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 =3D gdb-stabs.h gdb_stat_h =3D gdb_stat.h gdb_string_h =3D gdb_string.h gdb_thread_db_h =3D gdb_thread_db.h -gdbthread_h =3D gdbthread.h $(breakpoint_h) $(frame_h) +gdbthread_h =3D gdbthread.h $(breakpoint_h) $(frame_h) $(ui_out_h) gdbtypes_h =3D gdbtypes.h $(hashtab_h) gdb_vfork_h =3D gdb_vfork.h gdb_wait_h =3D 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{p= wd}. @subsubheading Synopsis =20 @smallexample - -thread-info + -thread-info [ @var{thread-id} ] @end smallexample =20 +Reports information about either a specific thread, if=20 +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 =20 -No equivalent. +The @samp{info thread} command prints the same information +about all threads. =20 @subsubheading Example -N.A. - - -@subheading The @code{-thread-list-all-threads} Command -@findex -thread-list-all-threads - -@subsubheading Synopsis =20 @smallexample - -thread-list-all-threads +-thread-info +^done,threads=3D[ +@{id=3D"2",target-id=3D"Thread 0xb7e14b90 (LWP 21257)", + frame=3D@{addr=3D"0xffffe410",func=3D"__kernel_vsyscall",args=3D[]@}, +@{id=3D"1",target-id=3D"Thread 0xb7e156b0 (LWP 21254)", + frame=3D@{addr=3D"0x0804891f",func=3D"foo",args=3D[@{name=3D"i",value= =3D"10"@}], + file=3D"/tmp/a.c",fullname=3D"/tmp/a.c",line=3D"158"@}@}], +current-thread-id=3D"1" +(gdb) @end smallexample =20 -@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 =20 @@ -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. =20 @end itemize =20 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" =20 +#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; =20 +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[] =3D { "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, in= t argc) } =20 enum mi_cmd_result +mi_cmd_thread_info (char *command, char **argv, int argc) +{ + int thread =3D -1; +=20=20 + if (argc !=3D 0 && argc !=3D 1) + { + mi_error_message =3D xstrprintf ("Invalid MI command"); + return MI_CMD_ERROR; + } + + if (argc =3D=3D 1) + thread =3D 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) =20 ui_out_field_string (uiout, NULL, "frozen-varobjs"); ui_out_field_string (uiout, NULL, "pending-breakpoints"); + ui_out_field_string (uiout, NULL, "thread-info"); =20=20=20=20=20=20=20 do_cleanups (cleanup); =20 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) } } =20 -/* Print information about currently known threads=20 - - * 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.=20=20 + 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 =3D -1; =20 /* Backup current thread and selected frame. */ saved_frame_id =3D get_frame_id (get_selected_frame (NULL)); old_chain =3D make_cleanup_restore_current_thread (inferior_ptid, saved_= frame_id); =20 + make_cleanup_ui_out_list_begin_end (uiout, "threads"); + prune_threads (); target_find_new_threads (); current_ptid =3D inferior_ptid; for (tp =3D thread_list; tp; tp =3D tp->next) { + struct cleanup *chain2; + + if (requested_thread !=3D -1 && tp->num !=3D requested_thread) + continue; + + chain2 =3D make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + if (ptid_equal (tp->ptid, current_ptid)) - printf_filtered ("* "); + { + current_thread =3D tp->num; + ui_out_text (uiout, "* "); + } else - printf_filtered (" "); + ui_out_text (uiout, " "); =20 - 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= )); =20 extra_info =3D 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); } =20 /* Restores the current thread and the frame selected before the "info threads" command. */ do_cleanups (old_chain); =20 + if (requested_thread =3D=3D -1) + { + gdb_assert (current_thread !=3D -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) =3D=3D 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); } } =20 + +/* Print information about currently known threads=20 + + * 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. */ =20 void --=20 1.5.3.5 --Boundary-00=_0/q2HUIt52z5O4O--