Don't elide all inlined frames
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 233d0f8ca5ef5a13ca0d05c80206918ee72927ba..df19478ef3c595d4c2ef3c2091279b106bef2138 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-struct-independent code to start (run) and stop an inferior
    process.
 
-   Copyright (C) 1986-2015 Free Software Foundation, Inc.
+   Copyright (C) 1986-2018 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -38,7 +38,7 @@
 #include "inf-loop.h"
 #include "regcache.h"
 #include "value.h"
-#include "observer.h"
+#include "observable.h"
 #include "language.h"
 #include "solib.h"
 #include "main.h"
 #include "target-dcache.h"
 #include "terminal.h"
 #include "solist.h"
+#include "event-loop.h"
+#include "thread-fsm.h"
+#include "common/enum-flags.h"
+#include "progspace-and-thread.h"
+#include "common/gdb_optional.h"
+#include "arch-utils.h"
 
 /* Prototypes for local functions */
 
-static void signals_info (char *, int);
-
-static void handle_command (char *, int);
-
 static void sig_print_info (enum gdb_signal);
 
 static void sig_print_header (void);
 
-static void resume_cleanups (void *);
-
-static int hook_stop_stub (void *);
-
-static int restore_selected_frame (void *);
-
 static int follow_fork (void);
 
 static int follow_fork_inferior (int follow_child, int detach_fork);
 
 static void follow_inferior_reset_breakpoints (void);
 
-static void set_schedlock_func (char *args, int from_tty,
-                               struct cmd_list_element *c);
-
 static int currently_stepping (struct thread_info *tp);
 
-void _initialize_infrun (void);
-
 void nullify_last_target_wait_ptid (void);
 
 static void insert_hp_step_resume_breakpoint_at_frame (struct frame_info *);
@@ -101,6 +92,43 @@ static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
 
 static int maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc);
 
+/* Asynchronous signal handler registered as event loop source for
+   when we have pending events ready to be passed to the core.  */
+static struct async_event_handler *infrun_async_inferior_event_token;
+
+/* Stores whether infrun_async was previously enabled or disabled.
+   Starts off as -1, indicating "never enabled/disabled".  */
+static int infrun_is_async = -1;
+
+/* See infrun.h.  */
+
+void
+infrun_async (int enable)
+{
+  if (infrun_is_async != enable)
+    {
+      infrun_is_async = enable;
+
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: infrun_async(%d)\n",
+                           enable);
+
+      if (enable)
+       mark_async_event_handler (infrun_async_inferior_event_token);
+      else
+       clear_async_event_handler (infrun_async_inferior_event_token);
+    }
+}
+
+/* See infrun.h.  */
+
+void
+mark_infrun_async_event_handler (void)
+{
+  mark_async_event_handler (infrun_async_inferior_event_token);
+}
+
 /* When set, stop the 'step' command if we enter a function which has
    no line number information.  The normal behavior is that we step
    over such function.  */
@@ -112,10 +140,6 @@ show_step_stop_if_no_debug (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Mode of the step operation is %s.\n"), value);
 }
 
-/* In asynchronous mode, but simulating synchronous execution.  */
-
-int sync_execution = 0;
-
 /* proceed and normal_stop use this to notify the user when the
    inferior stopped in a different thread than it had been running
    in.  */
@@ -166,7 +190,7 @@ show_disable_randomization (struct ui_file *file, int from_tty,
 }
 
 static void
-set_disable_randomization (char *args, int from_tty,
+set_disable_randomization (const char *args, int from_tty,
                           struct cmd_list_element *c)
 {
   if (!target_supports_disable_randomization ())
@@ -181,7 +205,7 @@ int non_stop = 0;
 static int non_stop_1 = 0;
 
 static void
-set_non_stop (char *args, int from_tty,
+set_non_stop (const char *args, int from_tty,
              struct cmd_list_element *c)
 {
   if (target_has_execution)
@@ -210,7 +234,7 @@ int observer_mode = 0;
 static int observer_mode_1 = 0;
 
 static void
-set_observer_mode (char *args, int from_tty,
+set_observer_mode (const char *args, int from_tty,
                   struct cmd_list_element *c)
 {
   if (target_has_execution)
@@ -335,7 +359,8 @@ int stop_on_solib_events;
    as appropriate when the above flag is changed.  */
 
 static void
-set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
+set_stop_on_solib_events (const char *args,
+                         int from_tty, struct cmd_list_element *c)
 {
   update_solib_breakpoints ();
 }
@@ -348,11 +373,6 @@ show_stop_on_solib_events (struct ui_file *file, int from_tty,
                    value);
 }
 
-/* Nonzero means expecting a trace trap
-   and should stop the inferior and return silently when it happens.  */
-
-int stop_after_trap;
-
 /* Nonzero after stop if current stack frame should be printed.  */
 
 static int stop_print_frame;
@@ -407,7 +427,7 @@ follow_fork_inferior (int follow_child, int detach_fork)
 
   if (has_vforked
       && !non_stop /* Non-stop always resumes both branches.  */
-      && (!target_is_async_p () || sync_execution)
+      && current_ui->prompt_state == PROMPT_BLOCKED
       && !(follow_child || detach_fork || sched_multi))
     {
       /* The parent stays blocked inside the vfork syscall until the
@@ -428,8 +448,6 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       /* Detach new forked process?  */
       if (detach_fork)
        {
-         struct cleanup *old_chain;
-
          /* Before detaching from the child, remove all breakpoints
             from it.  If we forked, then this has already been taken
             care of by infrun.c.  If we vforked however, any
@@ -443,14 +461,14 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
              remove_breakpoints_pid (ptid_get_pid (inferior_ptid));
            }
 
-         if (info_verbose || debug_infrun)
+         if (print_inferior_events)
            {
              /* Ensure that we have a process ptid.  */
              ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
 
-             target_terminal_ours_for_output ();
+             target_terminal::ours_for_output ();
              fprintf_filtered (gdb_stdlog,
-                               _("Detaching after %s from child %s.\n"),
+                               _("[Detaching after %s from child %s]\n"),
                                has_vforked ? "vfork" : "fork",
                                target_pid_to_str (process_ptid));
            }
@@ -458,7 +476,6 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       else
        {
          struct inferior *parent_inf, *child_inf;
-         struct cleanup *old_chain;
 
          /* Add process to GDB's tables.  */
          child_inf = add_inferior (ptid_get_pid (child_ptid));
@@ -469,11 +486,11 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          child_inf->gdbarch = parent_inf->gdbarch;
          copy_inferior_target_desc_info (child_inf, parent_inf);
 
-         old_chain = save_inferior_ptid ();
-         save_current_program_space ();
+         scoped_restore_current_pspace_and_thread restore_pspace_thread;
 
          inferior_ptid = child_ptid;
-         add_thread (inferior_ptid);
+         add_thread_silent (inferior_ptid);
+         set_current_inferior (child_inf);
          child_inf->symfile_flags = SYMFILE_NO_READ;
 
          /* If this is a vfork child, then the address-space is
@@ -494,7 +511,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          else
            {
              child_inf->aspace = new_address_space ();
-             child_inf->pspace = add_program_space (child_inf->aspace);
+             child_inf->pspace = new program_space (child_inf->aspace);
              child_inf->removable = 1;
              set_current_program_space (child_inf->pspace);
              clone_program_space (child_inf->pspace, parent_inf->pspace);
@@ -507,8 +524,6 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
                 required.  */
              solib_create_inferior_hook (0);
            }
-
-         do_cleanups (old_chain);
        }
 
       if (has_vforked)
@@ -534,14 +549,17 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       struct inferior *parent_inf, *child_inf;
       struct program_space *parent_pspace;
 
-      if (info_verbose || debug_infrun)
+      if (print_inferior_events)
        {
-         target_terminal_ours_for_output ();
+         std::string parent_pid = target_pid_to_str (parent_ptid);
+         std::string child_pid = target_pid_to_str (child_ptid);
+
+         target_terminal::ours_for_output ();
          fprintf_filtered (gdb_stdlog,
-                           _("Attaching after %s %s to child %s.\n"),
-                           target_pid_to_str (parent_ptid),
+                           _("[Attaching after %s %s to child %s]\n"),
+                           parent_pid.c_str (),
                            has_vforked ? "vfork" : "fork",
-                           target_pid_to_str (child_ptid));
+                           child_pid.c_str ());
        }
 
       /* Add the new inferior first, so that the target_detach below
@@ -579,19 +597,19 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
        }
       else if (detach_fork)
        {
-         if (info_verbose || debug_infrun)
+         if (print_inferior_events)
            {
              /* Ensure that we have a process ptid.  */
-             ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
+             ptid_t process_ptid = pid_to_ptid (ptid_get_pid (parent_ptid));
 
-             target_terminal_ours_for_output ();
+             target_terminal::ours_for_output ();
              fprintf_filtered (gdb_stdlog,
-                               _("Detaching after fork from "
-                                 "child %s.\n"),
+                               _("[Detaching after fork from "
+                                 "parent %s]\n"),
                                target_pid_to_str (process_ptid));
            }
 
-         target_detach (NULL, 0);
+         target_detach (parent_inf, 0);
        }
 
       /* Note that the detach above makes PARENT_INF dangling.  */
@@ -601,7 +619,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
         informing the solib layer about this new process.  */
 
       inferior_ptid = child_ptid;
-      add_thread (inferior_ptid);
+      add_thread_silent (inferior_ptid);
+      set_current_inferior (child_inf);
 
       /* If this is a vfork child, then the address-space is shared
         with the parent.  If we detached from the parent, then we can
@@ -614,7 +633,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       else
        {
          child_inf->aspace = new_address_space ();
-         child_inf->pspace = add_program_space (child_inf->aspace);
+         child_inf->pspace = new program_space (child_inf->aspace);
          child_inf->removable = 1;
          child_inf->symfile_flags = SYMFILE_NO_READ;
          set_current_program_space (child_inf->pspace);
@@ -652,7 +671,7 @@ follow_fork (void)
   CORE_ADDR step_range_start = 0;
   CORE_ADDR step_range_end = 0;
   struct frame_id step_frame_id = { 0 };
-  struct interp *command_interp = NULL;
+  struct thread_fsm *thread_fsm = NULL;
 
   if (!non_stop)
     {
@@ -704,7 +723,7 @@ follow_fork (void)
            step_frame_id = tp->control.step_frame_id;
            exception_resume_breakpoint
              = clone_momentary_breakpoint (tp->control.exception_resume_breakpoint);
-           command_interp = tp->control.command_interp;
+           thread_fsm = tp->thread_fsm;
 
            /* For now, delete the parent's sr breakpoint, otherwise,
               parent/child sr breakpoints are considered duplicates,
@@ -716,7 +735,7 @@ follow_fork (void)
            tp->control.step_range_end = 0;
            tp->control.step_frame_id = null_frame_id;
            delete_exception_resume_breakpoint (tp);
-           tp->control.command_interp = NULL;
+           tp->thread_fsm = NULL;
          }
 
        parent = inferior_ptid;
@@ -762,7 +781,7 @@ follow_fork (void)
                    tp->control.step_frame_id = step_frame_id;
                    tp->control.exception_resume_breakpoint
                      = exception_resume_breakpoint;
-                   tp->control.command_interp = command_interp;
+                   tp->thread_fsm = thread_fsm;
                  }
                else
                  {
@@ -773,7 +792,7 @@ follow_fork (void)
                       issued is most likely not applicable to the
                       child, so just warn, and refuse to resume.  */
                    warning (_("Not resuming: switched threads "
-                              "before following fork child.\n"));
+                              "before following fork child."));
                  }
 
                /* Reset breakpoints in the child as appropriate.  */
@@ -865,6 +884,22 @@ proceed_after_vfork_done (struct thread_info *thread,
   return 0;
 }
 
+/* Save/restore inferior_ptid, current program space and current
+   inferior.  Only use this if the current context points at an exited
+   inferior (and therefore there's no current thread to save).  */
+class scoped_restore_exited_inferior
+{
+public:
+  scoped_restore_exited_inferior ()
+    : m_saved_ptid (&inferior_ptid)
+  {}
+
+private:
+  scoped_restore_tmpl<ptid_t> m_saved_ptid;
+  scoped_restore_current_program_space m_pspace;
+  scoped_restore_current_inferior m_inferior;
+};
+
 /* Called whenever we notice an exec or exit event, to handle
    detaching or resuming a vfork parent.  */
 
@@ -884,7 +919,6 @@ handle_vfork_child_exec_or_exit (int exec)
       if (inf->vfork_parent->pending_detach)
        {
          struct thread_info *tp;
-         struct cleanup *old_chain;
          struct program_space *pspace;
          struct address_space *aspace;
 
@@ -892,16 +926,17 @@ handle_vfork_child_exec_or_exit (int exec)
 
          inf->vfork_parent->pending_detach = 0;
 
+         gdb::optional<scoped_restore_exited_inferior>
+           maybe_restore_inferior;
+         gdb::optional<scoped_restore_current_pspace_and_thread>
+           maybe_restore_thread;
+
+         /* If we're handling a child exit, then inferior_ptid points
+            at the inferior's pid, not to a thread.  */
          if (!exec)
-           {
-             /* If we're handling a child exit, then inferior_ptid
-                points at the inferior's pid, not to a thread.  */
-             old_chain = save_inferior_ptid ();
-             save_current_program_space ();
-             save_current_inferior ();
-           }
+           maybe_restore_inferior.emplace ();
          else
-           old_chain = save_current_space_and_thread ();
+           maybe_restore_thread.emplace ();
 
          /* We're letting loose of the parent.  */
          tp = any_live_thread_of_process (inf->vfork_parent->pid);
@@ -924,39 +959,38 @@ handle_vfork_child_exec_or_exit (int exec)
          inf->aspace = NULL;
          inf->pspace = NULL;
 
-         if (debug_infrun || info_verbose)
+         if (print_inferior_events)
            {
-             target_terminal_ours_for_output ();
+             const char *pidstr
+               = target_pid_to_str (pid_to_ptid (inf->vfork_parent->pid));
+
+             target_terminal::ours_for_output ();
 
              if (exec)
                {
                  fprintf_filtered (gdb_stdlog,
-                                   _("Detaching vfork parent process "
-                                     "%d after child exec.\n"),
-                                   inf->vfork_parent->pid);
+                                   _("[Detaching vfork parent %s "
+                                     "after child exec]\n"), pidstr);
                }
              else
                {
                  fprintf_filtered (gdb_stdlog,
-                                   _("Detaching vfork parent process "
-                                     "%d after child exit.\n"),
-                                   inf->vfork_parent->pid);
+                                   _("[Detaching vfork parent %s "
+                                     "after child exit]\n"), pidstr);
                }
            }
 
-         target_detach (NULL, 0);
+         target_detach (inf->vfork_parent, 0);
 
          /* Put it back.  */
          inf->pspace = pspace;
          inf->aspace = aspace;
-
-         do_cleanups (old_chain);
        }
       else if (exec)
        {
          /* We're staying attached to the parent, so, really give the
             child a new address space.  */
-         inf->pspace = add_program_space (maybe_new_address_space ());
+         inf->pspace = new program_space (maybe_new_address_space ());
          inf->aspace = inf->pspace->aspace;
          inf->removable = 1;
          set_current_program_space (inf->pspace);
@@ -968,7 +1002,6 @@ handle_vfork_child_exec_or_exit (int exec)
        }
       else
        {
-         struct cleanup *old_chain;
          struct program_space *pspace;
 
          /* If this is a vfork child exiting, then the pspace and
@@ -980,17 +1013,18 @@ handle_vfork_child_exec_or_exit (int exec)
             go ahead and create a new one for this exiting
             inferior.  */
 
-         /* Switch to null_ptid, so that clone_program_space doesn't want
-            to read the selected frame of a dead process.  */
-         old_chain = save_inferior_ptid ();
-         inferior_ptid = null_ptid;
+         /* Switch to null_ptid while running clone_program_space, so
+            that clone_program_space doesn't want to read the
+            selected frame of a dead process.  */
+         scoped_restore restore_ptid
+           = make_scoped_restore (&inferior_ptid, null_ptid);
 
          /* This inferior is dead, so avoid giving the breakpoints
             module the option to write through to it (cloning a
             program space resets breakpoints).  */
          inf->aspace = NULL;
          inf->pspace = NULL;
-         pspace = add_program_space (maybe_new_address_space ());
+         pspace = new program_space (maybe_new_address_space ());
          set_current_program_space (pspace);
          inf->removable = 1;
          inf->symfile_flags = SYMFILE_NO_READ;
@@ -998,10 +1032,6 @@ handle_vfork_child_exec_or_exit (int exec)
          inf->pspace = pspace;
          inf->aspace = pspace->aspace;
 
-         /* Put back inferior_ptid.  We'll continue mourning this
-            inferior.  */
-         do_cleanups (old_chain);
-
          resume_parent = inf->vfork_parent->pid;
          /* Break the bonds.  */
          inf->vfork_parent->vfork_child = NULL;
@@ -1015,7 +1045,7 @@ handle_vfork_child_exec_or_exit (int exec)
        {
          /* If the user wanted the parent to be running, let it go
             free now.  */
-         struct cleanup *old_chain = make_cleanup_restore_current_thread ();
+         scoped_restore_current_thread restore_thread;
 
          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog,
@@ -1023,8 +1053,6 @@ handle_vfork_child_exec_or_exit (int exec)
                                resume_parent);
 
          iterate_over_threads (proceed_after_vfork_done, &resume_parent);
-
-         do_cleanups (old_chain);
        }
     }
 }
@@ -1048,14 +1076,15 @@ show_follow_exec_mode_string (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Follow exec mode is \"%s\".\n"),  value);
 }
 
-/* EXECD_PATHNAME is assumed to be non-NULL.  */
+/* EXEC_FILE_TARGET is assumed to be non-NULL.  */
 
 static void
-follow_exec (ptid_t ptid, char *execd_pathname)
+follow_exec (ptid_t ptid, char *exec_file_target)
 {
   struct thread_info *th, *tmp;
   struct inferior *inf = current_inferior ();
   int pid = ptid_get_pid (ptid);
+  ptid_t process_ptid;
 
   /* This is an exec event that we actually wish to pay attention to.
      Refresh our symbol table to the newly exec'd program, remove any
@@ -1122,9 +1151,10 @@ follow_exec (ptid_t ptid, char *execd_pathname)
   update_breakpoints_after_exec ();
 
   /* What is this a.out's name?  */
+  process_ptid = pid_to_ptid (pid);
   printf_unfiltered (_("%s is executing new program: %s\n"),
-                    target_pid_to_str (inferior_ptid),
-                    execd_pathname);
+                    target_pid_to_str (process_ptid),
+                    exec_file_target);
 
   /* We've followed the inferior through an exec.  Therefore, the
      inferior has essentially been killed & reborn.  */
@@ -1133,14 +1163,17 @@ follow_exec (ptid_t ptid, char *execd_pathname)
 
   breakpoint_init_inferior (inf_execd);
 
-  if (gdb_sysroot != NULL && *gdb_sysroot != '\0')
-    {
-      char *name = exec_file_find (execd_pathname, NULL);
+  gdb::unique_xmalloc_ptr<char> exec_file_host
+    = exec_file_find (exec_file_target, NULL);
 
-      execd_pathname = alloca (strlen (name) + 1);
-      strcpy (execd_pathname, name);
-      xfree (name);
-    }
+  /* If we were unable to map the executable target pathname onto a host
+     pathname, tell the user that.  Otherwise GDB's subsequent behavior
+     is confusing.  Maybe it would even be better to stop at this point
+     so that the user can specify a file manually before continuing.  */
+  if (exec_file_host == NULL)
+    warning (_("Could not load symbols for executable %s.\n"
+              "Do you need \"set sysroot\"?"),
+            exec_file_target);
 
   /* Reset the shared library package.  This ensures that we get a
      shlib event when the child reaches "_start", at which point the
@@ -1152,20 +1185,20 @@ follow_exec (ptid_t ptid, char *execd_pathname)
 
   if (follow_exec_mode_string == follow_exec_mode_new)
     {
-      struct program_space *pspace;
-
       /* The user wants to keep the old inferior and program spaces
         around.  Create a new fresh one, and switch to it.  */
 
-      inf = add_inferior (current_inferior ()->pid);
-      pspace = add_program_space (maybe_new_address_space ());
-      inf->pspace = pspace;
-      inf->aspace = pspace->aspace;
-
+      /* Do exit processing for the original inferior before adding
+        the new inferior so we don't have two active inferiors with
+        the same ptid, which can confuse find_inferior_ptid.  */
       exit_inferior_num_silent (current_inferior ()->num);
 
+      inf = add_inferior_with_spaces ();
+      inf->pid = pid;
+      target_follow_exec (inf, exec_file_target);
+
       set_current_inferior (inf);
-      set_current_program_space (pspace);
+      set_current_program_space (inf->pspace);
     }
   else
     {
@@ -1180,21 +1213,12 @@ follow_exec (ptid_t ptid, char *execd_pathname)
 
   gdb_assert (current_program_space == inf->pspace);
 
-  /* That a.out is now the one to use.  */
-  exec_file_attach (execd_pathname, 0);
-
-  /* SYMFILE_DEFER_BP_RESET is used as the proper displacement for PIE
-     (Position Independent Executable) main symbol file will get applied by
-     solib_create_inferior_hook below.  breakpoint_re_set would fail to insert
-     the breakpoints with the zero displacement.  */
-
-  symbol_file_add (execd_pathname,
-                  (inf->symfile_flags
-                   | SYMFILE_MAINLINE | SYMFILE_DEFER_BP_RESET),
-                  NULL, 0);
-
-  if ((inf->symfile_flags & SYMFILE_NO_READ) == 0)
-    set_initial_language ();
+  /* Attempt to open the exec file.  SYMFILE_DEFER_BP_RESET is used
+     because the proper displacement for a PIE (Position Independent
+     Executable) main symbol file will only be computed by
+     solib_create_inferior_hook below.  breakpoint_re_set would fail
+     to insert the breakpoints with the zero displacement.  */
+  try_open_exec_file (exec_file_host.get (), inf, SYMFILE_DEFER_BP_RESET);
 
   /* If the target can specify a description, read it.  Must do this
      after flipping to the new executable (because the target supplied
@@ -1204,6 +1228,11 @@ follow_exec (ptid_t ptid, char *execd_pathname)
      registers.  */
   target_find_description ();
 
+  /* The add_thread call ends up reading registers, so do it after updating the
+     target description.  */
+  if (follow_exec_mode_string == follow_exec_mode_new)
+    add_thread (ptid);
+
   solib_create_inferior_hook (0);
 
   jit_inferior_created_hook ();
@@ -1221,6 +1250,29 @@ follow_exec (ptid_t ptid, char *execd_pathname)
      matically get reset there in the new process.).  */
 }
 
+/* The queue of threads that need to do a step-over operation to get
+   past e.g., a breakpoint.  What technique is used to step over the
+   breakpoint/watchpoint does not matter -- all threads end up in the
+   same queue, to maintain rough temporal order of execution, in order
+   to avoid starvation, otherwise, we could e.g., find ourselves
+   constantly stepping the same couple threads past their breakpoints
+   over and over, if the single-step finish fast enough.  */
+struct thread_info *step_over_queue_head;
+
+/* Bit flags indicating what the thread needs to step over.  */
+
+enum step_over_what_flag
+  {
+    /* Step over a breakpoint.  */
+    STEP_OVER_BREAKPOINT = 1,
+
+    /* Step past a non-continuable watchpoint, in order to let the
+       instruction execute so we can evaluate the watchpoint
+       expression.  */
+    STEP_OVER_WATCHPOINT = 2
+  };
+DEF_ENUM_FLAGS_TYPE (enum step_over_what_flag, step_over_what);
+
 /* Info about an instruction that is being stepped over.  */
 
 struct step_over_info
@@ -1229,12 +1281,15 @@ struct step_over_info
      and address of the instruction the breakpoint is set at.  We'll
      skip inserting all breakpoints here.  Valid iff ASPACE is
      non-NULL.  */
-  struct address_space *aspace;
+  const address_space *aspace;
   CORE_ADDR address;
 
   /* The instruction being stepped over triggers a nonsteppable
      watchpoint.  If true, we'll skip inserting watchpoints.  */
   int nonsteppable_watchpoint_p;
+
+  /* The thread's global number.  */
+  int thread;
 };
 
 /* The step-over info of the location that is being stepped over.
@@ -1264,15 +1319,19 @@ struct step_over_info
 static struct step_over_info step_over_info;
 
 /* Record the address of the breakpoint/instruction we're currently
-   stepping over.  */
+   stepping over.
+   N.B. We record the aspace and address now, instead of say just the thread,
+   because when we need the info later the thread may be running.  */
 
 static void
-set_step_over_info (struct address_space *aspace, CORE_ADDR address,
-                   int nonsteppable_watchpoint_p)
+set_step_over_info (const address_space *aspace, CORE_ADDR address,
+                   int nonsteppable_watchpoint_p,
+                   int thread)
 {
   step_over_info.aspace = aspace;
   step_over_info.address = address;
   step_over_info.nonsteppable_watchpoint_p = nonsteppable_watchpoint_p;
+  step_over_info.thread = thread;
 }
 
 /* Called when we're not longer stepping over a breakpoint / an
@@ -1281,9 +1340,13 @@ set_step_over_info (struct address_space *aspace, CORE_ADDR address,
 static void
 clear_step_over_info (void)
 {
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog,
+                       "infrun: clear_step_over_info\n");
   step_over_info.aspace = NULL;
   step_over_info.address = 0;
   step_over_info.nonsteppable_watchpoint_p = 0;
+  step_over_info.thread = -1;
 }
 
 /* See infrun.h.  */
@@ -1300,6 +1363,15 @@ stepping_past_instruction_at (struct address_space *aspace,
 
 /* See infrun.h.  */
 
+int
+thread_is_stepping_over_breakpoint (int thread)
+{
+  return (step_over_info.thread != -1
+         && thread == step_over_info.thread);
+}
+
+/* See infrun.h.  */
+
 int
 stepping_past_nonsteppable_watchpoint (void)
 {
@@ -1365,8 +1437,6 @@ step_over_info_valid_p (void)
      same effect the instruction would have had if we had executed it
      at its original address.  We use this in step n3.
 
-   - gdbarch_displaced_step_free_closure provides cleanup.
-
    The gdbarch_displaced_step_copy_insn and
    gdbarch_displaced_step_fixup functions must be written so that
    copying an instruction with gdbarch_displaced_step_copy_insn,
@@ -1404,11 +1474,9 @@ step_over_info_valid_p (void)
    displaced step operation on it.  See displaced_step_prepare and
    displaced_step_fixup for details.  */
 
-struct displaced_step_request
-{
-  ptid_t ptid;
-  struct displaced_step_request *next;
-};
+/* Default destructor for displaced_step_closure.  */
+
+displaced_step_closure::~displaced_step_closure () = default;
 
 /* Per-inferior displaced stepping state.  */
 struct displaced_step_inferior_state
@@ -1419,9 +1487,9 @@ struct displaced_step_inferior_state
   /* The process this displaced step state refers to.  */
   int pid;
 
-  /* A queue of pending displaced stepping requests.  One entry per
-     thread that needs to do a displaced step.  */
-  struct displaced_step_request *step_request_queue;
+  /* True if preparing a displaced step ever failed.  If so, we won't
+     try displaced stepping for this inferior again.  */
+  int failed_before;
 
   /* If this is not null_ptid, this is the thread carrying out a
      displaced single-step in process PID.  This thread's state will
@@ -1463,6 +1531,38 @@ get_displaced_stepping_state (int pid)
   return NULL;
 }
 
+/* Returns true if any inferior has a thread doing a displaced
+   step.  */
+
+static int
+displaced_step_in_progress_any_inferior (void)
+{
+  struct displaced_step_inferior_state *state;
+
+  for (state = displaced_step_inferior_states;
+       state != NULL;
+       state = state->next)
+    if (!ptid_equal (state->step_ptid, null_ptid))
+      return 1;
+
+  return 0;
+}
+
+/* Return true if thread represented by PTID is doing a displaced
+   step.  */
+
+static int
+displaced_step_in_progress_thread (ptid_t ptid)
+{
+  struct displaced_step_inferior_state *displaced;
+
+  gdb_assert (!ptid_equal (ptid, null_ptid));
+
+  displaced = get_displaced_stepping_state (ptid_get_pid (ptid));
+
+  return (displaced != NULL && ptid_equal (displaced->step_ptid, ptid));
+}
+
 /* Return true if process PID has a thread doing a displaced step.  */
 
 static int
@@ -1492,7 +1592,7 @@ add_displaced_stepping_state (int pid)
     if (state->pid == pid)
       return state;
 
-  state = xcalloc (1, sizeof (*state));
+  state = XCNEW (struct displaced_step_inferior_state);
   state->pid = pid;
   state->next = displaced_step_inferior_states;
   displaced_step_inferior_states = state;
@@ -1568,7 +1668,7 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
     fprintf_filtered (file,
                      _("Debugger's willingness to use displaced stepping "
                        "to step over breakpoints is %s (currently %s).\n"),
-                     value, non_stop ? "on" : "off");
+                     value, target_is_non_stop_p () ? "on" : "off");
   else
     fprintf_filtered (file,
                      _("Debugger's willingness to use displaced stepping "
@@ -1576,15 +1676,24 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
 }
 
 /* Return non-zero if displaced stepping can/should be used to step
-   over breakpoints.  */
+   over breakpoints of thread TP.  */
 
 static int
-use_displaced_stepping (struct gdbarch *gdbarch)
+use_displaced_stepping (struct thread_info *tp)
 {
-  return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO && non_stop)
+  struct regcache *regcache = get_thread_regcache (tp->ptid);
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct displaced_step_inferior_state *displaced_state;
+
+  displaced_state = get_displaced_stepping_state (ptid_get_pid (tp->ptid));
+
+  return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO
+           && target_is_non_stop_p ())
           || can_use_displaced_stepping == AUTO_BOOLEAN_TRUE)
          && gdbarch_displaced_step_copy_insn_p (gdbarch)
-         && find_record_target () == NULL);
+         && find_record_target () == NULL
+         && (displaced_state == NULL
+             || !displaced_state->failed_before));
 }
 
 /* Clean out any stray displaced stepping state.  */
@@ -1594,18 +1703,15 @@ displaced_step_clear (struct displaced_step_inferior_state *displaced)
   /* Indicate that there is no cleanup pending.  */
   displaced->step_ptid = null_ptid;
 
-  if (displaced->step_closure)
-    {
-      gdbarch_displaced_step_free_closure (displaced->step_gdbarch,
-                                           displaced->step_closure);
-      displaced->step_closure = NULL;
-    }
+  delete displaced->step_closure;
+  displaced->step_closure = NULL;
 }
 
 static void
 displaced_step_clear_cleanup (void *arg)
 {
-  struct displaced_step_inferior_state *state = arg;
+  struct displaced_step_inferior_state *state
+    = (struct displaced_step_inferior_state *) arg;
 
   displaced_step_clear (state);
 }
@@ -1636,14 +1742,17 @@ displaced_step_dump_bytes (struct ui_file *file,
    explain how we handle this case instead.
 
    Returns 1 if preparing was successful -- this thread is going to be
-   stepped now; or 0 if displaced stepping this thread got queued.  */
+   stepped now; 0 if displaced stepping this thread got queued; or -1
+   if this instruction can't be displaced stepped.  */
+
 static int
-displaced_step_prepare (ptid_t ptid)
+displaced_step_prepare_throw (ptid_t ptid)
 {
-  struct cleanup *old_cleanups, *ignore_cleanups;
+  struct cleanup *ignore_cleanups;
   struct thread_info *tp = find_thread_ptid (ptid);
   struct regcache *regcache = get_thread_regcache (ptid);
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
+  const address_space *aspace = regcache->aspace ();
   CORE_ADDR original, copy;
   ULONGEST len;
   struct displaced_step_closure *closure;
@@ -1654,6 +1763,9 @@ displaced_step_prepare (ptid_t ptid)
      support displaced stepping.  */
   gdb_assert (gdbarch_displaced_step_copy_insn_p (gdbarch));
 
+  /* Nor if the thread isn't meant to step over a breakpoint.  */
+  gdb_assert (tp->control.trap_expected);
+
   /* Disable range stepping while executing in the scratch pad.  We
      want a single-step even if executing the displaced instruction in
      the scratch buffer lands within the stepping range (e.g., a
@@ -1669,28 +1781,13 @@ displaced_step_prepare (ptid_t ptid)
     {
       /* Already waiting for a displaced step to finish.  Defer this
         request and place in queue.  */
-      struct displaced_step_request *req, *new_req;
 
       if (debug_displaced)
        fprintf_unfiltered (gdb_stdlog,
-                           "displaced: defering step of %s\n",
+                           "displaced: deferring step of %s\n",
                            target_pid_to_str (ptid));
 
-      new_req = xmalloc (sizeof (*new_req));
-      new_req->ptid = ptid;
-      new_req->next = NULL;
-
-      if (displaced->step_request_queue)
-       {
-         for (req = displaced->step_request_queue;
-              req && req->next;
-              req = req->next)
-           ;
-         req->next = new_req;
-       }
-      else
-       displaced->step_request_queue = new_req;
-
+      thread_step_over_chain_enqueue (tp);
       return 0;
     }
   else
@@ -1703,7 +1800,7 @@ displaced_step_prepare (ptid_t ptid)
 
   displaced_step_clear (displaced);
 
-  old_cleanups = save_inferior_ptid ();
+  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
   inferior_ptid = ptid;
 
   original = regcache_read_pc (regcache);
@@ -1711,8 +1808,29 @@ displaced_step_prepare (ptid_t ptid)
   copy = gdbarch_displaced_step_location (gdbarch);
   len = gdbarch_max_insn_length (gdbarch);
 
+  if (breakpoint_in_range_p (aspace, copy, len))
+    {
+      /* There's a breakpoint set in the scratch pad location range
+        (which is usually around the entry point).  We'd either
+        install it before resuming, which would overwrite/corrupt the
+        scratch pad, or if it was already inserted, this displaced
+        step would overwrite it.  The latter is OK in the sense that
+        we already assume that no thread is going to execute the code
+        in the scratch pad range (after initial startup) anyway, but
+        the former is unacceptable.  Simply punt and fallback to
+        stepping over this breakpoint in-line.  */
+      if (debug_displaced)
+       {
+         fprintf_unfiltered (gdb_stdlog,
+                             "displaced: breakpoint set in scratch pad.  "
+                             "Stepping over breakpoint in-line instead.\n");
+       }
+
+      return -1;
+    }
+
   /* Save the original contents of the copy area.  */
-  displaced->step_saved_copy = xmalloc (len);
+  displaced->step_saved_copy = (gdb_byte *) xmalloc (len);
   ignore_cleanups = make_cleanup (free_current_contents,
                                  &displaced->step_saved_copy);
   status = target_read_memory (copy, displaced->step_saved_copy, len);
@@ -1732,9 +1850,14 @@ displaced_step_prepare (ptid_t ptid)
 
   closure = gdbarch_displaced_step_copy_insn (gdbarch,
                                              original, copy, regcache);
-
-  /* We don't support the fully-simulated case at present.  */
-  gdb_assert (closure);
+  if (closure == NULL)
+    {
+      /* The architecture doesn't know how or want to displaced step
+        this instruction or instruction sequence.  Fallback to
+        stepping over the breakpoint in-line.  */
+      do_cleanups (ignore_cleanups);
+      return -1;
+    }
 
   /* Save the information we need to fix things up if the step
      succeeds.  */
@@ -1751,8 +1874,6 @@ displaced_step_prepare (ptid_t ptid)
 
   discard_cleanups (ignore_cleanups);
 
-  do_cleanups (old_cleanups);
-
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog, "displaced: displaced pc to %s\n",
                        paddress (gdbarch, copy));
@@ -1760,15 +1881,59 @@ displaced_step_prepare (ptid_t ptid)
   return 1;
 }
 
+/* Wrapper for displaced_step_prepare_throw that disabled further
+   attempts at displaced stepping if we get a memory error.  */
+
+static int
+displaced_step_prepare (ptid_t ptid)
+{
+  int prepared = -1;
+
+  TRY
+    {
+      prepared = displaced_step_prepare_throw (ptid);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      struct displaced_step_inferior_state *displaced_state;
+
+      if (ex.error != MEMORY_ERROR
+         && ex.error != NOT_SUPPORTED_ERROR)
+       throw_exception (ex);
+
+      if (debug_infrun)
+       {
+         fprintf_unfiltered (gdb_stdlog,
+                             "infrun: disabling displaced stepping: %s\n",
+                             ex.message);
+       }
+
+      /* Be verbose if "set displaced-stepping" is "on", silent if
+        "auto".  */
+      if (can_use_displaced_stepping == AUTO_BOOLEAN_TRUE)
+       {
+         warning (_("disabling displaced stepping: %s"),
+                  ex.message);
+       }
+
+      /* Disable further displaced stepping attempts.  */
+      displaced_state
+       = get_displaced_stepping_state (ptid_get_pid (ptid));
+      displaced_state->failed_before = 1;
+    }
+  END_CATCH
+
+  return prepared;
+}
+
 static void
 write_memory_ptid (ptid_t ptid, CORE_ADDR memaddr,
                   const gdb_byte *myaddr, int len)
 {
-  struct cleanup *ptid_cleanup = save_inferior_ptid ();
+  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
 
   inferior_ptid = ptid;
   write_memory (memaddr, myaddr, len);
-  do_cleanups (ptid_cleanup);
 }
 
 /* Restore the contents of the copy area for thread PTID.  */
@@ -1788,21 +1953,28 @@ displaced_step_restore (struct displaced_step_inferior_state *displaced,
                                  displaced->step_copy));
 }
 
-static void
+/* If we displaced stepped an instruction successfully, adjust
+   registers and memory to yield the same effect the instruction would
+   have had if we had executed it at its original address, and return
+   1.  If the instruction didn't complete, relocate the PC and return
+   -1.  If the thread wasn't displaced stepping, return 0.  */
+
+static int
 displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 {
   struct cleanup *old_cleanups;
   struct displaced_step_inferior_state *displaced
     = get_displaced_stepping_state (ptid_get_pid (event_ptid));
+  int ret;
 
   /* Was any thread of this process doing a displaced step?  */
   if (displaced == NULL)
-    return;
+    return 0;
 
   /* Was this event for the pid we displaced?  */
   if (ptid_equal (displaced->step_ptid, null_ptid)
       || ! ptid_equal (displaced->step_ptid, event_ptid))
-    return;
+    return 0;
 
   old_cleanups = make_cleanup (displaced_step_clear_cleanup, displaced);
 
@@ -1825,6 +1997,7 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
                                     displaced->step_original,
                                     displaced->step_copy,
                                     get_thread_regcache (displaced->step_ptid));
+      ret = 1;
     }
   else
     {
@@ -1835,92 +2008,166 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 
       pc = displaced->step_original + (pc - displaced->step_copy);
       regcache_write_pc (regcache, pc);
+      ret = -1;
     }
 
   do_cleanups (old_cleanups);
 
   displaced->step_ptid = null_ptid;
 
-  /* Are there any pending displaced stepping requests?  If so, run
-     one now.  Leave the state object around, since we're likely to
-     need it again soon.  */
-  while (displaced->step_request_queue)
-    {
-      struct displaced_step_request *head;
-      ptid_t ptid;
-      struct regcache *regcache;
-      struct gdbarch *gdbarch;
-      CORE_ADDR actual_pc;
-      struct address_space *aspace;
+  return ret;
+}
 
-      head = displaced->step_request_queue;
-      ptid = head->ptid;
-      displaced->step_request_queue = head->next;
-      xfree (head);
+/* Data to be passed around while handling an event.  This data is
+   discarded between events.  */
+struct execution_control_state
+{
+  ptid_t ptid;
+  /* The thread that got the event, if this was a thread event; NULL
+     otherwise.  */
+  struct thread_info *event_thread;
 
-      context_switch (ptid);
+  struct target_waitstatus ws;
+  int stop_func_filled_in;
+  CORE_ADDR stop_func_start;
+  CORE_ADDR stop_func_end;
+  const char *stop_func_name;
+  int wait_some_more;
 
-      regcache = get_thread_regcache (ptid);
-      actual_pc = regcache_read_pc (regcache);
-      aspace = get_regcache_aspace (regcache);
-      gdbarch = get_regcache_arch (regcache);
+  /* True if the event thread hit the single-step breakpoint of
+     another thread.  Thus the event doesn't cause a stop, the thread
+     needs to be single-stepped past the single-step breakpoint before
+     we can switch back to the original stepping thread.  */
+  int hit_singlestep_breakpoint;
+};
 
-      if (breakpoint_here_p (aspace, actual_pc))
-       {
-         if (debug_displaced)
-           fprintf_unfiltered (gdb_stdlog,
-                               "displaced: stepping queued %s now\n",
-                               target_pid_to_str (ptid));
+/* Clear ECS and set it to point at TP.  */
 
-         displaced_step_prepare (ptid);
+static void
+reset_ecs (struct execution_control_state *ecs, struct thread_info *tp)
+{
+  memset (ecs, 0, sizeof (*ecs));
+  ecs->event_thread = tp;
+  ecs->ptid = tp->ptid;
+}
 
-         if (debug_displaced)
-           {
-             CORE_ADDR actual_pc = regcache_read_pc (regcache);
-             gdb_byte buf[4];
+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);
 
-             fprintf_unfiltered (gdb_stdlog, "displaced: run %s: ",
-                                 paddress (gdbarch, actual_pc));
-             read_memory (actual_pc, buf, sizeof (buf));
-             displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
-           }
+/* Are there any pending step-over requests?  If so, run all we can
+   now and return true.  Otherwise, return false.  */
 
-         if (gdbarch_displaced_step_hw_singlestep (gdbarch,
-                                                   displaced->step_closure))
-           target_resume (ptid, 1, GDB_SIGNAL_0);
-         else
-           target_resume (ptid, 0, GDB_SIGNAL_0);
+static int
+start_step_over (void)
+{
+  struct thread_info *tp, *next;
+
+  /* Don't start a new step-over if we already have an in-line
+     step-over operation ongoing.  */
+  if (step_over_info_valid_p ())
+    return 0;
+
+  for (tp = step_over_queue_head; tp != NULL; tp = next)
+    {
+      struct execution_control_state ecss;
+      struct execution_control_state *ecs = &ecss;
+      step_over_what step_what;
+      int must_be_in_line;
+
+      gdb_assert (!tp->stop_requested);
+
+      next = thread_step_over_chain_next (tp);
 
-         /* Done, we're stepping a thread.  */
-         break;
+      /* If this inferior already has a displaced step in process,
+        don't start a new one.  */
+      if (displaced_step_in_progress (ptid_get_pid (tp->ptid)))
+       continue;
+
+      step_what = thread_still_needs_step_over (tp);
+      must_be_in_line = ((step_what & STEP_OVER_WATCHPOINT)
+                        || ((step_what & STEP_OVER_BREAKPOINT)
+                            && !use_displaced_stepping (tp)));
+
+      /* We currently stop all threads of all processes to step-over
+        in-line.  If we need to start a new in-line step-over, let
+        any pending displaced steps finish first.  */
+      if (must_be_in_line && displaced_step_in_progress_any_inferior ())
+       return 0;
+
+      thread_step_over_chain_remove (tp);
+
+      if (step_over_queue_head == NULL)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: step-over queue now empty\n");
        }
-      else
+
+      if (tp->control.trap_expected
+         || tp->resumed
+         || tp->executing)
        {
-         int step;
-         struct thread_info *tp = inferior_thread ();
+         internal_error (__FILE__, __LINE__,
+                         "[%s] has inconsistent state: "
+                         "trap_expected=%d, resumed=%d, executing=%d\n",
+                         target_pid_to_str (tp->ptid),
+                         tp->control.trap_expected,
+                         tp->resumed,
+                         tp->executing);
+       }
 
-         /* The breakpoint we were sitting under has since been
-            removed.  */
-         tp->control.trap_expected = 0;
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: resuming [%s] for step-over\n",
+                           target_pid_to_str (tp->ptid));
+
+      /* keep_going_pass_signal skips the step-over if the breakpoint
+        is no longer inserted.  In all-stop, we want to keep looking
+        for a thread that needs a step-over instead of resuming TP,
+        because we wouldn't be able to resume anything else until the
+        target stops again.  In non-stop, the resume always resumes
+        only TP, so it's OK to let the thread resume freely.  */
+      if (!target_is_non_stop_p () && !step_what)
+       continue;
 
-         /* Go back to what we were trying to do.  */
-         step = currently_stepping (tp);
+      switch_to_thread (tp->ptid);
+      reset_ecs (ecs, tp);
+      keep_going_pass_signal (ecs);
 
-         if (step)
-           step = maybe_software_singlestep (gdbarch, actual_pc);
+      if (!ecs->wait_some_more)
+       error (_("Command aborted."));
 
-         if (debug_displaced)
-           fprintf_unfiltered (gdb_stdlog,
-                               "displaced: breakpoint is gone: %s, step(%d)\n",
-                               target_pid_to_str (tp->ptid), step);
+      gdb_assert (tp->resumed);
 
-         target_resume (ptid, step, GDB_SIGNAL_0);
-         tp->suspend.stop_signal = GDB_SIGNAL_0;
+      /* If we started a new in-line step-over, we're done.  */
+      if (step_over_info_valid_p ())
+       {
+         gdb_assert (tp->control.trap_expected);
+         return 1;
+       }
 
-         /* This request was discarded.  See if there's any other
-            thread waiting for its turn.  */
+      if (!target_is_non_stop_p ())
+       {
+         /* On all-stop, shouldn't have resumed unless we needed a
+            step over.  */
+         gdb_assert (tp->control.trap_expected
+                     || tp->step_after_step_resume_breakpoint);
+
+         /* With remote targets (at least), in all-stop, we can't
+            issue any further remote commands until the program stops
+            again.  */
+         return 1;
        }
+
+      /* Either the thread no longer needed a step-over, or a new
+        displaced stepping sequence started.  Even in the latter
+        case, continue looking.  Maybe we can also start another
+        displaced step on a thread of other process. */
     }
+
+  return 0;
 }
 
 /* Update global variables holding ptids to hold NEW_PTID if they were
@@ -1928,7 +2175,6 @@ displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
 static void
 infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
 {
-  struct displaced_step_request *it;
   struct displaced_step_inferior_state *displaced;
 
   if (ptid_equal (inferior_ptid, old_ptid))
@@ -1940,36 +2186,23 @@ infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
     {
       if (ptid_equal (displaced->step_ptid, old_ptid))
        displaced->step_ptid = new_ptid;
-
-      for (it = displaced->step_request_queue; it; it = it->next)
-       if (ptid_equal (it->ptid, old_ptid))
-         it->ptid = new_ptid;
     }
 }
 
 \f
-/* Resuming.  */
-
-/* Things to clean up if we QUIT out of resume ().  */
-static void
-resume_cleanups (void *ignore)
-{
-  if (!ptid_equal (inferior_ptid, null_ptid))
-    delete_single_step_breakpoints (inferior_thread ());
-
-  normal_stop ();
-}
 
 static const char schedlock_off[] = "off";
 static const char schedlock_on[] = "on";
 static const char schedlock_step[] = "step";
+static const char schedlock_replay[] = "replay";
 static const char *const scheduler_enums[] = {
   schedlock_off,
   schedlock_on,
   schedlock_step,
+  schedlock_replay,
   NULL
 };
-static const char *scheduler_mode = schedlock_off;
+static const char *scheduler_mode = schedlock_replay;
 static void
 show_scheduler_mode (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
@@ -1981,7 +2214,7 @@ show_scheduler_mode (struct ui_file *file, int from_tty,
 }
 
 static void
-set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
+set_schedlock_func (const char *args, int from_tty, struct cmd_list_element *c)
 {
   if (!target_can_lock_scheduler)
     {
@@ -2007,11 +2240,9 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
   int hw_step = 1;
 
   if (execution_direction == EXEC_FORWARD
-      && gdbarch_software_single_step_p (gdbarch)
-      && gdbarch_software_single_step (gdbarch, get_current_frame ()))
-    {
-      hw_step = 0;
-    }
+      && gdbarch_software_single_step_p (gdbarch))
+    hw_step = !insert_single_step_breakpoints (gdbarch);
+
   return hw_step;
 }
 
@@ -2035,6 +2266,13 @@ user_visible_resume_ptid (int step)
         resume.  */
       resume_ptid = inferior_ptid;
     }
+  else if ((scheduler_mode == schedlock_replay)
+          && target_record_will_replay (minus_one_ptid, execution_direction))
+    {
+      /* User-settable 'scheduler' mode requires solo thread resume in replay
+        mode.  */
+      resume_ptid = inferior_ptid;
+    }
   else if (!sched_multi && target_supports_multi_process ())
     {
       /* Resume all threads of the current process (and none of other
@@ -2050,6 +2288,25 @@ user_visible_resume_ptid (int step)
   return resume_ptid;
 }
 
+/* Return a ptid representing the set of threads that we will resume,
+   in the perspective of the target, assuming run control handling
+   does not require leaving some threads stopped (e.g., stepping past
+   breakpoint).  USER_STEP indicates whether we're about to start the
+   target for a stepping command.  */
+
+static ptid_t
+internal_resume_ptid (int user_step)
+{
+  /* In non-stop, we always control threads individually.  Note that
+     the target may always work in non-stop mode even with "set
+     non-stop off", in which case user_visible_resume_ptid could
+     return a wildcard ptid.  */
+  if (target_is_non_stop_p ())
+    return inferior_ptid;
+  else
+    return user_visible_resume_ptid (user_step);
+}
+
 /* Wrapper for target_resume, that handles infrun-specific
    bookkeeping.  */
 
@@ -2058,8 +2315,10 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
 {
   struct thread_info *tp = inferior_thread ();
 
+  gdb_assert (!tp->stop_requested);
+
   /* Install inferior's terminal modes.  */
-  target_terminal_inferior ();
+  target_terminal::inferior ();
 
   /* Avoid confusing the next resume, if the next stop/resume
      happens to apply to another thread.  */
@@ -2091,24 +2350,22 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
     target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
 
   target_resume (resume_ptid, step, sig);
+
+  target_commit_resume ();
 }
 
-/* Resume the inferior, but allow a QUIT.  This is useful if the user
-   wants to interrupt some lengthy single-stepping operation
-   (for child processes, the SIGINT goes to the inferior, and so
-   we get a SIGINT random_signal, but for remote debugging and perhaps
-   other targets, that's not true).
+/* Resume the inferior.  SIG is the signal to give the inferior
+   (GDB_SIGNAL_0 for none).  Note: don't call this directly; instead
+   call 'resume', which handles exceptions.  */
 
-   SIG is the signal to give the inferior (zero for none).  */
-void
-resume (enum gdb_signal sig)
+static void
+resume_1 (enum gdb_signal sig)
 {
-  struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
   struct regcache *regcache = get_current_regcache ();
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct thread_info *tp = inferior_thread ();
   CORE_ADDR pc = regcache_read_pc (regcache);
-  struct address_space *aspace = get_regcache_aspace (regcache);
+  const address_space *aspace = regcache->aspace ();
   ptid_t resume_ptid;
   /* This represents the user's step vs continue request.  When
      deciding whether "set scheduler-locking step" applies, it's the
@@ -2120,14 +2377,47 @@ resume (enum gdb_signal sig)
      single-step).  */
   int step;
 
-  tp->stepped_breakpoint = 0;
-
-  QUIT;
+  gdb_assert (!tp->stop_requested);
+  gdb_assert (!thread_is_in_step_over_chain (tp));
 
-  /* Depends on stepped_breakpoint.  */
-  step = currently_stepping (tp);
-
-  if (current_inferior ()->waiting_for_vfork_done)
+  if (tp->suspend.waitstatus_pending_p)
+    {
+      if (debug_infrun)
+       {
+         std::string statstr
+           = target_waitstatus_to_string (&tp->suspend.waitstatus);
+
+         fprintf_unfiltered (gdb_stdlog,
+                             "infrun: resume: thread %s has pending wait "
+                             "status %s (currently_stepping=%d).\n",
+                             target_pid_to_str (tp->ptid), statstr.c_str (),
+                             currently_stepping (tp));
+       }
+
+      tp->resumed = 1;
+
+      /* FIXME: What should we do if we are supposed to resume this
+        thread with a signal?  Maybe we should maintain a queue of
+        pending signals to deliver.  */
+      if (sig != GDB_SIGNAL_0)
+       {
+         warning (_("Couldn't deliver signal %s to %s."),
+                  gdb_signal_to_name (sig), target_pid_to_str (tp->ptid));
+       }
+
+      tp->suspend.stop_signal = GDB_SIGNAL_0;
+
+      if (target_can_async_p ())
+       target_async (1);
+      return;
+    }
+
+  tp->stepped_breakpoint = 0;
+
+  /* Depends on stepped_breakpoint.  */
+  step = currently_stepping (tp);
+
+  if (current_inferior ()->waiting_for_vfork_done)
     {
       /* Don't try to single-step a vfork parent that is waiting for
         the child to get out of the shared memory region (by exec'ing
@@ -2225,9 +2515,9 @@ resume (enum gdb_signal sig)
              insert_single_step_breakpoint (gdbarch, aspace, pc);
              insert_breakpoints ();
 
-             resume_ptid = user_visible_resume_ptid (user_step);
+             resume_ptid = internal_resume_ptid (user_step);
              do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
-             discard_cleanups (old_cleanups);
+             tp->resumed = 1;
              return;
            }
        }
@@ -2249,37 +2539,49 @@ resume (enum gdb_signal sig)
      We can't use displaced stepping when we are waiting for vfork_done
      event, displaced stepping breaks the vfork child similarly as single
      step software breakpoint.  */
-  if (use_displaced_stepping (gdbarch)
-      && tp->control.trap_expected
+  if (tp->control.trap_expected
+      && use_displaced_stepping (tp)
       && !step_over_info_valid_p ()
       && sig == GDB_SIGNAL_0
       && !current_inferior ()->waiting_for_vfork_done)
     {
-      struct displaced_step_inferior_state *displaced;
-
-      if (!displaced_step_prepare (inferior_ptid))
-       {
-         /* Got placed in displaced stepping queue.  Will be resumed
-            later when all the currently queued displaced stepping
-            requests finish.  The thread is not executing at this
-            point, and the call to set_executing will be made later.
-            But we need to call set_running here, since from the
-            user/frontend's point of view, threads were set running.
-            Unless we're calling an inferior function, as in that
-            case we pretend the inferior doesn't run at all.  */
-         if (!tp->control.in_infcall)
-           set_running (user_visible_resume_ptid (user_step), 1);
-         discard_cleanups (old_cleanups);
+      int prepared = displaced_step_prepare (inferior_ptid);
+
+      if (prepared == 0)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "Got placed in step-over queue\n");
+
+         tp->control.trap_expected = 0;
          return;
        }
+      else if (prepared < 0)
+       {
+         /* Fallback to stepping over the breakpoint in-line.  */
+
+         if (target_is_non_stop_p ())
+           stop_all_threads ();
+
+         set_step_over_info (regcache->aspace (),
+                             regcache_read_pc (regcache), 0, tp->global_num);
+
+         step = maybe_software_singlestep (gdbarch, pc);
+
+         insert_breakpoints ();
+       }
+      else if (prepared > 0)
+       {
+         struct displaced_step_inferior_state *displaced;
 
-      /* Update pc to reflect the new address from which we will execute
-        instructions due to displaced stepping.  */
-      pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
+         /* Update pc to reflect the new address from which we will
+            execute instructions due to displaced stepping.  */
+         pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
 
-      displaced = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
-      step = gdbarch_displaced_step_hw_singlestep (gdbarch,
-                                                  displaced->step_closure);
+         displaced = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
+         step = gdbarch_displaced_step_hw_singlestep (gdbarch,
+                                                      displaced->step_closure);
+       }
     }
 
   /* Do we need to do it the hard way, w/temp breakpoints?  */
@@ -2338,39 +2640,32 @@ resume (enum gdb_signal sig)
      use singlestep breakpoint.  */
   gdb_assert (!(thread_has_single_step_breakpoints_set (tp) && step));
 
-  /* Decide the set of threads to ask the target to resume.  Start
-     by assuming everything will be resumed, than narrow the set
-     by applying increasingly restricting conditions.  */
-  resume_ptid = user_visible_resume_ptid (user_step);
-
-  /* Even if RESUME_PTID is a wildcard, and we end up resuming less
-     (e.g., we might need to step over a breakpoint), from the
-     user/frontend's point of view, all threads in RESUME_PTID are now
-     running.  Unless we're calling an inferior function, as in that
-     case pretend we inferior doesn't run at all.  */
-  if (!tp->control.in_infcall)
-    set_running (resume_ptid, 1);
-
-  /* Maybe resume a single thread after all.  */
-  if ((step || thread_has_single_step_breakpoints_set (tp))
-      && tp->control.trap_expected)
+  /* Decide the set of threads to ask the target to resume.  */
+  if (tp->control.trap_expected)
     {
       /* We're allowing a thread to run past a breakpoint it has
-        hit, by single-stepping the thread with the breakpoint
-        removed.  In which case, we need to single-step only this
-        thread, and keep others stopped, as they can miss this
-        breakpoint if allowed to run.  */
+        hit, either by single-stepping the thread with the breakpoint
+        removed, or by displaced stepping, with the breakpoint inserted.
+        In the former case, we need to single-step only this thread,
+        and keep others stopped, as they can miss this breakpoint if
+        allowed to run.  That's not really a problem for displaced
+        stepping, but, we still keep other threads stopped, in case
+        another thread is also stopped for a breakpoint waiting for
+        its turn in the displaced stepping queue.  */
       resume_ptid = inferior_ptid;
     }
+  else
+    resume_ptid = internal_resume_ptid (user_step);
 
   if (execution_direction != EXEC_REVERSE
       && step && breakpoint_inserted_here_p (aspace, pc))
     {
-      /* The only case we currently need to step a breakpoint
-        instruction is when we have a signal to deliver.  See
-        handle_signal_stop where we handle random signals that could
-        take out us out of the stepping range.  Normally, in that
-        case we end up continuing (instead of stepping) over the
+      /* There are two cases where we currently need to step a
+        breakpoint instruction when we have a signal to deliver:
+
+        - See handle_signal_stop where we handle random signals that
+        could take out us out of the stepping range.  Normally, in
+        that case we end up continuing (instead of stepping) over the
         signal handler with a breakpoint at PC, but there are cases
         where we should _always_ single-step, even if we have a
         step-resume breakpoint, like when a software watchpoint is
@@ -2383,8 +2678,20 @@ resume (enum gdb_signal sig)
         recurses and executes PC again, it'll miss the breakpoint.
         So we leave the breakpoint inserted anyway, but we need to
         record that we tried to step a breakpoint instruction, so
-        that adjust_pc_after_break doesn't end up confused.  */
-      gdb_assert (sig != GDB_SIGNAL_0);
+        that adjust_pc_after_break doesn't end up confused.
+
+         - In non-stop if we insert a breakpoint (e.g., a step-resume)
+        in one thread after another thread that was stepping had been
+        momentarily paused for a step-over.  When we re-resume the
+        stepping thread, it may be resumed from that address with a
+        breakpoint that hasn't trapped yet.  Seen with
+        gdb.threads/non-stop-fair-events.exp, on targets that don't
+        do displaced stepping.  */
+
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: resume: [%s] stepped breakpoint\n",
+                           target_pid_to_str (tp->ptid));
 
       tp->stepped_breakpoint = 1;
 
@@ -2396,12 +2703,12 @@ resume (enum gdb_signal sig)
     }
 
   if (debug_displaced
-      && use_displaced_stepping (gdbarch)
       && tp->control.trap_expected
+      && use_displaced_stepping (tp)
       && !step_over_info_valid_p ())
     {
       struct regcache *resume_regcache = get_thread_regcache (tp->ptid);
-      struct gdbarch *resume_gdbarch = get_regcache_arch (resume_regcache);
+      struct gdbarch *resume_gdbarch = resume_regcache->arch ();
       CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
       gdb_byte buf[4];
 
@@ -2422,11 +2729,64 @@ resume (enum gdb_signal sig)
     }
 
   do_target_resume (resume_ptid, step, sig);
-  discard_cleanups (old_cleanups);
+  tp->resumed = 1;
+}
+
+/* Resume the inferior.  SIG is the signal to give the inferior
+   (GDB_SIGNAL_0 for none).  This is a wrapper around 'resume_1' that
+   rolls back state on error.  */
+
+void
+resume (gdb_signal sig)
+{
+  TRY
+    {
+      resume_1 (sig);
+    }
+  CATCH (ex, RETURN_MASK_ALL)
+    {
+      /* If resuming is being aborted for any reason, delete any
+        single-step breakpoint resume_1 may have created, to avoid
+        confusing the following resumption, and to avoid leaving
+        single-step breakpoints perturbing other threads, in case
+        we're running in non-stop mode.  */
+      if (inferior_ptid != null_ptid)
+       delete_single_step_breakpoints (inferior_thread ());
+      throw_exception (ex);
+    }
+  END_CATCH
 }
+
 \f
 /* Proceeding.  */
 
+/* See infrun.h.  */
+
+/* Counter that tracks number of user visible stops.  This can be used
+   to tell whether a command has proceeded the inferior past the
+   current location.  This allows e.g., inferior function calls in
+   breakpoint commands to not interrupt the command list.  When the
+   call finishes successfully, the inferior is standing at the same
+   breakpoint as if nothing happened (and so we don't call
+   normal_stop).  */
+static ULONGEST current_stop_id;
+
+/* See infrun.h.  */
+
+ULONGEST
+get_stop_id (void)
+{
+  return current_stop_id;
+}
+
+/* Called when we report a user visible stop.  */
+
+static void
+new_stop_id (void)
+{
+  current_stop_id++;
+}
+
 /* Clear out all variables saying what to do when inferior is continued.
    First do this, then set the ones you want, then call `proceed'.  */
 
@@ -2438,11 +2798,44 @@ clear_proceed_status_thread (struct thread_info *tp)
                        "infrun: clear_proceed_status_thread (%s)\n",
                        target_pid_to_str (tp->ptid));
 
+  /* If we're starting a new sequence, then the previous finished
+     single-step is no longer relevant.  */
+  if (tp->suspend.waitstatus_pending_p)
+    {
+      if (tp->suspend.stop_reason == TARGET_STOPPED_BY_SINGLE_STEP)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: clear_proceed_status: pending "
+                               "event of %s was a finished step. "
+                               "Discarding.\n",
+                               target_pid_to_str (tp->ptid));
+
+         tp->suspend.waitstatus_pending_p = 0;
+         tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON;
+       }
+      else if (debug_infrun)
+       {
+         std::string statstr
+           = target_waitstatus_to_string (&tp->suspend.waitstatus);
+
+         fprintf_unfiltered (gdb_stdlog,
+                             "infrun: clear_proceed_status_thread: thread %s "
+                             "has pending wait status %s "
+                             "(currently_stepping=%d).\n",
+                             target_pid_to_str (tp->ptid), statstr.c_str (),
+                             currently_stepping (tp));
+       }
+    }
+
   /* If this signal should not be seen by program, give it zero.
      Used for debugging signals.  */
   if (!signal_pass_state (tp->suspend.stop_signal))
     tp->suspend.stop_signal = GDB_SIGNAL_0;
 
+  thread_fsm_delete (tp->thread_fsm);
+  tp->thread_fsm = NULL;
+
   tp->control.trap_expected = 0;
   tp->control.step_range_start = 0;
   tp->control.step_range_end = 0;
@@ -2457,7 +2850,6 @@ clear_proceed_status_thread (struct thread_info *tp)
 
   tp->control.proceed_to_finish = 0;
 
-  tp->control.command_interp = NULL;
   tp->control.stepping_command = 0;
 
   /* Discard any remaining commands or status from previous stop.  */
@@ -2467,6 +2859,18 @@ clear_proceed_status_thread (struct thread_info *tp)
 void
 clear_proceed_status (int step)
 {
+  /* With scheduler-locking replay, stop replaying other threads if we're
+     not replaying the user-visible resume ptid.
+
+     This is a convenience feature to not require the user to explicitly
+     stop replaying the other threads.  We're assuming that the user's
+     intent is to resume tracing the recorded process.  */
+  if (!non_stop && scheduler_mode == schedlock_replay
+      && target_record_is_replaying (minus_one_ptid)
+      && !target_record_will_replay (user_visible_resume_ptid (step),
+                                    execution_direction))
+    target_record_stop_replaying ();
+
   if (!non_stop)
     {
       struct thread_info *tp;
@@ -2499,11 +2903,7 @@ clear_proceed_status (int step)
       inferior->control.stop_soon = NO_STOP_QUIETLY;
     }
 
-  stop_after_trap = 0;
-
-  clear_step_over_info ();
-
-  observer_notify_about_to_proceed ();
+  gdb::observers::about_to_proceed.notify ();
 }
 
 /* Returns true if TP is still stopped at a breakpoint that needs
@@ -2511,13 +2911,13 @@ clear_proceed_status (int step)
    meanwhile, we can skip the whole step-over dance.  */
 
 static int
-thread_still_needs_step_over (struct thread_info *tp)
+thread_still_needs_step_over_bp (struct thread_info *tp)
 {
   if (tp->stepping_over_breakpoint)
     {
       struct regcache *regcache = get_thread_regcache (tp->ptid);
 
-      if (breakpoint_here_p (get_regcache_aspace (regcache),
+      if (breakpoint_here_p (regcache->aspace (),
                             regcache_read_pc (regcache))
          == ordinary_breakpoint_here)
        return 1;
@@ -2528,6 +2928,25 @@ thread_still_needs_step_over (struct thread_info *tp)
   return 0;
 }
 
+/* Check whether thread TP still needs to start a step-over in order
+   to make progress when resumed.  Returns an bitwise or of enum
+   step_over_what bits, indicating what needs to be stepped over.  */
+
+static step_over_what
+thread_still_needs_step_over (struct thread_info *tp)
+{
+  step_over_what what = 0;
+
+  if (thread_still_needs_step_over_bp (tp))
+    what |= STEP_OVER_BREAKPOINT;
+
+  if (tp->stepping_over_watchpoint
+      && !target_have_steppable_watchpoint)
+    what |= STEP_OVER_WATCHPOINT;
+
+  return what;
+}
+
 /* Returns true if scheduler locking applies.  STEP indicates whether
    we're about to do a step/next-like command to a thread.  */
 
@@ -2536,49 +2955,10 @@ schedlock_applies (struct thread_info *tp)
 {
   return (scheduler_mode == schedlock_on
          || (scheduler_mode == schedlock_step
-             && tp->control.stepping_command));
-}
-
-/* Look a thread other than EXCEPT that has previously reported a
-   breakpoint event, and thus needs a step-over in order to make
-   progress.  Returns NULL is none is found.  */
-
-static struct thread_info *
-find_thread_needs_step_over (struct thread_info *except)
-{
-  struct thread_info *tp, *current;
-
-  /* With non-stop mode on, threads are always handled individually.  */
-  gdb_assert (! non_stop);
-
-  current = inferior_thread ();
-
-  /* If scheduler locking applies, we can avoid iterating over all
-     threads.  */
-  if (schedlock_applies (except))
-    {
-      if (except != current
-         && thread_still_needs_step_over (current))
-       return current;
-
-      return NULL;
-    }
-
-  ALL_NON_EXITED_THREADS (tp)
-    {
-      /* Ignore the EXCEPT thread.  */
-      if (tp == except)
-       continue;
-      /* Ignore threads of processes we're not resuming.  */
-      if (!sched_multi
-         && ptid_get_pid (tp->ptid) != ptid_get_pid (inferior_ptid))
-       continue;
-
-      if (thread_still_needs_step_over (tp))
-       return tp;
-    }
-
-  return NULL;
+             && tp->control.stepping_command)
+         || (scheduler_mode == schedlock_replay
+             && target_record_will_replay (minus_one_ptid,
+                                           execution_direction)));
 }
 
 /* Basic routine for continuing the program in various fashions.
@@ -2600,7 +2980,10 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   struct gdbarch *gdbarch;
   struct thread_info *tp;
   CORE_ADDR pc;
-  struct address_space *aspace;
+  ptid_t resume_ptid;
+  struct execution_control_state ecss;
+  struct execution_control_state *ecs = &ecss;
+  int started;
 
   /* If we're stopped at a fork/vfork, follow the branch set by the
      "set follow-fork-mode" command; otherwise, we'll just proceed
@@ -2618,14 +3001,17 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   previous_inferior_ptid = inferior_ptid;
 
   regcache = get_current_regcache ();
-  gdbarch = get_regcache_arch (regcache);
-  aspace = get_regcache_aspace (regcache);
+  gdbarch = regcache->arch ();
+  const address_space *aspace = regcache->aspace ();
+
   pc = regcache_read_pc (regcache);
   tp = inferior_thread ();
 
   /* Fill in with reasonable starting values.  */
   init_thread_stepping_state (tp);
 
+  gdb_assert (!thread_is_in_step_over_chain (tp));
+
   if (addr == (CORE_ADDR) -1)
     {
       if (pc == stop_pc
@@ -2655,13 +3041,21 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   if (siggnal != GDB_SIGNAL_DEFAULT)
     tp->suspend.stop_signal = siggnal;
 
-  /* Record the interpreter that issued the execution command that
-     caused this thread to resume.  If the top level interpreter is
-     MI/async, and the execution command was a CLI command
-     (next/step/etc.), we'll want to print stop event output to the MI
-     console channel (the stepped-to line, etc.), as if the user
-     entered the execution command on a real GDB console.  */
-  inferior_thread ()->control.command_interp = command_interp ();
+  resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
+
+  /* If an exception is thrown from this point on, make sure to
+     propagate GDB's knowledge of the executing state to the
+     frontend/user running state.  */
+  scoped_finish_thread_state finish_state (resume_ptid);
+
+  /* Even if RESUME_PTID is a wildcard, and we end up resuming fewer
+     threads (e.g., we might need to set threads stepping over
+     breakpoints first), from the user/frontend's point of view, all
+     threads in RESUME_PTID are now running.  Unless we're calling an
+     inferior function, as in that case we pretend the inferior
+     doesn't run at all.  */
+  if (!tp->control.in_infcall)
+   set_running (resume_ptid, 1);
 
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
@@ -2669,101 +3063,151 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
                        paddress (gdbarch, addr),
                        gdb_signal_to_symbol_string (siggnal));
 
-  if (non_stop)
-    /* In non-stop, each thread is handled individually.  The context
-       must already be set to the right thread here.  */
-    ;
-  else
+  annotate_starting ();
+
+  /* Make sure that output from GDB appears before output from the
+     inferior.  */
+  gdb_flush (gdb_stdout);
+
+  /* Since we've marked the inferior running, give it the terminal.  A
+     QUIT/Ctrl-C from here on is forwarded to the target (which can
+     still detect attempts to unblock a stuck connection with repeated
+     Ctrl-C from within target_pass_ctrlc).  */
+  target_terminal::inferior ();
+
+  /* In a multi-threaded task we may select another thread and
+     then continue or step.
+
+     But if a thread that we're resuming had stopped at a breakpoint,
+     it will immediately cause another breakpoint stop without any
+     execution (i.e. it will report a breakpoint hit incorrectly).  So
+     we must step over it first.
+
+     Look for threads other than the current (TP) that reported a
+     breakpoint hit and haven't been resumed yet since.  */
+
+  /* If scheduler locking applies, we can avoid iterating over all
+     threads.  */
+  if (!non_stop && !schedlock_applies (tp))
     {
-      struct thread_info *step_over;
+      struct thread_info *current = tp;
+
+      ALL_NON_EXITED_THREADS (tp)
+        {
+         /* Ignore the current thread here.  It's handled
+            afterwards.  */
+         if (tp == current)
+           continue;
+
+         /* Ignore threads of processes we're not resuming.  */
+         if (!ptid_match (tp->ptid, resume_ptid))
+           continue;
 
-      /* In a multi-threaded task we may select another thread and
-        then continue or step.
+         if (!thread_still_needs_step_over (tp))
+           continue;
 
-        But if the old thread was stopped at a breakpoint, it will
-        immediately cause another breakpoint stop without any
-        execution (i.e. it will report a breakpoint hit incorrectly).
-        So we must step over it first.
+         gdb_assert (!thread_is_in_step_over_chain (tp));
 
-        Look for a thread other than the current (TP) that reported a
-        breakpoint hit and hasn't been resumed yet since.  */
-      step_over = find_thread_needs_step_over (tp);
-      if (step_over != NULL)
-       {
          if (debug_infrun)
            fprintf_unfiltered (gdb_stdlog,
                                "infrun: need to step-over [%s] first\n",
-                               target_pid_to_str (step_over->ptid));
+                               target_pid_to_str (tp->ptid));
 
-         /* Store the prev_pc for the stepping thread too, needed by
-            switch_back_to_stepped_thread.  */
-         tp->prev_pc = regcache_read_pc (get_current_regcache ());
-         switch_to_thread (step_over->ptid);
-         tp = step_over;
+         thread_step_over_chain_enqueue (tp);
        }
+
+      tp = current;
     }
 
-  /* If we need to step over a breakpoint, and we're not using
-     displaced stepping to do so, insert all breakpoints (watchpoints,
-     etc.) but the one we're stepping over, step one instruction, and
-     then re-insert the breakpoint when that step is finished.  */
-  if (tp->stepping_over_breakpoint && !use_displaced_stepping (gdbarch))
-    {
-      struct regcache *regcache = get_current_regcache ();
+  /* Enqueue the current thread last, so that we move all other
+     threads over their breakpoints first.  */
+  if (tp->stepping_over_breakpoint)
+    thread_step_over_chain_enqueue (tp);
 
-      set_step_over_info (get_regcache_aspace (regcache),
-                         regcache_read_pc (regcache), 0);
-    }
-  else
-    clear_step_over_info ();
+  /* If the thread isn't started, we'll still need to set its prev_pc,
+     so that switch_back_to_stepped_thread knows the thread hasn't
+     advanced.  Must do this before resuming any thread, as in
+     all-stop/remote, once we resume we can't send any other packet
+     until the target stops again.  */
+  tp->prev_pc = regcache_read_pc (regcache);
 
-  insert_breakpoints ();
+  {
+    scoped_restore save_defer_tc = make_scoped_defer_target_commit_resume ();
 
-  tp->control.trap_expected = tp->stepping_over_breakpoint;
+    started = start_step_over ();
 
-  annotate_starting ();
+    if (step_over_info_valid_p ())
+      {
+       /* Either this thread started a new in-line step over, or some
+          other thread was already doing one.  In either case, don't
+          resume anything else until the step-over is finished.  */
+      }
+    else if (started && !target_is_non_stop_p ())
+      {
+       /* A new displaced stepping sequence was started.  In all-stop,
+          we can't talk to the target anymore until it next stops.  */
+      }
+    else if (!non_stop && target_is_non_stop_p ())
+      {
+       /* In all-stop, but the target is always in non-stop mode.
+          Start all other threads that are implicitly resumed too.  */
+       ALL_NON_EXITED_THREADS (tp)
+        {
+         /* Ignore threads of processes we're not resuming.  */
+         if (!ptid_match (tp->ptid, resume_ptid))
+           continue;
 
-  /* Make sure that output from GDB appears before output from the
-     inferior.  */
-  gdb_flush (gdb_stdout);
+         if (tp->resumed)
+           {
+             if (debug_infrun)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "infrun: proceed: [%s] resumed\n",
+                                   target_pid_to_str (tp->ptid));
+             gdb_assert (tp->executing || tp->suspend.waitstatus_pending_p);
+             continue;
+           }
+
+         if (thread_is_in_step_over_chain (tp))
+           {
+             if (debug_infrun)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "infrun: proceed: [%s] needs step-over\n",
+                                   target_pid_to_str (tp->ptid));
+             continue;
+           }
+
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: proceed: resuming %s\n",
+                               target_pid_to_str (tp->ptid));
+
+         reset_ecs (ecs, tp);
+         switch_to_thread (tp->ptid);
+         keep_going_pass_signal (ecs);
+         if (!ecs->wait_some_more)
+           error (_("Command aborted."));
+       }
+      }
+    else if (!tp->resumed && !thread_is_in_step_over_chain (tp))
+      {
+       /* The thread wasn't started, and isn't queued, run it now.  */
+       reset_ecs (ecs, tp);
+       switch_to_thread (tp->ptid);
+       keep_going_pass_signal (ecs);
+       if (!ecs->wait_some_more)
+         error (_("Command aborted."));
+      }
+  }
+
+  target_commit_resume ();
 
-  /* Refresh prev_pc value just prior to resuming.  This used to be
-     done in stop_waiting, however, setting prev_pc there did not handle
-     scenarios such as inferior function calls or returning from
-     a function via the return command.  In those cases, the prev_pc
-     value was not set properly for subsequent commands.  The prev_pc value 
-     is used to initialize the starting line number in the ecs.  With an 
-     invalid value, the gdb next command ends up stopping at the position
-     represented by the next line table entry past our start position.
-     On platforms that generate one line table entry per line, this
-     is not a problem.  However, on the ia64, the compiler generates
-     extraneous line table entries that do not increase the line number.
-     When we issue the gdb next command on the ia64 after an inferior call
-     or a return command, we often end up a few instructions forward, still 
-     within the original line we started.
-
-     An attempt was made to refresh the prev_pc at the same time the
-     execution_control_state is initialized (for instance, just before
-     waiting for an inferior event).  But this approach did not work
-     because of platforms that use ptrace, where the pc register cannot
-     be read unless the inferior is stopped.  At that point, we are not
-     guaranteed the inferior is stopped and so the regcache_read_pc() call
-     can fail.  Setting the prev_pc value here ensures the value is updated
-     correctly when the inferior is stopped.  */
-  tp->prev_pc = regcache_read_pc (get_current_regcache ());
-
-  /* Resume inferior.  */
-  resume (tp->suspend.stop_signal);
-
-  /* Wait for it to stop (if not standalone)
-     and in any case decode why it stopped, and act accordingly.  */
-  /* Do this only if we are not using the event loop, or if the target
-     does not support asynchronous execution.  */
+  finish_state.release ();
+
+  /* Tell the event loop to wait for it to stop.  If the target
+     supports asynchronous execution, it'll do this from within
+     target_resume.  */
   if (!target_can_async_p ())
-    {
-      wait_for_inferior ();
-      normal_stop ();
-    }
+    mark_async_event_handler (infrun_async_inferior_event_token);
 }
 \f
 
@@ -2796,7 +3240,7 @@ start_remote (int from_tty)
   /* Now that the inferior has stopped, do any bookkeeping like
      loading shared libraries.  We want to do this before normal_stop,
      so that the displayed frame is up to date.  */
-  post_create_inferior (&current_target, from_tty);
+  post_create_inferior (target_stack, from_tty);
 
   normal_stop ();
 }
@@ -2821,28 +3265,6 @@ init_wait_for_inferior (void)
 }
 
 \f
-/* Data to be passed around while handling an event.  This data is
-   discarded between events.  */
-struct execution_control_state
-{
-  ptid_t ptid;
-  /* The thread that got the event, if this was a thread event; NULL
-     otherwise.  */
-  struct thread_info *event_thread;
-
-  struct target_waitstatus ws;
-  int stop_func_filled_in;
-  CORE_ADDR stop_func_start;
-  CORE_ADDR stop_func_end;
-  const char *stop_func_name;
-  int wait_some_more;
-
-  /* True if the event thread hit the single-step breakpoint of
-     another thread.  Thus the event doesn't cause a stop, the thread
-     needs to be single-stepped past the single-step breakpoint before
-     we can switch back to the original stepping thread.  */
-  int hit_singlestep_breakpoint;
-};
 
 static void handle_inferior_event (struct execution_control_state *ecs);
 
@@ -2856,123 +3278,75 @@ static void check_exception_resume (struct execution_control_state *,
 
 static void end_stepping_range (struct execution_control_state *ecs);
 static void stop_waiting (struct execution_control_state *ecs);
-static void prepare_to_wait (struct execution_control_state *ecs);
 static void keep_going (struct execution_control_state *ecs);
 static void process_event_stop_test (struct execution_control_state *ecs);
 static int switch_back_to_stepped_thread (struct execution_control_state *ecs);
 
-/* Callback for iterate over threads.  If the thread is stopped, but
-   the user/frontend doesn't know about that yet, go through
-   normal_stop, as if the thread had just stopped now.  ARG points at
-   a ptid.  If PTID is MINUS_ONE_PTID, applies to all threads.  If
-   ptid_is_pid(PTID) is true, applies to all threads of the process
-   pointed at by PTID.  Otherwise, apply only to the thread pointed by
-   PTID.  */
+/* This function is attached as a "thread_stop_requested" observer.
+   Cleanup local state that assumed the PTID was to be resumed, and
+   report the stop to the frontend.  */
 
-static int
-infrun_thread_stop_requested_callback (struct thread_info *info, void *arg)
+static void
+infrun_thread_stop_requested (ptid_t ptid)
 {
-  ptid_t ptid = * (ptid_t *) arg;
+  struct thread_info *tp;
 
-  if ((ptid_equal (info->ptid, ptid)
-       || ptid_equal (minus_one_ptid, ptid)
-       || (ptid_is_pid (ptid)
-          && ptid_get_pid (ptid) == ptid_get_pid (info->ptid)))
-      && is_running (info->ptid)
-      && !is_executing (info->ptid))
-    {
-      struct cleanup *old_chain;
-      struct execution_control_state ecss;
-      struct execution_control_state *ecs = &ecss;
+  /* PTID was requested to stop.  If the thread was already stopped,
+     but the user/frontend doesn't know about that yet (e.g., the
+     thread had been temporarily paused for some step-over), set up
+     for reporting the stop now.  */
+  ALL_NON_EXITED_THREADS (tp)
+    if (ptid_match (tp->ptid, ptid))
+      {
+       if (tp->state != THREAD_RUNNING)
+         continue;
+       if (tp->executing)
+         continue;
+
+       /* Remove matching threads from the step-over queue, so
+          start_step_over doesn't try to resume them
+          automatically.  */
+       if (thread_is_in_step_over_chain (tp))
+         thread_step_over_chain_remove (tp);
+
+       /* If the thread is stopped, but the user/frontend doesn't
+          know about that yet, queue a pending event, as if the
+          thread had just stopped now.  Unless the thread already had
+          a pending event.  */
+       if (!tp->suspend.waitstatus_pending_p)
+         {
+           tp->suspend.waitstatus_pending_p = 1;
+           tp->suspend.waitstatus.kind = TARGET_WAITKIND_STOPPED;
+           tp->suspend.waitstatus.value.sig = GDB_SIGNAL_0;
+         }
 
-      memset (ecs, 0, sizeof (*ecs));
+       /* Clear the inline-frame state, since we're re-processing the
+          stop.  */
+       clear_inline_frame_state (tp->ptid);
+
+       /* If this thread was paused because some other thread was
+          doing an inline-step over, let that finish first.  Once
+          that happens, we'll restart all threads and consume pending
+          stop events then.  */
+       if (step_over_info_valid_p ())
+         continue;
+
+       /* Otherwise we can process the (new) pending event now.  Set
+          it so this pending event is considered by
+          do_target_wait.  */
+       tp->resumed = 1;
+      }
+}
 
-      old_chain = make_cleanup_restore_current_thread ();
+static void
+infrun_thread_thread_exit (struct thread_info *tp, int silent)
+{
+  if (ptid_equal (target_last_wait_ptid, tp->ptid))
+    nullify_last_target_wait_ptid ();
+}
 
-      overlay_cache_invalid = 1;
-      /* Flush target cache before starting to handle each event.
-        Target was running and cache could be stale.  This is just a
-        heuristic.  Running threads may modify target memory, but we
-        don't get any event.  */
-      target_dcache_invalidate ();
-
-      /* Go through handle_inferior_event/normal_stop, so we always
-        have consistent output as if the stop event had been
-        reported.  */
-      ecs->ptid = info->ptid;
-      ecs->event_thread = find_thread_ptid (info->ptid);
-      ecs->ws.kind = TARGET_WAITKIND_STOPPED;
-      ecs->ws.value.sig = GDB_SIGNAL_0;
-
-      handle_inferior_event (ecs);
-
-      if (!ecs->wait_some_more)
-       {
-         struct thread_info *tp;
-
-         normal_stop ();
-
-         /* Finish off the continuations.  */
-         tp = inferior_thread ();
-         do_all_intermediate_continuations_thread (tp, 1);
-         do_all_continuations_thread (tp, 1);
-       }
-
-      do_cleanups (old_chain);
-    }
-
-  return 0;
-}
-
-/* This function is attached as a "thread_stop_requested" observer.
-   Cleanup local state that assumed the PTID was to be resumed, and
-   report the stop to the frontend.  */
-
-static void
-infrun_thread_stop_requested (ptid_t ptid)
-{
-  struct displaced_step_inferior_state *displaced;
-
-  /* PTID was requested to stop.  Remove it from the displaced
-     stepping queue, so we don't try to resume it automatically.  */
-
-  for (displaced = displaced_step_inferior_states;
-       displaced;
-       displaced = displaced->next)
-    {
-      struct displaced_step_request *it, **prev_next_p;
-
-      it = displaced->step_request_queue;
-      prev_next_p = &displaced->step_request_queue;
-      while (it)
-       {
-         if (ptid_match (it->ptid, ptid))
-           {
-             *prev_next_p = it->next;
-             it->next = NULL;
-             xfree (it);
-           }
-         else
-           {
-             prev_next_p = &it->next;
-           }
-
-         it = *prev_next_p;
-       }
-    }
-
-  iterate_over_threads (infrun_thread_stop_requested_callback, &ptid);
-}
-
-static void
-infrun_thread_thread_exit (struct thread_info *tp, int silent)
-{
-  if (ptid_equal (target_last_wait_ptid, tp->ptid))
-    nullify_last_target_wait_ptid ();
-}
-
-/* Delete the step resume, single-step and longjmp/exception resume
-   breakpoints of TP.  */
+/* Delete the step resume, single-step and longjmp/exception resume
+   breakpoints of TP.  */
 
 static void
 delete_thread_infrun_breakpoints (struct thread_info *tp)
@@ -2995,7 +3369,7 @@ for_each_just_stopped_thread (for_each_just_stopped_thread_callback_func func)
   if (!target_has_execution || ptid_equal (inferior_ptid, null_ptid))
     return;
 
-  if (non_stop)
+  if (target_is_non_stop_p ())
     {
       /* If in non-stop mode, only the current thread stopped.  */
       func (inferior_thread ());
@@ -3038,49 +3412,209 @@ delete_just_stopped_threads_infrun_breakpoints_cleanup (void *arg)
   delete_just_stopped_threads_infrun_breakpoints ();
 }
 
-/* Pretty print the results of target_wait, for debugging purposes.  */
+/* See infrun.h.  */
 
-static void
+void
 print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
                           const struct target_waitstatus *ws)
 {
-  char *status_string = target_waitstatus_to_string (ws);
-  struct ui_file *tmp_stream = mem_fileopen ();
-  char *text;
+  std::string status_string = target_waitstatus_to_string (ws);
+  string_file stb;
 
   /* The text is split over several lines because it was getting too long.
      Call fprintf_unfiltered (gdb_stdlog) once so that the text is still
      output as a unit; we want only one timestamp printed if debug_timestamp
      is set.  */
 
-  fprintf_unfiltered (tmp_stream,
-                     "infrun: target_wait (%d.%ld.%ld",
-                     ptid_get_pid (waiton_ptid),
-                     ptid_get_lwp (waiton_ptid),
-                     ptid_get_tid (waiton_ptid));
+  stb.printf ("infrun: target_wait (%d.%ld.%ld",
+             ptid_get_pid (waiton_ptid),
+             ptid_get_lwp (waiton_ptid),
+             ptid_get_tid (waiton_ptid));
   if (ptid_get_pid (waiton_ptid) != -1)
-    fprintf_unfiltered (tmp_stream,
-                       " [%s]", target_pid_to_str (waiton_ptid));
-  fprintf_unfiltered (tmp_stream, ", status) =\n");
-  fprintf_unfiltered (tmp_stream,
-                     "infrun:   %d.%ld.%ld [%s],\n",
-                     ptid_get_pid (result_ptid),
-                     ptid_get_lwp (result_ptid),
-                     ptid_get_tid (result_ptid),
-                     target_pid_to_str (result_ptid));
-  fprintf_unfiltered (tmp_stream,
-                     "infrun:   %s\n",
-                     status_string);
-
-  text = ui_file_xstrdup (tmp_stream, NULL);
+    stb.printf (" [%s]", target_pid_to_str (waiton_ptid));
+  stb.printf (", status) =\n");
+  stb.printf ("infrun:   %d.%ld.%ld [%s],\n",
+             ptid_get_pid (result_ptid),
+             ptid_get_lwp (result_ptid),
+             ptid_get_tid (result_ptid),
+             target_pid_to_str (result_ptid));
+  stb.printf ("infrun:   %s\n", status_string.c_str ());
 
   /* This uses %s in part to handle %'s in the text, but also to avoid
      a gcc error: the format attribute requires a string literal.  */
-  fprintf_unfiltered (gdb_stdlog, "%s", text);
+  fprintf_unfiltered (gdb_stdlog, "%s", stb.c_str ());
+}
+
+/* Select a thread at random, out of those which are resumed and have
+   had events.  */
+
+static struct thread_info *
+random_pending_event_thread (ptid_t waiton_ptid)
+{
+  struct thread_info *event_tp;
+  int num_events = 0;
+  int random_selector;
+
+  /* First see how many events we have.  Count only resumed threads
+     that have an event pending.  */
+  ALL_NON_EXITED_THREADS (event_tp)
+    if (ptid_match (event_tp->ptid, waiton_ptid)
+       && event_tp->resumed
+       && event_tp->suspend.waitstatus_pending_p)
+      num_events++;
+
+  if (num_events == 0)
+    return NULL;
+
+  /* Now randomly pick a thread out of those that have had events.  */
+  random_selector = (int)
+    ((num_events * (double) rand ()) / (RAND_MAX + 1.0));
+
+  if (debug_infrun && num_events > 1)
+    fprintf_unfiltered (gdb_stdlog,
+                       "infrun: Found %d events, selecting #%d\n",
+                       num_events, random_selector);
+
+  /* Select the Nth thread that has had an event.  */
+  ALL_NON_EXITED_THREADS (event_tp)
+    if (ptid_match (event_tp->ptid, waiton_ptid)
+       && event_tp->resumed
+       && event_tp->suspend.waitstatus_pending_p)
+      if (random_selector-- == 0)
+       break;
+
+  return event_tp;
+}
+
+/* Wrapper for target_wait that first checks whether threads have
+   pending statuses to report before actually asking the target for
+   more events.  */
+
+static ptid_t
+do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
+{
+  ptid_t event_ptid;
+  struct thread_info *tp;
+
+  /* First check if there is a resumed thread with a wait status
+     pending.  */
+  if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
+    {
+      tp = random_pending_event_thread (ptid);
+    }
+  else
+    {
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: Waiting for specific thread %s.\n",
+                           target_pid_to_str (ptid));
+
+      /* We have a specific thread to check.  */
+      tp = find_thread_ptid (ptid);
+      gdb_assert (tp != NULL);
+      if (!tp->suspend.waitstatus_pending_p)
+       tp = NULL;
+    }
+
+  if (tp != NULL
+      && (tp->suspend.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
+         || tp->suspend.stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT))
+    {
+      struct regcache *regcache = get_thread_regcache (tp->ptid);
+      struct gdbarch *gdbarch = regcache->arch ();
+      CORE_ADDR pc;
+      int discard = 0;
+
+      pc = regcache_read_pc (regcache);
+
+      if (pc != tp->suspend.stop_pc)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: PC of %s changed.  was=%s, now=%s\n",
+                               target_pid_to_str (tp->ptid),
+                               paddress (gdbarch, tp->prev_pc),
+                               paddress (gdbarch, pc));
+         discard = 1;
+       }
+      else if (!breakpoint_inserted_here_p (regcache->aspace (), pc))
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: previous breakpoint of %s, at %s gone\n",
+                               target_pid_to_str (tp->ptid),
+                               paddress (gdbarch, pc));
+
+         discard = 1;
+       }
+
+      if (discard)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: pending event of %s cancelled.\n",
+                               target_pid_to_str (tp->ptid));
+
+         tp->suspend.waitstatus.kind = TARGET_WAITKIND_SPURIOUS;
+         tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON;
+       }
+    }
+
+  if (tp != NULL)
+    {
+      if (debug_infrun)
+       {
+         std::string statstr
+           = target_waitstatus_to_string (&tp->suspend.waitstatus);
+
+         fprintf_unfiltered (gdb_stdlog,
+                             "infrun: Using pending wait status %s for %s.\n",
+                             statstr.c_str (),
+                             target_pid_to_str (tp->ptid));
+       }
+
+      /* Now that we've selected our final event LWP, un-adjust its PC
+        if it was a software breakpoint (and the target doesn't
+        always adjust the PC itself).  */
+      if (tp->suspend.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
+         && !target_supports_stopped_by_sw_breakpoint ())
+       {
+         struct regcache *regcache;
+         struct gdbarch *gdbarch;
+         int decr_pc;
+
+         regcache = get_thread_regcache (tp->ptid);
+         gdbarch = regcache->arch ();
+
+         decr_pc = gdbarch_decr_pc_after_break (gdbarch);
+         if (decr_pc != 0)
+           {
+             CORE_ADDR pc;
+
+             pc = regcache_read_pc (regcache);
+             regcache_write_pc (regcache, pc + decr_pc);
+           }
+       }
+
+      tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON;
+      *status = tp->suspend.waitstatus;
+      tp->suspend.waitstatus_pending_p = 0;
+
+      /* Wake up the event loop again, until all pending events are
+        processed.  */
+      if (target_is_async_p ())
+       mark_async_event_handler (infrun_async_inferior_event_token);
+      return tp->ptid;
+    }
+
+  /* But if we don't find one, we'll have to wait.  */
+
+  if (deprecated_target_wait_hook)
+    event_ptid = deprecated_target_wait_hook (ptid, status, options);
+  else
+    event_ptid = target_wait (ptid, status, options);
 
-  xfree (status_string);
-  xfree (text);
-  ui_file_delete (tmp_stream);
+  return event_ptid;
 }
 
 /* Prepare and stabilize the inferior for detaching it.  E.g.,
@@ -3093,7 +3627,6 @@ prepare_for_detach (void)
 {
   struct inferior *inf = current_inferior ();
   ptid_t pid_ptid = pid_to_ptid (inf->pid);
-  struct cleanup *old_chain_1;
   struct displaced_step_inferior_state *displaced;
 
   displaced = get_displaced_stepping_state (inf->pid);
@@ -3107,12 +3640,10 @@ prepare_for_detach (void)
     fprintf_unfiltered (gdb_stdlog,
                        "displaced-stepping in-process while detaching");
 
-  old_chain_1 = make_cleanup_restore_integer (&inf->detaching);
-  inf->detaching = 1;
+  scoped_restore restore_detaching = make_scoped_restore (&inf->detaching, true);
 
   while (!ptid_equal (displaced->step_ptid, null_ptid))
     {
-      struct cleanup *old_chain_2;
       struct execution_control_state ecss;
       struct execution_control_state *ecs;
 
@@ -3126,10 +3657,7 @@ prepare_for_detach (void)
         don't get any event.  */
       target_dcache_invalidate ();
 
-      if (deprecated_target_wait_hook)
-       ecs->ptid = deprecated_target_wait_hook (pid_ptid, &ecs->ws, 0);
-      else
-       ecs->ptid = target_wait (pid_ptid, &ecs->ws, 0);
+      ecs->ptid = do_target_wait (pid_ptid, &ecs->ws, 0);
 
       if (debug_infrun)
        print_target_wait_results (pid_ptid, ecs->ptid, &ecs->ws);
@@ -3137,26 +3665,25 @@ prepare_for_detach (void)
       /* If an error happens while handling the event, propagate GDB's
         knowledge of the executing state to the frontend/user running
         state.  */
-      old_chain_2 = make_cleanup (finish_thread_state_cleanup,
-                                 &minus_one_ptid);
+      scoped_finish_thread_state finish_state (minus_one_ptid);
 
       /* Now figure out what to do with the result of the result.  */
       handle_inferior_event (ecs);
 
       /* No error, don't finish the state yet.  */
-      discard_cleanups (old_chain_2);
+      finish_state.release ();
 
       /* Breakpoints and watchpoints are not installed on the target
         at this point, and signals are passed directly to the
         inferior, so this must mean the process is gone.  */
       if (!ecs->wait_some_more)
        {
-         discard_cleanups (old_chain_1);
+         restore_detaching.release ();
          error (_("Program exited while detaching"));
        }
     }
 
-  discard_cleanups (old_chain_1);
+  restore_detaching.release ();
 }
 
 /* Wait for control to return from inferior to debugger.
@@ -3170,7 +3697,6 @@ void
 wait_for_inferior (void)
 {
   struct cleanup *old_cleanups;
-  struct cleanup *thread_state_chain;
 
   if (debug_infrun)
     fprintf_unfiltered
@@ -3183,7 +3709,7 @@ wait_for_inferior (void)
   /* If an error happens while handling the event, propagate GDB's
      knowledge of the executing state to the frontend/user running
      state.  */
-  thread_state_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+  scoped_finish_thread_state finish_state (minus_one_ptid);
 
   while (1)
     {
@@ -3201,10 +3727,7 @@ wait_for_inferior (void)
         don't get any event.  */
       target_dcache_invalidate ();
 
-      if (deprecated_target_wait_hook)
-       ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws, 0);
-      else
-       ecs->ptid = target_wait (waiton_ptid, &ecs->ws, 0);
+      ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, 0);
 
       if (debug_infrun)
        print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
@@ -3217,7 +3740,7 @@ wait_for_inferior (void)
     }
 
   /* No error, don't finish the state yet.  */
-  discard_cleanups (thread_state_chain);
+  finish_state.release ();
 
   do_cleanups (old_cleanups);
 }
@@ -3235,7 +3758,9 @@ wait_for_inferior (void)
 static void
 reinstall_readline_callback_handler_cleanup (void *arg)
 {
-  if (!interpreter_async)
+  struct ui *ui = current_ui;
+
+  if (!ui->async)
     {
       /* We're not going back to the top level event loop yet.  Don't
         install the readline callback, as it'd prep the terminal,
@@ -3245,10 +3770,80 @@ reinstall_readline_callback_handler_cleanup (void *arg)
       return;
     }
 
-  if (async_command_editing_p && !sync_execution)
+  if (ui->command_editing && ui->prompt_state != PROMPT_BLOCKED)
     gdb_rl_callback_handler_reinstall ();
 }
 
+/* Clean up the FSMs of threads that are now stopped.  In non-stop,
+   that's just the event thread.  In all-stop, that's all threads.  */
+
+static void
+clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs)
+{
+  struct thread_info *thr = ecs->event_thread;
+
+  if (thr != NULL && thr->thread_fsm != NULL)
+    thread_fsm_clean_up (thr->thread_fsm, thr);
+
+  if (!non_stop)
+    {
+      ALL_NON_EXITED_THREADS (thr)
+        {
+         if (thr->thread_fsm == NULL)
+           continue;
+         if (thr == ecs->event_thread)
+           continue;
+
+         switch_to_thread (thr->ptid);
+         thread_fsm_clean_up (thr->thread_fsm, thr);
+       }
+
+      if (ecs->event_thread != NULL)
+       switch_to_thread (ecs->event_thread->ptid);
+    }
+}
+
+/* Helper for all_uis_check_sync_execution_done that works on the
+   current UI.  */
+
+static void
+check_curr_ui_sync_execution_done (void)
+{
+  struct ui *ui = current_ui;
+
+  if (ui->prompt_state == PROMPT_NEEDED
+      && ui->async
+      && !gdb_in_secondary_prompt_p (ui))
+    {
+      target_terminal::ours ();
+      gdb::observers::sync_execution_done.notify ();
+      ui_register_input_event_handler (ui);
+    }
+}
+
+/* See infrun.h.  */
+
+void
+all_uis_check_sync_execution_done (void)
+{
+  SWITCH_THRU_ALL_UIS ()
+    {
+      check_curr_ui_sync_execution_done ();
+    }
+}
+
+/* See infrun.h.  */
+
+void
+all_uis_on_sync_execution_starting (void)
+{
+  SWITCH_THRU_ALL_UIS ()
+    {
+      if (current_ui->prompt_state == PROMPT_NEEDED)
+       async_disable_stdin ();
+    }
+}
+
 /* Asynchronous version of wait_for_inferior.  It is called by the
    event loop whenever a change of state is detected on the file
    descriptor corresponding to the target.  It can be called more than
@@ -3264,13 +3859,16 @@ fetch_inferior_event (void *client_data)
   struct execution_control_state ecss;
   struct execution_control_state *ecs = &ecss;
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-  struct cleanup *ts_old_chain;
-  int was_sync = sync_execution;
   int cmd_done = 0;
   ptid_t waiton_ptid = minus_one_ptid;
 
   memset (ecs, 0, sizeof (*ecs));
 
+  /* Events are always processed with the main UI as current UI.  This
+     way, warnings, debug output, etc. are always consistently sent to
+     the main console.  */
+  scoped_restore save_ui = make_scoped_restore (&current_ui, main_ui);
+
   /* End up with readline processing input, if necessary.  */
   make_cleanup (reinstall_readline_callback_handler_cleanup, NULL);
 
@@ -3278,18 +3876,21 @@ fetch_inferior_event (void *client_data)
      debugging.  If we're looking at traceframes while the target is
      running, we're going to need to get back to that mode after
      handling the event.  */
+  gdb::optional<scoped_restore_current_traceframe> maybe_restore_traceframe;
   if (non_stop)
     {
-      make_cleanup_restore_current_traceframe ();
+      maybe_restore_traceframe.emplace ();
       set_current_traceframe (-1);
     }
 
+  gdb::optional<scoped_restore_current_thread> maybe_restore_thread;
+
   if (non_stop)
     /* In non-stop mode, the user/frontend should not notice a thread
        switch due to internal events.  Make sure we reverse to the
        user selected thread and frame after handling the event and
        running any breakpoint commands.  */
-    make_cleanup_restore_current_thread ();
+    maybe_restore_thread.emplace ();
 
   overlay_cache_invalid = 1;
   /* Flush target cache before starting to handle each event.  Target
@@ -3298,14 +3899,11 @@ fetch_inferior_event (void *client_data)
      event.  */
   target_dcache_invalidate ();
 
-  make_cleanup_restore_integer (&execution_direction);
-  execution_direction = target_execution_direction ();
+  scoped_restore save_exec_dir
+    = make_scoped_restore (&execution_direction, target_execution_direction ());
 
-  if (deprecated_target_wait_hook)
-    ecs->ptid =
-      deprecated_target_wait_hook (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
-  else
-    ecs->ptid = target_wait (waiton_ptid, &ecs->ws, TARGET_WNOHANG);
+  ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws,
+                             target_can_async_p () ? TARGET_WNOHANG : 0);
 
   if (debug_infrun)
     print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
@@ -3313,14 +3911,12 @@ fetch_inferior_event (void *client_data)
   /* If an error happens while handling the event, propagate GDB's
      knowledge of the executing state to the frontend/user running
      state.  */
-  if (!non_stop)
-    ts_old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
-  else
-    ts_old_chain = make_cleanup (finish_thread_state_cleanup, &ecs->ptid);
+  ptid_t finish_ptid = !target_is_non_stop_p () ? minus_one_ptid : ecs->ptid;
+  scoped_finish_thread_state finish_state (finish_ptid);
 
   /* Get executed before make_cleanup_restore_current_thread above to apply
      still for the thread which has thrown the exception.  */
-  make_bpstat_clear_actions_cleanup ();
+  struct cleanup *ts_old_chain = make_bpstat_clear_actions_cleanup ();
 
   make_cleanup (delete_just_stopped_threads_infrun_breakpoints_cleanup, NULL);
 
@@ -3330,41 +3926,65 @@ fetch_inferior_event (void *client_data)
   if (!ecs->wait_some_more)
     {
       struct inferior *inf = find_inferior_ptid (ecs->ptid);
+      int should_stop = 1;
+      struct thread_info *thr = ecs->event_thread;
+      int should_notify_stop = 1;
 
       delete_just_stopped_threads_infrun_breakpoints ();
 
-      /* We may not find an inferior if this was a process exit.  */
-      if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY)
-       normal_stop ();
-
-      if (target_has_execution
-         && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED
-         && ecs->ws.kind != TARGET_WAITKIND_EXITED
-         && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
-         && ecs->event_thread->step_multi
-         && ecs->event_thread->control.stop_step)
-       inferior_event_handler (INF_EXEC_CONTINUE, NULL);
+      if (thr != NULL)
+       {
+         struct thread_fsm *thread_fsm = thr->thread_fsm;
+
+         if (thread_fsm != NULL)
+           should_stop = thread_fsm_should_stop (thread_fsm, thr);
+       }
+
+      if (!should_stop)
+       {
+         keep_going (ecs);
+       }
       else
        {
-         inferior_event_handler (INF_EXEC_COMPLETE, NULL);
-         cmd_done = 1;
+         clean_up_just_stopped_threads_fsms (ecs);
+
+         if (thr != NULL && thr->thread_fsm != NULL)
+           {
+             should_notify_stop
+               = thread_fsm_should_notify_stop (thr->thread_fsm);
+           }
+
+         if (should_notify_stop)
+           {
+             int proceeded = 0;
+
+             /* We may not find an inferior if this was a process exit.  */
+             if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY)
+               proceeded = normal_stop ();
+
+             if (!proceeded)
+               {
+                 inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+                 cmd_done = 1;
+               }
+           }
        }
     }
 
-  /* No error, don't finish the thread states yet.  */
   discard_cleanups (ts_old_chain);
 
+  /* No error, don't finish the thread states yet.  */
+  finish_state.release ();
+
   /* Revert thread and frame.  */
   do_cleanups (old_chain);
 
-  /* If the inferior was in sync execution mode, and now isn't,
-     restore the prompt (a synchronous execution command has finished,
-     and we're ready for input).  */
-  if (interpreter_async && was_sync && !sync_execution)
-    observer_notify_sync_execution_done ();
+  /* If a UI was in sync execution mode, and now isn't, restore its
+     prompt (a synchronous execution command has finished, and we're
+     ready for input).  */
+  all_uis_check_sync_execution_done ();
 
   if (cmd_done
-      && !was_sync
       && exec_done_display_p
       && (ptid_equal (inferior_ptid, null_ptid)
          || !is_running (inferior_ptid)))
@@ -3397,7 +4017,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;
@@ -3438,12 +4058,17 @@ context_switch (ptid_t ptid)
   switch_to_thread (ptid);
 }
 
+/* If the target can't tell whether we've hit breakpoints
+   (target_supports_stopped_by_sw_breakpoint), and we got a SIGTRAP,
+   check whether that could have been caused by a breakpoint.  If so,
+   adjust the PC, per gdbarch_decr_pc_after_break.  */
+
 static void
-adjust_pc_after_break (struct execution_control_state *ecs)
+adjust_pc_after_break (struct thread_info *thread,
+                      struct target_waitstatus *ws)
 {
   struct regcache *regcache;
   struct gdbarch *gdbarch;
-  struct address_space *aspace;
   CORE_ADDR breakpoint_pc, decr_pc;
 
   /* If we've hit a breakpoint, we'll normally be stopped with SIGTRAP.  If
@@ -3467,10 +4092,10 @@ adjust_pc_after_break (struct execution_control_state *ecs)
      target with both of these set in GDB history, and it seems unlikely to be
      correct, so gdbarch_have_nonsteppable_watchpoint is not checked here.  */
 
-  if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
+  if (ws->kind != TARGET_WAITKIND_STOPPED)
     return;
 
-  if (ecs->ws.value.sig != GDB_SIGNAL_TRAP)
+  if (ws->value.sig != GDB_SIGNAL_TRAP)
     return;
 
   /* In reverse execution, when a breakpoint is hit, the instruction
@@ -3516,14 +4141,14 @@ adjust_pc_after_break (struct execution_control_state *ecs)
 
   /* If this target does not decrement the PC after breakpoints, then
      we have nothing to do.  */
-  regcache = get_thread_regcache (ecs->ptid);
-  gdbarch = get_regcache_arch (regcache);
+  regcache = get_thread_regcache (thread->ptid);
+  gdbarch = regcache->arch ();
 
   decr_pc = gdbarch_decr_pc_after_break (gdbarch);
   if (decr_pc == 0)
     return;
 
-  aspace = get_regcache_aspace (regcache);
+  const address_space *aspace = regcache->aspace ();
 
   /* Find the location where (if we've hit a breakpoint) the
      breakpoint would be.  */
@@ -3546,12 +4171,14 @@ adjust_pc_after_break (struct execution_control_state *ecs)
      to get the "stopped by SW BP and needs adjustment" info out of
      the target/kernel (and thus never reach here; see above).  */
   if (software_breakpoint_inserted_here_p (aspace, breakpoint_pc)
-      || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
+      || (target_is_non_stop_p ()
+         && moribund_breakpoint_here_p (aspace, breakpoint_pc)))
     {
-      struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
+      gdb::optional<scoped_restore_tmpl<int>> restore_operation_disable;
 
       if (record_full_is_used ())
-       record_full_gdb_operation_disable_set ();
+       restore_operation_disable.emplace
+         (record_full_gdb_operation_disable_set ());
 
       /* When using hardware single-step, a SIGTRAP is reported for both
         a completed single-step and a software breakpoint.  Need to
@@ -3570,13 +4197,11 @@ adjust_pc_after_break (struct execution_control_state *ecs)
         software breakpoint.  In this case (prev_pc == breakpoint_pc),
         we also need to back up to the breakpoint address.  */
 
-      if (thread_has_single_step_breakpoints_set (ecs->event_thread)
-         || !currently_stepping (ecs->event_thread)
-         || (ecs->event_thread->stepped_breakpoint
-             && ecs->event_thread->prev_pc == breakpoint_pc))
+      if (thread_has_single_step_breakpoints_set (thread)
+         || !currently_stepping (thread)
+         || (thread->stepped_breakpoint
+             && thread->prev_pc == breakpoint_pc))
        regcache_write_pc (regcache, breakpoint_pc);
-
-      do_cleanups (old_cleanups);
     }
 }
 
@@ -3596,6 +4221,23 @@ stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id)
   return 0;
 }
 
+/* If the event thread has the stop requested flag set, pretend it
+   stopped for a GDB_SIGNAL_0 (i.e., as if it stopped due to
+   target_stop).  */
+
+static bool
+handle_stop_requested (struct execution_control_state *ecs)
+{
+  if (ecs->event_thread->stop_requested)
+    {
+      ecs->ws.kind = TARGET_WAITKIND_STOPPED;
+      ecs->ws.value.sig = GDB_SIGNAL_0;
+      handle_signal_stop (ecs);
+      return true;
+    }
+  return false;
+}
+
 /* Auxiliary function that handles syscall entry/return events.
    It returns 1 if the inferior should keep going (and GDB
    should ignore the event), or 0 if the event deserves to be
@@ -3622,9 +4264,12 @@ handle_syscall_event (struct execution_control_state *ecs)
                             syscall_number);
 
       ecs->event_thread->control.stop_bpstat
-       = bpstat_stop_status (get_regcache_aspace (regcache),
+       = bpstat_stop_status (regcache->aspace (),
                              stop_pc, ecs->ptid, &ecs->ws);
 
+      if (handle_stop_requested (ecs))
+       return 0;
+
       if (bpstat_causes_stop (ecs->event_thread->control.stop_bpstat))
        {
          /* Catchpoint hit.  */
@@ -3632,6 +4277,9 @@ handle_syscall_event (struct execution_control_state *ecs)
        }
     }
 
+  if (handle_stop_requested (ecs))
+    return 0;
+
   /* If no catchpoint triggered for this, then keep going.  */
   keep_going (ecs);
   return 1;
@@ -3672,31 +4320,493 @@ get_inferior_stop_soon (ptid_t ptid)
   return inf->control.stop_soon;
 }
 
-/* Given an execution control state that has been freshly filled in by
-   an event from the inferior, figure out what it means and take
-   appropriate action.
+/* Wait for one event.  Store the resulting waitstatus in WS, and
+   return the event ptid.  */
 
-   The alternatives are:
+static ptid_t
+wait_one (struct target_waitstatus *ws)
+{
+  ptid_t event_ptid;
+  ptid_t wait_ptid = minus_one_ptid;
 
-   1) stop_waiting and return; to really stop and return to the
-   debugger.
+  overlay_cache_invalid = 1;
 
-   2) keep_going and return; to wait for the next event (set
-   ecs->event_thread->stepping_over_breakpoint to 1 to single step
-   once).  */
+  /* Flush target cache before starting to handle each event.
+     Target was running and cache could be stale.  This is just a
+     heuristic.  Running threads may modify target memory, but we
+     don't get any event.  */
+  target_dcache_invalidate ();
+
+  if (deprecated_target_wait_hook)
+    event_ptid = deprecated_target_wait_hook (wait_ptid, ws, 0);
+  else
+    event_ptid = target_wait (wait_ptid, ws, 0);
+
+  if (debug_infrun)
+    print_target_wait_results (wait_ptid, event_ptid, ws);
+
+  return event_ptid;
+}
+
+/* Generate a wrapper for target_stopped_by_REASON that works on PTID
+   instead of the current thread.  */
+#define THREAD_STOPPED_BY(REASON)              \
+static int                                     \
+thread_stopped_by_ ## REASON (ptid_t ptid)     \
+{                                              \
+  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid); \
+  inferior_ptid = ptid;                                \
+                                               \
+  return target_stopped_by_ ## REASON ();      \
+}
+
+/* Generate thread_stopped_by_watchpoint.  */
+THREAD_STOPPED_BY (watchpoint)
+/* Generate thread_stopped_by_sw_breakpoint.  */
+THREAD_STOPPED_BY (sw_breakpoint)
+/* Generate thread_stopped_by_hw_breakpoint.  */
+THREAD_STOPPED_BY (hw_breakpoint)
+
+/* Cleanups that switches to the PTID pointed at by PTID_P.  */
 
 static void
-handle_inferior_event_1 (struct execution_control_state *ecs)
+switch_to_thread_cleanup (void *ptid_p)
 {
-  enum stop_kind stop_soon;
+  ptid_t ptid = *(ptid_t *) ptid_p;
 
-  if (ecs->ws.kind == TARGET_WAITKIND_IGNORE)
-    {
-      /* We had an event in the inferior, but we are not interested in
-        handling it at this level.  The lower layers have already
-        done what needs to be done, if anything.
+  switch_to_thread (ptid);
+}
 
-        One of the possible circumstances for this is when the
+/* Save the thread's event and stop reason to process it later.  */
+
+static void
+save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws)
+{
+  struct regcache *regcache;
+
+  if (debug_infrun)
+    {
+      std::string statstr = target_waitstatus_to_string (ws);
+
+      fprintf_unfiltered (gdb_stdlog,
+                         "infrun: saving status %s for %d.%ld.%ld\n",
+                         statstr.c_str (),
+                         ptid_get_pid (tp->ptid),
+                         ptid_get_lwp (tp->ptid),
+                         ptid_get_tid (tp->ptid));
+    }
+
+  /* Record for later.  */
+  tp->suspend.waitstatus = *ws;
+  tp->suspend.waitstatus_pending_p = 1;
+
+  regcache = get_thread_regcache (tp->ptid);
+  const address_space *aspace = regcache->aspace ();
+
+  if (ws->kind == TARGET_WAITKIND_STOPPED
+      && ws->value.sig == GDB_SIGNAL_TRAP)
+    {
+      CORE_ADDR pc = regcache_read_pc (regcache);
+
+      adjust_pc_after_break (tp, &tp->suspend.waitstatus);
+
+      if (thread_stopped_by_watchpoint (tp->ptid))
+       {
+         tp->suspend.stop_reason
+           = TARGET_STOPPED_BY_WATCHPOINT;
+       }
+      else if (target_supports_stopped_by_sw_breakpoint ()
+              && thread_stopped_by_sw_breakpoint (tp->ptid))
+       {
+         tp->suspend.stop_reason
+           = TARGET_STOPPED_BY_SW_BREAKPOINT;
+       }
+      else if (target_supports_stopped_by_hw_breakpoint ()
+              && thread_stopped_by_hw_breakpoint (tp->ptid))
+       {
+         tp->suspend.stop_reason
+           = TARGET_STOPPED_BY_HW_BREAKPOINT;
+       }
+      else if (!target_supports_stopped_by_hw_breakpoint ()
+              && hardware_breakpoint_inserted_here_p (aspace,
+                                                      pc))
+       {
+         tp->suspend.stop_reason
+           = TARGET_STOPPED_BY_HW_BREAKPOINT;
+       }
+      else if (!target_supports_stopped_by_sw_breakpoint ()
+              && software_breakpoint_inserted_here_p (aspace,
+                                                      pc))
+       {
+         tp->suspend.stop_reason
+           = TARGET_STOPPED_BY_SW_BREAKPOINT;
+       }
+      else if (!thread_has_single_step_breakpoints_set (tp)
+              && currently_stepping (tp))
+       {
+         tp->suspend.stop_reason
+           = TARGET_STOPPED_BY_SINGLE_STEP;
+       }
+    }
+}
+
+/* A cleanup that disables thread create/exit events.  */
+
+static void
+disable_thread_events (void *arg)
+{
+  target_thread_events (0);
+}
+
+/* See infrun.h.  */
+
+void
+stop_all_threads (void)
+{
+  /* We may need multiple passes to discover all threads.  */
+  int pass;
+  int iterations = 0;
+  ptid_t entry_ptid;
+  struct cleanup *old_chain;
+
+  gdb_assert (target_is_non_stop_p ());
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads\n");
+
+  entry_ptid = inferior_ptid;
+  old_chain = make_cleanup (switch_to_thread_cleanup, &entry_ptid);
+
+  target_thread_events (1);
+  make_cleanup (disable_thread_events, NULL);
+
+  /* Request threads to stop, and then wait for the stops.  Because
+     threads we already know about can spawn more threads while we're
+     trying to stop them, and we only learn about new threads when we
+     update the thread list, do this in a loop, and keep iterating
+     until two passes find no threads that need to be stopped.  */
+  for (pass = 0; pass < 2; pass++, iterations++)
+    {
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: stop_all_threads, pass=%d, "
+                           "iterations=%d\n", pass, iterations);
+      while (1)
+       {
+         ptid_t event_ptid;
+         struct target_waitstatus ws;
+         int need_wait = 0;
+         struct thread_info *t;
+
+         update_thread_list ();
+
+         /* Go through all threads looking for threads that we need
+            to tell the target to stop.  */
+         ALL_NON_EXITED_THREADS (t)
+           {
+             if (t->executing)
+               {
+                 /* If already stopping, don't request a stop again.
+                    We just haven't seen the notification yet.  */
+                 if (!t->stop_requested)
+                   {
+                     if (debug_infrun)
+                       fprintf_unfiltered (gdb_stdlog,
+                                           "infrun:   %s executing, "
+                                           "need stop\n",
+                                           target_pid_to_str (t->ptid));
+                     target_stop (t->ptid);
+                     t->stop_requested = 1;
+                   }
+                 else
+                   {
+                     if (debug_infrun)
+                       fprintf_unfiltered (gdb_stdlog,
+                                           "infrun:   %s executing, "
+                                           "already stopping\n",
+                                           target_pid_to_str (t->ptid));
+                   }
+
+                 if (t->stop_requested)
+                   need_wait = 1;
+               }
+             else
+               {
+                 if (debug_infrun)
+                   fprintf_unfiltered (gdb_stdlog,
+                                       "infrun:   %s not executing\n",
+                                       target_pid_to_str (t->ptid));
+
+                 /* The thread may be not executing, but still be
+                    resumed with a pending status to process.  */
+                 t->resumed = 0;
+               }
+           }
+
+         if (!need_wait)
+           break;
+
+         /* If we find new threads on the second iteration, restart
+            over.  We want to see two iterations in a row with all
+            threads stopped.  */
+         if (pass > 0)
+           pass = -1;
+
+         event_ptid = wait_one (&ws);
+         if (ws.kind == TARGET_WAITKIND_NO_RESUMED)
+           {
+             /* All resumed threads exited.  */
+           }
+         else if (ws.kind == TARGET_WAITKIND_THREAD_EXITED
+                  || ws.kind == TARGET_WAITKIND_EXITED
+                  || ws.kind == TARGET_WAITKIND_SIGNALLED)
+           {
+             if (debug_infrun)
+               {
+                 ptid_t ptid = pid_to_ptid (ws.value.integer);
+
+                 fprintf_unfiltered (gdb_stdlog,
+                                     "infrun: %s exited while "
+                                     "stopping threads\n",
+                                     target_pid_to_str (ptid));
+               }
+           }
+         else
+           {
+             struct inferior *inf;
+
+             t = find_thread_ptid (event_ptid);
+             if (t == NULL)
+               t = add_thread (event_ptid);
+
+             t->stop_requested = 0;
+             t->executing = 0;
+             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)
+               {
+                 /* We caught the event that we intended to catch, so
+                    there's no event pending.  */
+                 t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
+                 t->suspend.waitstatus_pending_p = 0;
+
+                 if (displaced_step_fixup (t->ptid, GDB_SIGNAL_0) < 0)
+                   {
+                     /* Add it back to the step-over queue.  */
+                     if (debug_infrun)
+                       {
+                         fprintf_unfiltered (gdb_stdlog,
+                                             "infrun: displaced-step of %s "
+                                             "canceled: adding back to the "
+                                             "step-over queue\n",
+                                             target_pid_to_str (t->ptid));
+                       }
+                     t->control.trap_expected = 0;
+                     thread_step_over_chain_enqueue (t);
+                   }
+               }
+             else
+               {
+                 enum gdb_signal sig;
+                 struct regcache *regcache;
+
+                 if (debug_infrun)
+                   {
+                     std::string statstr = target_waitstatus_to_string (&ws);
+
+                     fprintf_unfiltered (gdb_stdlog,
+                                         "infrun: target_wait %s, saving "
+                                         "status for %d.%ld.%ld\n",
+                                         statstr.c_str (),
+                                         ptid_get_pid (t->ptid),
+                                         ptid_get_lwp (t->ptid),
+                                         ptid_get_tid (t->ptid));
+                   }
+
+                 /* Record for later.  */
+                 save_waitstatus (t, &ws);
+
+                 sig = (ws.kind == TARGET_WAITKIND_STOPPED
+                        ? ws.value.sig : GDB_SIGNAL_0);
+
+                 if (displaced_step_fixup (t->ptid, sig) < 0)
+                   {
+                     /* Add it back to the step-over queue.  */
+                     t->control.trap_expected = 0;
+                     thread_step_over_chain_enqueue (t);
+                   }
+
+                 regcache = get_thread_regcache (t->ptid);
+                 t->suspend.stop_pc = regcache_read_pc (regcache);
+
+                 if (debug_infrun)
+                   {
+                     fprintf_unfiltered (gdb_stdlog,
+                                         "infrun: saved stop_pc=%s for %s "
+                                         "(currently_stepping=%d)\n",
+                                         paddress (target_gdbarch (),
+                                                   t->suspend.stop_pc),
+                                         target_pid_to_str (t->ptid),
+                                         currently_stepping (t));
+                   }
+               }
+           }
+       }
+    }
+
+  do_cleanups (old_chain);
+
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads done\n");
+}
+
+/* Handle a TARGET_WAITKIND_NO_RESUMED event.  */
+
+static int
+handle_no_resumed (struct execution_control_state *ecs)
+{
+  struct inferior *inf;
+  struct thread_info *thread;
+
+  if (target_can_async_p ())
+    {
+      struct ui *ui;
+      int any_sync = 0;
+
+      ALL_UIS (ui)
+       {
+         if (ui->prompt_state == PROMPT_BLOCKED)
+           {
+             any_sync = 1;
+             break;
+           }
+       }
+      if (!any_sync)
+       {
+         /* There were no unwaited-for children left in the target, but,
+            we're not synchronously waiting for events either.  Just
+            ignore.  */
+
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: TARGET_WAITKIND_NO_RESUMED "
+                               "(ignoring: bg)\n");
+         prepare_to_wait (ecs);
+         return 1;
+       }
+    }
+
+  /* Otherwise, if we were running a synchronous execution command, we
+     may need to cancel it and give the user back the terminal.
+
+     In non-stop mode, the target can't tell whether we've already
+     consumed previous stop events, so it can end up sending us a
+     no-resumed event like so:
+
+       #0 - thread 1 is left stopped
+
+       #1 - thread 2 is resumed and hits breakpoint
+               -> TARGET_WAITKIND_STOPPED
+
+       #2 - thread 3 is resumed and exits
+            this is the last resumed thread, so
+              -> TARGET_WAITKIND_NO_RESUMED
+
+       #3 - gdb processes stop for thread 2 and decides to re-resume
+            it.
+
+       #4 - gdb processes the TARGET_WAITKIND_NO_RESUMED event.
+            thread 2 is now resumed, so the event should be ignored.
+
+     IOW, if the stop for thread 2 doesn't end a foreground command,
+     then we need to ignore the following TARGET_WAITKIND_NO_RESUMED
+     event.  But it could be that the event meant that thread 2 itself
+     (or whatever other thread was the last resumed thread) exited.
+
+     To address this we refresh the thread list and check whether we
+     have resumed threads _now_.  In the example above, this removes
+     thread 3 from the thread list.  If thread 2 was re-resumed, we
+     ignore this event.  If we find no thread resumed, then we cancel
+     the synchronous command show "no unwaited-for " to the user.  */
+  update_thread_list ();
+
+  ALL_NON_EXITED_THREADS (thread)
+    {
+      if (thread->executing
+         || thread->suspend.waitstatus_pending_p)
+       {
+         /* There were no unwaited-for children left in the target at
+            some point, but there are now.  Just ignore.  */
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: TARGET_WAITKIND_NO_RESUMED "
+                               "(ignoring: found resumed)\n");
+         prepare_to_wait (ecs);
+         return 1;
+       }
+    }
+
+  /* Note however that we may find no resumed thread because the whole
+     process exited meanwhile (thus updating the thread list results
+     in an empty thread list).  In this case we know we'll be getting
+     a process exit event shortly.  */
+  ALL_INFERIORS (inf)
+    {
+      if (inf->pid == 0)
+       continue;
+
+      thread = any_live_thread_of_process (inf->pid);
+      if (thread == NULL)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: TARGET_WAITKIND_NO_RESUMED "
+                               "(expect process exit)\n");
+         prepare_to_wait (ecs);
+         return 1;
+       }
+    }
+
+  /* Go ahead and report the event.  */
+  return 0;
+}
+
+/* Given an execution control state that has been freshly filled in by
+   an event from the inferior, figure out what it means and take
+   appropriate action.
+
+   The alternatives are:
+
+   1) stop_waiting and return; to really stop and return to the
+   debugger.
+
+   2) keep_going and return; to wait for the next event (set
+   ecs->event_thread->stepping_over_breakpoint to 1 to single step
+   once).  */
+
+static void
+handle_inferior_event_1 (struct execution_control_state *ecs)
+{
+  enum stop_kind stop_soon;
+
+  if (ecs->ws.kind == TARGET_WAITKIND_IGNORE)
+    {
+      /* We had an event in the inferior, but we are not interested in
+        handling it at this level.  The lower layers have already
+        done what needs to be done, if anything.
+
+        One of the possible circumstances for this is when the
         inferior produces output for the console.  The inferior has
         not stopped, and we are ignoring the event.  Another possible
         circumstance is any event which the lower level knows will be
@@ -3707,21 +4817,18 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
       return;
     }
 
-  if (ecs->ws.kind == TARGET_WAITKIND_NO_RESUMED
-      && target_can_async_p () && !sync_execution)
+  if (ecs->ws.kind == TARGET_WAITKIND_THREAD_EXITED)
     {
-      /* There were no unwaited-for children left in the target, but,
-        we're not synchronously waiting for events either.  Just
-        ignore.  Otherwise, if we were running a synchronous
-        execution command, we need to cancel it and give the user
-        back the terminal.  */
       if (debug_infrun)
-       fprintf_unfiltered (gdb_stdlog,
-                           "infrun: TARGET_WAITKIND_NO_RESUMED (ignoring)\n");
+       fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_THREAD_EXITED\n");
       prepare_to_wait (ecs);
       return;
     }
 
+  if (ecs->ws.kind == TARGET_WAITKIND_NO_RESUMED
+      && handle_no_resumed (ecs))
+    return;
+
   /* Cache the last pid/waitstatus.  */
   set_last_target_status (ecs->ptid, ecs->ws);
 
@@ -3754,7 +4861,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
     }
 
   /* Dependent on valid ECS->EVENT_THREAD.  */
-  adjust_pc_after_break (ecs);
+  adjust_pc_after_break (ecs->event_thread, &ecs->ws);
 
   /* Dependent on the current PC value modified by adjust_pc_after_break.  */
   reinit_frame_cache ();
@@ -3778,7 +4885,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
     {
       struct regcache *regcache = get_thread_regcache (ecs->ptid);
 
-      if (breakpoint_inserted_here_p (get_regcache_aspace (regcache),
+      if (breakpoint_inserted_here_p (regcache->aspace (),
                                      regcache_read_pc (regcache)))
        {
          if (debug_infrun)
@@ -3790,15 +4897,39 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
 
   /* Mark the non-executing threads accordingly.  In all-stop, all
      threads of all processes are stopped when we get any event
-     reported.  In non-stop mode, only the event thread stops.  If
-     we're handling a process exit in non-stop mode, there's nothing
-     to do, as threads of the dead process are gone, and threads of
-     any other process were left running.  */
-  if (!non_stop)
-    set_executing (minus_one_ptid, 0);
-  else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
-          && ecs->ws.kind != TARGET_WAITKIND_EXITED)
-    set_executing (ecs->ptid, 0);
+     reported.  In non-stop mode, only the event thread stops.  */
+  {
+    ptid_t mark_ptid;
+
+    if (!target_is_non_stop_p ())
+      mark_ptid = minus_one_ptid;
+    else if (ecs->ws.kind == TARGET_WAITKIND_SIGNALLED
+            || ecs->ws.kind == TARGET_WAITKIND_EXITED)
+      {
+       /* If we're handling a process exit in non-stop mode, even
+          though threads haven't been deleted yet, one would think
+          that there is nothing to do, as threads of the dead process
+          will be soon deleted, and threads of any other process were
+          left running.  However, on some targets, threads survive a
+          process exit event.  E.g., for the "checkpoint" command,
+          when the current checkpoint/fork exits, linux-fork.c
+          automatically switches to another fork from within
+          target_mourn_inferior, by associating the same
+          inferior/thread to another fork.  We haven't mourned yet at
+          this point, but we must mark any threads left in the
+          process as not-executing so that finish_thread_state marks
+          them stopped (in the user's perspective) if/when we present
+          the stop to the user.  */
+       mark_ptid = pid_to_ptid (ptid_get_pid (ecs->ptid));
+      }
+    else
+      mark_ptid = ecs->ptid;
+
+    set_executing (mark_ptid, 0);
+
+    /* Likewise the resumed flag.  */
+    set_resumed (mark_ptid, 0);
+  }
 
   switch (ecs->ws.kind)
     {
@@ -3824,9 +4955,12 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
          handle_solib_event ();
 
          ecs->event_thread->control.stop_bpstat
-           = bpstat_stop_status (get_regcache_aspace (regcache),
+           = bpstat_stop_status (regcache->aspace (),
                                  stop_pc, ecs->ptid, &ecs->ws);
 
+         if (handle_stop_requested (ecs))
+           return;
+
          if (bpstat_causes_stop (ecs->event_thread->control.stop_bpstat))
            {
              /* A catchpoint triggered.  */
@@ -3881,12 +5015,25 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
     case TARGET_WAITKIND_SPURIOUS:
       if (debug_infrun)
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SPURIOUS\n");
+      if (handle_stop_requested (ecs))
+       return;
       if (!ptid_equal (ecs->ptid, inferior_ptid))
        context_switch (ecs->ptid);
       resume (GDB_SIGNAL_0);
       prepare_to_wait (ecs);
       return;
 
+    case TARGET_WAITKIND_THREAD_CREATED:
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_THREAD_CREATED\n");
+      if (handle_stop_requested (ecs))
+       return;
+      if (!ptid_equal (ecs->ptid, inferior_ptid))
+       context_switch (ecs->ptid);
+      if (!switch_back_to_stepped_thread (ecs))
+       keep_going (ecs);
+      return;
+
     case TARGET_WAITKIND_EXITED:
     case TARGET_WAITKIND_SIGNALLED:
       if (debug_infrun)
@@ -3903,7 +5050,7 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
       set_current_inferior (find_inferior_ptid (ecs->ptid));
       set_current_program_space (current_inferior ()->pspace);
       handle_vfork_child_exec_or_exit (0);
-      target_terminal_ours (); /* Must do this before mourn anyway.  */
+      target_terminal::ours ();        /* Must do this before mourn anyway.  */
 
       /* Clearing any previous state of convenience variables.  */
       clear_exit_convenience_vars ();
@@ -3922,12 +5069,12 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
          /* Support the --return-child-result option.  */
          return_child_result_value = ecs->ws.value.integer;
 
-         observer_notify_exited (ecs->ws.value.integer);
+         gdb::observers::exited.notify (ecs->ws.value.integer);
        }
       else
        {
          struct regcache *regcache = get_thread_regcache (ecs->ptid);
-         struct gdbarch *gdbarch = get_regcache_arch (regcache);
+         struct gdbarch *gdbarch = regcache->arch ();
 
          if (gdbarch_gdb_signal_to_target_p (gdbarch))
            {
@@ -3951,11 +5098,11 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
 Cannot fill $_exitsignal with the correct signal number.\n"));
            }
 
-         observer_notify_signal_exited (ecs->ws.value.sig);
+         gdb::observers::signal_exited.notify (ecs->ws.value.sig);
        }
 
       gdb_flush (gdb_stdout);
-      target_mourn_inferior ();
+      target_mourn_inferior (inferior_ptid);
       stop_print_frame = 0;
       stop_waiting (ecs);
       return;
@@ -3975,13 +5122,11 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
       /* Check whether the inferior is displaced stepping.  */
       {
        struct regcache *regcache = get_thread_regcache (ecs->ptid);
-       struct gdbarch *gdbarch = get_regcache_arch (regcache);
-       struct displaced_step_inferior_state *displaced
-         = get_displaced_stepping_state (ptid_get_pid (ecs->ptid));
+       struct gdbarch *gdbarch = regcache->arch ();
 
        /* If checking displaced stepping is supported, and thread
           ecs->ptid is displaced stepping.  */
-       if (displaced && ptid_equal (displaced->step_ptid, ecs->ptid))
+       if (displaced_step_in_progress_thread (ecs->ptid))
          {
            struct inferior *parent_inf
              = find_inferior_ptid (ecs->ptid);
@@ -3994,9 +5139,15 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
               that this operation also cleans up the child process for vfork,
               because their pages are shared.  */
            displaced_step_fixup (ecs->ptid, GDB_SIGNAL_TRAP);
+           /* Start a new step-over in another thread if there's one
+              that needs it.  */
+           start_step_over ();
 
            if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
              {
+               struct displaced_step_inferior_state *displaced
+                 = get_displaced_stepping_state (ptid_get_pid (ecs->ptid));
+
                /* Restore scratch pad for child process.  */
                displaced_step_restore (displaced, ecs->ws.value.related_pid);
              }
@@ -4058,9 +5209,12 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
       ecs->event_thread->control.stop_bpstat
-       = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
+       = bpstat_stop_status (get_current_regcache ()->aspace (),
                              stop_pc, ecs->ptid, &ecs->ws);
 
+      if (handle_stop_requested (ecs))
+       return;
+
       /* If no catchpoint triggered for this, then keep going.  Note
         that we're interested in knowing the bpstat actually causes a
         stop, not just if it may explain the signal.  Software
@@ -4080,8 +5234,20 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
          parent = ecs->ptid;
          child = ecs->ws.value.related_pid;
 
+         /* At this point, the parent is marked running, and the
+            child is marked stopped.  */
+
+         /* If not resuming the parent, mark it stopped.  */
+         if (follow_child && !detach_fork && !non_stop && !sched_multi)
+           set_running (parent, 0);
+
+         /* If resuming the child, mark it running.  */
+         if (follow_child || (!detach_fork && (non_stop || sched_multi)))
+           set_running (child, 1);
+
          /* In non-stop mode, also resume the other branch.  */
-         if (non_stop && !detach_fork)
+         if (!detach_fork && (non_stop
+                              || (sched_multi && target_is_non_stop_p ())))
            {
              if (follow_child)
                switch_to_thread (parent);
@@ -4114,114 +5280,375 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
       /* Done with the shared memory region.  Re-insert breakpoints in
         the parent, and keep going.  */
 
-      if (debug_infrun)
-       fprintf_unfiltered (gdb_stdlog,
-                           "infrun: TARGET_WAITKIND_VFORK_DONE\n");
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: TARGET_WAITKIND_VFORK_DONE\n");
+
+      if (!ptid_equal (ecs->ptid, inferior_ptid))
+       context_switch (ecs->ptid);
+
+      current_inferior ()->waiting_for_vfork_done = 0;
+      current_inferior ()->pspace->breakpoints_not_allowed = 0;
+
+      if (handle_stop_requested (ecs))
+       return;
+
+      /* This also takes care of reinserting breakpoints in the
+        previously locked inferior.  */
+      keep_going (ecs);
+      return;
+
+    case TARGET_WAITKIND_EXECD:
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n");
+
+      /* Note we can't read registers yet (the stop_pc), because we
+        don't yet know the inferior's post-exec architecture.
+        'stop_pc' is explicitly read below instead.  */
+      if (!ptid_equal (ecs->ptid, inferior_ptid))
+       switch_to_thread_no_regs (ecs->event_thread);
+
+      /* Do whatever is necessary to the parent branch of the vfork.  */
+      handle_vfork_child_exec_or_exit (1);
+
+      /* This causes the eventpoints and symbol table to be reset.
+         Must do this now, before trying to determine whether to
+         stop.  */
+      follow_exec (inferior_ptid, ecs->ws.value.execd_pathname);
+
+      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+
+      /* In follow_exec we may have deleted the original thread and
+        created a new one.  Make sure that the event thread is the
+        execd thread for that case (this is a nop otherwise).  */
+      ecs->event_thread = inferior_thread ();
+
+      ecs->event_thread->control.stop_bpstat
+       = bpstat_stop_status (get_current_regcache ()->aspace (),
+                             stop_pc, ecs->ptid, &ecs->ws);
+
+      /* Note that this may be referenced from inside
+        bpstat_stop_status above, through inferior_has_execd.  */
+      xfree (ecs->ws.value.execd_pathname);
+      ecs->ws.value.execd_pathname = NULL;
+
+      if (handle_stop_requested (ecs))
+       return;
+
+      /* If no catchpoint triggered for this, then keep going.  */
+      if (!bpstat_causes_stop (ecs->event_thread->control.stop_bpstat))
+       {
+         ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+         keep_going (ecs);
+         return;
+       }
+      process_event_stop_test (ecs);
+      return;
+
+      /* Be careful not to try to gather much state about a thread
+         that's in a syscall.  It's frequently a losing proposition.  */
+    case TARGET_WAITKIND_SYSCALL_ENTRY:
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog,
+                           "infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n");
+      /* Getting the current syscall number.  */
+      if (handle_syscall_event (ecs) == 0)
+       process_event_stop_test (ecs);
+      return;
+
+      /* Before examining the threads further, step this thread to
+         get it entirely out of the syscall.  (We get notice of the
+         event when the thread is just on the verge of exiting a
+         syscall.  Stepping one instruction seems to get it back
+         into user code.)  */
+    case TARGET_WAITKIND_SYSCALL_RETURN:
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog,
+                           "infrun: TARGET_WAITKIND_SYSCALL_RETURN\n");
+      if (handle_syscall_event (ecs) == 0)
+       process_event_stop_test (ecs);
+      return;
+
+    case TARGET_WAITKIND_STOPPED:
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n");
+      handle_signal_stop (ecs);
+      return;
+
+    case TARGET_WAITKIND_NO_HISTORY:
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_NO_HISTORY\n");
+      /* Reverse execution: target ran out of history info.  */
+
+      /* Switch to the stopped thread.  */
+      if (!ptid_equal (ecs->ptid, inferior_ptid))
+       context_switch (ecs->ptid);
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
+
+      delete_just_stopped_threads_single_step_breakpoints ();
+      stop_pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
+
+      if (handle_stop_requested (ecs))
+       return;
+
+      gdb::observers::no_history.notify ();
+      stop_waiting (ecs);
+      return;
+    }
+}
+
+/* A wrapper around handle_inferior_event_1, which also makes sure
+   that all temporary struct value objects that were created during
+   the handling of the event get deleted at the end.  */
+
+static void
+handle_inferior_event (struct execution_control_state *ecs)
+{
+  struct value *mark = value_mark ();
+
+  handle_inferior_event_1 (ecs);
+  /* Purge all temporary values created during the event handling,
+     as it could be a long time before we return to the command level
+     where such values would otherwise be purged.  */
+  value_free_to_mark (mark);
+}
+
+/* Restart threads back to what they were trying to do back when we
+   paused them for an in-line step-over.  The EVENT_THREAD thread is
+   ignored.  */
+
+static void
+restart_threads (struct thread_info *event_thread)
+{
+  struct thread_info *tp;
+
+  /* In case the instruction just stepped spawned a new thread.  */
+  update_thread_list ();
+
+  ALL_NON_EXITED_THREADS (tp)
+    {
+      if (tp == event_thread)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: restart threads: "
+                               "[%s] is event thread\n",
+                               target_pid_to_str (tp->ptid));
+         continue;
+       }
+
+      if (!(tp->state == THREAD_RUNNING || tp->control.in_infcall))
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: restart threads: "
+                               "[%s] not meant to be running\n",
+                               target_pid_to_str (tp->ptid));
+         continue;
+       }
+
+      if (tp->resumed)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: restart threads: [%s] resumed\n",
+                               target_pid_to_str (tp->ptid));
+         gdb_assert (tp->executing || tp->suspend.waitstatus_pending_p);
+         continue;
+       }
+
+      if (thread_is_in_step_over_chain (tp))
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: restart threads: "
+                               "[%s] needs step-over\n",
+                               target_pid_to_str (tp->ptid));
+         gdb_assert (!tp->resumed);
+         continue;
+       }
+
+
+      if (tp->suspend.waitstatus_pending_p)
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: restart threads: "
+                               "[%s] has pending status\n",
+                               target_pid_to_str (tp->ptid));
+         tp->resumed = 1;
+         continue;
+       }
+
+      gdb_assert (!tp->stop_requested);
+
+      /* If some thread needs to start a step-over at this point, it
+        should still be in the step-over queue, and thus skipped
+        above.  */
+      if (thread_still_needs_step_over (tp))
+       {
+         internal_error (__FILE__, __LINE__,
+                         "thread [%s] needs a step-over, but not in "
+                         "step-over queue\n",
+                         target_pid_to_str (tp->ptid));
+       }
+
+      if (currently_stepping (tp))
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: restart threads: [%s] was stepping\n",
+                               target_pid_to_str (tp->ptid));
+         keep_going_stepped_thread (tp);
+       }
+      else
+       {
+         struct execution_control_state ecss;
+         struct execution_control_state *ecs = &ecss;
+
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: restart threads: [%s] continuing\n",
+                               target_pid_to_str (tp->ptid));
+         reset_ecs (ecs, tp);
+         switch_to_thread (tp->ptid);
+         keep_going_pass_signal (ecs);
+       }
+    }
+}
+
+/* Callback for iterate_over_threads.  Find a resumed thread that has
+   a pending waitstatus.  */
+
+static int
+resumed_thread_with_pending_status (struct thread_info *tp,
+                                   void *arg)
+{
+  return (tp->resumed
+         && tp->suspend.waitstatus_pending_p);
+}
+
+/* Called when we get an event that may finish an in-line or
+   out-of-line (displaced stepping) step-over started previously.
+   Return true if the event is processed and we should go back to the
+   event loop; false if the caller should continue processing the
+   event.  */
+
+static int
+finish_step_over (struct execution_control_state *ecs)
+{
+  int had_step_over_info;
+
+  displaced_step_fixup (ecs->ptid,
+                       ecs->event_thread->suspend.stop_signal);
+
+  had_step_over_info = step_over_info_valid_p ();
 
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
+  if (had_step_over_info)
+    {
+      /* If we're stepping over a breakpoint with all threads locked,
+        then only the thread that was stepped should be reporting
+        back an event.  */
+      gdb_assert (ecs->event_thread->control.trap_expected);
 
-      current_inferior ()->waiting_for_vfork_done = 0;
-      current_inferior ()->pspace->breakpoints_not_allowed = 0;
-      /* This also takes care of reinserting breakpoints in the
-        previously locked inferior.  */
-      keep_going (ecs);
-      return;
+      clear_step_over_info ();
+    }
 
-    case TARGET_WAITKIND_EXECD:
-      if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n");
+  if (!target_is_non_stop_p ())
+    return 0;
 
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
+  /* Start a new step-over in another thread if there's one that
+     needs it.  */
+  start_step_over ();
 
-      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+  /* If we were stepping over a breakpoint before, and haven't started
+     a new in-line step-over sequence, then restart all other threads
+     (except the event thread).  We can't do this in all-stop, as then
+     e.g., we wouldn't be able to issue any other remote packet until
+     these other threads stop.  */
+  if (had_step_over_info && !step_over_info_valid_p ())
+    {
+      struct thread_info *pending;
 
-      /* Do whatever is necessary to the parent branch of the vfork.  */
-      handle_vfork_child_exec_or_exit (1);
+      /* If we only have threads with pending statuses, the restart
+        below won't restart any thread and so nothing re-inserts the
+        breakpoint we just stepped over.  But we need it inserted
+        when we later process the pending events, otherwise if
+        another thread has a pending event for this breakpoint too,
+        we'd discard its event (because the breakpoint that
+        originally caused the event was no longer inserted).  */
+      context_switch (ecs->ptid);
+      insert_breakpoints ();
 
-      /* This causes the eventpoints and symbol table to be reset.
-         Must do this now, before trying to determine whether to
-         stop.  */
-      follow_exec (inferior_ptid, ecs->ws.value.execd_pathname);
+      restart_threads (ecs->event_thread);
 
-      ecs->event_thread->control.stop_bpstat
-       = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
-                             stop_pc, ecs->ptid, &ecs->ws);
+      /* If we have events pending, go through handle_inferior_event
+        again, picking up a pending event at random.  This avoids
+        thread starvation.  */
 
-      /* Note that this may be referenced from inside
-        bpstat_stop_status above, through inferior_has_execd.  */
-      xfree (ecs->ws.value.execd_pathname);
-      ecs->ws.value.execd_pathname = NULL;
+      /* But not if we just stepped over a watchpoint in order to let
+        the instruction execute so we can evaluate its expression.
+        The set of watchpoints that triggered is recorded in the
+        breakpoint objects themselves (see bp->watchpoint_triggered).
+        If we processed another event first, that other event could
+        clobber this info.  */
+      if (ecs->event_thread->stepping_over_watchpoint)
+       return 0;
 
-      /* If no catchpoint triggered for this, then keep going.  */
-      if (!bpstat_causes_stop (ecs->event_thread->control.stop_bpstat))
+      pending = iterate_over_threads (resumed_thread_with_pending_status,
+                                     NULL);
+      if (pending != NULL)
        {
-         ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
-         keep_going (ecs);
-         return;
-       }
-      process_event_stop_test (ecs);
-      return;
+         struct thread_info *tp = ecs->event_thread;
+         struct regcache *regcache;
 
-      /* Be careful not to try to gather much state about a thread
-         that's in a syscall.  It's frequently a losing proposition.  */
-    case TARGET_WAITKIND_SYSCALL_ENTRY:
-      if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog,
-                           "infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n");
-      /* Getting the current syscall number.  */
-      if (handle_syscall_event (ecs) == 0)
-       process_event_stop_test (ecs);
-      return;
+         if (debug_infrun)
+           {
+             fprintf_unfiltered (gdb_stdlog,
+                                 "infrun: found resumed threads with "
+                                 "pending events, saving status\n");
+           }
 
-      /* Before examining the threads further, step this thread to
-         get it entirely out of the syscall.  (We get notice of the
-         event when the thread is just on the verge of exiting a
-         syscall.  Stepping one instruction seems to get it back
-         into user code.)  */
-    case TARGET_WAITKIND_SYSCALL_RETURN:
-      if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog,
-                           "infrun: TARGET_WAITKIND_SYSCALL_RETURN\n");
-      if (handle_syscall_event (ecs) == 0)
-       process_event_stop_test (ecs);
-      return;
+         gdb_assert (pending != tp);
 
-    case TARGET_WAITKIND_STOPPED:
-      if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n");
-      ecs->event_thread->suspend.stop_signal = ecs->ws.value.sig;
-      handle_signal_stop (ecs);
-      return;
+         /* Record the event thread's event for later.  */
+         save_waitstatus (tp, &ecs->ws);
+         /* This was cleared early, by handle_inferior_event.  Set it
+            so this pending event is considered by
+            do_target_wait.  */
+         tp->resumed = 1;
 
-    case TARGET_WAITKIND_NO_HISTORY:
-      if (debug_infrun)
-        fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_NO_HISTORY\n");
-      /* Reverse execution: target ran out of history info.  */
+         gdb_assert (!tp->executing);
 
-      delete_just_stopped_threads_single_step_breakpoints ();
-      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
-      observer_notify_no_history ();
-      stop_waiting (ecs);
-      return;
-    }
-}
+         regcache = get_thread_regcache (tp->ptid);
+         tp->suspend.stop_pc = regcache_read_pc (regcache);
 
-/* A wrapper around handle_inferior_event_1, which also makes sure
-   that all temporary struct value objects that were created during
-   the handling of the event get deleted at the end.  */
+         if (debug_infrun)
+           {
+             fprintf_unfiltered (gdb_stdlog,
+                                 "infrun: saved stop_pc=%s for %s "
+                                 "(currently_stepping=%d)\n",
+                                 paddress (target_gdbarch (),
+                                           tp->suspend.stop_pc),
+                                 target_pid_to_str (tp->ptid),
+                                 currently_stepping (tp));
+           }
 
-static void
-handle_inferior_event (struct execution_control_state *ecs)
-{
-  struct value *mark = value_mark ();
+         /* This in-line step-over finished; clear this so we won't
+            start a new one.  This is what handle_signal_stop would
+            do, if we returned false.  */
+         tp->stepping_over_breakpoint = 0;
 
-  handle_inferior_event_1 (ecs);
-  /* Purge all temporary values created during the event handling,
-     as it could be a long time before we return to the command level
-     where such values would otherwise be purged.  */
-  value_free_to_mark (mark);
+         /* Wake up the event loop again.  */
+         mark_async_event_handler (infrun_async_inferior_event_token);
+
+         prepare_to_wait (ecs);
+         return 1;
+       }
+    }
+
+  return 0;
 }
 
 /* Come here when the program has stopped with a signal.  */
@@ -4237,11 +5664,13 @@ handle_signal_stop (struct execution_control_state *ecs)
 
   gdb_assert (ecs->ws.kind == TARGET_WAITKIND_STOPPED);
 
+  ecs->event_thread->suspend.stop_signal = ecs->ws.value.sig;
+
   /* Do we need to clean up the state of a thread that has
      completed a displaced single-step?  (Doing so usually affects
      the PC, so do it here, before we set stop_pc.)  */
-  displaced_step_fixup (ecs->ptid,
-                       ecs->event_thread->suspend.stop_signal);
+  if (finish_step_over (ecs))
+    return;
 
   /* If we either finished a single-step or hit a breakpoint, but
      the user wanted this thread to be stopped, pretend we got a
@@ -4255,8 +5684,8 @@ handle_signal_stop (struct execution_control_state *ecs)
   if (debug_infrun)
     {
       struct regcache *regcache = get_thread_regcache (ecs->ptid);
-      struct gdbarch *gdbarch = get_regcache_arch (regcache);
-      struct cleanup *old_chain = save_inferior_ptid ();
+      struct gdbarch *gdbarch = regcache->arch ();
+      scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
 
       inferior_ptid = ecs->ptid;
 
@@ -4268,7 +5697,7 @@ handle_signal_stop (struct execution_control_state *ecs)
 
          fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
 
-          if (target_stopped_data_address (&current_target, &addr))
+         if (target_stopped_data_address (target_stack, &addr))
             fprintf_unfiltered (gdb_stdlog,
                                 "infrun: stopped data address = %s\n",
                                 paddress (gdbarch, addr));
@@ -4276,8 +5705,6 @@ handle_signal_stop (struct execution_control_state *ecs)
             fprintf_unfiltered (gdb_stdlog,
                                 "infrun: (no data address available)\n");
        }
-
-      do_cleanups (old_chain);
     }
 
   /* This is originated from start_remote(), start_inferior() and
@@ -4294,18 +5721,6 @@ handle_signal_stop (struct execution_control_state *ecs)
       return;
     }
 
-  if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-      && stop_after_trap)
-    {
-      if (!ptid_equal (ecs->ptid, inferior_ptid))
-       context_switch (ecs->ptid);
-      if (debug_infrun)
-       fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
-      stop_print_frame = 0;
-      stop_waiting (ecs);
-      return;
-    }
-
   /* This originates from attach_command().  We need to overwrite
      the stop_signal here, because some kernels don't ignore a
      SIGSTOP in a subsequent ptrace(PTRACE_CONT,SIGSTOP) call.
@@ -4347,7 +5762,7 @@ handle_signal_stop (struct execution_control_state *ecs)
       context_switch (ecs->ptid);
 
       if (deprecated_context_hook)
-       deprecated_context_hook (pid_to_thread_id (ecs->ptid));
+       deprecated_context_hook (ptid_to_global_thread_id (ecs->ptid));
     }
 
   /* At this point, get hold of the now-current thread's frame.  */
@@ -4358,11 +5773,11 @@ handle_signal_stop (struct execution_control_state *ecs)
   if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
     {
       struct regcache *regcache;
-      struct address_space *aspace;
       CORE_ADDR pc;
 
       regcache = get_thread_regcache (ecs->ptid);
-      aspace = get_regcache_aspace (regcache);
+      const address_space *aspace = regcache->aspace ();
+
       pc = regcache_read_pc (regcache);
 
       /* However, before doing so, if this single-step breakpoint was
@@ -4447,14 +5862,15 @@ handle_signal_stop (struct execution_control_state *ecs)
   ecs->event_thread->control.stop_step = 0;
   stop_print_frame = 1;
   stopped_by_random_signal = 0;
+  bpstat stop_chain = NULL;
 
   /* Hide inlined functions starting here, unless we just performed stepi or
      nexti.  After stepi and nexti, always show the innermost frame (not any
      inline function call sites).  */
   if (ecs->event_thread->control.step_range_end != 1)
     {
-      struct address_space *aspace = 
-       get_regcache_aspace (get_thread_regcache (ecs->ptid));
+      const address_space *aspace =
+       get_thread_regcache (ecs->ptid)->aspace ();
 
       /* skip_inline_frames is expensive, so we avoid it if we can
         determine that the address is one where functions cannot have
@@ -4478,7 +5894,8 @@ handle_signal_stop (struct execution_control_state *ecs)
                                             ecs->event_thread->prev_pc,
                                             &ecs->ws)))
        {
-         skip_inline_frames (ecs->ptid);
+         stop_chain = build_bpstat_chain (aspace, stop_pc, &ecs->ws);
+         skip_inline_frames (ecs->ptid, stop_chain);
 
          /* Re-fetch current thread's frame in case that invalidated
             the frame cache.  */
@@ -4526,8 +5943,8 @@ handle_signal_stop (struct execution_control_state *ecs)
   /* See if there is a breakpoint/watchpoint/catchpoint/etc. that
      handles this event.  */
   ecs->event_thread->control.stop_bpstat
-    = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
-                         stop_pc, ecs->ptid, &ecs->ws);
+    = bpstat_stop_status (get_current_regcache ()->aspace (),
+                         stop_pc, ecs->ptid, &ecs->ws, stop_chain);
 
   /* Following in case break condition called a
      function.  */
@@ -4590,14 +6007,14 @@ handle_signal_stop (struct execution_control_state *ecs)
          decr_pc = gdbarch_decr_pc_after_break (gdbarch);
          if (decr_pc != 0)
            {
-             struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
+             gdb::optional<scoped_restore_tmpl<int>>
+               restore_operation_disable;
 
              if (record_full_is_used ())
-               record_full_gdb_operation_disable_set ();
+               restore_operation_disable.emplace
+                 (record_full_gdb_operation_disable_set ());
 
              regcache_write_pc (regcache, stop_pc + decr_pc);
-
-             do_cleanups (old_cleanups);
            }
        }
       else
@@ -4638,6 +6055,15 @@ handle_signal_stop (struct execution_control_state *ecs)
   if (random_signal)
     random_signal = !stopped_by_watchpoint;
 
+  /* Always stop if the user explicitly requested this thread to
+     remain stopped.  */
+  if (ecs->event_thread->stop_requested)
+    {
+      random_signal = 1;
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog, "infrun: user-requested stop\n");
+    }
+
   /* For the program's own signals, act according to
      the signal handling tables.  */
 
@@ -4671,9 +6097,9 @@ handle_signal_stop (struct execution_control_state *ecs)
       if (signal_print[ecs->event_thread->suspend.stop_signal])
        {
          /* The signal table tells us to print about this signal.  */
-         target_terminal_ours_for_output ();
-         observer_notify_signal_received (ecs->event_thread->suspend.stop_signal);
-         target_terminal_inferior ();
+         target_terminal::ours_for_output ();
+         gdb::observers::signal_received.notify (ecs->event_thread->suspend.stop_signal);
+         target_terminal::inferior ();
        }
 
       /* Clear the signal if it should not be passed.  */
@@ -4732,6 +6158,7 @@ handle_signal_stop (struct execution_control_state *ecs)
                                 "infrun: signal may take us out of "
                                 "single-step range\n");
 
+         clear_step_over_info ();
          insert_hp_step_resume_breakpoint_at_frame (frame);
          ecs->event_thread->step_after_step_resume_breakpoint = 1;
          /* Reset trap_expected to ensure breakpoints are re-inserted.  */
@@ -4788,6 +6215,10 @@ process_event_stop_test (struct execution_control_state *ecs)
       stop_stack_dummy = what.call_dummy;
     }
 
+  /* A few breakpoint types have callbacks associated (e.g.,
+     bp_jit_event).  Run them now.  */
+  bpstat_run_callbacks (ecs->event_thread->control.stop_bpstat);
+
   /* If we hit an internal event that triggers symbol changes, the
      current frame will be invalidated within bpstat_what (e.g., if we
      hit an internal solib event).  Re-fetch it.  */
@@ -5128,9 +6559,7 @@ process_event_stop_test (struct execution_control_state *ecs)
        {
          /* Set up a step-resume breakpoint at the address
             indicated by SKIP_SOLIB_RESOLVER.  */
-         struct symtab_and_line sr_sal;
-
-         init_sal (&sr_sal);
+         symtab_and_line sr_sal;
          sr_sal.pc = pc_after_resolver;
          sr_sal.pspace = get_frame_program_space (frame);
 
@@ -5142,6 +6571,17 @@ process_event_stop_test (struct execution_control_state *ecs)
       return;
     }
 
+  /* Step through an indirect branch thunk.  */
+  if (ecs->event_thread->control.step_over_calls != STEP_OVER_NONE
+      && gdbarch_in_indirect_branch_thunk (gdbarch, stop_pc))
+    {
+      if (debug_infrun)
+        fprintf_unfiltered (gdb_stdlog,
+                            "infrun: stepped into indirect branch thunk\n");
+      keep_going (ecs);
+      return;
+    }
+
   if (ecs->event_thread->control.step_range_end != 1
       && (ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
          || ecs->event_thread->control.step_over_calls == STEP_OVER_ALL)
@@ -5181,9 +6621,7 @@ process_event_stop_test (struct execution_control_state *ecs)
       if (real_stop_pc)
        {
          /* And put the step-breakpoint there and go until there.  */
-         struct symtab_and_line sr_sal;
-
-         init_sal (&sr_sal);   /* initialize to zeroes */
+         symtab_and_line sr_sal;
          sr_sal.pc = real_stop_pc;
          sr_sal.section = find_pc_overlay (sr_sal.pc);
          sr_sal.pspace = get_frame_program_space (frame);
@@ -5281,10 +6719,8 @@ process_event_stop_test (struct execution_control_state *ecs)
                 to the caller.  */
              if (ecs->stop_func_start != stop_pc && ecs->stop_func_start != 0)
                {
-                 struct symtab_and_line sr_sal;
-
                  /* Normal function call return (static or dynamic).  */
-                 init_sal (&sr_sal);
+                 symtab_and_line sr_sal;
                  sr_sal.pc = ecs->stop_func_start;
                  sr_sal.pspace = get_frame_program_space (frame);
                  insert_step_resume_breakpoint_at_sal (gdbarch,
@@ -5311,9 +6747,7 @@ process_event_stop_test (struct execution_control_state *ecs)
 
       if (real_stop_pc != 0 && in_solib_dynsym_resolve_code (real_stop_pc))
        {
-         struct symtab_and_line sr_sal;
-
-         init_sal (&sr_sal);
+         symtab_and_line sr_sal;
          sr_sal.pc = ecs->stop_func_start;
          sr_sal.pspace = get_frame_program_space (frame);
 
@@ -5336,7 +6770,7 @@ process_event_stop_test (struct execution_control_state *ecs)
        tmp_sal = find_pc_line (ecs->stop_func_start, 0);
        if (tmp_sal.line != 0
            && !function_name_is_marked_for_skip (ecs->stop_func_name,
-                                                 &tmp_sal))
+                                                 tmp_sal))
          {
            if (execution_direction == EXEC_REVERSE)
              handle_step_into_function_backward (gdbarch, ecs);
@@ -5367,9 +6801,7 @@ process_event_stop_test (struct execution_control_state *ecs)
            {
              /* Set a breakpoint at callee's start address.
                 From there we can step once and be back in the caller.  */
-             struct symtab_and_line sr_sal;
-
-             init_sal (&sr_sal);
+             symtab_and_line sr_sal;
              sr_sal.pc = ecs->stop_func_start;
              sr_sal.pspace = get_frame_program_space (frame);
              insert_step_resume_breakpoint_at_sal (gdbarch,
@@ -5407,9 +6839,7 @@ process_event_stop_test (struct execution_control_state *ecs)
          /* Stepped backward into the solib dynsym resolver.
             Set a breakpoint at its start and continue, then
             one more step will take us out.  */
-         struct symtab_and_line sr_sal;
-
-         init_sal (&sr_sal);
+         symtab_and_line sr_sal;
          sr_sal.pc = ecs->stop_func_start;
          sr_sal.pspace = get_frame_program_space (frame);
          insert_step_resume_breakpoint_at_sal (gdbarch, 
@@ -5489,13 +6919,11 @@ process_event_stop_test (struct execution_control_state *ecs)
                   ecs->event_thread->control.step_frame_id)
       && inline_skipped_frames (ecs->ptid))
     {
-      struct symtab_and_line call_sal;
-
       if (debug_infrun)
        fprintf_unfiltered (gdb_stdlog,
                            "infrun: stepped into inlined function\n");
 
-      find_frame_sal (get_current_frame (), &call_sal);
+      symtab_and_line call_sal = find_frame_sal (get_current_frame ());
 
       if (ecs->event_thread->control.step_over_calls != STEP_OVER_ALL)
        {
@@ -5587,11 +7015,10 @@ process_event_stop_test (struct execution_control_state *ecs)
 static int
 switch_back_to_stepped_thread (struct execution_control_state *ecs)
 {
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     {
       struct thread_info *tp;
       struct thread_info *stepping_thread;
-      struct thread_info *step_over;
 
       /* If any thread is blocked on some internal breakpoint, and we
         simply need to step over that breakpoint to get it going
@@ -5634,14 +7061,20 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
         return 1;
        }
 
-      /* Otherwise, we no longer expect a trap in the current thread.
-        Clear the trap_expected flag before switching back -- this is
-        what keep_going does as well, if we call it.  */
-      ecs->event_thread->control.trap_expected = 0;
-
-      /* Likewise, clear the signal if it should not be passed.  */
-      if (!signal_program[ecs->event_thread->suspend.stop_signal])
-       ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+      /* If this thread needs yet another step-over (e.g., stepping
+        through a delay slot), do it first before moving on to
+        another thread.  */
+      if (thread_still_needs_step_over (ecs->event_thread))
+       {
+         if (debug_infrun)
+           {
+             fprintf_unfiltered (gdb_stdlog,
+                                 "infrun: thread [%s] still needs step-over\n",
+                                 target_pid_to_str (ecs->event_thread->ptid));
+           }
+         keep_going (ecs);
+         return 1;
+       }
 
       /* If scheduler locking applies even if not stepping, there's no
         need to walk over threads.  Above we've checked whether the
@@ -5651,24 +7084,46 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
       if (schedlock_applies (ecs->event_thread))
        return 0;
 
-      /* Look for the stepping/nexting thread, and check if any other
-        thread other than the stepping thread needs to start a
-        step-over.  Do all step-overs before actually proceeding with
+      /* Otherwise, we no longer expect a trap in the current thread.
+        Clear the trap_expected flag before switching back -- this is
+        what keep_going does as well, if we call it.  */
+      ecs->event_thread->control.trap_expected = 0;
+
+      /* Likewise, clear the signal if it should not be passed.  */
+      if (!signal_program[ecs->event_thread->suspend.stop_signal])
+       ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+
+      /* Do all pending step-overs before actually proceeding with
         step/next/etc.  */
+      if (start_step_over ())
+       {
+         prepare_to_wait (ecs);
+         return 1;
+       }
+
+      /* Look for the stepping/nexting thread.  */
       stepping_thread = NULL;
-      step_over = NULL;
+
       ALL_NON_EXITED_THREADS (tp)
         {
-         /* Ignore threads of processes we're not resuming.  */
+         /* Ignore threads of processes the caller is not
+            resuming.  */
          if (!sched_multi
-             && ptid_get_pid (tp->ptid) != ptid_get_pid (inferior_ptid))
+             && ptid_get_pid (tp->ptid) != ptid_get_pid (ecs->ptid))
            continue;
 
          /* When stepping over a breakpoint, we lock all threads
             except the one that needs to move past the breakpoint.
             If a non-event thread has this set, the "incomplete
             step-over" check above should have caught it earlier.  */
-         gdb_assert (!tp->control.trap_expected);
+         if (tp->control.trap_expected)
+           {
+             internal_error (__FILE__, __LINE__,
+                             "[%s] has inconsistent state: "
+                             "trap_expected=%d\n",
+                             target_pid_to_str (tp->ptid),
+                             tp->control.trap_expected);
+           }
 
          /* Did we find the stepping thread?  */
          if (tp->control.step_range_end)
@@ -5688,145 +7143,131 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 
              stepping_thread = tp;
            }
-         else if (thread_still_needs_step_over (tp))
-           {
-             step_over = tp;
-
-             /* At the top we've returned early if the event thread
-                is stepping.  If some other thread not the event
-                thread is stepping, then scheduler locking can't be
-                in effect, and we can resume this thread.  No need to
-                keep looking for the stepping thread then.  */
-             break;
-           }
        }
 
-      if (step_over != NULL)
+      if (stepping_thread != NULL)
        {
-         tp = step_over;
          if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: switching back to stepped thread\n");
+
+         if (keep_going_stepped_thread (stepping_thread))
            {
-             fprintf_unfiltered (gdb_stdlog,
-                                 "infrun: need to step-over [%s]\n",
-                                 target_pid_to_str (tp->ptid));
+             prepare_to_wait (ecs);
+             return 1;
            }
+       }
+    }
 
-         /* Only the stepping thread should have this set.  */
-         gdb_assert (tp->control.step_range_end == 0);
+  return 0;
+}
 
-         ecs->ptid = tp->ptid;
-         ecs->event_thread = tp;
-         switch_to_thread (ecs->ptid);
-         keep_going (ecs);
-         return 1;
-       }
+/* Set a previously stepped thread back to stepping.  Returns true on
+   success, false if the resume is not possible (e.g., the thread
+   vanished).  */
 
-      if (stepping_thread != NULL)
-       {
-         struct frame_info *frame;
-         struct gdbarch *gdbarch;
+static int
+keep_going_stepped_thread (struct thread_info *tp)
+{
+  struct frame_info *frame;
+  struct execution_control_state ecss;
+  struct execution_control_state *ecs = &ecss;
 
-         tp = stepping_thread;
-
-         /* If the stepping thread exited, then don't try to switch
-            back and resume it, which could fail in several different
-            ways depending on the target.  Instead, just keep going.
-
-            We can find a stepping dead thread in the thread list in
-            two cases:
-
-            - The target supports thread exit events, and when the
-            target tries to delete the thread from the thread list,
-            inferior_ptid pointed at the exiting thread.  In such
-            case, calling delete_thread does not really remove the
-            thread from the list; instead, the thread is left listed,
-            with 'exited' state.
-
-            - The target's debug interface does not support thread
-            exit events, and so we have no idea whatsoever if the
-            previously stepping thread is still alive.  For that
-            reason, we need to synchronously query the target
-            now.  */
-         if (is_exited (tp->ptid)
-             || !target_thread_alive (tp->ptid))
-           {
-             if (debug_infrun)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "infrun: not switching back to "
-                                   "stepped thread, it has vanished\n");
+  /* If the stepping thread exited, then don't try to switch back and
+     resume it, which could fail in several different ways depending
+     on the target.  Instead, just keep going.
 
-             delete_thread (tp->ptid);
-             keep_going (ecs);
-             return 1;
-           }
+     We can find a stepping dead thread in the thread list in two
+     cases:
 
-         if (debug_infrun)
-           fprintf_unfiltered (gdb_stdlog,
-                               "infrun: switching back to stepped thread\n");
+     - The target supports thread exit events, and when the target
+       tries to delete the thread from the thread list, inferior_ptid
+       pointed at the exiting thread.  In such case, calling
+       delete_thread does not really remove the thread from the list;
+       instead, the thread is left listed, with 'exited' state.
 
-         ecs->event_thread = tp;
-         ecs->ptid = tp->ptid;
-         context_switch (ecs->ptid);
+     - The target's debug interface does not support thread exit
+       events, and so we have no idea whatsoever if the previously
+       stepping thread is still alive.  For that reason, we need to
+       synchronously query the target now.  */
 
-         stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
-         frame = get_current_frame ();
-         gdbarch = get_frame_arch (frame);
+  if (is_exited (tp->ptid)
+      || !target_thread_alive (tp->ptid))
+    {
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: not resuming previously  "
+                           "stepped thread, it has vanished\n");
 
-         /* If the PC of the thread we were trying to single-step has
-            changed, then that thread has trapped or been signaled,
-            but the event has not been reported to GDB yet.  Re-poll
-            the target looking for this particular thread's event
-            (i.e. temporarily enable schedlock) by:
+      delete_thread (tp->ptid);
+      return 0;
+    }
 
-              - setting a break at the current PC
-              - resuming that particular thread, only (by setting
-                trap expected)
+  if (debug_infrun)
+    fprintf_unfiltered (gdb_stdlog,
+                       "infrun: resuming previously stepped thread\n");
 
-            This prevents us continuously moving the single-step
-            breakpoint forward, one instruction at a time,
-            overstepping.  */
+  reset_ecs (ecs, tp);
+  switch_to_thread (tp->ptid);
 
-         if (stop_pc != tp->prev_pc)
-           {
-             ptid_t resume_ptid;
+  stop_pc = regcache_read_pc (get_thread_regcache (tp->ptid));
+  frame = get_current_frame ();
 
-             if (debug_infrun)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "infrun: expected thread advanced also\n");
-
-             /* Clear the info of the previous step-over, as it's no
-                longer valid.  It's what keep_going would do too, if
-                we called it.  Must do this before trying to insert
-                the sss breakpoint, otherwise if we were previously
-                trying to step over this exact address in another
-                thread, the breakpoint ends up not installed.  */
-             clear_step_over_info ();
-
-             insert_single_step_breakpoint (get_frame_arch (frame),
-                                            get_frame_address_space (frame),
-                                            stop_pc);
-
-             resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
-             do_target_resume (resume_ptid,
-                               currently_stepping (tp), GDB_SIGNAL_0);
-             prepare_to_wait (ecs);
-           }
-         else
-           {
-             if (debug_infrun)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "infrun: expected thread still "
-                                   "hasn't advanced\n");
-             keep_going (ecs);
-           }
+  /* If the PC of the thread we were trying to single-step has
+     changed, then that thread has trapped or been signaled, but the
+     event has not been reported to GDB yet.  Re-poll the target
+     looking for this particular thread's event (i.e. temporarily
+     enable schedlock) by:
+
+     - setting a break at the current PC
+     - resuming that particular thread, only (by setting trap
+     expected)
+
+     This prevents us continuously moving the single-step breakpoint
+     forward, one instruction at a time, overstepping.  */
+
+  if (stop_pc != tp->prev_pc)
+    {
+      ptid_t resume_ptid;
+
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: expected thread advanced also (%s -> %s)\n",
+                           paddress (target_gdbarch (), tp->prev_pc),
+                           paddress (target_gdbarch (), stop_pc));
+
+      /* Clear the info of the previous step-over, as it's no longer
+        valid (if the thread was trying to step over a breakpoint, it
+        has already succeeded).  It's what keep_going would do too,
+        if we called it.  Do this before trying to insert the sss
+        breakpoint, otherwise if we were previously trying to step
+        over this exact address in another thread, the breakpoint is
+        skipped.  */
+      clear_step_over_info ();
+      tp->control.trap_expected = 0;
+
+      insert_single_step_breakpoint (get_frame_arch (frame),
+                                    get_frame_address_space (frame),
+                                    stop_pc);
+
+      tp->resumed = 1;
+      resume_ptid = internal_resume_ptid (tp->control.stepping_command);
+      do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
+    }
+  else
+    {
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: expected thread still hasn't advanced\n");
 
-         return 1;
-       }
+      keep_going_pass_signal (ecs);
     }
-  return 0;
+  return 1;
 }
 
-/* Is thread TP in the middle of single-stepping?  */
+/* Is thread TP in the middle of (software or hardware)
+   single-stepping?  (Note the result of this function must never be
+   passed directly as target_resume's STEP parameter.)  */
 
 static int
 currently_stepping (struct thread_info *tp)
@@ -5846,17 +7287,14 @@ static void
 handle_step_into_function (struct gdbarch *gdbarch,
                           struct execution_control_state *ecs)
 {
-  struct compunit_symtab *cust;
-  struct symtab_and_line stop_func_sal, sr_sal;
-
   fill_in_stop_func (gdbarch, ecs);
 
-  cust = find_pc_compunit_symtab (stop_pc);
+  compunit_symtab *cust = find_pc_compunit_symtab (stop_pc);
   if (cust != NULL && compunit_language (cust) != language_asm)
-    ecs->stop_func_start = gdbarch_skip_prologue (gdbarch,
-                                                 ecs->stop_func_start);
+    ecs->stop_func_start
+      = gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
 
-  stop_func_sal = find_pc_line (ecs->stop_func_start, 0);
+  symtab_and_line stop_func_sal = find_pc_line (ecs->stop_func_start, 0);
   /* Use the step_resume_break to step until the end of the prologue,
      even if that involves jumps (as it seems to on the vax under
      4.2).  */
@@ -5900,7 +7338,7 @@ handle_step_into_function (struct gdbarch *gdbarch,
   else
     {
       /* Put the step-breakpoint there and go until there.  */
-      init_sal (&sr_sal);      /* initialize to zeroes */
+      symtab_and_line sr_sal;
       sr_sal.pc = ecs->stop_func_start;
       sr_sal.section = find_pc_overlay (ecs->stop_func_start);
       sr_sal.pspace = get_frame_program_space (get_current_frame ());
@@ -5932,8 +7370,8 @@ handle_step_into_function_backward (struct gdbarch *gdbarch,
 
   cust = find_pc_compunit_symtab (stop_pc);
   if (cust != NULL && compunit_language (cust) != language_asm)
-    ecs->stop_func_start = gdbarch_skip_prologue (gdbarch,
-                                                 ecs->stop_func_start);
+    ecs->stop_func_start
+      = gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
 
   stop_func_sal = find_pc_line (stop_pc, 0);
 
@@ -5976,7 +7414,7 @@ insert_step_resume_breakpoint_at_sal_1 (struct gdbarch *gdbarch,
                        paddress (gdbarch, sr_sal.pc));
 
   inferior_thread ()->control.step_resume_breakpoint
-    = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type);
+    = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type).release ();
 }
 
 void
@@ -5999,13 +7437,11 @@ insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch,
 static void
 insert_hp_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
 {
-  struct symtab_and_line sr_sal;
-  struct gdbarch *gdbarch;
-
   gdb_assert (return_frame != NULL);
-  init_sal (&sr_sal);          /* initialize to zeros */
 
-  gdbarch = get_frame_arch (return_frame);
+  struct gdbarch *gdbarch = get_frame_arch (return_frame);
+
+  symtab_and_line sr_sal;
   sr_sal.pc = gdbarch_addr_bits_remove (gdbarch, get_frame_pc (return_frame));
   sr_sal.section = find_pc_overlay (sr_sal.pc);
   sr_sal.pspace = get_frame_program_space (return_frame);
@@ -6032,16 +7468,13 @@ insert_hp_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
 static void
 insert_step_resume_breakpoint_at_caller (struct frame_info *next_frame)
 {
-  struct symtab_and_line sr_sal;
-  struct gdbarch *gdbarch;
-
   /* We shouldn't have gotten here if we don't know where the call site
      is.  */
   gdb_assert (frame_id_p (frame_unwind_caller_id (next_frame)));
 
-  init_sal (&sr_sal);          /* initialize to zeros */
+  struct gdbarch *gdbarch = frame_unwind_caller_arch (next_frame);
 
-  gdbarch = frame_unwind_caller_arch (next_frame);
+  symtab_and_line sr_sal;
   sr_sal.pc = gdbarch_addr_bits_remove (gdbarch,
                                        frame_unwind_caller_pc (next_frame));
   sr_sal.section = find_pc_overlay (sr_sal.pc);
@@ -6070,7 +7503,7 @@ insert_longjmp_resume_breakpoint (struct gdbarch *gdbarch, CORE_ADDR pc)
                        paddress (gdbarch, pc));
 
   inferior_thread ()->control.exception_resume_breakpoint =
-    set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume);
+    set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume).release ();
 }
 
 /* Insert an exception resume breakpoint.  TP is the thread throwing
@@ -6087,13 +7520,14 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
 {
   TRY
     {
-      struct symbol *vsym;
+      struct block_symbol vsym;
       struct value *value;
       CORE_ADDR handler;
       struct breakpoint *bp;
 
-      vsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, NULL);
-      value = read_var_value (vsym, frame);
+      vsym = lookup_symbol_search_name (SYMBOL_SEARCH_NAME (sym),
+                                       b, VAR_DOMAIN);
+      value = read_var_value (vsym.symbol, vsym.block, frame);
       /* If the value was optimized out, revert to the old behavior.  */
       if (! value_optimized_out (value))
        {
@@ -6105,12 +7539,13 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
                                (unsigned long) handler);
 
          bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
-                                              handler, bp_exception_resume);
+                                              handler,
+                                              bp_exception_resume).release ();
 
          /* set_momentary_breakpoint_at_pc invalidates FRAME.  */
          frame = NULL;
 
-         bp->thread = tp->num;
+         bp->thread = tp->global_num;
          inferior_thread ()->control.exception_resume_breakpoint = bp;
        }
     }
@@ -6146,8 +7581,8 @@ insert_exception_resume_from_probe (struct thread_info *tp,
                                  handler));
 
   bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
-                                      handler, bp_exception_resume);
-  bp->thread = tp->num;
+                                      handler, bp_exception_resume).release ();
+  bp->thread = tp->global_num;
   inferior_thread ()->control.exception_resume_breakpoint = bp;
 }
 
@@ -6167,7 +7602,7 @@ check_exception_resume (struct execution_control_state *ecs,
      CFA and the HANDLER.  We ignore the CFA, extract the handler, and
      set a breakpoint there.  */
   probe = find_probe_by_pc (get_frame_pc (frame));
-  if (probe.probe)
+  if (probe.prob)
     {
       insert_exception_resume_from_probe (ecs->event_thread, &probe, frame);
       return;
@@ -6226,42 +7661,76 @@ stop_waiting (struct execution_control_state *ecs)
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog, "infrun: stop_waiting\n");
 
-  clear_step_over_info ();
-
   /* Let callers know we don't want to wait for the inferior anymore.  */
   ecs->wait_some_more = 0;
+
+  /* If all-stop, but the target is always in non-stop mode, stop all
+     threads now that we're presenting the stop to the user.  */
+  if (!non_stop && target_is_non_stop_p ())
+    stop_all_threads ();
 }
 
-/* Called when we should continue running the inferior, because the
-   current event doesn't cause a user visible stop.  This does the
-   resuming part; waiting for the next event is done elsewhere.  */
+/* Like keep_going, but passes the signal to the inferior, even if the
+   signal is set to nopass.  */
 
 static void
-keep_going (struct execution_control_state *ecs)
+keep_going_pass_signal (struct execution_control_state *ecs)
 {
-  /* Make sure normal_stop is called if we get a QUIT handled before
-     reaching resume.  */
-  struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
+  gdb_assert (ptid_equal (ecs->event_thread->ptid, inferior_ptid));
+  gdb_assert (!ecs->event_thread->resumed);
 
   /* Save the pc before execution, to compare with pc after stop.  */
   ecs->event_thread->prev_pc
     = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
-  if (ecs->event_thread->control.trap_expected
-      && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_TRAP)
+  if (ecs->event_thread->control.trap_expected)
     {
+      struct thread_info *tp = ecs->event_thread;
+
+      if (debug_infrun)
+       fprintf_unfiltered (gdb_stdlog,
+                           "infrun: %s has trap_expected set, "
+                           "resuming to collect trap\n",
+                           target_pid_to_str (tp->ptid));
+
       /* We haven't yet gotten our trap, and either: intercepted a
         non-signal event (e.g., a fork); or took a signal which we
         are supposed to pass through to the inferior.  Simply
         continue.  */
-      discard_cleanups (old_cleanups);
       resume (ecs->event_thread->suspend.stop_signal);
     }
+  else if (step_over_info_valid_p ())
+    {
+      /* Another thread is stepping over a breakpoint in-line.  If
+        this thread needs a step-over too, queue the request.  In
+        either case, this resume must be deferred for later.  */
+      struct thread_info *tp = ecs->event_thread;
+
+      if (ecs->hit_singlestep_breakpoint
+         || thread_still_needs_step_over (tp))
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: step-over already in progress: "
+                               "step-over for %s deferred\n",
+                               target_pid_to_str (tp->ptid));
+         thread_step_over_chain_enqueue (tp);
+       }
+      else
+       {
+         if (debug_infrun)
+           fprintf_unfiltered (gdb_stdlog,
+                               "infrun: step-over in progress: "
+                               "resume of %s deferred\n",
+                               target_pid_to_str (tp->ptid));
+       }
+    }
   else
     {
       struct regcache *regcache = get_current_regcache ();
       int remove_bp;
       int remove_wps;
+      step_over_what step_what;
 
       /* Either the trap was not expected, but we are continuing
         anyway (if we got a signal, the user asked it be passed to
@@ -6282,25 +7751,32 @@ keep_going (struct execution_control_state *ecs)
         instruction, and then re-insert the breakpoint when that step
         is finished.  */
 
+      step_what = thread_still_needs_step_over (ecs->event_thread);
+
       remove_bp = (ecs->hit_singlestep_breakpoint
-                  || thread_still_needs_step_over (ecs->event_thread));
-      remove_wps = (ecs->event_thread->stepping_over_watchpoint
-                   && !target_have_steppable_watchpoint);
+                  || (step_what & STEP_OVER_BREAKPOINT));
+      remove_wps = (step_what & STEP_OVER_WATCHPOINT);
 
       /* We can't use displaced stepping if we need to step past a
         watchpoint.  The instruction copied to the scratch pad would
         still trigger the watchpoint.  */
       if (remove_bp
-         && (remove_wps
-             || !use_displaced_stepping (get_regcache_arch (regcache))))
+         && (remove_wps || !use_displaced_stepping (ecs->event_thread)))
        {
-         set_step_over_info (get_regcache_aspace (regcache),
-                             regcache_read_pc (regcache), remove_wps);
+         set_step_over_info (regcache->aspace (),
+                             regcache_read_pc (regcache), remove_wps,
+                             ecs->event_thread->global_num);
        }
       else if (remove_wps)
-       set_step_over_info (NULL, 0, remove_wps);
-      else
-       clear_step_over_info ();
+       set_step_over_info (NULL, 0, remove_wps, -1);
+
+      /* If we now need to do an in-line step-over, we need to stop
+        all other threads.  Note this must be done before
+        insert_breakpoints below, because that removes the breakpoint
+        we're about to step over, otherwise other threads could miss
+        it.  */
+      if (step_over_info_valid_p () && target_is_non_stop_p ())
+       stop_all_threads ();
 
       /* Stop stepping if inserting breakpoints fails.  */
       TRY
@@ -6311,34 +7787,35 @@ keep_going (struct execution_control_state *ecs)
        {
          exception_print (gdb_stderr, e);
          stop_waiting (ecs);
-         discard_cleanups (old_cleanups);
+         clear_step_over_info ();
          return;
        }
       END_CATCH
 
       ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
 
-      /* Do not deliver GDB_SIGNAL_TRAP (except when the user
-        explicitly specifies that such a signal should be delivered
-        to the target program).  Typically, that would occur when a
-        user is debugging a target monitor on a simulator: the target
-        monitor sets a breakpoint; the simulator encounters this
-        breakpoint and halts the simulation handing control to GDB;
-        GDB, noting that the stop address doesn't map to any known
-        breakpoint, returns control back to the simulator; the
-        simulator then delivers the hardware equivalent of a
-        GDB_SIGNAL_TRAP to the program being debugged.  */
-      if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
-         && !signal_program[ecs->event_thread->suspend.stop_signal])
-       ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
-
-      discard_cleanups (old_cleanups);
       resume (ecs->event_thread->suspend.stop_signal);
     }
 
   prepare_to_wait (ecs);
 }
 
+/* Called when we should continue running the inferior, because the
+   current event doesn't cause a user visible stop.  This does the
+   resuming part; waiting for the next event is done elsewhere.  */
+
+static void
+keep_going (struct execution_control_state *ecs)
+{
+  if (ecs->event_thread->control.trap_expected
+      && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
+    ecs->event_thread->control.trap_expected = 0;
+
+  if (!signal_program[ecs->event_thread->suspend.stop_signal])
+    ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+  keep_going_pass_signal (ecs);
+}
+
 /* This function normally comes after a resume, before
    handle_inferior_event exits.  It takes care of any last bits of
    housekeeping, and sets the all-important wait_some_more flag.  */
@@ -6349,10 +7826,10 @@ prepare_to_wait (struct execution_control_state *ecs)
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog, "infrun: prepare_to_wait\n");
 
-  /* This is the old end of the while loop.  Let everybody know we
-     want to wait for the inferior some more and get called again
-     soon.  */
   ecs->wait_some_more = 1;
+
+  if (!target_is_async_p ())
+    mark_infrun_async_event_handler ();
 }
 
 /* We are done with the step range of a step/next/si/ni command.
@@ -6381,9 +7858,9 @@ print_end_stepping_range_reason (struct ui_out *uiout)
 {
   /* For CLI-like interpreters, print nothing.  */
 
-  if (ui_out_is_mi_like_p (uiout))
+  if (uiout->is_mi_like_p ())
     {
-      ui_out_field_string (uiout, "reason",
+      uiout->field_string ("reason",
                           async_reason_lookup (EXEC_ASYNC_END_STEPPING_RANGE));
     }
 }
@@ -6392,21 +7869,21 @@ void
 print_signal_exited_reason (struct ui_out *uiout, enum gdb_signal siggnal)
 {
   annotate_signalled ();
-  if (ui_out_is_mi_like_p (uiout))
-    ui_out_field_string
-      (uiout, "reason", async_reason_lookup (EXEC_ASYNC_EXITED_SIGNALLED));
-  ui_out_text (uiout, "\nProgram terminated with signal ");
+  if (uiout->is_mi_like_p ())
+    uiout->field_string
+      ("reason", async_reason_lookup (EXEC_ASYNC_EXITED_SIGNALLED));
+  uiout->text ("\nProgram terminated with signal ");
   annotate_signal_name ();
-  ui_out_field_string (uiout, "signal-name",
+  uiout->field_string ("signal-name",
                       gdb_signal_to_name (siggnal));
   annotate_signal_name_end ();
-  ui_out_text (uiout, ", ");
+  uiout->text (", ");
   annotate_signal_string ();
-  ui_out_field_string (uiout, "signal-meaning",
+  uiout->field_string ("signal-meaning",
                       gdb_signal_to_string (siggnal));
   annotate_signal_string_end ();
-  ui_out_text (uiout, ".\n");
-  ui_out_text (uiout, "The program no longer exists.\n");
+  uiout->text (".\n");
+  uiout->text ("The program no longer exists.\n");
 }
 
 void
@@ -6418,68 +7895,97 @@ print_exited_reason (struct ui_out *uiout, int exitstatus)
   annotate_exited (exitstatus);
   if (exitstatus)
     {
-      if (ui_out_is_mi_like_p (uiout))
-       ui_out_field_string (uiout, "reason", 
-                            async_reason_lookup (EXEC_ASYNC_EXITED));
-      ui_out_text (uiout, "[Inferior ");
-      ui_out_text (uiout, plongest (inf->num));
-      ui_out_text (uiout, " (");
-      ui_out_text (uiout, pidstr);
-      ui_out_text (uiout, ") exited with code ");
-      ui_out_field_fmt (uiout, "exit-code", "0%o", (unsigned int) exitstatus);
-      ui_out_text (uiout, "]\n");
+      if (uiout->is_mi_like_p ())
+       uiout->field_string ("reason", async_reason_lookup (EXEC_ASYNC_EXITED));
+      uiout->text ("[Inferior ");
+      uiout->text (plongest (inf->num));
+      uiout->text (" (");
+      uiout->text (pidstr);
+      uiout->text (") exited with code ");
+      uiout->field_fmt ("exit-code", "0%o", (unsigned int) exitstatus);
+      uiout->text ("]\n");
     }
   else
     {
-      if (ui_out_is_mi_like_p (uiout))
-       ui_out_field_string
-         (uiout, "reason", async_reason_lookup (EXEC_ASYNC_EXITED_NORMALLY));
-      ui_out_text (uiout, "[Inferior ");
-      ui_out_text (uiout, plongest (inf->num));
-      ui_out_text (uiout, " (");
-      ui_out_text (uiout, pidstr);
-      ui_out_text (uiout, ") exited normally]\n");
+      if (uiout->is_mi_like_p ())
+       uiout->field_string
+         ("reason", async_reason_lookup (EXEC_ASYNC_EXITED_NORMALLY));
+      uiout->text ("[Inferior ");
+      uiout->text (plongest (inf->num));
+      uiout->text (" (");
+      uiout->text (pidstr);
+      uiout->text (") exited normally]\n");
     }
 }
 
+/* Some targets/architectures can do extra processing/display of
+   segmentation faults.  E.g., Intel MPX boundary faults.
+   Call the architecture dependent function to handle the fault.  */
+
+static void
+handle_segmentation_fault (struct ui_out *uiout)
+{
+  struct regcache *regcache = get_current_regcache ();
+  struct gdbarch *gdbarch = regcache->arch ();
+
+  if (gdbarch_handle_segmentation_fault_p (gdbarch))
+    gdbarch_handle_segmentation_fault (gdbarch, uiout);
+}
+
 void
 print_signal_received_reason (struct ui_out *uiout, enum gdb_signal siggnal)
 {
+  struct thread_info *thr = inferior_thread ();
+
   annotate_signal ();
 
-  if (siggnal == GDB_SIGNAL_0 && !ui_out_is_mi_like_p (uiout))
+  if (uiout->is_mi_like_p ())
+    ;
+  else if (show_thread_that_caused_stop ())
     {
-      struct thread_info *t = inferior_thread ();
+      const char *name;
 
-      ui_out_text (uiout, "\n[");
-      ui_out_field_string (uiout, "thread-name",
-                          target_pid_to_str (t->ptid));
-      ui_out_field_fmt (uiout, "thread-id", "] #%d", t->num);
-      ui_out_text (uiout, " stopped");
+      uiout->text ("\nThread ");
+      uiout->field_fmt ("thread-id", "%s", print_thread_id (thr));
+
+      name = thr->name != NULL ? thr->name : target_thread_name (thr);
+      if (name != NULL)
+       {
+         uiout->text (" \"");
+         uiout->field_fmt ("name", "%s", name);
+         uiout->text ("\"");
+       }
     }
+  else
+    uiout->text ("\nProgram");
+
+  if (siggnal == GDB_SIGNAL_0 && !uiout->is_mi_like_p ())
+    uiout->text (" stopped");
   else
     {
-      ui_out_text (uiout, "\nProgram received signal ");
+      uiout->text (" received signal ");
       annotate_signal_name ();
-      if (ui_out_is_mi_like_p (uiout))
-       ui_out_field_string
-         (uiout, "reason", async_reason_lookup (EXEC_ASYNC_SIGNAL_RECEIVED));
-      ui_out_field_string (uiout, "signal-name",
-                          gdb_signal_to_name (siggnal));
+      if (uiout->is_mi_like_p ())
+       uiout->field_string
+         ("reason", async_reason_lookup (EXEC_ASYNC_SIGNAL_RECEIVED));
+      uiout->field_string ("signal-name", gdb_signal_to_name (siggnal));
       annotate_signal_name_end ();
-      ui_out_text (uiout, ", ");
+      uiout->text (", ");
       annotate_signal_string ();
-      ui_out_field_string (uiout, "signal-meaning",
-                          gdb_signal_to_string (siggnal));
+      uiout->field_string ("signal-meaning", gdb_signal_to_string (siggnal));
+
+      if (siggnal == GDB_SIGNAL_SEGV)
+       handle_segmentation_fault (uiout);
+
       annotate_signal_string_end ();
     }
-  ui_out_text (uiout, ".\n");
+  uiout->text (".\n");
 }
 
 void
 print_no_history_reason (struct ui_out *uiout)
 {
-  ui_out_text (uiout, "\nNo more reverse-execution history.\n");
+  uiout->text ("\nNo more reverse-execution history.\n");
 }
 
 /* Print current location without a level number, if we have changed
@@ -6487,11 +7993,11 @@ print_no_history_reason (struct ui_out *uiout)
    bpstat_print contains the logic deciding in detail what to print,
    based on the event(s) that just occurred.  */
 
-void
-print_stop_event (struct target_waitstatus *ws)
+static void
+print_stop_location (struct target_waitstatus *ws)
 {
   int bpstat_ret;
-  int source_flag;
+  enum print_what source_flag;
   int do_frame_printing = 1;
   struct thread_info *tp = inferior_thread ();
 
@@ -6539,38 +8045,165 @@ print_stop_event (struct target_waitstatus *ws)
      SRC_AND_LOC: Print location and source line.  */
   if (do_frame_printing)
     print_stack_frame (get_selected_frame (NULL), 0, source_flag, 1);
-
-  /* Display the auto-display expressions.  */
-  do_displays ();
 }
 
-/* Here to return control to GDB when the inferior stops for real.
-   Print appropriate messages, remove breakpoints, give terminal our modes.
+/* See infrun.h.  */
+
+void
+print_stop_event (struct ui_out *uiout)
+{
+  struct target_waitstatus last;
+  ptid_t last_ptid;
+  struct thread_info *tp;
+
+  get_last_target_status (&last_ptid, &last);
+
+  {
+    scoped_restore save_uiout = make_scoped_restore (&current_uiout, uiout);
+
+    print_stop_location (&last);
+
+    /* Display the auto-display expressions.  */
+    do_displays ();
+  }
+
+  tp = inferior_thread ();
+  if (tp->thread_fsm != NULL
+      && thread_fsm_finished_p (tp->thread_fsm))
+    {
+      struct return_value_info *rv;
+
+      rv = thread_fsm_return_value (tp->thread_fsm);
+      if (rv != NULL)
+       print_return_value (uiout, rv);
+    }
+}
 
-   STOP_PRINT_FRAME nonzero means print the executing frame
-   (pc, function, args, file, line number and line text).
-   BREAKPOINTS_FAILED nonzero means stop was due to error
-   attempting to insert breakpoints.  */
+/* See infrun.h.  */
 
 void
+maybe_remove_breakpoints (void)
+{
+  if (!breakpoints_should_be_inserted_now () && target_has_execution)
+    {
+      if (remove_breakpoints ())
+       {
+         target_terminal::ours_for_output ();
+         printf_filtered (_("Cannot remove breakpoints because "
+                            "program is no longer writable.\nFurther "
+                            "execution is probably impossible.\n"));
+       }
+    }
+}
+
+/* The execution context that just caused a normal stop.  */
+
+struct stop_context
+{
+  /* The stop ID.  */
+  ULONGEST stop_id;
+
+  /* The event PTID.  */
+
+  ptid_t ptid;
+
+  /* If stopp for a thread event, this is the thread that caused the
+     stop.  */
+  struct thread_info *thread;
+
+  /* The inferior that caused the stop.  */
+  int inf_num;
+};
+
+/* Returns a new stop context.  If stopped for a thread event, this
+   takes a strong reference to the thread.  */
+
+static struct stop_context *
+save_stop_context (void)
+{
+  struct stop_context *sc = XNEW (struct stop_context);
+
+  sc->stop_id = get_stop_id ();
+  sc->ptid = inferior_ptid;
+  sc->inf_num = current_inferior ()->num;
+
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    {
+      /* Take a strong reference so that the thread can't be deleted
+        yet.  */
+      sc->thread = inferior_thread ();
+      sc->thread->incref ();
+    }
+  else
+    sc->thread = NULL;
+
+  return sc;
+}
+
+/* Release a stop context previously created with save_stop_context.
+   Releases the strong reference to the thread as well. */
+
+static void
+release_stop_context_cleanup (void *arg)
+{
+  struct stop_context *sc = (struct stop_context *) arg;
+
+  if (sc->thread != NULL)
+    sc->thread->decref ();
+  xfree (sc);
+}
+
+/* Return true if the current context no longer matches the saved stop
+   context.  */
+
+static int
+stop_context_changed (struct stop_context *prev)
+{
+  if (!ptid_equal (prev->ptid, inferior_ptid))
+    return 1;
+  if (prev->inf_num != current_inferior ()->num)
+    return 1;
+  if (prev->thread != NULL && prev->thread->state != THREAD_STOPPED)
+    return 1;
+  if (get_stop_id () != prev->stop_id)
+    return 1;
+  return 0;
+}
+
+/* See infrun.h.  */
+
+int
 normal_stop (void)
 {
   struct target_waitstatus last;
   ptid_t last_ptid;
-  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
 
   get_last_target_status (&last_ptid, &last);
 
+  new_stop_id ();
+
   /* If an exception is thrown from this point on, make sure to
      propagate GDB's knowledge of the executing state to the
      frontend/user running state.  A QUIT is an easy exception to see
      here, so do this before any filtered output.  */
+
+  gdb::optional<scoped_finish_thread_state> maybe_finish_thread_state;
+
   if (!non_stop)
-    make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
-  else if (last.kind != TARGET_WAITKIND_SIGNALLED
-          && last.kind != TARGET_WAITKIND_EXITED
-          && last.kind != TARGET_WAITKIND_NO_RESUMED)
-    make_cleanup (finish_thread_state_cleanup, &inferior_ptid);
+    maybe_finish_thread_state.emplace (minus_one_ptid);
+  else if (last.kind == TARGET_WAITKIND_SIGNALLED
+          || last.kind == TARGET_WAITKIND_EXITED)
+    {
+      /* On some targets, we may still have live threads in the
+        inferior when we get a process exit event.  E.g., for
+        "checkpoint", when the current checkpoint/fork exits,
+        linux-fork.c automatically switches to another fork from
+        within target_mourn_inferior.  */
+      if (inferior_ptid != null_ptid)
+       maybe_finish_thread_state.emplace (ptid_t (inferior_ptid.pid ()));
+    }
+  else if (last.kind != TARGET_WAITKIND_NO_RESUMED)
+    maybe_finish_thread_state.emplace (inferior_ptid);
 
   /* As we're presenting a stop, and potentially removing breakpoints,
      update the thread list so we can tell whether there are threads
@@ -6583,7 +8216,7 @@ normal_stop (void)
   update_thread_list ();
 
   if (last.kind == TARGET_WAITKIND_STOPPED && stopped_by_random_signal)
-    observer_notify_signal_received (inferior_thread ()->suspend.stop_signal);
+    gdb::observers::signal_received.notify (inferior_thread ()->suspend.stop_signal);
 
   /* As with the notification of thread events, we want to delay
      notifying the user that we've switched thread context until
@@ -6602,38 +8235,34 @@ normal_stop (void)
      after this event is handled, so we're not really switching, only
      informing of a stop.  */
   if (!non_stop
-      && !ptid_equal (previous_inferior_ptid, inferior_ptid)
+      && previous_inferior_ptid != inferior_ptid
       && target_has_execution
       && last.kind != TARGET_WAITKIND_SIGNALLED
       && last.kind != TARGET_WAITKIND_EXITED
       && last.kind != TARGET_WAITKIND_NO_RESUMED)
     {
-      target_terminal_ours_for_output ();
-      printf_filtered (_("[Switching to %s]\n"),
-                      target_pid_to_str (inferior_ptid));
-      annotate_thread_changed ();
+      SWITCH_THRU_ALL_UIS ()
+       {
+         target_terminal::ours_for_output ();
+         printf_filtered (_("[Switching to %s]\n"),
+                          target_pid_to_str (inferior_ptid));
+         annotate_thread_changed ();
+       }
       previous_inferior_ptid = inferior_ptid;
     }
 
   if (last.kind == TARGET_WAITKIND_NO_RESUMED)
     {
-      gdb_assert (sync_execution || !target_can_async_p ());
-
-      target_terminal_ours_for_output ();
-      printf_filtered (_("No unwaited-for children left.\n"));
+      SWITCH_THRU_ALL_UIS ()
+       if (current_ui->prompt_state == PROMPT_BLOCKED)
+         {
+           target_terminal::ours_for_output ();
+           printf_filtered (_("No unwaited-for children left.\n"));
+         }
     }
 
   /* Note: this depends on the update_thread_list call above.  */
-  if (!breakpoints_should_be_inserted_now () && target_has_execution)
-    {
-      if (remove_breakpoints ())
-       {
-         target_terminal_ours_for_output ();
-         printf_filtered (_("Cannot remove breakpoints because "
-                            "program is no longer writable.\nFurther "
-                            "execution is probably impossible.\n"));
-       }
-    }
+  maybe_remove_breakpoints ();
 
   /* If an auto-display called a function and that got a signal,
      delete that auto-display to avoid an infinite recursion.  */
@@ -6641,123 +8270,83 @@ normal_stop (void)
   if (stopped_by_random_signal)
     disable_current_display ();
 
-  /* Notify observers if we finished a "step"-like command, etc.  */
-  if (target_has_execution
-      && last.kind != TARGET_WAITKIND_SIGNALLED
-      && last.kind != TARGET_WAITKIND_EXITED
-      && inferior_thread ()->control.stop_step)
-    {
-      /* But not if in the middle of doing a "step n" operation for
-        n > 1 */
-      if (inferior_thread ()->step_multi)
-       goto done;
-
-      observer_notify_end_stepping_range ();
-    }
-
-  target_terminal_ours ();
-  async_enable_stdin ();
-
-  /* Set the current source location.  This will also happen if we
-     display the frame below, but the current SAL will be incorrect
-     during a user hook-stop function.  */
-  if (has_stack_frames () && !stop_stack_dummy)
-    set_current_sal_from_frame (get_current_frame ());
-
-  /* Let the user/frontend see the threads as stopped, but do nothing
-     if the thread was running an infcall.  We may be e.g., evaluating
-     a breakpoint condition.  In that case, the thread had state
-     THREAD_RUNNING before the infcall, and shall remain set to
-     running, all without informing the user/frontend about state
-     transition changes.  If this is actually a call command, then the
-     thread was originally already stopped, so there's no state to
-     finish either.  */
-  if (target_has_execution && inferior_thread ()->control.in_infcall)
-    discard_cleanups (old_chain);
-  else
-    do_cleanups (old_chain);
-
-  /* Look up the hook_stop and run it (CLI internally handles problem
-     of stop_command's pre-hook not existing).  */
-  if (stop_command)
-    catch_errors (hook_stop_stub, stop_command,
-                 "Error while running hook_stop:\n", RETURN_MASK_ALL);
-
-  if (!has_stack_frames ())
-    goto done;
+  SWITCH_THRU_ALL_UIS ()
+    {
+      async_enable_stdin ();
+    }
 
-  if (last.kind == TARGET_WAITKIND_SIGNALLED
-      || last.kind == TARGET_WAITKIND_EXITED)
-    goto done;
+  /* Let the user/frontend see the threads as stopped.  */
+  maybe_finish_thread_state.reset ();
 
   /* Select innermost stack frame - i.e., current frame is frame 0,
-     and current location is based on that.
-     Don't do this on return from a stack dummy routine,
-     or if the program has exited.  */
+     and current location is based on that.  Handle the case where the
+     dummy call is returning after being stopped.  E.g. the dummy call
+     previously hit a breakpoint.  (If the dummy call returns
+     normally, we won't reach here.)  Do this before the stop hook is
+     run, so that it doesn't get to see the temporary dummy frame,
+     which is not where we'll present the stop.  */
+  if (has_stack_frames ())
+    {
+      if (stop_stack_dummy == STOP_STACK_DUMMY)
+       {
+         /* Pop the empty frame that contains the stack dummy.  This
+            also restores inferior state prior to the call (struct
+            infcall_suspend_state).  */
+         struct frame_info *frame = get_current_frame ();
+
+         gdb_assert (get_frame_type (frame) == DUMMY_FRAME);
+         frame_pop (frame);
+         /* frame_pop calls reinit_frame_cache as the last thing it
+            does which means there's now no selected frame.  */
+       }
 
-  if (!stop_stack_dummy)
-    {
       select_frame (get_current_frame ());
 
-      /* If --batch-silent is enabled then there's no need to print the current
-        source location, and to try risks causing an error message about
-        missing source files.  */
-      if (stop_print_frame && !batch_silent)
-       print_stop_event (&last);
-    }
-
-  if (stop_stack_dummy == STOP_STACK_DUMMY)
-    {
-      /* Pop the empty frame that contains the stack dummy.
-        This also restores inferior state prior to the call
-        (struct infcall_suspend_state).  */
-      struct frame_info *frame = get_current_frame ();
-
-      gdb_assert (get_frame_type (frame) == DUMMY_FRAME);
-      frame_pop (frame);
-      /* frame_pop() calls reinit_frame_cache as the last thing it
-        does which means there's currently no selected frame.  We
-        don't need to re-establish a selected frame if the dummy call
-        returns normally, that will be done by
-        restore_infcall_control_state.  However, we do have to handle
-        the case where the dummy call is returning after being
-        stopped (e.g. the dummy call previously hit a breakpoint).
-        We can't know which case we have so just always re-establish
-        a selected frame here.  */
-      select_frame (get_current_frame ());
+      /* Set the current source location.  */
+      set_current_sal_from_frame (get_current_frame ());
     }
 
-done:
-  annotate_stopped ();
-
-  /* Suppress the stop observer if we're in the middle of:
+  /* Look up the hook_stop and run it (CLI internally handles problem
+     of stop_command's pre-hook not existing).  */
+  if (stop_command != NULL)
+    {
+      struct stop_context *saved_context = save_stop_context ();
+      struct cleanup *old_chain
+       = make_cleanup (release_stop_context_cleanup, saved_context);
 
-     - a step n (n > 1), as there still more steps to be done.
+      TRY
+       {
+         execute_cmd_pre_hook (stop_command);
+       }
+      CATCH (ex, RETURN_MASK_ALL)
+       {
+         exception_fprintf (gdb_stderr, ex,
+                            "Error while running hook_stop:\n");
+       }
+      END_CATCH
 
-     - a "finish" command, as the observer will be called in
-       finish_command_continuation, so it can include the inferior
-       function's return value.
+      /* If the stop hook resumes the target, then there's no point in
+        trying to notify about the previous stop; its context is
+        gone.  Likewise if the command switches thread or inferior --
+        the observers would print a stop for the wrong
+        thread/inferior.  */
+      if (stop_context_changed (saved_context))
+       {
+         do_cleanups (old_chain);
+         return 1;
+       }
+      do_cleanups (old_chain);
+    }
 
-     - calling an inferior function, as we pretend we inferior didn't
-       run at all.  The return value of the call is handled by the
-       expression evaluator, through call_function_by_hand.  */
+  /* Notify observers about the stop.  This is where the interpreters
+     print the stop event.  */
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    gdb::observers::normal_stop.notify (inferior_thread ()->control.stop_bpstat,
+                                stop_print_frame);
+  else
+    gdb::observers::normal_stop.notify (NULL, stop_print_frame);
 
-  if (!target_has_execution
-      || last.kind == TARGET_WAITKIND_SIGNALLED
-      || last.kind == TARGET_WAITKIND_EXITED
-      || last.kind == TARGET_WAITKIND_NO_RESUMED
-      || (!(inferior_thread ()->step_multi
-           && inferior_thread ()->control.stop_step)
-         && !(inferior_thread ()->control.stop_bpstat
-              && inferior_thread ()->control.proceed_to_finish)
-         && !inferior_thread ()->control.in_infcall))
-    {
-      if (!ptid_equal (inferior_ptid, null_ptid))
-       observer_notify_normal_stop (inferior_thread ()->control.stop_bpstat,
-                                    stop_print_frame);
-      else
-       observer_notify_normal_stop (NULL, stop_print_frame);
-    }
+  annotate_stopped ();
 
   if (target_has_execution)
     {
@@ -6772,13 +8361,8 @@ done:
      longer needed.  Keeping those around slows down things linearly.
      Note that this never removes the current inferior.  */
   prune_inferiors ();
-}
 
-static int
-hook_stop_stub (void *cmd)
-{
-  execute_cmd_pre_hook ((struct cmd_list_element *) cmd);
-  return (0);
+  return 0;
 }
 \f
 int
@@ -6887,16 +8471,14 @@ sig_print_info (enum gdb_signal oursig)
 /* Specify how various signals in the inferior should be handled.  */
 
 static void
-handle_command (char *args, int from_tty)
+handle_command (const char *args, int from_tty)
 {
-  char **argv;
   int digits, wordlen;
   int sigfirst, signum, siglast;
   enum gdb_signal oursig;
   int allsigs;
   int nsigs;
   unsigned char *sigs;
-  struct cleanup *old_chain;
 
   if (args == NULL)
     {
@@ -6911,24 +8493,23 @@ handle_command (char *args, int from_tty)
 
   /* Break the command line up into args.  */
 
-  argv = gdb_buildargv (args);
-  old_chain = make_cleanup_freeargv (argv);
+  gdb_argv built_argv (args);
 
   /* Walk through the args, looking for signal oursigs, signal names, and
      actions.  Signal numbers and signal names may be interspersed with
      actions, with the actions being performed for all signals cumulatively
      specified.  Signal ranges can be specified as <LOW>-<HIGH>.  */
 
-  while (*argv != NULL)
+  for (char *arg : built_argv)
     {
-      wordlen = strlen (*argv);
-      for (digits = 0; isdigit ((*argv)[digits]); digits++)
+      wordlen = strlen (arg);
+      for (digits = 0; isdigit (arg[digits]); digits++)
        {;
        }
       allsigs = 0;
       sigfirst = siglast = -1;
 
-      if (wordlen >= 1 && !strncmp (*argv, "all", wordlen))
+      if (wordlen >= 1 && !strncmp (arg, "all", wordlen))
        {
          /* Apply action to all signals except those used by the
             debugger.  Silently skip those.  */
@@ -6936,37 +8517,37 @@ handle_command (char *args, int from_tty)
          sigfirst = 0;
          siglast = nsigs - 1;
        }
-      else if (wordlen >= 1 && !strncmp (*argv, "stop", wordlen))
+      else if (wordlen >= 1 && !strncmp (arg, "stop", wordlen))
        {
          SET_SIGS (nsigs, sigs, signal_stop);
          SET_SIGS (nsigs, sigs, signal_print);
        }
-      else if (wordlen >= 1 && !strncmp (*argv, "ignore", wordlen))
+      else if (wordlen >= 1 && !strncmp (arg, "ignore", wordlen))
        {
          UNSET_SIGS (nsigs, sigs, signal_program);
        }
-      else if (wordlen >= 2 && !strncmp (*argv, "print", wordlen))
+      else if (wordlen >= 2 && !strncmp (arg, "print", wordlen))
        {
          SET_SIGS (nsigs, sigs, signal_print);
        }
-      else if (wordlen >= 2 && !strncmp (*argv, "pass", wordlen))
+      else if (wordlen >= 2 && !strncmp (arg, "pass", wordlen))
        {
          SET_SIGS (nsigs, sigs, signal_program);
        }
-      else if (wordlen >= 3 && !strncmp (*argv, "nostop", wordlen))
+      else if (wordlen >= 3 && !strncmp (arg, "nostop", wordlen))
        {
          UNSET_SIGS (nsigs, sigs, signal_stop);
        }
-      else if (wordlen >= 3 && !strncmp (*argv, "noignore", wordlen))
+      else if (wordlen >= 3 && !strncmp (arg, "noignore", wordlen))
        {
          SET_SIGS (nsigs, sigs, signal_program);
        }
-      else if (wordlen >= 4 && !strncmp (*argv, "noprint", wordlen))
+      else if (wordlen >= 4 && !strncmp (arg, "noprint", wordlen))
        {
          UNSET_SIGS (nsigs, sigs, signal_print);
          UNSET_SIGS (nsigs, sigs, signal_stop);
        }
-      else if (wordlen >= 4 && !strncmp (*argv, "nopass", wordlen))
+      else if (wordlen >= 4 && !strncmp (arg, "nopass", wordlen))
        {
          UNSET_SIGS (nsigs, sigs, signal_program);
        }
@@ -6979,11 +8560,11 @@ handle_command (char *args, int from_tty)
             SIGHUP, SIGINT, SIGALRM, etc. will work right anyway.  */
 
          sigfirst = siglast = (int)
-           gdb_signal_from_command (atoi (*argv));
-         if ((*argv)[digits] == '-')
+           gdb_signal_from_command (atoi (arg));
+         if (arg[digits] == '-')
            {
              siglast = (int)
-               gdb_signal_from_command (atoi ((*argv) + digits + 1));
+               gdb_signal_from_command (atoi (arg + digits + 1));
            }
          if (sigfirst > siglast)
            {
@@ -6995,7 +8576,7 @@ handle_command (char *args, int from_tty)
        }
       else
        {
-         oursig = gdb_signal_from_name (*argv);
+         oursig = gdb_signal_from_name (arg);
          if (oursig != GDB_SIGNAL_UNKNOWN)
            {
              sigfirst = siglast = (int) oursig;
@@ -7003,7 +8584,7 @@ handle_command (char *args, int from_tty)
          else
            {
              /* Not a number and not a recognized flag word => complain.  */
-             error (_("Unrecognized or ambiguous flag word: \"%s\"."), *argv);
+             error (_("Unrecognized or ambiguous flag word: \"%s\"."), arg);
            }
        }
 
@@ -7041,8 +8622,6 @@ Are you sure you want to change it? "),
              break;
            }
        }
-
-      argv++;
     }
 
   for (signum = 0; signum < nsigs; signum++)
@@ -7058,22 +8637,20 @@ Are you sure you want to change it? "),
            sig_print_header ();
            for (; signum < nsigs; signum++)
              if (sigs[signum])
-               sig_print_info (signum);
+               sig_print_info ((enum gdb_signal) signum);
          }
 
        break;
       }
-
-  do_cleanups (old_chain);
 }
 
 /* Complete the "handle" command.  */
 
-static VEC (char_ptr) *
+static void
 handle_completer (struct cmd_list_element *ignore,
+                 completion_tracker &tracker,
                  const char *text, const char *word)
 {
-  VEC (char_ptr) *vec_signals, *vec_keywords, *return_val;
   static const char * const keywords[] =
     {
       "all",
@@ -7088,13 +8665,8 @@ handle_completer (struct cmd_list_element *ignore,
       NULL,
     };
 
-  vec_signals = signal_completer (ignore, text, word);
-  vec_keywords = complete_on_enum (keywords, word, word);
-
-  return_val = VEC_merge (char_ptr, vec_signals, vec_keywords);
-  VEC_free (char_ptr, vec_signals);
-  VEC_free (char_ptr, vec_keywords);
-  return return_val;
+  signal_completer (ignore, tracker, text, word);
+  complete_on_enum (tracker, keywords, word, word);
 }
 
 enum gdb_signal
@@ -7112,7 +8684,7 @@ Use \"info signals\" for a list of symbolic signals."));
    targets, all signals should be in the signal tables).  */
 
 static void
-signals_info (char *signum_exp, int from_tty)
+info_signals_command (const char *signum_exp, int from_tty)
 {
   enum gdb_signal oursig;
 
@@ -7149,25 +8721,6 @@ signals_info (char *signum_exp, int from_tty)
                     "to change these tables.\n"));
 }
 
-/* Check if it makes sense to read $_siginfo from the current thread
-   at this point.  If not, throw an error.  */
-
-static void
-validate_siginfo_access (void)
-{
-  /* No current inferior, no siginfo.  */
-  if (ptid_equal (inferior_ptid, null_ptid))
-    error (_("No thread selected."));
-
-  /* Don't try to read from a dead thread.  */
-  if (is_exited (inferior_ptid))
-    error (_("The current thread has terminated"));
-
-  /* ... or from a spinning thread.  */
-  if (is_running (inferior_ptid))
-    error (_("Selected thread is running."));
-}
-
 /* The $_siginfo convenience variable is a bit special.  We don't know
    for sure the type of the value until we actually have a chance to
    fetch the data.  The type can change depending on gdbarch, so it is
@@ -7186,10 +8739,12 @@ siginfo_value_read (struct value *v)
 {
   LONGEST transferred;
 
-  validate_siginfo_access ();
+  /* If we can access registers, so can we access $_siginfo.  Likewise
+     vice versa.  */
+  validate_registers_access ();
 
   transferred =
-    target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO,
+    target_read (target_stack, TARGET_OBJECT_SIGNAL_INFO,
                 NULL,
                 value_contents_all_raw (v),
                 value_offset (v),
@@ -7207,9 +8762,11 @@ siginfo_value_write (struct value *v, struct value *fromval)
 {
   LONGEST transferred;
 
-  validate_siginfo_access ();
+  /* If we can access registers, so can we access $_siginfo.  Likewise
+     vice versa.  */
+  validate_registers_access ();
 
-  transferred = target_write (&current_target,
+  transferred = target_write (target_stack,
                              TARGET_OBJECT_SIGNAL_INFO,
                              NULL,
                              value_contents_all_raw (fromval),
@@ -7259,7 +8816,7 @@ struct infcall_suspend_state
 
   /* Other fields:  */
   CORE_ADDR stop_pc;
-  struct regcache *registers;
+  readonly_detached_regcache *registers;
 
   /* Format of SIGINFO_DATA or NULL if it is not present.  */
   struct gdbarch *siginfo_gdbarch;
@@ -7276,7 +8833,7 @@ save_infcall_suspend_state (void)
   struct infcall_suspend_state *inf_state;
   struct thread_info *tp = inferior_thread ();
   struct regcache *regcache = get_current_regcache ();
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   gdb_byte *siginfo_data = NULL;
 
   if (gdbarch_get_siginfo_type_p (gdbarch))
@@ -7285,10 +8842,10 @@ save_infcall_suspend_state (void)
       size_t len = TYPE_LENGTH (type);
       struct cleanup *back_to;
 
-      siginfo_data = xmalloc (len);
+      siginfo_data = (gdb_byte *) xmalloc (len);
       back_to = make_cleanup (xfree, siginfo_data);
 
-      if (target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+      if (target_read (target_stack, TARGET_OBJECT_SIGNAL_INFO, NULL,
                       siginfo_data, 0, len) == len)
        discard_cleanups (back_to);
       else
@@ -7315,7 +8872,7 @@ save_infcall_suspend_state (void)
 
   inf_state->stop_pc = stop_pc;
 
-  inf_state->registers = regcache_dup (regcache);
+  inf_state->registers = new readonly_detached_regcache (*regcache);
 
   return inf_state;
 }
@@ -7327,7 +8884,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
   struct thread_info *tp = inferior_thread ();
   struct regcache *regcache = get_current_regcache ();
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
 
   tp->suspend = inf_state->thread_suspend;
 
@@ -7338,7 +8895,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
       struct type *type = gdbarch_get_siginfo_type (gdbarch);
 
       /* Errors ignored.  */
-      target_write (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+      target_write (target_stack, TARGET_OBJECT_SIGNAL_INFO, NULL,
                    inf_state->siginfo_data, 0, TYPE_LENGTH (type));
     }
 
@@ -7346,7 +8903,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
      (and perhaps other times).  */
   if (target_has_execution)
     /* NB: The register write goes through to the target.  */
-    regcache_cpy (regcache, inf_state->registers);
+    regcache->restore (inf_state->registers);
 
   discard_infcall_suspend_state (inf_state);
 }
@@ -7354,7 +8911,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 static void
 do_restore_infcall_suspend_state_cleanup (void *state)
 {
-  restore_infcall_suspend_state (state);
+  restore_infcall_suspend_state ((struct infcall_suspend_state *) state);
 }
 
 struct cleanup *
@@ -7367,12 +8924,12 @@ make_cleanup_restore_infcall_suspend_state
 void
 discard_infcall_suspend_state (struct infcall_suspend_state *inf_state)
 {
-  regcache_xfree (inf_state->registers);
+  delete inf_state->registers;
   xfree (inf_state->siginfo_data);
   xfree (inf_state);
 }
 
-struct regcache *
+readonly_detached_regcache *
 get_infcall_suspend_state_regcache (struct infcall_suspend_state *inf_state)
 {
   return inf_state->registers;
@@ -7390,7 +8947,6 @@ struct infcall_control_state
   /* Other fields:  */
   enum stop_stack_kind stop_stack_dummy;
   int stopped_by_random_signal;
-  int stop_after_trap;
 
   /* ID if the selected frame when the inferior function call was made.  */
   struct frame_id selected_frame_id;
@@ -7402,7 +8958,8 @@ struct infcall_control_state
 struct infcall_control_state *
 save_infcall_control_state (void)
 {
-  struct infcall_control_state *inf_status = xmalloc (sizeof (*inf_status));
+  struct infcall_control_state *inf_status =
+    XNEW (struct infcall_control_state);
   struct thread_info *tp = inferior_thread ();
   struct inferior *inf = current_inferior ();
 
@@ -7421,32 +8978,26 @@ save_infcall_control_state (void)
   /* Other fields:  */
   inf_status->stop_stack_dummy = stop_stack_dummy;
   inf_status->stopped_by_random_signal = stopped_by_random_signal;
-  inf_status->stop_after_trap = stop_after_trap;
 
   inf_status->selected_frame_id = get_frame_id (get_selected_frame (NULL));
 
   return inf_status;
 }
 
-static int
-restore_selected_frame (void *args)
+static void
+restore_selected_frame (const frame_id &fid)
 {
-  struct frame_id *fid = (struct frame_id *) args;
-  struct frame_info *frame;
-
-  frame = frame_find_by_id (*fid);
+  frame_info *frame = frame_find_by_id (fid);
 
   /* If inf_status->selected_frame_id is NULL, there was no previously
      selected frame.  */
   if (frame == NULL)
     {
       warning (_("Unable to restore previously selected frame."));
-      return 0;
+      return;
     }
 
   select_frame (frame);
-
-  return (1);
 }
 
 /* Restore inferior session state to INF_STATUS.  */
@@ -7473,20 +9024,25 @@ restore_infcall_control_state (struct infcall_control_state *inf_status)
   /* Other fields:  */
   stop_stack_dummy = inf_status->stop_stack_dummy;
   stopped_by_random_signal = inf_status->stopped_by_random_signal;
-  stop_after_trap = inf_status->stop_after_trap;
 
   if (target_has_stack)
     {
-      /* The point of catch_errors is that if the stack is clobbered,
+      /* The point of the try/catch is that if the stack is clobbered,
          walking the stack might encounter a garbage pointer and
          error() trying to dereference it.  */
-      if (catch_errors
-         (restore_selected_frame, &inf_status->selected_frame_id,
-          "Unable to restore previously selected frame:\n",
-          RETURN_MASK_ERROR) == 0)
-       /* Error in restoring the selected frame.  Select the innermost
-          frame.  */
-       select_frame (get_current_frame ());
+      TRY
+       {
+         restore_selected_frame (inf_status->selected_frame_id);
+       }
+      CATCH (ex, RETURN_MASK_ERROR)
+       {
+         exception_fprintf (gdb_stderr, ex,
+                            "Unable to restore previously selected frame:\n");
+         /* Error in restoring the selected frame.  Select the
+            innermost frame.  */
+         select_frame (get_current_frame ());
+       }
+      END_CATCH
     }
 
   xfree (inf_status);
@@ -7495,7 +9051,7 @@ restore_infcall_control_state (struct infcall_control_state *inf_status)
 static void
 do_restore_infcall_control_state_cleanup (void *sts)
 {
-  restore_infcall_control_state (sts);
+  restore_infcall_control_state ((struct infcall_control_state *) sts);
 }
 
 struct cleanup *
@@ -7522,33 +9078,6 @@ discard_infcall_control_state (struct infcall_control_state *inf_status)
   xfree (inf_status);
 }
 \f
-/* restore_inferior_ptid() will be used by the cleanup machinery
-   to restore the inferior_ptid value saved in a call to
-   save_inferior_ptid().  */
-
-static void
-restore_inferior_ptid (void *arg)
-{
-  ptid_t *saved_ptid_ptr = arg;
-
-  inferior_ptid = *saved_ptid_ptr;
-  xfree (arg);
-}
-
-/* Save the value of inferior_ptid so that it may be restored by a
-   later call to do_cleanups().  Returns the struct cleanup pointer
-   needed for later doing the cleanup.  */
-
-struct cleanup *
-save_inferior_ptid (void)
-{
-  ptid_t *saved_ptid_ptr;
-
-  saved_ptid_ptr = xmalloc (sizeof (ptid_t));
-  *saved_ptid_ptr = inferior_ptid;
-  return make_cleanup (restore_inferior_ptid, saved_ptid_ptr);
-}
-
 /* See infrun.h.  */
 
 void
@@ -7563,7 +9092,7 @@ clear_exit_convenience_vars (void)
    Set exec-direction / show exec-direction commands
    (returns error unless target implements to_set_exec_direction method).  */
 
-int execution_direction = EXEC_FORWARD;
+enum exec_direction_kind execution_direction = EXEC_FORWARD;
 static const char exec_forward[] = "forward";
 static const char exec_reverse[] = "reverse";
 static const char *exec_direction = exec_forward;
@@ -7574,7 +9103,7 @@ static const char *const exec_direction_names[] = {
 };
 
 static void
-set_exec_direction_func (char *args, int from_tty,
+set_exec_direction_func (const char *args, int from_tty,
                         struct cmd_list_element *cmd)
 {
   if (target_can_execute_reverse)
@@ -7626,6 +9155,15 @@ static const struct internalvar_funcs siginfo_funcs =
   NULL
 };
 
+/* Callback for infrun's target events source.  This is marked when a
+   thread has a pending status to process.  */
+
+static void
+infrun_async_inferior_event_handler (gdb_client_data data)
+{
+  inferior_event_handler (INF_REG_EVENT, NULL);
+}
+
 void
 _initialize_infrun (void)
 {
@@ -7633,7 +9171,11 @@ _initialize_infrun (void)
   int numsigs;
   struct cmd_list_element *c;
 
-  add_info ("signals", signals_info, _("\
+  /* Register extra event sources in the event loop.  */
+  infrun_async_inferior_event_token
+    = create_async_event_handler (infrun_async_inferior_event_handler, NULL);
+
+  add_info ("signals", info_signals_command, _("\
 What debugger does when program gets various signals.\n\
 Specify a signal as argument to print info on that signal only."));
   add_info_alias ("handle", "signals", 0);
@@ -7709,15 +9251,11 @@ leave it stopped or free to run as needed."),
                           &showlist);
 
   numsigs = (int) GDB_SIGNAL_LAST;
-  signal_stop = (unsigned char *) xmalloc (sizeof (signal_stop[0]) * numsigs);
-  signal_print = (unsigned char *)
-    xmalloc (sizeof (signal_print[0]) * numsigs);
-  signal_program = (unsigned char *)
-    xmalloc (sizeof (signal_program[0]) * numsigs);
-  signal_catch = (unsigned char *)
-    xmalloc (sizeof (signal_catch[0]) * numsigs);
-  signal_pass = (unsigned char *)
-    xmalloc (sizeof (signal_pass[0]) * numsigs);
+  signal_stop = XNEWVEC (unsigned char, numsigs);
+  signal_print = XNEWVEC (unsigned char, numsigs);
+  signal_program = XNEWVEC (unsigned char, numsigs);
+  signal_catch = XNEWVEC (unsigned char, numsigs);
+  signal_pass = XNEWVEC (unsigned char, numsigs);
   for (i = 0; i < numsigs; i++)
     {
       signal_stop[i] = 1;
@@ -7726,8 +9264,19 @@ leave it stopped or free to run as needed."),
       signal_catch[i] = 0;
     }
 
-  /* Signals caused by debugger's own actions
-     should not be given to the program afterwards.  */
+  /* Signals caused by debugger's own actions should not be given to
+     the program afterwards.
+
+     Do not deliver GDB_SIGNAL_TRAP by default, except when the user
+     explicitly specifies that it should be delivered to the target
+     program.  Typically, that would occur when a user is debugging a
+     target monitor on a simulator: the target monitor sets a
+     breakpoint; the simulator encounters this breakpoint and halts
+     the simulation handing control to GDB; GDB, noting that the stop
+     address doesn't map to any known breakpoint, returns control back
+     to the simulator; the simulator then delivers the hardware
+     equivalent of a GDB_SIGNAL_TRAP to the program being
+     debugged.  */
   signal_program[GDB_SIGNAL_TRAP] = 0;
   signal_program[GDB_SIGNAL_INT] = 0;
 
@@ -7761,6 +9310,8 @@ leave it stopped or free to run as needed."),
   signal_print[GDB_SIGNAL_WAITING] = 0;
   signal_stop[GDB_SIGNAL_CANCEL] = 0;
   signal_print[GDB_SIGNAL_CANCEL] = 0;
+  signal_stop[GDB_SIGNAL_LIBRT] = 0;
+  signal_print[GDB_SIGNAL_LIBRT] = 0;
 
   /* Update cached state.  */
   signal_cache_update (-1);
@@ -7818,10 +9369,13 @@ By default, the debugger will use the same inferior."),
                        scheduler_enums, &scheduler_mode, _("\
 Set mode for locking scheduler during execution."), _("\
 Show mode for locking scheduler during execution."), _("\
-off  == no locking (threads may preempt at any time)\n\
-on   == full locking (no thread except the current thread may run)\n\
-step == scheduler locked during stepping commands (step, next, stepi, nexti).\n\
-       In this mode, other threads may run during other commands."),
+off    == no locking (threads may preempt at any time)\n\
+on     == full locking (no thread except the current thread may run)\n\
+          This applies to both normal execution and replay mode.\n\
+step   == scheduler locked during stepping commands (step, next, stepi, nexti).\n\
+          In this mode, other threads may run during other commands.\n\
+          This applies to both normal execution and replay mode.\n\
+replay == scheduler locked in replay mode and unlocked during normal execution."),
                        set_schedlock_func,     /* traps on target vector */
                        show_scheduler_mode,
                        &setlist, &showlist);
@@ -7895,10 +9449,10 @@ enabled by default on some platforms."),
   inferior_ptid = null_ptid;
   target_last_wait_ptid = minus_one_ptid;
 
-  observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
-  observer_attach_thread_stop_requested (infrun_thread_stop_requested);
-  observer_attach_thread_exit (infrun_thread_thread_exit);
-  observer_attach_inferior_exit (infrun_inferior_exit);
+  gdb::observers::thread_ptid_changed.attach (infrun_thread_ptid_changed);
+  gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested);
+  gdb::observers::thread_exit.attach (infrun_thread_thread_exit);
+  gdb::observers::inferior_exit.attach (infrun_inferior_exit);
 
   /* Explicitly create without lookup, since that tries to create a
      value with a void typed value, and when we get here, gdbarch
This page took 0.108121 seconds and 4 git commands to generate.