diff options
author | Pedro Alves <palves@redhat.com> | 2008-10-24 20:38:26 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2008-10-24 20:38:26 +0000 |
commit | 74531fed1f2d662debc2c209b8b3faddceb55960 (patch) | |
tree | 92adb77a295893fe62720a05b2c71e9c50fe97e8 /gdb/infcmd.c | |
parent | 50d01748162c1853ccb2d4659e9471f1029e9a7d (diff) | |
download | gdb-74531fed1f2d662debc2c209b8b3faddceb55960.zip gdb-74531fed1f2d662debc2c209b8b3faddceb55960.tar.gz gdb-74531fed1f2d662debc2c209b8b3faddceb55960.tar.bz2 |
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.
Diffstat (limited to 'gdb/infcmd.c')
-rw-r--r-- | gdb/infcmd.c | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 06e3bc5..1854985 100644 --- a/gdb/infcmd.c +++ b/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) |