summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Prus <vladimir@codesourcery.com>2008-11-17 16:43:32 +0000
committerVladimir Prus <vladimir@codesourcery.com>2008-11-17 16:43:32 +0000
commit6b3e8b0e7a179e728d896a97c43decc6a12ca5c0 (patch)
tree69f60b19af35b095fd29d7132016e245afb83e95
parent0c5574a0fc1b1b66e39bad41eb636efdc674eb05 (diff)
downloadgdb-6b3e8b0e7a179e728d896a97c43decc6a12ca5c0.tar.gz
Implement =thread-selected notification.
* 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.
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/doc/ChangeLog5
-rw-r--r--gdb/doc/gdb.texinfo13
-rw-r--r--gdb/mi/mi-common.h15
-rw-r--r--gdb/mi/mi-interp.c16
-rw-r--r--gdb/mi/mi-main.c37
-rw-r--r--gdb/testsuite/ChangeLog8
-rw-r--r--gdb/testsuite/gdb.mi/mi-pthreads.exp6
-rw-r--r--gdb/testsuite/lib/mi-support.exp13
9 files changed, 103 insertions, 19 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 03b066089e1..2327ee17e90 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2008-11-17 Vladimir Prus <vladimir@codesourcery.com>
+ Implement =thread-selected notification.
+
+ * 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.
+
+2008-11-17 Vladimir Prus <vladimir@codesourcery.com>
+
Implement continue/interrupt of thread groups.
* mi/mi-main.c (proceed_thread_callback): New.
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 18f665000c1..e0b6aa41bce 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,5 +1,10 @@
2008-11-17 Vladimir Prus <vladimir@codesourcery.com>
+ * gdb.texinfo (GDB/MI Async Records): Document
+ =thread-selected.
+
+2008-11-17 Vladimir Prus <vladimir@codesourcery.com>
+
* observer.texi (new_inferior, inferior_exit): New observers.
2008-10-27 Pedro Alves <pedro@codesourcery.com>
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 261d1c7e7b9..26cf4b64cf2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19273,6 +19273,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 @code{-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
+@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 to apply to
+that thread.
+
@end table
diff --git a/gdb/mi/mi-common.h b/gdb/mi/mi-common.h
index e47afd1ca30..8778e745a8d 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 e05b1ad5e2b..5aa0e6c8255 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 6e5511fee99..7f5ec2f6778 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"
@@ -1203,6 +1204,7 @@ mi_execute_command (char *cmd, int from_tty)
if (command != NULL)
{
struct gdb_exception result;
+ ptid_t previous_ptid = inferior_ptid;
if (do_timings)
{
@@ -1227,6 +1229,41 @@ mi_execute_command (char *cmd, int from_tty)
mi_out_rewind (uiout);
}
+ if (/* The notifications are only output when the top-level
+ interpreter (specified on the command line) is MI. */
+ ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ()))
+ /* Don't try report anything if there are no threads --
+ the program is dead. */
+ && thread_count () != 0
+ /* -thread-select explicitly changes thread. If frontend uses that
+ internally, we don't want to emit =thread-selected, since
+ =thread-selected is supposed to indicate user's intentions. */
+ && strcmp (command->command, "thread-select") != 0)
+ {
+ struct mi_interp *mi = top_level_interpreter_data ();
+ struct thread_info *ti = inferior_thread ();
+ int report_change;
+
+ if (command->thread == -1)
+ {
+ report_change = !ptid_equal (previous_ptid, null_ptid)
+ && !ptid_equal (inferior_ptid, previous_ptid);
+ }
+ else
+ {
+ report_change = (ti->num != command->thread);
+ }
+
+ if (report_change)
+ {
+ 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/ChangeLog b/gdb/testsuite/ChangeLog
index 1c66e082afa..58b2a2a176e 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,13 @@
2008-11-17 Vladimir Prus <vladimir@codesourcery.com>
+ * 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): Be prepared for
+ =thread-selected.
+
+2008-11-17 Vladimir Prus <vladimir@codesourcery.com>
+
* gdb.mi/mi-nonstop.exp: Expect 'group-id' field.
* lib/mi-support.exp: Likewise.
diff --git a/gdb/testsuite/gdb.mi/mi-pthreads.exp b/gdb/testsuite/gdb.mi/mi-pthreads.exp
index dbb3ece3ffa..0ab57158798 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 39db896306e..56c1b9fd510 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -30,6 +30,8 @@ global mi_inferior_tty_name
set MIFLAGS "-i=mi"
+set thread_selected_re "=thread-selected,id=\"\[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
if [target_info exists gdb_init_command] {
send_gdb "[target_info gdb_init_command]\n";
@@ -816,7 +819,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\",group-id=\"\[0-9\]+\"\r\n)*${mi_gdb_prompt}" {
+ -re "220\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n|=thread-created,id=\"1\",group-id=\"\[0-9\]+\"\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
set after_stopped ""
set after_reason ""
@@ -1014,9 +1018,9 @@ proc mi_expect_stop { reason func args file line extra test } {
set any "\[^\n\]*"
- verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=$any,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}\r\n$after_stopped$prompt_re"
+ verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=$any,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n($thread_selected_re)?$prompt_re"
gdb_expect {
- -re "\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=$any,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n$prompt_re" {
+ -re "\\*stopped,${r}${a}${bn}thread-id=\"$decimal\",stopped-threads=$any,frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\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} {
global mi_gdb_prompt
+ global thread_selected_re
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_re)?${mi_gdb_prompt}" {
# Note that lack of 'pass' call here -- this works around limitation
# in DejaGNU xfail mechanism. mi-until.exp has this:
#