From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32519 invoked by alias); 13 Nov 2008 14:15:04 -0000 Received: (qmail 32290 invoked by uid 22791); 13 Nov 2008 14:14:59 -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; Thu, 13 Nov 2008 14:14:21 +0000 Received: (qmail 16150 invoked from network); 13 Nov 2008 14:14:18 -0000 Received: from unknown (HELO localhost) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 13 Nov 2008 14:14:18 -0000 From: Vladimir Prus To: Pedro Alves , gdb-patches@sources.redhat.com Subject: Re: [RFC] Implement =thread-selected notification. Date: Thu, 13 Nov 2008 15:53:00 -0000 User-Agent: KMail/1.9.10 References: <200811122343.24950.vladimir@codesourcery.com> <200811122122.54320.pedro@codesourcery.com> In-Reply-To: <200811122122.54320.pedro@codesourcery.com> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_2YDHJ/eJHbU8nbL" Message-Id: <200811131714.14566.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-11/txt/msg00274.txt.bz2 --Boundary-00=_2YDHJ/eJHbU8nbL Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 966 On Thursday 13 November 2008 00:22:54 Pedro Alves wrote: > > + /* The notifications are only output when the top-level > > + interpreter (specified on the command line) is MI. */ > > + top_name = top_level_interpreter_name (); > > + if (had_execution && target_has_execution > > > + && strstr (top_name, "mi") == top_name) > > Why not, > > ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ()))) > > instead of relying on the interpreter name? > > > + { > > + struct mi_interp *mi = top_level_interpreter_data (); > > + if (!ptid_equal (previous_ptid, null_ptid) > > + && !ptid_equal (inferior_ptid, previous_ptid)) > > + { > > Checking for target_has_execution means that these new > notifications will not be emitted when using the "thread" command while debugging > a multi-threaded core file. Seems like this condition is a little bit more messed up than that. I attach a reworked patch. Thanks, Volodya --Boundary-00=_2YDHJ/eJHbU8nbL Content-Type: text/x-diff; charset="iso 8859-15"; name="0001-Implement-thread-selected-notification.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-Implement-thread-selected-notification.patch" Content-length: 9914 =46rom 60404f585b782623df370cee31c07b171bb89fc9 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Wed, 13 Aug 2008 16:32:32 +0400 Subject: [RFA] Implement =3Dthread-selected notification. To: gdb-patches@sources.redhat.com X-KMail-Transport: CodeSourcery X-KMail-Identity: 901867920 [doc/ChangeLog] * gdb.texinfo (GDB/MI Async Records): Document =3Dthread-selected. [ChangeLog] * mi/mi-common.h (struct mi_interp): New, moved from ... * mi/mi-interp.c: ...here. * mi/mi-main.c (mi_execute_command): If the thread changed as result of command, report that. [testsuite/ChangeLog] * gdb.mi/mi-pthreads.exp (check_mi_thread_command_set): Make sure "thread N" results in =3Dthread-selected. * lib/mi-support (mi_run_cmd, mi_expect_stop) (mi_send_resuming_command_raw, mi_get_stop_line): Be prepared for =3Dthread-selected. --- gdb/doc/gdb.texinfo | 13 ++++++++++++ gdb/mi/mi-common.h | 15 +++++++++++++ gdb/mi/mi-interp.c | 16 +------------- gdb/mi/mi-main.c | 37 ++++++++++++++++++++++++++++++= ++++ gdb/testsuite/gdb.mi/mi-pthreads.exp | 6 +++++ gdb/testsuite/lib/mi-support.exp | 16 ++++++++++---- 6 files changed, 83 insertions(+), 20 deletions(-) diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 261d1c7..ca8759d 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -19273,6 +19273,19 @@ A signal was received by the inferior. @itemx =3Dthread-exited,id=3D"@var{id}" A thread either was created, or has exited. The @var{id} field contains the @value{GDBN} identifier of the thread. + +@item =3Dthread-selected,id=3D"@var{id}" +Informs that the selected thread was changed as result of the last +command. This notification is not emitted as result of @code{-thread-sele= ct} +command but is emitted whenever an MI command that is not documented +to change the selected thread actually changes it. In particular, +invoking, directly or indirectly (via user-defined command), the CLI +@code{thread} command, will generate this notification. + +We suggest that in response to this notification, front ends +highlight the selected thread and cause subsequent commands apply to +that thread. + @end table =20 =20 diff --git a/gdb/mi/mi-common.h b/gdb/mi/mi-common.h index e47afd1..8778e74 100644 --- a/gdb/mi/mi-common.h +++ b/gdb/mi/mi-common.h @@ -41,4 +41,19 @@ enum async_reply_reason =20 const char *async_reason_lookup (enum async_reply_reason reason); =20 +struct mi_interp +{ + /* MI's output channels */ + struct ui_file *out; + struct ui_file *err; + struct ui_file *log; + struct ui_file *targ; + struct ui_file *event_channel; + + /* This is the interpreter for the mi... */ + struct interp *mi2_interp; + struct interp *mi1_interp; + struct interp *mi_interp; +}; + #endif diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index e05b1ad..5aa0e6c 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -31,24 +31,10 @@ #include "mi-cmds.h" #include "mi-out.h" #include "mi-console.h" +#include "mi-common.h" #include "observer.h" #include "gdbthread.h" =20 -struct mi_interp -{ - /* MI's output channels */ - struct ui_file *out; - struct ui_file *err; - struct ui_file *log; - struct ui_file *targ; - struct ui_file *event_channel; - - /* This is the interpreter for the mi... */ - struct interp *mi2_interp; - struct interp *mi1_interp; - struct interp *mi_interp; -}; - /* These are the interpreter setup, etc. functions for the MI interpreter = */ static void mi_execute_command_wrapper (char *cmd); static void mi_command_loop (int mi_version); diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index bd149ef..bd5ce69 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -44,6 +44,7 @@ #include "gdb.h" #include "frame.h" #include "mi-main.h" +#include "mi-common.h" #include "language.h" #include "valprint.h" #include "inferior.h" @@ -1167,6 +1168,7 @@ mi_execute_command (char *cmd, int from_tty) if (command !=3D NULL) { struct gdb_exception result; + ptid_t previous_ptid =3D inferior_ptid; =20 if (do_timings) { @@ -1191,6 +1193,41 @@ mi_execute_command (char *cmd, int from_tty) mi_out_rewind (uiout); } =20 + if (/* The notifications are only output when the top-level + interpreter (specified on the command line) is MI. */=20=20=20=20= =20=20 + ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())) + /* Don't try report anything if there are no thread --=20 + the program is dead. */ + && thread_count () !=3D 0 + /* -thread-select explicitly changes thread. If frontend uses that + internally, we don't want to emit =3Dthread-selected, since + =3Dthread-selected is supposed to indicate user's intentions. */ + && strcmp (command->command, "thread-select") !=3D 0) + { + struct mi_interp *mi =3D top_level_interpreter_data (); + struct thread_info *ti =3D inferior_thread (); + int report_change; + + if (command->thread =3D=3D -1) + { + report_change =3D !ptid_equal (previous_ptid, null_ptid) + && !ptid_equal (inferior_ptid, previous_ptid); + } + else + { + report_change =3D (ti->num !=3D command->thread); + } + + if (report_change) + {=20=20=20=20=20 + target_terminal_ours (); + fprintf_unfiltered (mi->event_channel,=20 + "thread-selected,id=3D\"%d\"", + ti->num); + gdb_flush (mi->event_channel); + } + } + mi_parse_free (command); } =20 diff --git a/gdb/testsuite/gdb.mi/mi-pthreads.exp b/gdb/testsuite/gdb.mi/mi= -pthreads.exp index dbb3ece..0ab5715 100644 --- a/gdb/testsuite/gdb.mi/mi-pthreads.exp +++ b/gdb/testsuite/gdb.mi/mi-pthreads.exp @@ -55,6 +55,12 @@ proc check_mi_thread_command_set {} { "\\^done,new-thread-id=3D\"$thread\",frame=3D{.*}(,line=3D\"(-)?\[0-= 9\]+\",file=3D\".*\")?" \ "check_mi_thread_command_set: -thread-select $thread" } + + foreach thread $thread_list { + mi_gdb_test "-interpreter-exec console \"thread $thread\"" \ + ".*\\^done\r\n=3Dthread-selected,id=3D\"$thread\"" \ + "check =3Dthread-selected: thread $thread" + } } =20 # diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-suppor= t.exp index 9ef9df9..55116d6 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -30,6 +30,8 @@ global mi_inferior_tty_name =20 set MIFLAGS "-i=3Dmi" =20 +set thread_selected_re "=3Dthread-selected,id=3D\"\[0-9+\]\"\r\n" + # # mi_gdb_exit -- exit the GDB, killing the target program if necessary # @@ -775,6 +777,7 @@ proc mi_run_cmd {args} { return -1 } global mi_gdb_prompt + global thread_selected_re =20 if [target_info exists gdb_init_command] { send_gdb "[target_info gdb_init_command]\n"; @@ -816,7 +819,7 @@ proc mi_run_cmd {args} { =20 send_gdb "220-exec-run $args\n" gdb_expect { - -re "220\\^running\r\n(\\*running,thread-id=3D\"\[^\"\]+\"\r\n|=3Dthread-= created,id=3D\"1\"\r\n)*${mi_gdb_prompt}" { + -re "220\\^running\r\n(\\*running,thread-id=3D\"\[^\"\]+\"\r\n|=3Dthread-= created,id=3D\"1\"\r\n)*($thread_selected_re)?${mi_gdb_prompt}" { } timeout { perror "Unable to start target" @@ -954,6 +957,7 @@ proc mi_expect_stop { reason func args file line extra = test } { global decimal global fullname_syntax global async + global thread_selected_re =20 set after_stopped "" set after_reason "" @@ -1014,9 +1018,9 @@ proc mi_expect_stop { reason func args file line extr= a test } { =20 set any "\[^\n\]*" =20 - verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}threa= d-id=3D\"$decimal\",stopped-threads=3D$any,frame=3D\{addr=3D\"$hex\",func= =3D\"$func\",args=3D$args,file=3D\"$any$file\",fullname=3D\"${fullname_synt= ax}$file\",line=3D\"$line\"\}\r\n$after_stopped$prompt_re" + verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}threa= d-id=3D\"$decimal\",stopped-threads=3D$any,frame=3D\{addr=3D\"$hex\",func= =3D\"$func\",args=3D$args,file=3D\"$any$file\",fullname=3D\"${fullname_synt= ax}$file\",line=3D\"$line\"\}\r\n${after_stopped}($thread_selected_re)?$pro= mpt_re" gdb_expect { - -re "\\*stopped,${r}${a}${bn}thread-id=3D\"$decimal\",stopped-threads=3D$= any,frame=3D\{addr=3D\"$hex\",func=3D\"$func\",args=3D$args,file=3D\"$any$f= ile\",fullname=3D\"${fullname_syntax}$file\",line=3D\"($line)\"\}$after_sto= pped\r\n$prompt_re" { + -re "\\*stopped,${r}${a}${bn}thread-id=3D\"$decimal\",stopped-threads=3D$= any,frame=3D\{addr=3D\"$hex\",func=3D\"$func\",args=3D$args,file=3D\"$any$f= ile\",fullname=3D\"${fullname_syntax}$file\",line=3D\"($line)\"\}${after_st= opped}\r\n($thread_selected_re)?$prompt_re" { pass "$test" return $expect_out(2,string) } @@ -1430,10 +1434,11 @@ proc mi_tbreak {location} { proc mi_send_resuming_command_raw {command test} { =20 global mi_gdb_prompt + global thread_selected_re =20 send_gdb "$command\n" gdb_expect { - -re "\\^running\r\n\\*running,thread-id=3D\"\[^\"\]+\"\r\n${mi_gdb= _prompt}" { + -re "\\^running\r\n\\*running,thread-id=3D\"\[^\"\]+\"\r\n($thread= _selected_re)?${mi_gdb_prompt}" { # Note that lack of 'pass' call here -- this works around limi= tation # in DejaGNU xfail mechanism. mi-until.exp has this: # @@ -1483,6 +1488,7 @@ proc mi_get_stop_line {test} { =20 global mi_gdb_prompt global async + global thread_selected_re =20 if {$async} { set prompt_re "" @@ -1491,7 +1497,7 @@ proc mi_get_stop_line {test} { } =20 gdb_expect { - -re ".*line=3D\"(\[0-9\]*)\".*\r\n$prompt_re" { + -re ".*line=3D\"(\[0-9\]*)\".*\r\n($thread_selected_re)?$prompt_re" { return $expect_out(1,string) } -re ".*$mi_gdb_prompt" { --=20 1.5.3.5 --Boundary-00=_2YDHJ/eJHbU8nbL--