Implement *running.

* Makefile.in: Update dependencies.
        * gdbthread.h (struct thread_info): New field
        running_.
        (set_running, is_running): New.
        * thread.c (set_running, is_running): New.
        * inferior.h (suppress_normal_stop_observer): Rename to...
        (suppress_run_stop_observers): ..this.
        * infcmd.c (suppress_normal_stop_observer): Rename to...
        (suppress_run_stop_observers): ..this.
        (finish_command_continuation, finish_command): Adjust.
        * infcall.c (call_function_by_hand): Adjust.
        * infrun.c (normal_stop): Call set_running.
        * target.c (target_resume): New.  Call set_running.
        * target.h (target_resume): Convert from macro to
        a function.

        * mi/mi-interp.c (mi_on_resume): New.
        (mi_interpreter_init): Register mi_on_resume.
This commit is contained in:
Vladimir Prus 2008-06-10 10:23:54 +00:00
parent f7f9a841a3
commit e1ac332873
20 changed files with 176 additions and 34 deletions

View file

@ -1,3 +1,25 @@
2008-06-10 Vladimir Prus <vladimir@codesourcery.com>
Implement *running.
* Makefile.in: Update dependencies.
* gdbthread.h (struct thread_info): New field
running_.
(set_running, is_running): New.
* thread.c (set_running, is_running): New.
* inferior.h (suppress_normal_stop_observer): Rename to...
(suppress_run_stop_observers): ..this.
* infcmd.c (suppress_normal_stop_observer): Rename to...
(suppress_run_stop_observers): ..this.
(finish_command_continuation, finish_command): Adjust.
* infcall.c (call_function_by_hand): Adjust.
* infrun.c (normal_stop): Call set_running.
* target.c (target_resume): New. Call set_running.
* target.h (target_resume): Convert from macro to
a function.
* mi/mi-interp.c (mi_on_resume): New.
(mi_interpreter_init): Register mi_on_resume.
2008-06-10 Vladimir Prus <vladimir@codesourcery.com>
Use observers to report stop events in MI.

View file

@ -2923,7 +2923,7 @@ symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \
target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
$(exceptions_h) $(target_descriptions_h) $(gdb_stdint_h)
$(exceptions_h) $(target_descriptions_h) $(gdb_stdint_h) $(gdbthread_h)
target-descriptions.o: target-descriptions.c $(defs_h) $(arch_utils_h) \
$(target_h) $(target_descriptions_h) $(vec_h) $(xml_tdesc_h) \
$(gdbcmd_h) $(gdb_assert_h) $(gdbtypes_h) $(reggroups_h) \

View file

@ -1,3 +1,8 @@
2008-06-10 Vladimir Prus <vladimir@codesourcery.com>
* observer.texi (target_resumed): New observer.
* gdb.texinfo (GDB/MI Output Records): Document *running.
2008-06-06 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Completion): Add field name example.

View file

@ -18335,6 +18335,17 @@ The following is the list of possible async records:
@table @code
@item *running,thread-id="@var{thread}"
The target is now running. The @var{thread} field tells which
specific thread is now running, and can be @samp{all} if all threads
are running. The frontend should assume that no interaction with a
running thread is possible after this notification is produced.
The frontend should not assume that this notification is output
only once for any command. @value{GDBN} may emit this notification
several times, either for different threads, because it cannot resume
all threads together, or even for a single thread, if the thread must
be stepped though some code before letting it run freely.
@item *stopped,reason="@var{reason}"
The target has stopped. The @var{reason} field can have one of the
following values:

View file

@ -137,3 +137,8 @@ The thread specified by @var{t} has been created.
The thread specified by @var{t} has exited.
@end deftypefun
@deftypefun void target_resumed (ptid_t @var{ptid})
The target was resumed. The @var{ptid} parameter specifies which
thread was resume, and may be RESUME_ALL if all threads are resumed.
@end deftypefun

View file

@ -63,6 +63,10 @@ struct thread_info
when we finally do stop stepping. */
bpstat stepping_through_solib_catchpoints;
/* This field is internal for thread.c. Never access it directly,
use is_running instead. */
int running_;
/* Private data used by the target vector implementation. */
struct private_thread_info *private;
};
@ -146,6 +150,13 @@ extern void load_infrun_state (ptid_t ptid,
/* Switch from one thread to another. */
extern void switch_to_thread (ptid_t ptid);
/* Marks thread PTID is running, or stopped.
If PIDGET (PTID) is -1, marks all threads. */
extern void set_running (ptid_t ptid, int running);
/* Reports if thread PTID is know to be running right now. */
extern int is_running (ptid_t ptid);
/* Commands with a prefix of `thread'. */
extern struct cmd_list_element *thread_cmd_list;

View file

@ -721,8 +721,8 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
saved_async = target_async_mask (0);
old_cleanups2 = make_cleanup_restore_integer
(&suppress_normal_stop_observer);
suppress_normal_stop_observer = 1;
(&suppress_run_stop_observers);
suppress_run_stop_observers = 1;
proceed (real_pc, TARGET_SIGNAL_0, 0);
do_cleanups (old_cleanups2);

View file

@ -207,8 +207,9 @@ int step_multi;
struct gdb_environ *inferior_environ;
/* When set, normal_stop will not call the normal_stop observer. */
int suppress_normal_stop_observer = 0;
/* When set, normal_stop will not call the normal_stop observer.
Resume observer likewise will not be called. */
int suppress_run_stop_observers = 0;
/* Accessor routines. */
@ -1303,7 +1304,7 @@ finish_command_continuation (struct continuation_arg *arg, int error_p)
observer_notify_normal_stop (stop_bpstat);
}
suppress_normal_stop_observer = 0;
suppress_run_stop_observers = 0;
delete_breakpoint (breakpoint);
}
@ -1370,8 +1371,8 @@ finish_command (char *arg, int from_tty)
}
proceed_to_finish = 1; /* We want stop_registers, please... */
make_cleanup_restore_integer (&suppress_normal_stop_observer);
suppress_normal_stop_observer = 1;
make_cleanup_restore_integer (&suppress_run_stop_observers);
suppress_run_stop_observers = 1;
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
arg1 =

View file

@ -393,7 +393,7 @@ void displaced_step_dump_bytes (struct ui_file *file,
/* When set, normal_stop will not call the normal_stop observer. */
extern int suppress_normal_stop_observer;
extern int suppress_run_stop_observers;
/* Possible values for gdbarch_call_dummy_location. */
#define ON_STACK 1

View file

@ -3772,11 +3772,12 @@ Further execution is probably impossible.\n"));
done:
annotate_stopped ();
if (!suppress_normal_stop_observer && !step_multi)
if (!suppress_run_stop_observers && !step_multi)
observer_notify_normal_stop (stop_bpstat);
/* Delete the breakpoint we stopped at, if it wants to be deleted.
Delete any breakpoint that is to be deleted at the next stop. */
breakpoint_auto_delete (stop_bpstat);
set_running (pid_to_ptid (-1), 0);
}
static int

View file

@ -69,6 +69,7 @@ static void mi_on_normal_stop (struct bpstats *bs);
static void mi_new_thread (struct thread_info *t);
static void mi_thread_exit (struct thread_info *t);
static void mi_on_resume (ptid_t ptid);
static void *
mi_interpreter_init (int top_level)
@ -94,6 +95,7 @@ mi_interpreter_init (int top_level)
observer_attach_new_thread (mi_new_thread);
observer_attach_thread_exit (mi_thread_exit);
observer_attach_normal_stop (mi_on_normal_stop);
observer_attach_target_resumed (mi_on_resume);
}
return mi;
@ -327,6 +329,19 @@ mi_on_normal_stop (struct bpstats *bs)
gdb_flush (raw_stdout);
}
static void
mi_on_resume (ptid_t ptid)
{
if (PIDGET (ptid) == -1)
fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
else
{
struct thread_info *ti = find_thread_pid (ptid);
gdb_assert (ti);
fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n", ti->num);
}
}
extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
void

View file

@ -40,6 +40,7 @@
#include "exceptions.h"
#include "target-descriptions.h"
#include "gdb_stdint.h"
#include "gdbthread.h"
static void target_info (char *, int);
@ -1715,6 +1716,14 @@ target_disconnect (char *args, int from_tty)
tcomplain ();
}
void
target_resume (ptid_t ptid, int step, enum target_signal signal)
{
dcache_invalidate (target_dcache);
(*current_target.to_resume) (ptid, step, signal);
set_running (ptid, 1);
}
/* Look through the list of possible targets for a target that can
follow forks. */

View file

@ -586,11 +586,7 @@ extern void target_disconnect (char *, int);
the target, or TARGET_SIGNAL_0 for no signal. The caller may not
pass TARGET_SIGNAL_DEFAULT. */
#define target_resume(ptid, step, siggnal) \
do { \
dcache_invalidate(target_dcache); \
(*current_target.to_resume) (ptid, step, siggnal); \
} while (0)
extern void target_resume (ptid_t ptid, int step, enum target_signal signal);
/* Wait for process pid to do something. PTID = -1 to wait for any
pid to do something. Return pid of child, or -1 in case of error;

View file

@ -1,3 +1,12 @@
2008-06-10 Vladimir Prus <vladimir@codesourcery.com>
* gdb.mi/mi-console.exp: Adjust.
* gdb.mi/mi-syn-frame.exp: Adjust.
* gdb.mi/mi2-console.exp: Adjust.
* gdb.mi/mi2-syn-frame.exp: Adjust.
* lib/mi-support.exp (mi_run_cmd): Adjust.
(mi_send_resuming_command): Adjust.
2008-06-10 Vladimir Prus <vladimir@codesourcery.com>
* gdb.mi/mi-break.exp (test_ignore_count): Adjust stopped pattern.

View file

@ -52,7 +52,7 @@ mi_run_to_main
# Next over the hello() call which will produce lots of output
mi_gdb_test "220-exec-next" \
"220\\^running" \
"220\\^running(\r\n\\*running,thread-id=\"all\")?" \
"Testing console output" \
"Hello \\\\\"!\[\r\n\]+"

View file

@ -46,7 +46,7 @@ mi_create_breakpoint "foo" 2 keep foo ".*mi-syn-frame.c" $decimal $hex \
# Call foo() by hand, where we'll hit a breakpoint.
#
mi_gdb_test "401-data-evaluate-expression foo()" "401\\^error,msg=\"The program being debugged stopped while in a function called from GDB.\\\\nWhen the function \\(foo\\) is done executing, GDB will silently\\\\nstop \\(instead of continuing to evaluate the expression containing\\\\nthe function call\\).\"" "call inferior's function with a breakpoint set in it"
mi_gdb_test "401-data-evaluate-expression foo()" ".*401\\^error,msg=\"The program being debugged stopped while in a function called from GDB.\\\\nWhen the function \\(foo\\) is done executing, GDB will silently\\\\nstop \\(instead of continuing to evaluate the expression containing\\\\nthe function call\\).\"" "call inferior's function with a breakpoint set in it"
mi_gdb_test "402-stack-list-frames" "402\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"foo\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"1\",addr=\"$hex\",func=\"<function called from gdb>\"\},frame=\{level=\"2\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\}.*\\\]" "backtrace from inferior function stopped at bp, showing gdb dummy frame"
@ -54,9 +54,7 @@ mi_gdb_test "402-stack-list-frames" "402\\^done,stack=\\\[frame=\{level=\"0\",ad
#
# Continue back to main()
#
mi_gdb_test "403-exec-continue" \
"403\\^running" \
"testing exec continue"
mi_send_resuming_command "exec-continue" "testing exec continue"
mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
@ -73,7 +71,7 @@ mi_create_breakpoint "subroutine" 3 keep subroutine ".*mi-syn-frame.c" $decimal
"insert breakpoint subroutine"
mi_gdb_test "406-data-evaluate-expression have_a_very_merry_interrupt()" \
"406\\^error,msg=\"The program being debugged stopped while in a function called from GDB.\\\\nWhen the function \\(have_a_very_merry_interrupt\\) is done executing, GDB will silently\\\\nstop \\(instead of continuing to evaluate the expression containing\\\\nthe function call\\).\"" \
".*406\\^error,msg=\"The program being debugged stopped while in a function called from GDB.\\\\nWhen the function \\(have_a_very_merry_interrupt\\) is done executing, GDB will silently\\\\nstop \\(instead of continuing to evaluate the expression containing\\\\nthe function call\\).\"" \
"data evaluate expression"
# We should have both a signal handler and a call dummy frame
@ -84,7 +82,7 @@ mi_gdb_test "407-stack-list-frames" \
"list stack frames"
mi_gdb_test "408-exec-continue" "408\\^running"
mi_send_resuming_command "exec-continue" "testing exec continue"
mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
@ -97,7 +95,7 @@ mi_gdb_test "409-stack-list-frames 0 0" \
#
mi_gdb_test "410-data-evaluate-expression bar()" \
"410\\^error,msg=\"The program being debugged was signaled while in a function called from GDB.\\\\nGDB remains in the frame where the signal was received.\\\\nTo change this behavior use \\\\\"set unwindonsignal on\\\\\"\\\\nEvaluation of the expression containing the function \\(bar\\) will be abandoned.\"" \
".*410\\^error,msg=\"The program being debugged was signaled while in a function called from GDB.\\\\nGDB remains in the frame where the signal was received.\\\\nTo change this behavior use \\\\\"set unwindonsignal on\\\\\"\\\\nEvaluation of the expression containing the function \\(bar\\) will be abandoned.\"" \
"call inferior function which raises exception"
mi_gdb_test "411-stack-list-frames" "411\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"bar\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"},frame=\{level=\"1\",addr=\"$hex\",func=\"<function called from gdb>\"\},frame=\{level=\"2\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"}.*\\\]" "backtrace from inferior function at exception"

View file

@ -53,7 +53,7 @@ mi_run_to_main
# Next over the hello() call which will produce lots of output
send_gdb "220-exec-next\n"
gdb_expect {
-re "220\\^running\r\n$mi_gdb_prompt" {
-re "220\\^running\r\n(\\*running,thread-id=\"all\"\r\n)?$mi_gdb_prompt" {
pass "Started step over hello"
}
timeout {

View file

@ -48,7 +48,7 @@ mi_create_breakpoint "foo" 2 keep foo ".*mi-syn-frame.c" $decimal $hex \
# Call foo() by hand, where we'll hit a breakpoint.
#
mi_gdb_test "401-data-evaluate-expression foo()" "401\\^error,msg=\"The program being debugged stopped while in a function called from GDB.\\\\nWhen the function \\(foo\\) is done executing, GDB will silently\\\\nstop \\(instead of continuing to evaluate the expression containing\\\\nthe function call\\).\"" "call inferior's function with a breakpoint set in it"
mi_gdb_test "401-data-evaluate-expression foo()" ".*401\\^error,msg=\"The program being debugged stopped while in a function called from GDB.\\\\nWhen the function \\(foo\\) is done executing, GDB will silently\\\\nstop \\(instead of continuing to evaluate the expression containing\\\\nthe function call\\).\"" "call inferior's function with a breakpoint set in it"
mi_gdb_test "402-stack-list-frames" "402\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"foo\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"1\",addr=\"$hex\",func=\"<function called from gdb>\"\},frame=\{level=\"2\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\}.*\\\]" "backtrace from inferior function stopped at bp, showing gdb dummy frame"
@ -56,9 +56,7 @@ mi_gdb_test "402-stack-list-frames" "402\\^done,stack=\\\[frame=\{level=\"0\",ad
# Continue back to main()
#
mi_gdb_test "403-exec-continue" \
"403\\^running" \
"testing exec continue"
mi_send_resuming_command "exec-continue" "testing exec continue"
mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
@ -75,7 +73,7 @@ mi_create_breakpoint "subroutine" 3 keep subroutine ".*mi-syn-frame.c" $decimal
"insert breakpoint subroutine"
mi_gdb_test "406-data-evaluate-expression have_a_very_merry_interrupt()" \
"406\\^error,msg=\"The program being debugged stopped while in a function called from GDB.\\\\nWhen the function \\(have_a_very_merry_interrupt\\) is done executing, GDB will silently\\\\nstop \\(instead of continuing to evaluate the expression containing\\\\nthe function call\\).\"" \
".*406\\^error,msg=\"The program being debugged stopped while in a function called from GDB.\\\\nWhen the function \\(have_a_very_merry_interrupt\\) is done executing, GDB will silently\\\\nstop \\(instead of continuing to evaluate the expression containing\\\\nthe function call\\).\"" \
"evaluate expression have_a_very_merry_interrupt"
# We should have both a signal handler and a call dummy frame
@ -85,7 +83,7 @@ mi_gdb_test "407-stack-list-frames" \
"407\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"subroutine\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"1\",addr=\"$hex\",func=\"handler\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"2\",addr=\"$hex\",func=\"<signal handler called>\"\},.*frame=\{level=\"$decimal\",addr=\"$hex\",func=\"have_a_very_merry_interrupt\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"$decimal\",addr=\"$hex\",func=\"<function called from gdb>\"\},frame=\{level=\"$decimal\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\}.*\\\]" \
"list stack frames"
mi_gdb_test "408-exec-continue" "408\\^running"
mi_send_resuming_command "exec-continue" "testing exec continue"
mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
@ -97,7 +95,7 @@ mi_gdb_test "409-stack-list-frames 0 0" \
# Call bar() by hand, which should get an exception while running.
#
mi_gdb_test "410-data-evaluate-expression bar()" "410\\^error,msg=\"The program being debugged was signaled while in a function called from GDB.\\\\nGDB remains in the frame where the signal was received.\\\\nTo change this behavior use \\\\\"set unwindonsignal on\\\\\"\\\\nEvaluation of the expression containing the function \\(bar\\) will be abandoned.\"" "call inferior function which raises exception"
mi_gdb_test "410-data-evaluate-expression bar()" ".*410\\^error,msg=\"The program being debugged was signaled while in a function called from GDB.\\\\nGDB remains in the frame where the signal was received.\\\\nTo change this behavior use \\\\\"set unwindonsignal on\\\\\"\\\\nEvaluation of the expression containing the function \\(bar\\) will be abandoned.\"" "call inferior function which raises exception"
mi_gdb_test "411-stack-list-frames" "411\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"bar\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"},frame=\{level=\"1\",addr=\"$hex\",func=\"<function called from gdb>\"\},frame=\{level=\"2\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"}.*\\\]" "backtrace from inferior function at exception"

View file

@ -802,7 +802,7 @@ proc mi_run_cmd {args} {
if [target_info exists gdb,do_reload_on_run] {
send_gdb "220-exec-continue\n";
gdb_expect 60 {
-re "220\\^running\[\r\n\]+$mi_gdb_prompt$" {}
-re "220\\^running\[\r\n\]+(\\*running,thread-id=\"\[^\"\]+\"\r\n)?$mi_gdb_prompt$" {}
default {}
}
return;
@ -823,7 +823,7 @@ proc mi_run_cmd {args} {
send_gdb "220-exec-run $args\n"
gdb_expect {
-re "220\\^running\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)*${mi_gdb_prompt}" {
}
timeout {
perror "Unable to start target"
@ -1399,7 +1399,7 @@ proc mi_send_resuming_command {command test} {
send_gdb "220-$command\n"
gdb_expect {
-re "220\\^running\r\n${mi_gdb_prompt}" {
-re "220\\^running\r\n(\\*running,thread-id=\"\[^\"\]+\"\r\n)?${mi_gdb_prompt}" {
}
-re ".*${mi_gdb_prompt}" {
fail "$test (failed to resume)"

View file

@ -414,6 +414,67 @@ prune_threads (void)
}
}
static int main_thread_running = 0;
void
set_running (ptid_t ptid, int running)
{
struct thread_info *tp;
if (!thread_list)
{
/* This is one of the targets that does not add main
thread to the thread list. Just use a single
global flag to indicate that a thread is running.
This problem is unique to ST programs. For MT programs,
the main thread is always present in the thread list. If it's
not, the first call to context_switch will mess up GDB internal
state. */
if (running && !main_thread_running && !suppress_run_stop_observers)
observer_notify_target_resumed (ptid);
main_thread_running = running;
return;
}
/* We try not to notify the observer if no thread has actually changed
the running state -- merely to reduce the number of messages to
frontend. Frontend is supposed to handle multiple *running just fine. */
if (PIDGET (ptid) == -1)
{
int any_started = 0;
for (tp = thread_list; tp; tp = tp->next)
{
if (running && !tp->running_)
any_started = 1;
tp->running_ = running;
}
if (any_started && !suppress_run_stop_observers)
observer_notify_target_resumed (ptid);
}
else
{
tp = find_thread_pid (ptid);
gdb_assert (tp);
if (running && !tp->running_ && !suppress_run_stop_observers)
observer_notify_target_resumed (ptid);
tp->running_ = running;
}
}
int
is_running (ptid_t ptid)
{
struct thread_info *tp;
if (!thread_list)
return main_thread_running;
tp = find_thread_pid (ptid);
gdb_assert (tp);
return tp->running_;
}
/* Prints the list of threads and their details on UIOUT.
This is a version of 'info_thread_command' suitable for
use from MI.