From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28754 invoked by alias); 12 Nov 2008 20:44:05 -0000 Received: (qmail 28573 invoked by uid 22791); 12 Nov 2008 20:44:04 -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; Wed, 12 Nov 2008 20:43:27 +0000 Received: (qmail 720 invoked from network); 12 Nov 2008 20:39:12 -0000 Received: from unknown (HELO localhost) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 12 Nov 2008 20:39:12 -0000 From: Vladimir Prus To: gdb-patches@sources.redhat.com Subject: [RFC] Implement =thread-selected notification. Date: Wed, 12 Nov 2008 23:20:00 -0000 User-Agent: KMail/1.9.10 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Message-Id: <200811122343.24950.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/msg00251.txt.bz2 This patch implements =3Dthread-selected notification, needed so that if us= er types "thread N" in GDB console of a frontend, frontend can understand that user wants to see a different thread. Is the interps.{c,h} change OK? Eli, is the doc patch fine with you? - Volodya =46rom a760fdf6dd4b68ab8c5c64a0066b4d79e584a693 Mon Sep 17 00:00:00 2001 [doc/ChangeLog] * gdb.texinfo (GDB/MI Async Records): Document =3Dthread-selected. [ChangeLog] * interps.c (top_level_interpreter_name): New. * interps.h (top_level_interpreter_name): Declare. * 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/interps.c | 7 +++++++ gdb/interps.h | 1 + gdb/mi/mi-common.h | 15 +++++++++++++++ gdb/mi/mi-interp.c | 16 +--------------- gdb/mi/mi-main.c | 30 ++++++++++++++++++++++++++++++ gdb/testsuite/gdb.mi/mi-pthreads.exp | 6 ++++++ gdb/testsuite/lib/mi-support.exp | 10 +++++----- 8 files changed, 78 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/interps.c b/gdb/interps.c index 73bc51c..6f6232c 100644 --- a/gdb/interps.c +++ b/gdb/interps.c @@ -479,6 +479,13 @@ top_level_interpreter_data (void) return top_level_interpreter_ptr->data;=20=20 } =20 +const char * +top_level_interpreter_name (void) +{ + gdb_assert (top_level_interpreter_ptr); + return top_level_interpreter_ptr->name;=20=20 +} + /* This just adds the "interpreter-exec" command. */ void _initialize_interpreter (void) diff --git a/gdb/interps.h b/gdb/interps.h index 353ed0a..e6aa57a 100644 --- a/gdb/interps.h +++ b/gdb/interps.h @@ -67,6 +67,7 @@ extern void current_interp_command_loop (void); /* Returns opaque data associated with the top-level interpreter. */ extern void *top_level_interpreter_data (void); extern struct interp *top_level_interpreter (void); +extern const char *top_level_interpreter_name (void); =20 extern void clear_interpreter_hooks (void); =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..a205395 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,9 @@ mi_execute_command (char *cmd, int from_tty) if (command !=3D NULL) { struct gdb_exception result; + ptid_t previous_ptid =3D inferior_ptid; + int had_execution =3D target_has_execution; + const char *top_name; =20 if (do_timings) { @@ -1191,6 +1195,32 @@ mi_execute_command (char *cmd, int from_tty) mi_out_rewind (uiout); } =20 + /* The notifications are only output when the top-level + interpreter (specified on the command line) is MI. */=20=20=20=20=20=20 + top_name =3D top_level_interpreter_name (); + if (had_execution && target_has_execution=20 + && strstr (top_name, "mi") =3D=3D top_name) + { + struct mi_interp *mi =3D top_level_interpreter_data (); + if (!ptid_equal (previous_ptid, null_ptid) + && !ptid_equal (inferior_ptid, previous_ptid)) + { + /* If there are no threads in thread table, we cannot report + anything. */ + if (strcmp (command->command, "thread-select") !=3D 0 + && thread_count () !=3D 0) + { + struct thread_info *ti =3D find_thread_pid (inferior_ptid); + gdb_assert (ti);=09=20=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..f29ecd4 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -816,7 +816,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)*(=3Dthread-selected,id=3D\".*\"\r\n)?${mi_gdb_promp= t}" { } timeout { perror "Unable to start target" @@ -1014,9 +1014,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(=3Dthread-selected,id=3D\".= *\"\r\n)?$prompt_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_sto= pped\r\n(=3Dthread-selected,id=3D\".*\"\r\n)?$prompt_re" { pass "$test" return $expect_out(2,string) } @@ -1433,7 +1433,7 @@ proc mi_send_resuming_command_raw {command test} { =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(=3Dthre= ad-selected,id=3D\".*\"\r\n)?${mi_gdb_prompt}" { # Note that lack of 'pass' call here -- this works around limi= tation # in DejaGNU xfail mechanism. mi-until.exp has this: # @@ -1491,7 +1491,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(=3Dthread-selected,id=3D\".*\"\r\= n)?$prompt_re" { return $expect_out(1,string) } -re ".*$mi_gdb_prompt" { --=20 1.5.3.5