From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4389 invoked by alias); 13 Aug 2008 12:41:14 -0000 Received: (qmail 4375 invoked by uid 22791); 13 Aug 2008 12:41:13 -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, 13 Aug 2008 12:40:31 +0000 Received: (qmail 20757 invoked from network); 13 Aug 2008 12:40:29 -0000 Received: from unknown (HELO localhost) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 13 Aug 2008 12:40:29 -0000 From: Vladimir Prus Date: Wed, 13 Aug 2008 12:41:00 -0000 Subject: [RFA/RFC] Implement =thread-selected notification. To: gdb-patches@sources.redhat.com X-TUID: 179682afe9c5070c X-Length: 9860 X-UID: 291 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200808131640.16054.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-08/txt/msg00343.txt.bz2 I've previously posted a spec of how thread management should work between MI frontend and GDB. Parts of that spec -- namely --thread and --frame options were implemented. This patch adds =thread-selected notification, so that I go ahead and convert that spec into manual section. I went with Dan's suggestion of reporting the change if we end up with different thread after MI command is done -- which means we don't have to carefully suppress notifications due to "internal" thread switches. Only doc changes need formal approval; feedback on other bits is appreciated. - Volodya [doc/ChangeLog] * gdb.texinfo (GDB/MI Async Records): Document =thread-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 =thread-selected. * lib/mi-support (mi_run_cmd, mi_expect_stop) (mi_send_resuming_command_raw, mi_get_stop_line): Be prepared for =thread-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 72455f3..e8238d8 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -18821,6 +18821,19 @@ A signal was received by the inferior. @itemx =thread-exited,id="@var{id}" A thread either was created, or has exited. The @var{id} field contains the @value{GDBN} identifier of the thread. + +@item =thread-selected,id="@var{id}" +Informs that the selected thread was changed as result of the last +command. This notification is not emitted as result of -thread-select +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 +``thread'' command, will generate this notification. + +It is suggested that the frontend, in response to this notification, +hightlights the selected thread and makes any further operations +apply to this thread. + @end table diff --git a/gdb/interps.c b/gdb/interps.c index 3bb7811..dcd430c 100644 --- a/gdb/interps.c +++ b/gdb/interps.c @@ -484,6 +484,13 @@ top_level_interpreter_data (void) return top_level_interpreter_ptr->data; } +const char * +top_level_interpreter_name (void) +{ + gdb_assert (top_level_interpreter_ptr); + return top_level_interpreter_ptr->name; +} + /* 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); extern void clear_interpreter_hooks (void); 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 const char *async_reason_lookup (enum async_reply_reason reason); +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 361cf7f..e7b9244 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" -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 733fc47..a77d811 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 @@ -1031,6 +1032,9 @@ mi_execute_command (char *cmd, int from_tty) if (command != NULL) { struct gdb_exception result; + ptid_t previous_ptid = inferior_ptid; + int had_execution = target_has_execution; + const char *top_name; if (do_timings) { @@ -1055,6 +1059,32 @@ mi_execute_command (char *cmd, int from_tty) mi_out_rewind (uiout); } + /* 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) + { + struct mi_interp *mi = 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") != 0 + && thread_count () != 0) + { + struct thread_info *ti = find_thread_pid (inferior_ptid); + gdb_assert (ti); + target_terminal_ours (); + fprintf_unfiltered (mi->event_channel, + "thread-selected,id=\"%d\"", + ti->num); + gdb_flush (mi->event_channel); + } + } + } + mi_parse_free (command); } 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=\"$thread\",frame={.*}(,line=\"(-)?\[0-9\]+\",file=\".*\")?" \ "check_mi_thread_command_set: -thread-select $thread" } + + foreach thread $thread_list { + mi_gdb_test "-interpreter-exec console \"thread $thread\"" \ + ".*\\^done\r\n=thread-selected,id=\"$thread\"" \ + "check =thread-selected: thread $thread" + } } # diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index 762e4e2..30961b2 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -816,7 +816,7 @@ proc mi_run_cmd {args} { send_gdb "220-exec-run $args\n" gdb_expect { - -re "220\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n|=thread-created,id=\"1\"\r\n)*${mi_gdb_prompt}" { + -re "220\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n|=thread-created,id=\"1\"\r\n)*(=thread-selected,id=\".*\"\r\n)?${mi_gdb_prompt}" { } timeout { perror "Unable to start target" @@ -1009,9 +1009,9 @@ proc mi_expect_stop { reason func args file line extra test } { set a $after_reason - verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=.*,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n$prompt_re$" + verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=.*,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n(=thread-selected,id=\".*\"\r\n)?$prompt_re$" gdb_expect { - -re "\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=.*,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n$prompt_re$" { + -re "\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=.*,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n(=thread-selected,id=\".*\"\r\n)?$prompt_re$" { pass "$test" return $expect_out(2,string) } @@ -1390,7 +1390,7 @@ proc mi_send_resuming_command_raw {command test} { send_gdb "$command\n" gdb_expect { - -re "\\^running\r\n\\*running,thread-id=\"\[^\"\]+\"\r\n${mi_gdb_prompt}" { + -re "\\^running\r\n\\*running,thread-id=\"\[^\"\]+\"\r\n(=thread-selected,id=\".*\"\r\n)?${mi_gdb_prompt}" { # Note that lack of 'pass' call here -- this works around limitation # in DejaGNU xfail mechanism. mi-until.exp has this: # @@ -1446,7 +1446,7 @@ proc mi_get_stop_line {test} { } gdb_expect { - -re ".*line=\"(.*)\".*\r\n$prompt_re$" { + -re ".*line=\"(\[0-9\]+)\"\[^\r\]*\r\n(=thread-selected,id=\".*\"\r\n)?$prompt_re$" { return $expect_out(1,string) } -re ".*$mi_gdb_prompt$" { -- 1.5.3.5