mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-25 11:04:18 +08:00
Remote non-stop mode support.
* remote.c (pending_stop_reply): New. (struct remote_state) <non_stop_aware, support_vCont_t>: New fields. (remote_async_inferior_event_token) (remote_async_get_pending_events_token): New. (notice_new_inferiors): New, abstracted out from record_currthread. (record_currthread): Call it. (remote_threads_info): Default threads to running in non-stop mode. In non-stop mode, only qfThreadInfo is supported. (remote_close): Discard all pending stop_replies. Close the event sources. (set_stop_requested_callback): New. (remote_start_remote): Implement non-stop mode startup. In all-stop, don't clear the thread list here. (remote_non_stop_feature): New. (remote_protocol_features): Add a "QNonStop" feature. (remote_open_1): Clear cached_wait_status and non_stop_aware. Clear the thread list here. (remote_detach_1): Discard pending stop replies of the process we detached from. (extended_remote_attach_1): Implement non-stop mode. (remote_vcont_probe): Recognize `vCont;t'. (remote_vcont_resume): Implement non-stop mode. (remote_resume): Don't set waiting_for_stop_reply in non-stop mode. (remote_stop_ns): New. (remote_stop): Rename to ... (remote_stop_as): ... this. If we have a cached wait status, don't bother interrupting the remote. (remote_stop): Reimplement as wrapper around remote_stop_as and remote_stop_ns. (interrupt_query): Don't query in async mode. (struct cached_reg, cahed_reg_t): New. (struct stop_reply): New. (stop_reply_queue): New. (stop_reply_xmalloc, stop_reply_xfree) (discard_pending_stop_replies, do_stop_reply_xfree) (queued_stop_reply, push_stop_reply, peek_stop_reply) (remote_parse_stop_reply, remote_get_pending_stop_replies) (process_stop_reply): New. (remote_wait_ns): New. (remote_wait_as): Use remote_parse_stop_reply. Invalidate the notion of current general thread is a process exit was reported. (remote_wait): Call remote_wait_ns in non-stop mode. (handle_notification): New. (putpkt_binary): Handle notifications. Don't care for waiting_for_stop_reply in non-stop mode. (getpkt_sane): Rename to ... (getpkt_or_notif_sane_1): ... this. Add `expecting_notif' argument. Handle it. Handle notifications. (getpkt_sane): Reimplement as wrapper around getpkt_or_notif_sane_1. (getpkt_or_notif_sane): New. (select_new_thread_callback): Check for exited state instead of comparing the ptid against minus_one_ptid. (extended_remote_create_inferior_1): Query the remote about the current thread. (remote_supports_non_stop): New. (init_remote_ops): Register it. (remote_async_inferior_event_handler): New. (remote_async_get_pending_events_handler): New. * infcmd.c (proceed_thread_callback): Comment. (proceed_after_attach_callback, proceed_after_attach): New. (attach_command_post_wait): In background attach, resume all threads, but only if they are unsignalled, and not explicitly stopped. In foreground attach, in non-stop mode, make sure to stop all threads of the just attached to process. (attach_command): In non-stop mode: If doing a background attach, stop at least one thread. If a foreground attach, stop all threads.
This commit is contained in:
parent
50d0174816
commit
74531fed1f
@ -1,3 +1,78 @@
|
||||
2008-10-24 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
Remote non-stop mode support.
|
||||
|
||||
* remote.c (pending_stop_reply): New.
|
||||
(struct remote_state) <non_stop_aware, support_vCont_t>: New
|
||||
fields.
|
||||
(remote_async_inferior_event_token)
|
||||
(remote_async_get_pending_events_token): New.
|
||||
(notice_new_inferiors): New, abstracted out from record_currthread.
|
||||
(record_currthread): Call it.
|
||||
(remote_threads_info): Default threads to running in non-stop
|
||||
mode. In non-stop mode, only qfThreadInfo is supported.
|
||||
(remote_close): Discard all pending stop_replies. Close the event
|
||||
sources.
|
||||
(set_stop_requested_callback): New.
|
||||
(remote_start_remote): Implement non-stop mode startup. In
|
||||
all-stop, don't clear the thread list here.
|
||||
(remote_non_stop_feature): New.
|
||||
(remote_protocol_features): Add a "QNonStop" feature.
|
||||
(remote_open_1): Clear cached_wait_status and non_stop_aware.
|
||||
Clear the thread list here.
|
||||
(remote_detach_1): Discard pending stop replies of the process we
|
||||
detached from.
|
||||
(extended_remote_attach_1): Implement non-stop mode.
|
||||
(remote_vcont_probe): Recognize `vCont;t'.
|
||||
(remote_vcont_resume): Implement non-stop mode.
|
||||
(remote_resume): Don't set waiting_for_stop_reply in non-stop
|
||||
mode.
|
||||
(remote_stop_ns): New.
|
||||
(remote_stop): Rename to ...
|
||||
(remote_stop_as): ... this. If we have a cached wait status,
|
||||
don't bother interrupting the remote.
|
||||
(remote_stop): Reimplement as wrapper around remote_stop_as and
|
||||
remote_stop_ns.
|
||||
(interrupt_query): Don't query in async mode.
|
||||
(struct cached_reg, cahed_reg_t): New.
|
||||
(struct stop_reply): New.
|
||||
(stop_reply_queue): New.
|
||||
(stop_reply_xmalloc, stop_reply_xfree)
|
||||
(discard_pending_stop_replies, do_stop_reply_xfree)
|
||||
(queued_stop_reply, push_stop_reply, peek_stop_reply)
|
||||
(remote_parse_stop_reply, remote_get_pending_stop_replies)
|
||||
(process_stop_reply): New.
|
||||
(remote_wait_ns): New.
|
||||
(remote_wait_as): Use remote_parse_stop_reply. Invalidate the
|
||||
notion of current general thread is a process exit was reported.
|
||||
(remote_wait): Call remote_wait_ns in non-stop mode.
|
||||
(handle_notification): New.
|
||||
(putpkt_binary): Handle notifications. Don't care for
|
||||
waiting_for_stop_reply in non-stop mode.
|
||||
(getpkt_sane): Rename to ...
|
||||
(getpkt_or_notif_sane_1): ... this. Add `expecting_notif'
|
||||
argument. Handle it. Handle notifications.
|
||||
(getpkt_sane): Reimplement as wrapper around getpkt_or_notif_sane_1.
|
||||
(getpkt_or_notif_sane): New.
|
||||
(select_new_thread_callback): Check for exited state instead of
|
||||
comparing the ptid against minus_one_ptid.
|
||||
(extended_remote_create_inferior_1): Query the remote about the
|
||||
current thread.
|
||||
(remote_supports_non_stop): New.
|
||||
(init_remote_ops): Register it.
|
||||
(remote_async_inferior_event_handler): New.
|
||||
(remote_async_get_pending_events_handler): New.
|
||||
|
||||
* infcmd.c (proceed_thread_callback): Comment.
|
||||
(proceed_after_attach_callback, proceed_after_attach): New.
|
||||
(attach_command_post_wait): In background attach, resume all
|
||||
threads, but only if they are unsignalled, and not explicitly
|
||||
stopped. In foreground attach, in non-stop mode, make sure to
|
||||
stop all threads of the just attached to process.
|
||||
(attach_command): In non-stop mode: If doing a background attach,
|
||||
stop at least one thread. If a foreground attach, stop all
|
||||
threads.
|
||||
|
||||
2008-10-24 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* event-loop.h: Mention async_event_handlers.
|
||||
|
101
gdb/infcmd.c
101
gdb/infcmd.c
@ -570,6 +570,15 @@ start_command (char *args, int from_tty)
|
||||
static int
|
||||
proceed_thread_callback (struct thread_info *thread, void *arg)
|
||||
{
|
||||
/* We go through all threads individually instead of compressing
|
||||
into a single target `resume_all' request, because some threads
|
||||
may be stopped in internal breakpoints/events, or stopped waiting
|
||||
for its turn in the displaced stepping queue (that is, they are
|
||||
running && !executing). The target side has no idea about why
|
||||
the thread is stopped, so a `resume_all' command would resume too
|
||||
much. If/when GDB gains a way to tell the target `hold this
|
||||
thread stopped until I say otherwise', then we can optimize
|
||||
this. */
|
||||
if (!is_stopped (thread->ptid))
|
||||
return 0;
|
||||
|
||||
@ -2011,6 +2020,48 @@ vector_info (char *args, int from_tty)
|
||||
}
|
||||
|
||||
|
||||
/* Used in `attach&' command. ARG is a point to an integer
|
||||
representing a process id. Proceed threads of this process iff
|
||||
they stopped due to debugger request, and when they did, they
|
||||
reported a clean stop (TARGET_SIGNAL_0). Do not proceed threads
|
||||
that have been explicitly been told to stop. */
|
||||
|
||||
static int
|
||||
proceed_after_attach_callback (struct thread_info *thread,
|
||||
void *arg)
|
||||
{
|
||||
int pid = * (int *) arg;
|
||||
|
||||
if (ptid_get_pid (thread->ptid) == pid
|
||||
&& !is_exited (thread->ptid)
|
||||
&& !is_executing (thread->ptid)
|
||||
&& !thread->stop_requested
|
||||
&& thread->stop_signal == TARGET_SIGNAL_0)
|
||||
{
|
||||
switch_to_thread (thread->ptid);
|
||||
clear_proceed_status ();
|
||||
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
proceed_after_attach (int pid)
|
||||
{
|
||||
/* Don't error out if the current thread is running, because
|
||||
there may be other stopped threads. */
|
||||
struct cleanup *old_chain;
|
||||
|
||||
/* Backup current thread and selected frame. */
|
||||
old_chain = make_cleanup_restore_current_thread ();
|
||||
|
||||
iterate_over_threads (proceed_after_attach_callback, &pid);
|
||||
|
||||
/* Restore selected ptid. */
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Should save/restore the tty state since it might be that the
|
||||
@ -2075,11 +2126,44 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
|
||||
target_terminal_inferior ();
|
||||
|
||||
if (async_exec)
|
||||
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
|
||||
{
|
||||
/* The user requested an `attach&', so be sure to leave threads
|
||||
that didn't get a signal running. */
|
||||
|
||||
/* Immediatelly resume all suspended threads of this inferior,
|
||||
and this inferior only. This should have no effect on
|
||||
already running threads. If a thread has been stopped with a
|
||||
signal, leave it be. */
|
||||
if (non_stop)
|
||||
proceed_after_attach (inferior->pid);
|
||||
else
|
||||
{
|
||||
if (inferior_thread ()->stop_signal == TARGET_SIGNAL_0)
|
||||
{
|
||||
clear_proceed_status ();
|
||||
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The user requested a plain `attach', so be sure to leave
|
||||
the inferior stopped. */
|
||||
|
||||
if (target_can_async_p ())
|
||||
async_enable_stdin ();
|
||||
|
||||
/* At least the current thread is already stopped. */
|
||||
|
||||
/* In all-stop, by definition, all threads have to be already
|
||||
stopped at this point. In non-stop, however, although the
|
||||
selected thread is stopped, others may still be executing.
|
||||
Be sure to explicitly stop all threads of the process. This
|
||||
should have no effect on already stopped threads. */
|
||||
if (non_stop)
|
||||
target_stop (pid_to_ptid (inferior->pid));
|
||||
|
||||
/* Tell the user/frontend where we're stopped. */
|
||||
normal_stop ();
|
||||
if (deprecated_attach_hook)
|
||||
deprecated_attach_hook ();
|
||||
@ -2161,6 +2245,21 @@ attach_command (char *args, int from_tty)
|
||||
init_wait_for_inferior ();
|
||||
clear_proceed_status ();
|
||||
|
||||
if (non_stop)
|
||||
{
|
||||
/* If we find that the current thread isn't stopped, explicitly
|
||||
do so now, because we're going to install breakpoints and
|
||||
poke at memory. */
|
||||
|
||||
if (async_exec)
|
||||
/* The user requested an `attach&'; stop just one thread. */
|
||||
target_stop (inferior_ptid);
|
||||
else
|
||||
/* The user requested an `attach', so stop all threads of this
|
||||
inferior. */
|
||||
target_stop (pid_to_ptid (ptid_get_pid (inferior_ptid)));
|
||||
}
|
||||
|
||||
/* Some system don't generate traps when attaching to inferior.
|
||||
E.g. Mach 3 or GNU hurd. */
|
||||
if (!target_attach_no_wait)
|
||||
|
1342
gdb/remote.c
1342
gdb/remote.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user