diff options
author | Pedro Alves <palves@redhat.com> | 2015-11-30 16:05:13 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2015-11-30 18:36:37 +0000 |
commit | 6efcd9a8b3dc6a01cd1f212a2d854e5f8896715e (patch) | |
tree | c037bfbc8a183642709bbcd8b6f6a36d6fe5dbd3 /gdb/infrun.c | |
parent | f015c27b5294eaf87d0aa814d94972e65c7cc90e (diff) | |
download | gdb-6efcd9a8b3dc6a01cd1f212a2d854e5f8896715e.zip gdb-6efcd9a8b3dc6a01cd1f212a2d854e5f8896715e.tar.gz gdb-6efcd9a8b3dc6a01cd1f212a2d854e5f8896715e.tar.bz2 |
Remote all-stop-on-top-of-non-stop
This is the first pass at implementing support for all-stop mode
running against the remote target using the non-stop variant of the
protocol.
The trickiest part here is the initial connection setup/synching. We
need to fetch all inferiors' target descriptions etc. before stopping
threads, because stop_all_threads needs to read the threads' registers
(to record each thread's stop_pc). But OTOH, the initial inferior
setup (target_post_attach, post_create_inferior, etc.), only works
correctly if the inferior is stopped... So I've split that initial
setup part from attach_command_post_wait to a separate function, and
added a "still needs setup" flag to the inferior structure. This is
similar to gdbserver/linux-low.c's handling of discovering the
process's target description). Then if on connection all threads of
the remote inferior are running, when we go about stopping them, as
soon as they stop we call setup_inferior, from within
stop_all_threads.
Also, in all-stop, we need to process all the initial stop replies to
learn about all the pending signal the threads may already be stopped
for, and pick the one to report as current. This is exposed by
gdb.threads/reconnect-signal.exp.
gdb/
2015-11-30 Pedro Alves <palves@redhat.com>
* gdbthread.h (switch_to_thread_no_regs): Declare.
* infcmd.c (setup_inferior): New function, factored out from ...
(attach_command_post_wait): ... this. Rename to ...
(attach_post_wait): ... this. Replace parameter async_exec with
attach_post_wait_mode parameter. Adjust.
(enum attach_post_wait_mode): New enum.
(struct attach_command_continuation_args): Replace 'async_exec'
field with 'mode' field.
(attach_command_continuation): Adjust.
(attach_command): Add comment. Mark the inferior as needing
setup. Adjust to use enum attach_post_wait_mode.
(notice_new_inferior): Use switch_to_thread_no_regs. Adjust to
use enum attach_post_wait_mode.
* inferior.h (setup_inferior): Declare.
(struct inferior) <needs_setup>: New field.
* infrun.c (set_last_target_status): Make extern.
(stop_all_threads): Make extern. Setup inferior, if necessary.
* infrun.h (set_last_target_status, stop_all_threads): Declare.
* remote-notif.c (remote_async_get_pending_events_handler)
(handle_notification): Replace non_stop checks with
target_is_non_stop_p() checks.
* remote.c (remote_notice_new_inferior): Remove non_stop check.
(remote_update_thread_list): Replace non_stop check with
target_is_non_stop_p() check.
(print_one_stopped_thread): New function.
(process_initial_stop_replies): New 'from_tty' parameter.
"Notice" all new live inferiors after storing initial stops as
pending status in each corresponding thread. If all-stop, stop
all threads, try picking a signalled thread as current, and print
the status of that one thread. Record the last target status.
(remote_start_remote): Replace non_stop checks with
target_is_non_stop_p() checks. Don't query for the remote current
thread of use qOffsets here. Pass from_tty to
process_initial_stop_replies.
(extended_remote_attach): Replace non_stop checks with
target_is_non_stop_p() checks.
(extended_remote_post_attach): Send qOffsets here.
(remote_vcont_resume, remote_resume, remote_stop)
(remote_interrupt, remote_parse_stop_reply, remote_wait): Replace
non_stop checks with target_is_non_stop_p() checks.
(remote_async): If target is non-stop, mark/clear the pending
events token.
* thread.c (switch_to_thread_no_regs): New function.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index b14f34c..266b892 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2052,7 +2052,6 @@ static void keep_going_pass_signal (struct execution_control_state *ecs); static void prepare_to_wait (struct execution_control_state *ecs); static int keep_going_stepped_thread (struct thread_info *tp); static step_over_what thread_still_needs_step_over (struct thread_info *tp); -static void stop_all_threads (void); /* Are there any pending step-over requests? If so, run all we can now and return true. Otherwise, return false. */ @@ -4015,7 +4014,7 @@ init_thread_stepping_state (struct thread_info *tss) /* Set the cached copy of the last ptid/waitstatus. */ -static void +void set_last_target_status (ptid_t ptid, struct target_waitstatus status) { target_last_wait_ptid = ptid; @@ -4437,9 +4436,9 @@ save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws) } } -/* Stop all threads. */ +/* See infrun.h. */ -static void +void stop_all_threads (void) { /* We may need multiple passes to discover all threads. */ @@ -4548,6 +4547,8 @@ stop_all_threads (void) } else { + struct inferior *inf; + t = find_thread_ptid (event_ptid); if (t == NULL) t = add_thread (event_ptid); @@ -4557,6 +4558,15 @@ stop_all_threads (void) t->resumed = 0; t->control.may_range_step = 0; + /* This may be the first time we see the inferior report + a stop. */ + inf = find_inferior_ptid (event_ptid); + if (inf->needs_setup) + { + switch_to_thread_no_regs (t); + setup_inferior (0); + } + if (ws.kind == TARGET_WAITKIND_STOPPED && ws.value.sig == GDB_SIGNAL_0) { |