gdb: fix python/lib/gdb/__init__.py formatting
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 29bbc209d188c8ee03360f12cf149d6172cd3482..9469b74af397dac9a3d47e362a49107e4e25cd67 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-struct-independent code to start (run) and stop an inferior
    process.
 
-   Copyright (C) 1986-2020 Free Software Foundation, Inc.
+   Copyright (C) 1986-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -153,15 +153,7 @@ static ptid_t previous_inferior_ptid;
 
 static bool detach_fork = true;
 
-bool debug_displaced = false;
-static void
-show_debug_displaced (struct ui_file *file, int from_tty,
-                     struct cmd_list_element *c, const char *value)
-{
-  fprintf_filtered (file, _("Displace stepping debugging is %s.\n"), value);
-}
-
-unsigned int debug_infrun = 0;
+bool debug_infrun = false;
 static void
 show_debug_infrun (struct ui_file *file, int from_tty,
                   struct cmd_list_element *c, const char *value)
@@ -229,7 +221,7 @@ show_non_stop (struct ui_file *file, int from_tty,
    non-stop, in which all GDB operations that might affect the
    target's execution have been disabled.  */
 
-bool observer_mode = false;
+static bool observer_mode = false;
 static bool observer_mode_1 = false;
 
 static void
@@ -434,7 +426,7 @@ follow_fork_inferior (bool follow_child, bool detach_fork)
 Can not resume the parent process over vfork in the foreground while\n\
 holding the child stopped.  Try \"set detach-on-fork\" or \
 \"set schedule-multiple\".\n"));
-      return 1;
+      return true;
     }
 
   if (!follow_child)
@@ -485,7 +477,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          set_current_inferior (child_inf);
          switch_to_no_thread ();
          child_inf->symfile_flags = SYMFILE_NO_READ;
-         push_target (parent_inf->process_target ());
+         child_inf->push_target (parent_inf->process_target ());
          thread_info *child_thr
            = add_thread_silent (child_inf->process_target (), child_ptid);
 
@@ -529,6 +521,9 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
                 breakpoint.  If a "cloned-VM" event was propagated
                 better throughout the core, this wouldn't be
                 required.  */
+             scoped_restore restore_in_initial_library_scan
+               = make_scoped_restore (&child_inf->in_initial_library_scan,
+                                      true);
              solib_create_inferior_hook (0);
            }
        }
@@ -635,7 +630,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
           informing the solib layer about this new process.  */
 
        set_current_inferior (child_inf);
-       push_target (target);
+       child_inf->push_target (target);
       }
 
       thread_info *child_thr = add_thread_silent (target, child_ptid);
@@ -664,13 +659,17 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
             shared libraries, and install the solib event breakpoint.
             If a "cloned-VM" event was propagated better throughout
             the core, this wouldn't be required.  */
+         scoped_restore restore_in_initial_library_scan
+           = make_scoped_restore (&child_inf->in_initial_library_scan, true);
          solib_create_inferior_hook (0);
        }
 
       switch_to_thread (child_thr);
     }
 
-  return target_follow_fork (follow_child, detach_fork);
+  target_follow_fork (follow_child, detach_fork);
+
+  return false;
 }
 
 /* Tell the target to follow the fork we're stopped at.  Returns true
@@ -1070,7 +1069,6 @@ show_follow_exec_mode_string (struct ui_file *file, int from_tty,
 static void
 follow_exec (ptid_t ptid, const char *exec_file_target)
 {
-  struct inferior *inf = current_inferior ();
   int pid = ptid.pid ();
   ptid_t process_ptid;
 
@@ -1173,6 +1171,8 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
      previous incarnation of this process.  */
   no_shared_libraries (NULL, 0);
 
+  struct inferior *inf = current_inferior ();
+
   if (follow_exec_mode_string == follow_exec_mode_new)
     {
       /* The user wants to keep the old inferior and program spaces
@@ -1182,18 +1182,16 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
         inferior's pid.  Having two inferiors with the same pid would confuse
         find_inferior_p(t)id.  Transfer the terminal state and info from the
          old to the new inferior.  */
-      inf = add_inferior_with_spaces ();
-      swap_terminal_info (inf, current_inferior ());
-      exit_inferior_silent (current_inferior ());
+      inferior *new_inferior = add_inferior_with_spaces ();
 
-      inf->pid = pid;
-      target_follow_exec (inf, exec_file_target);
+      swap_terminal_info (new_inferior, inf);
+      exit_inferior_silent (inf);
 
-      inferior *org_inferior = current_inferior ();
-      switch_to_inferior_no_thread (inf);
-      push_target (org_inferior->process_target ());
-      thread_info *thr = add_thread (inf->process_target (), ptid);
-      switch_to_thread (thr);
+      new_inferior->pid = pid;
+      target_follow_exec (new_inferior, ptid, exec_file_target);
+
+      /* We continue with the new inferior.  */
+      inf = new_inferior;
     }
   else
     {
@@ -1204,8 +1202,10 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
         around (its description is later cleared/refetched on
         restart).  */
       target_clear_description ();
+      target_follow_exec (inf, ptid, exec_file_target);
     }
 
+  gdb_assert (current_inferior () == inf);
   gdb_assert (current_program_space == inf->pspace);
 
   /* Attempt to open the exec file.  SYMFILE_DEFER_BP_RESET is used
@@ -1269,15 +1269,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.  */
-  const address_space *aspace;
-  CORE_ADDR address;
+  const address_space *aspace = nullptr;
+  CORE_ADDR address = 0;
 
   /* The instruction being stepped over triggers a nonsteppable
      watchpoint.  If true, we'll skip inserting watchpoints.  */
-  int nonsteppable_watchpoint_p;
+  int nonsteppable_watchpoint_p = 0;
 
   /* The thread's global number.  */
-  int thread;
+  int thread = -1;
 };
 
 /* The step-over info of the location that is being stepped over.
@@ -1460,26 +1460,6 @@ step_over_info_valid_p (void)
    displaced step operation on it.  See displaced_step_prepare and
    displaced_step_finish for details.  */
 
-/* Default destructor for displaced_step_copy_insn_closure.  */
-
-displaced_step_copy_insn_closure::~displaced_step_copy_insn_closure ()
-  = default;
-
-/* Returns true if any inferior has a thread doing a displaced
-   step.  */
-
-static bool
-displaced_step_in_progress_any_inferior ()
-{
-  for (inferior *i : all_inferiors ())
-    {
-      if (i->displaced_step_state.step_thread != nullptr)
-       return true;
-    }
-
-  return false;
-}
-
 /* Return true if THREAD is doing a displaced step.  */
 
 static bool
@@ -1487,7 +1467,7 @@ displaced_step_in_progress_thread (thread_info *thread)
 {
   gdb_assert (thread != NULL);
 
-  return thread->inf->displaced_step_state.step_thread == thread;
+  return thread->displaced_step_state.in_progress ();
 }
 
 /* Return true if INF has a thread doing a displaced step.  */
@@ -1495,25 +1475,21 @@ displaced_step_in_progress_thread (thread_info *thread)
 static bool
 displaced_step_in_progress (inferior *inf)
 {
-  return inf->displaced_step_state.step_thread != nullptr;
+  return inf->displaced_step_state.in_progress_count > 0;
 }
 
-/* If inferior is in displaced stepping, and ADDR equals to starting address
-   of copy area, return corresponding displaced_step_copy_insn_closure.
-   Otherwise, return NULL.  */
+/* Return true if any thread is doing a displaced step.  */
 
-displaced_step_copy_insn_closure *
-get_displaced_step_copy_insn_closure_by_addr (CORE_ADDR addr)
+static bool
+displaced_step_in_progress_any_thread ()
 {
-  displaced_step_inferior_state &displaced
-    = current_inferior ()->displaced_step_state;
-
-  /* If checking the mode of displaced instruction in copy area.  */
-  if (displaced.step_thread != nullptr
-      && displaced.step_copy == addr)
-    return displaced.step_closure.get ();
+  for (inferior *inf : all_non_exited_inferiors ())
+    {
+      if (displaced_step_in_progress (inf))
+       return true;
+    }
 
-  return NULL;
+  return false;
 }
 
 static void
@@ -1525,12 +1501,15 @@ infrun_inferior_exit (struct inferior *inf)
 static void
 infrun_inferior_execd (inferior *inf)
 {
-  /* If a thread was doing a displaced step in this inferior at the moment of
-     the exec, it no longer exists.  Even if the exec'ing thread was the one
+  /* If some threads where was doing a displaced step in this inferior at the
+     moment of the exec, they no longer exist.  Even if the exec'ing thread
      doing a displaced step, we don't want to to any fixup nor restore displaced
      stepping buffer bytes.  */
   inf->displaced_step_state.reset ();
 
+  for (thread_info *thread : inf->threads ())
+    thread->displaced_step_state.reset ();
+
   /* Since an in-line step is done with everything else stopped, if there was
      one in progress at the time of the exec, it must have been the exec'ing
      thread.  */
@@ -1568,9 +1547,9 @@ show_can_use_displaced_stepping (struct ui_file *file, int from_tty,
 static bool
 gdbarch_supports_displaced_stepping (gdbarch *arch)
 {
-  /* Only check for the presence of step_copy_insn.  Other required methods
-     are checked by the gdbarch validation.  */
-  return gdbarch_displaced_step_copy_insn_p (arch);
+  /* Only check for the presence of `prepare`.  The gdbarch verification ensures
+     that if `prepare` is provided, so is `finish`.  */
+  return gdbarch_displaced_step_prepare_p (arch);
 }
 
 /* Return non-zero if displaced stepping can/should be used to step
@@ -1608,10 +1587,10 @@ use_displaced_stepping (thread_info *tp)
   return true;
 }
 
-/* Simple function wrapper around displaced_step_inferior_state::reset.  */
+/* Simple function wrapper around displaced_step_thread_state::reset.  */
 
 static void
-displaced_step_reset (displaced_step_inferior_state *displaced)
+displaced_step_reset (displaced_step_thread_state *displaced)
 {
   displaced->reset ();
 }
@@ -1662,10 +1641,8 @@ displaced_step_prepare_throw (thread_info *tp)
 {
   regcache *regcache = get_thread_regcache (tp);
   struct gdbarch *gdbarch = regcache->arch ();
-  const address_space *aspace = regcache->aspace ();
-  CORE_ADDR original, copy;
-  ULONGEST len;
-  int status;
+  displaced_step_thread_state &disp_step_thread_state
+    = tp->displaced_step_state;
 
   /* We should never reach this function if the architecture does not
      support displaced stepping.  */
@@ -1680,15 +1657,14 @@ displaced_step_prepare_throw (thread_info *tp)
      jump/branch).  */
   tp->control.may_range_step = 0;
 
-  /* We have to displaced step one thread at a time, as we only have
-     access to a single scratch space per inferior.  */
+  /* We are about to start a displaced step for this thread.  If one is already
+     in progress, something's wrong.  */
+  gdb_assert (!disp_step_thread_state.in_progress ());
 
-  displaced_step_inferior_state *displaced = &tp->inf->displaced_step_state;
-
-  if (displaced->step_thread != nullptr)
+  if (tp->inf->displaced_step_state.unavailable)
     {
-      /* Already waiting for a displaced step to finish.  Defer this
-        request and place in queue.  */
+      /* The gdbarch tells us it's not worth asking to try a prepare because
+        it is likely that it will return unavailable, so don't bother asking.  */
 
       displaced_debug_printf ("deferring step of %s",
                              target_pid_to_str (tp->ptid).c_str ());
@@ -1696,79 +1672,54 @@ displaced_step_prepare_throw (thread_info *tp)
       global_thread_step_over_chain_enqueue (tp);
       return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
     }
-  else
-    displaced_debug_printf ("stepping %s now",
-                           target_pid_to_str (tp->ptid).c_str ());
 
-  displaced_step_reset (displaced);
+  displaced_debug_printf ("displaced-stepping %s now",
+                         target_pid_to_str (tp->ptid).c_str ());
 
   scoped_restore_current_thread restore_thread;
 
   switch_to_thread (tp);
 
-  original = regcache_read_pc (regcache);
+  CORE_ADDR original_pc = regcache_read_pc (regcache);
+  CORE_ADDR displaced_pc;
 
-  copy = gdbarch_displaced_step_location (gdbarch);
-  len = gdbarch_max_insn_length (gdbarch);
+  displaced_step_prepare_status status
+    = gdbarch_displaced_step_prepare (gdbarch, tp, displaced_pc);
 
-  if (breakpoint_in_range_p (aspace, copy, len))
+  if (status == DISPLACED_STEP_PREPARE_STATUS_CANT)
     {
-      /* 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.  */
-      displaced_debug_printf ("breakpoint set in scratch pad.  "
-                             "Stepping over breakpoint in-line instead.");
+      displaced_debug_printf ("failed to prepare (%s)",
+                             target_pid_to_str (tp->ptid).c_str ());
 
       return DISPLACED_STEP_PREPARE_STATUS_CANT;
     }
+  else if (status == DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE)
+    {
+      /* Not enough displaced stepping resources available, defer this
+        request by placing it the queue.  */
 
-  /* Save the original contents of the copy area.  */
-  displaced->step_saved_copy.resize (len);
-  status = target_read_memory (copy, displaced->step_saved_copy.data (), len);
-  if (status != 0)
-    throw_error (MEMORY_ERROR,
-                _("Error accessing memory address %s (%s) for "
-                  "displaced-stepping scratch space."),
-                paddress (gdbarch, copy), safe_strerror (status));
+      displaced_debug_printf ("not enough resources available, "
+                             "deferring step of %s",
+                             target_pid_to_str (tp->ptid).c_str ());
 
-  displaced_debug_printf ("saved %s: %s",
-                         paddress (gdbarch, copy),
-                         displaced_step_dump_bytes
-                           (displaced->step_saved_copy.data (), len).c_str ());
+      global_thread_step_over_chain_enqueue (tp);
 
-  displaced->step_closure
-    = gdbarch_displaced_step_copy_insn (gdbarch, original, copy, regcache);
-  if (displaced->step_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.  */
-      return DISPLACED_STEP_PREPARE_STATUS_CANT;
+      return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
     }
 
+  gdb_assert (status == DISPLACED_STEP_PREPARE_STATUS_OK);
+
   /* Save the information we need to fix things up if the step
      succeeds.  */
-  displaced->step_thread = tp;
-  displaced->step_gdbarch = gdbarch;
-  displaced->step_original = original;
-  displaced->step_copy = copy;
-
-  {
-    displaced_step_reset_cleanup cleanup (displaced);
+  disp_step_thread_state.set (gdbarch);
 
-    /* Resume execution at the copy.  */
-    regcache_write_pc (regcache, copy);
-
-    cleanup.release ();
-  }
+  tp->inf->displaced_step_state.in_progress_count++;
 
-  displaced_debug_printf ("displaced pc to %s", paddress (gdbarch, copy));
+  displaced_debug_printf ("prepared successfully thread=%s, "
+                         "original_pc=%s, displaced_pc=%s",
+                         target_pid_to_str (tp->ptid).c_str (),
+                         paddress (gdbarch, original_pc),
+                         paddress (gdbarch, displaced_pc));
 
   return DISPLACED_STEP_PREPARE_STATUS_OK;
 }
@@ -1810,33 +1761,6 @@ displaced_step_prepare (thread_info *thread)
   return status;
 }
 
-static void
-write_memory_ptid (ptid_t ptid, CORE_ADDR memaddr,
-                  const gdb_byte *myaddr, int len)
-{
-  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
-
-  inferior_ptid = ptid;
-  write_memory (memaddr, myaddr, len);
-}
-
-/* Restore the contents of the copy area for thread PTID.  */
-
-static void
-displaced_step_restore (struct displaced_step_inferior_state *displaced,
-                       ptid_t ptid)
-{
-  ULONGEST len = gdbarch_max_insn_length (displaced->step_gdbarch);
-
-  write_memory_ptid (ptid, displaced->step_copy,
-                    displaced->step_saved_copy.data (), len);
-
-  displaced_debug_printf ("restored %s %s",
-                         target_pid_to_str (ptid).c_str (),
-                         paddress (displaced->step_gdbarch,
-                                   displaced->step_copy));
-}
-
 /* 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
@@ -1849,50 +1773,27 @@ displaced_step_restore (struct displaced_step_inferior_state *displaced,
 static displaced_step_finish_status
 displaced_step_finish (thread_info *event_thread, enum gdb_signal signal)
 {
-  displaced_step_inferior_state *displaced
-    = &event_thread->inf->displaced_step_state;
+  displaced_step_thread_state *displaced = &event_thread->displaced_step_state;
 
-  /* Was this event for the thread we displaced?  */
-  if (displaced->step_thread != event_thread)
+  /* Was this thread performing a displaced step?  */
+  if (!displaced->in_progress ())
     return DISPLACED_STEP_FINISH_STATUS_OK;
 
+  gdb_assert (event_thread->inf->displaced_step_state.in_progress_count > 0);
+  event_thread->inf->displaced_step_state.in_progress_count--;
+
   /* Fixup may need to read memory/registers.  Switch to the thread
      that we're fixing up.  Also, target_stopped_by_watchpoint checks
      the current thread, and displaced_step_restore performs ptid-dependent
-     memory accesses using current_inferior() and current_top_target().  */
+     memory accesses using current_inferior().  */
   switch_to_thread (event_thread);
 
   displaced_step_reset_cleanup cleanup (displaced);
 
-  displaced_step_restore (displaced, displaced->step_thread->ptid);
-
-  /* Did the instruction complete successfully?  */
-  if (signal == GDB_SIGNAL_TRAP
-      && !(target_stopped_by_watchpoint ()
-          && (gdbarch_have_nonsteppable_watchpoint (displaced->step_gdbarch)
-              || target_have_steppable_watchpoint ())))
-    {
-      /* Fix up the resulting state.  */
-      gdbarch_displaced_step_fixup (displaced->step_gdbarch,
-                                   displaced->step_closure.get (),
-                                   displaced->step_original,
-                                   displaced->step_copy,
-                                   get_thread_regcache (displaced->step_thread));
-
-      return DISPLACED_STEP_FINISH_STATUS_OK;
-    }
-  else
-    {
-      /* Since the instruction didn't complete, all we can do is
-        relocate the PC.  */
-      struct regcache *regcache = get_thread_regcache (event_thread);
-      CORE_ADDR pc = regcache_read_pc (regcache);
-
-      pc = displaced->step_original + (pc - displaced->step_copy);
-      regcache_write_pc (regcache, pc);
-
-      return DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED;
-    }
+  /* Do the fixup, and release the resources acquired to do the displaced
+     step. */
+  return gdbarch_displaced_step_finish (displaced->get_original_gdbarch (),
+                                       event_thread, signal);
 }
 
 /* Data to be passed around while handling an event.  This data is
@@ -1940,14 +1841,44 @@ static step_over_what thread_still_needs_step_over (struct thread_info *tp);
 static bool
 start_step_over (void)
 {
-  struct thread_info *tp, *next;
+  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
+
+  thread_info *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 false;
 
-  for (tp = global_thread_step_over_chain_head; tp != NULL; tp = next)
+  /* Steal the global thread step over chain.  As we try to initiate displaced
+     steps, threads will be enqueued in the global chain if no buffers are
+     available.  If we iterated on the global chain directly, we might iterate
+     indefinitely.  */
+  thread_info *threads_to_step = global_thread_step_over_chain_head;
+  global_thread_step_over_chain_head = NULL;
+
+  infrun_debug_printf ("stealing global queue of threads to step, length = %d",
+                      thread_step_over_chain_length (threads_to_step));
+
+  bool started = false;
+
+  /* On scope exit (whatever the reason, return or exception), if there are
+     threads left in the THREADS_TO_STEP chain, put back these threads in the
+     global list.  */
+  SCOPE_EXIT
+    {
+      if (threads_to_step == nullptr)
+       infrun_debug_printf ("step-over queue now empty");
+      else
+       {
+         infrun_debug_printf ("putting back %d threads to step in global queue",
+                              thread_step_over_chain_length (threads_to_step));
+
+         global_thread_step_over_chain_enqueue_chain (threads_to_step);
+       }
+    };
+
+  for (thread_info *tp = threads_to_step; tp != NULL; tp = next)
     {
       struct execution_control_state ecss;
       struct execution_control_state *ecs = &ecss;
@@ -1956,12 +1887,23 @@ start_step_over (void)
 
       gdb_assert (!tp->stop_requested);
 
-      next = global_thread_step_over_chain_next (tp);
+      next = thread_step_over_chain_next (threads_to_step, tp);
 
-      /* If this inferior already has a displaced step in process,
-        don't start a new one.  */
-      if (displaced_step_in_progress (tp->inf))
-       continue;
+      if (tp->inf->displaced_step_state.unavailable)
+       {
+         /* The arch told us to not even try preparing another displaced step
+            for this inferior.  Just leave the thread in THREADS_TO_STEP, it
+            will get moved to the global chain on scope exit.  */
+         continue;
+       }
+
+      /* Remove thread from the THREADS_TO_STEP chain.  If anything goes wrong
+        while we try to prepare the displaced step, we don't add it back to
+        the global step over chain.  This is to avoid a thread staying in the
+        step over chain indefinitely if something goes wrong when resuming it
+        If the error is intermittent and it still needs a step over, it will
+        get enqueued again when we try to resume it normally.  */
+      thread_step_over_chain_remove (&threads_to_step, tp);
 
       step_what = thread_still_needs_step_over (tp);
       must_be_in_line = ((step_what & STEP_OVER_WATCHPOINT)
@@ -1971,13 +1913,11 @@ start_step_over (void)
       /* 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 false;
-
-      global_thread_step_over_chain_remove (tp);
-
-      if (global_thread_step_over_chain_head == NULL)
-       infrun_debug_printf ("step-over queue now empty");
+      if (must_be_in_line && displaced_step_in_progress_any_thread ())
+       {
+         global_thread_step_over_chain_enqueue (tp);
+         continue;
+       }
 
       if (tp->control.trap_expected
          || tp->resumed
@@ -2011,13 +1951,27 @@ start_step_over (void)
       if (!ecs->wait_some_more)
        error (_("Command aborted."));
 
-      gdb_assert (tp->resumed);
+      /* If the thread's step over could not be initiated because no buffers
+        were available, it was re-added to the global step over chain.  */
+      if (tp->resumed)
+       {
+         infrun_debug_printf ("[%s] was resumed.",
+                              target_pid_to_str (tp->ptid).c_str ());
+         gdb_assert (!thread_is_in_step_over_chain (tp));
+       }
+      else
+       {
+         infrun_debug_printf ("[%s] was NOT resumed.",
+                              target_pid_to_str (tp->ptid).c_str ());
+         gdb_assert (thread_is_in_step_over_chain (tp));
+       }
 
       /* 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 true;
+         started = true;
+         break;
        }
 
       if (!target_is_non_stop_p ())
@@ -2030,7 +1984,8 @@ start_step_over (void)
          /* With remote targets (at least), in all-stop, we can't
             issue any further remote commands until the program stops
             again.  */
-         return true;
+         started = true;
+         break;
        }
 
       /* Either the thread no longer needed a step-over, or a new
@@ -2039,7 +1994,7 @@ start_step_over (void)
         displaced step on a thread of other process. */
     }
 
-  return false;
+  return started;
 }
 
 /* Update global variables holding ptids to hold NEW_PTID if they were
@@ -2083,7 +2038,8 @@ set_schedlock_func (const char *args, int from_tty, struct cmd_list_element *c)
   if (!target_can_lock_scheduler ())
     {
       scheduler_mode = schedlock_off;
-      error (_("Target '%s' cannot support this command."), target_shortname);
+      error (_("Target '%s' cannot support this command."),
+            target_shortname ());
     }
 }
 
@@ -2225,8 +2181,6 @@ do_target_resume (ptid_t resume_ptid, bool step, enum gdb_signal sig)
 
   target_resume (resume_ptid, step, sig);
 
-  target_commit_resume ();
-
   if (target_can_async_p ())
     target_async (1);
 }
@@ -2813,28 +2767,220 @@ schedlock_applies (struct thread_info *tp)
                                            execution_direction)));
 }
 
-/* Calls target_commit_resume on all targets.  */
+/* Set process_stratum_target::COMMIT_RESUMED_STATE in all target
+   stacks that have threads executing and don't have threads with
+   pending events.  */
 
 static void
-commit_resume_all_targets ()
+maybe_set_commit_resumed_all_targets ()
 {
   scoped_restore_current_thread restore_thread;
 
-  /* Map between process_target and a representative inferior.  This
-     is to avoid committing a resume in the same target more than
-     once.  Resumptions must be idempotent, so this is an
-     optimization.  */
-  std::unordered_map<process_stratum_target *, inferior *> conn_inf;
-
   for (inferior *inf : all_non_exited_inferiors ())
-    if (inf->has_execution ())
-      conn_inf[inf->process_target ()] = inf;
+    {
+      process_stratum_target *proc_target = inf->process_target ();
+
+      if (proc_target->commit_resumed_state)
+       {
+         /* We already set this in a previous iteration, via another
+            inferior sharing the process_stratum target.  */
+         continue;
+       }
+
+      /* If the target has no resumed threads, it would be useless to
+        ask it to commit the resumed threads.  */
+      if (!proc_target->threads_executing)
+       {
+         infrun_debug_printf ("not requesting commit-resumed for target "
+                              "%s, no resumed threads",
+                              proc_target->shortname ());
+         continue;
+       }
+
+      /* As an optimization, if a thread from this target has some
+        status to report, handle it before requiring the target to
+        commit its resumed threads: handling the status might lead to
+        resuming more threads.  */
+      bool has_thread_with_pending_status = false;
+      for (thread_info *thread : all_non_exited_threads (proc_target))
+       if (thread->resumed && thread->suspend.waitstatus_pending_p)
+         {
+           has_thread_with_pending_status = true;
+           break;
+         }
+
+      if (has_thread_with_pending_status)
+       {
+         infrun_debug_printf ("not requesting commit-resumed for target %s, a"
+                              " thread has a pending waitstatus",
+                              proc_target->shortname ());
+         continue;
+       }
+
+      switch_to_inferior_no_thread (inf);
+
+      if (target_has_pending_events ())
+       {
+         infrun_debug_printf ("not requesting commit-resumed for target %s, "
+                              "target has pending events",
+                              proc_target->shortname ());
+         continue;
+       }
+
+      infrun_debug_printf ("enabling commit-resumed for target %s",
+                          proc_target->shortname ());
+
+      proc_target->commit_resumed_state = true;
+    }
+}
 
-  for (const auto &ci : conn_inf)
+/* See infrun.h.  */
+
+void
+maybe_call_commit_resumed_all_targets ()
+{
+  scoped_restore_current_thread restore_thread;
+
+  for (inferior *inf : all_non_exited_inferiors ())
     {
-      inferior *inf = ci.second;
+      process_stratum_target *proc_target = inf->process_target ();
+
+      if (!proc_target->commit_resumed_state)
+       continue;
+
       switch_to_inferior_no_thread (inf);
-      target_commit_resume ();
+
+      infrun_debug_printf ("calling commit_resumed for target %s",
+                          proc_target->shortname());
+
+      target_commit_resumed ();
+    }
+}
+
+/* To track nesting of scoped_disable_commit_resumed objects, ensuring
+   that only the outermost one attempts to re-enable
+   commit-resumed.  */
+static bool enable_commit_resumed = true;
+
+/* See infrun.h.  */
+
+scoped_disable_commit_resumed::scoped_disable_commit_resumed
+  (const char *reason)
+  : m_reason (reason),
+    m_prev_enable_commit_resumed (enable_commit_resumed)
+{
+  infrun_debug_printf ("reason=%s", m_reason);
+
+  enable_commit_resumed = false;
+
+  for (inferior *inf : all_non_exited_inferiors ())
+    {
+      process_stratum_target *proc_target = inf->process_target ();
+
+      if (m_prev_enable_commit_resumed)
+       {
+         /* This is the outermost instance: force all
+            COMMIT_RESUMED_STATE to false.  */
+         proc_target->commit_resumed_state = false;
+       }
+      else
+       {
+         /* This is not the outermost instance, we expect
+            COMMIT_RESUMED_STATE to have been cleared by the
+            outermost instance.  */
+         gdb_assert (!proc_target->commit_resumed_state);
+       }
+    }
+}
+
+/* See infrun.h.  */
+
+void
+scoped_disable_commit_resumed::reset ()
+{
+  if (m_reset)
+    return;
+  m_reset = true;
+
+  infrun_debug_printf ("reason=%s", m_reason);
+
+  gdb_assert (!enable_commit_resumed);
+
+  enable_commit_resumed = m_prev_enable_commit_resumed;
+
+  if (m_prev_enable_commit_resumed)
+    {
+      /* This is the outermost instance, re-enable
+         COMMIT_RESUMED_STATE on the targets where it's possible.  */
+      maybe_set_commit_resumed_all_targets ();
+    }
+  else
+    {
+      /* This is not the outermost instance, we expect
+        COMMIT_RESUMED_STATE to still be false.  */
+      for (inferior *inf : all_non_exited_inferiors ())
+       {
+         process_stratum_target *proc_target = inf->process_target ();
+         gdb_assert (!proc_target->commit_resumed_state);
+       }
+    }
+}
+
+/* See infrun.h.  */
+
+scoped_disable_commit_resumed::~scoped_disable_commit_resumed ()
+{
+  reset ();
+}
+
+/* See infrun.h.  */
+
+void
+scoped_disable_commit_resumed::reset_and_commit ()
+{
+  reset ();
+  maybe_call_commit_resumed_all_targets ();
+}
+
+/* See infrun.h.  */
+
+scoped_enable_commit_resumed::scoped_enable_commit_resumed
+  (const char *reason)
+  : m_reason (reason),
+    m_prev_enable_commit_resumed (enable_commit_resumed)
+{
+  infrun_debug_printf ("reason=%s", m_reason);
+
+  if (!enable_commit_resumed)
+    {
+      enable_commit_resumed = true;
+
+      /* Re-enable COMMIT_RESUMED_STATE on the targets where it's
+        possible.  */
+      maybe_set_commit_resumed_all_targets ();
+
+      maybe_call_commit_resumed_all_targets ();
+    }
+}
+
+/* See infrun.h.  */
+
+scoped_enable_commit_resumed::~scoped_enable_commit_resumed ()
+{
+  infrun_debug_printf ("reason=%s", m_reason);
+
+  gdb_assert (enable_commit_resumed);
+
+  enable_commit_resumed = m_prev_enable_commit_resumed;
+
+  if (!enable_commit_resumed)
+    {
+      /* Force all COMMIT_RESUMED_STATE back to false.  */
+      for (inferior *inf : all_non_exited_inferiors ())
+       {
+         process_stratum_target *proc_target = inf->process_target ();
+         proc_target->commit_resumed_state = false;
+       }
     }
 }
 
@@ -2862,7 +3008,7 @@ check_multi_target_resumption (process_stratum_target *resume_target)
         always-non-stop mode.  */
       inferior *first_not_non_stop = nullptr;
 
-      for (inferior *inf : all_non_exited_inferiors (resume_target))
+      for (inferior *inf : all_non_exited_inferiors ())
        {
          switch_to_inferior_no_thread (inf);
 
@@ -2904,6 +3050,8 @@ check_multi_target_resumption (process_stratum_target *resume_target)
 void
 proceed (CORE_ADDR addr, enum gdb_signal siggnal)
 {
+  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
+
   struct regcache *regcache;
   struct gdbarch *gdbarch;
   CORE_ADDR pc;
@@ -3056,7 +3204,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   cur_thr->prev_pc = regcache_read_pc_protected (regcache);
 
   {
-    scoped_restore save_defer_tc = make_scoped_defer_target_commit_resume ();
+    scoped_disable_commit_resumed disable_commit_resumed ("proceeding");
 
     started = start_step_over ();
 
@@ -3073,6 +3221,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
       }
     else if (!non_stop && target_is_non_stop_p ())
       {
+       INFRUN_SCOPED_DEBUG_START_END
+         ("resuming threads, all-stop-on-top-of-non-stop");
+
        /* In all-stop, but the target is always in non-stop mode.
           Start all other threads that are implicitly resumed too.  */
        for (thread_info *tp : all_non_exited_threads (resume_target,
@@ -3121,9 +3272,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
        if (!ecs->wait_some_more)
          error (_("Command aborted."));
       }
-  }
 
-  commit_resume_all_targets ();
+    disable_commit_resumed.reset_and_commit ();
+  }
 
   finish_state.release ();
 
@@ -3330,31 +3481,17 @@ void
 print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
                           const struct target_waitstatus *ws)
 {
-  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.  */
-
-  stb.printf ("[infrun] target_wait (%d.%ld.%ld",
-             waiton_ptid.pid (),
-             waiton_ptid.lwp (),
-             waiton_ptid.tid ());
-  if (waiton_ptid.pid () != -1)
-    stb.printf (" [%s]", target_pid_to_str (waiton_ptid).c_str ());
-  stb.printf (", status) =\n");
-  stb.printf ("[infrun]   %d.%ld.%ld [%s],\n",
-             result_ptid.pid (),
-             result_ptid.lwp (),
-             result_ptid.tid (),
-             target_pid_to_str (result_ptid).c_str ());
-  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", stb.c_str ());
+  infrun_debug_printf ("target_wait (%d.%ld.%ld [%s], status) =",
+                      waiton_ptid.pid (),
+                      waiton_ptid.lwp (),
+                      waiton_ptid.tid (),
+                      target_pid_to_str (waiton_ptid).c_str ());
+  infrun_debug_printf ("  %d.%ld.%ld [%s],",
+                      result_ptid.pid (),
+                      result_ptid.lwp (),
+                      result_ptid.tid (),
+                      target_pid_to_str (result_ptid).c_str ());
+  infrun_debug_printf ("  %s", target_waitstatus_to_string (ws).c_str ());
 }
 
 /* Select a thread at random, out of those which are resumed and have
@@ -3533,8 +3670,7 @@ do_target_wait_1 (inferior *inf, ptid_t ptid,
    more events.  Polls for events from all inferiors/targets.  */
 
 static bool
-do_target_wait (ptid_t wait_ptid, execution_control_state *ecs,
-               target_wait_flags options)
+do_target_wait (execution_control_state *ecs, target_wait_flags options)
 {
   int num_inferiors = 0;
   int random_selector;
@@ -3544,10 +3680,9 @@ do_target_wait (ptid_t wait_ptid, execution_control_state *ecs,
      polling the rest of the inferior list starting from that one in a
      circular fashion until the whole list is polled once.  */
 
-  auto inferior_matches = [&wait_ptid] (inferior *inf)
+  auto inferior_matches = [] (inferior *inf)
     {
-      return (inf->process_target () != NULL
-             && ptid_t (inf->pid).matches (wait_ptid));
+      return inf->process_target () != nullptr;
     };
 
   /* First see how many matching inferiors we have.  */
@@ -3586,7 +3721,7 @@ do_target_wait (ptid_t wait_ptid, execution_control_state *ecs,
 
   auto do_wait = [&] (inferior *inf)
   {
-    ecs->ptid = do_target_wait_1 (inf, wait_ptid, &ecs->ws, options);
+    ecs->ptid = do_target_wait_1 (inf, minus_one_ptid, &ecs->ws, options);
     ecs->target = inf->process_target ();
     return (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
   };
@@ -3613,6 +3748,23 @@ do_target_wait (ptid_t wait_ptid, execution_control_state *ecs,
   return false;
 }
 
+/* An event reported by wait_one.  */
+
+struct wait_one_event
+{
+  /* The target the event came out of.  */
+  process_stratum_target *target;
+
+  /* The PTID the event was for.  */
+  ptid_t ptid;
+
+  /* The waitstatus.  */
+  target_waitstatus ws;
+};
+
+static bool handle_one (const wait_one_event &event);
+static void restart_threads (struct thread_info *event_thread);
+
 /* Prepare and stabilize the inferior for detaching it.  E.g.,
    detaching while a thread is displaced stepping is a recipe for
    crashing it, as nothing would readjust the PC out of the scratch
@@ -3623,61 +3775,90 @@ prepare_for_detach (void)
 {
   struct inferior *inf = current_inferior ();
   ptid_t pid_ptid = ptid_t (inf->pid);
-
-  displaced_step_inferior_state *displaced = &inf->displaced_step_state;
-
-  /* Is any thread of this process displaced stepping?  If not,
-     there's nothing else to do.  */
-  if (displaced->step_thread == nullptr)
-    return;
-
-  infrun_debug_printf ("displaced-stepping in-process while detaching");
+  scoped_restore_current_thread restore_thread;
 
   scoped_restore restore_detaching = make_scoped_restore (&inf->detaching, true);
 
-  while (displaced->step_thread != nullptr)
+  /* Remove all threads of INF from the global step-over chain.  We
+     want to stop any ongoing step-over, not start any new one.  */
+  thread_info *next;
+  for (thread_info *tp = global_thread_step_over_chain_head;
+       tp != nullptr;
+       tp = next)
     {
-      struct execution_control_state ecss;
-      struct execution_control_state *ecs;
-
-      ecs = &ecss;
-      memset (ecs, 0, sizeof (*ecs));
+      next = global_thread_step_over_chain_next (tp);
+      if (tp->inf == inf)
+       global_thread_step_over_chain_remove (tp);
+    }
 
-      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 ();
+  /* If we were already in the middle of an inline step-over, and the
+     thread stepping belongs to the inferior we're detaching, we need
+     to restart the threads of other inferiors.  */
+  if (step_over_info.thread != -1)
+    {
+      infrun_debug_printf ("inline step-over in-process while detaching");
 
-      do_target_wait (pid_ptid, ecs, 0);
+      thread_info *thr = find_thread_global_id (step_over_info.thread);
+      if (thr->inf == inf)
+       {
+         /* Since we removed threads of INF from the step-over chain,
+            we know this won't start a step-over for INF.  */
+         clear_step_over_info ();
 
-      if (debug_infrun)
-       print_target_wait_results (pid_ptid, ecs->ptid, &ecs->ws);
+         if (target_is_non_stop_p ())
+           {
+             /* Start a new step-over in another thread if there's
+                one that needs it.  */
+             start_step_over ();
+
+             /* Restart all other threads (except the
+                previously-stepping thread, since that one is still
+                running).  */
+             if (!step_over_info_valid_p ())
+               restart_threads (thr);
+           }
+       }
+    }
 
-      /* If an error happens while handling the event, propagate GDB's
-        knowledge of the executing state to the frontend/user running
-        state.  */
-      scoped_finish_thread_state finish_state (inf->process_target (),
-                                              minus_one_ptid);
+  if (displaced_step_in_progress (inf))
+    {
+      infrun_debug_printf ("displaced-stepping in-process while detaching");
 
-      /* Now figure out what to do with the result of the result.  */
-      handle_inferior_event (ecs);
+      /* Stop threads currently displaced stepping, aborting it.  */
 
-      /* No error, don't finish the state yet.  */
-      finish_state.release ();
+      for (thread_info *thr : inf->non_exited_threads ())
+       {
+         if (thr->displaced_step_state.in_progress ())
+           {
+             if (thr->executing)
+               {
+                 if (!thr->stop_requested)
+                   {
+                     target_stop (thr->ptid);
+                     thr->stop_requested = true;
+                   }
+               }
+             else
+               thr->resumed = false;
+           }
+       }
 
-      /* 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)
+      while (displaced_step_in_progress (inf))
        {
-         restore_detaching.release ();
-         error (_("Program exited while detaching"));
+         wait_one_event event;
+
+         event.target = inf->process_target ();
+         event.ptid = do_target_wait_1 (inf, pid_ptid, &event.ws, 0);
+
+         if (debug_infrun)
+           print_target_wait_results (pid_ptid, event.ptid, &event.ws);
+
+         handle_one (event);
        }
-    }
 
-  restore_detaching.release ();
+      /* It's OK to leave some of the threads of INF stopped, since
+        they'll be detached shortly.  */
+    }
 }
 
 /* Wait for control to return from inferior to debugger.
@@ -3842,6 +4023,8 @@ all_uis_on_sync_execution_starting (void)
 void
 fetch_inferior_event ()
 {
+  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
+
   struct execution_control_state ecss;
   struct execution_control_state *ecs = &ecss;
   int cmd_done = 0;
@@ -3891,8 +4074,16 @@ fetch_inferior_event ()
       = make_scoped_restore (&execution_direction,
                             target_execution_direction ());
 
-    if (!do_target_wait (minus_one_ptid, ecs, TARGET_WNOHANG))
-      return;
+    /* Allow targets to pause their resumed threads while we handle
+       the event.  */
+    scoped_disable_commit_resumed disable_commit_resumed ("handling event");
+
+    if (!do_target_wait (ecs, TARGET_WNOHANG))
+      {
+       infrun_debug_printf ("do_target_wait returned no event");
+       disable_commit_resumed.reset_and_commit ();
+       return;
+      }
 
     gdb_assert (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
 
@@ -3983,6 +4174,8 @@ fetch_inferior_event ()
     /* No error, don't finish the thread states yet.  */
     finish_state.release ();
 
+    disable_commit_resumed.reset_and_commit ();
+
     /* This scope is used to ensure that readline callbacks are
        reinstalled here.  */
   }
@@ -4428,20 +4621,6 @@ poll_one_curr_target (struct target_waitstatus *ws)
   return event_ptid;
 }
 
-/* An event reported by wait_one.  */
-
-struct wait_one_event
-{
-  /* The target the event came out of.  */
-  process_stratum_target *target;
-
-  /* The PTID the event was for.  */
-  ptid_t ptid;
-
-  /* The waitstatus.  */
-  target_waitstatus ws;
-};
-
 /* Wait for one event out of any target.  */
 
 static wait_one_event
@@ -4528,12 +4707,11 @@ save_waitstatus (struct thread_info *tp, const target_waitstatus *ws)
   tp->suspend.waitstatus = *ws;
   tp->suspend.waitstatus_pending_p = 1;
 
-  struct regcache *regcache = get_thread_regcache (tp);
-  const address_space *aspace = regcache->aspace ();
-
   if (ws->kind == TARGET_WAITKIND_STOPPED
       && ws->value.sig == GDB_SIGNAL_TRAP)
     {
+      struct regcache *regcache = get_thread_regcache (tp);
+      const address_space *aspace = regcache->aspace ();
       CORE_ADDR pc = regcache_read_pc (regcache);
 
       adjust_pc_after_break (tp, &tp->suspend.waitstatus);
@@ -4622,6 +4800,159 @@ mark_non_executing_threads (process_stratum_target *target,
   set_resumed (target, mark_ptid, false);
 }
 
+/* Handle one event after stopping threads.  If the eventing thread
+   reports back any interesting event, we leave it pending.  If the
+   eventing thread was in the middle of a displaced step, we
+   cancel/finish it, and unless the thread's inferior is being
+   detached, put the thread back in the step-over chain.  Returns true
+   if there are no resumed threads left in the target (thus there's no
+   point in waiting further), false otherwise.  */
+
+static bool
+handle_one (const wait_one_event &event)
+{
+  infrun_debug_printf
+    ("%s %s", target_waitstatus_to_string (&event.ws).c_str (),
+     target_pid_to_str (event.ptid).c_str ());
+
+  if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED)
+    {
+      /* All resumed threads exited.  */
+      return true;
+    }
+  else if (event.ws.kind == TARGET_WAITKIND_THREAD_EXITED
+          || event.ws.kind == TARGET_WAITKIND_EXITED
+          || event.ws.kind == TARGET_WAITKIND_SIGNALLED)
+    {
+      /* One thread/process exited/signalled.  */
+
+      thread_info *t = nullptr;
+
+      /* The target may have reported just a pid.  If so, try
+        the first non-exited thread.  */
+      if (event.ptid.is_pid ())
+       {
+         int pid  = event.ptid.pid ();
+         inferior *inf = find_inferior_pid (event.target, pid);
+         for (thread_info *tp : inf->non_exited_threads ())
+           {
+             t = tp;
+             break;
+           }
+
+         /* If there is no available thread, the event would
+            have to be appended to a per-inferior event list,
+            which does not exist (and if it did, we'd have
+            to adjust run control command to be able to
+            resume such an inferior).  We assert here instead
+            of going into an infinite loop.  */
+         gdb_assert (t != nullptr);
+
+         infrun_debug_printf
+           ("using %s", target_pid_to_str (t->ptid).c_str ());
+       }
+      else
+       {
+         t = find_thread_ptid (event.target, event.ptid);
+         /* Check if this is the first time we see this thread.
+            Don't bother adding if it individually exited.  */
+         if (t == nullptr
+             && event.ws.kind != TARGET_WAITKIND_THREAD_EXITED)
+           t = add_thread (event.target, event.ptid);
+       }
+
+      if (t != nullptr)
+       {
+         /* Set the threads as non-executing to avoid
+            another stop attempt on them.  */
+         switch_to_thread_no_regs (t);
+         mark_non_executing_threads (event.target, event.ptid,
+                                     event.ws);
+         save_waitstatus (t, &event.ws);
+         t->stop_requested = false;
+       }
+    }
+  else
+    {
+      thread_info *t = find_thread_ptid (event.target, event.ptid);
+      if (t == NULL)
+       t = add_thread (event.target, event.ptid);
+
+      t->stop_requested = 0;
+      t->executing = 0;
+      t->resumed = false;
+      t->control.may_range_step = 0;
+
+      /* This may be the first time we see the inferior report
+        a stop.  */
+      inferior *inf = find_inferior_ptid (event.target, event.ptid);
+      if (inf->needs_setup)
+       {
+         switch_to_thread_no_regs (t);
+         setup_inferior (0);
+       }
+
+      if (event.ws.kind == TARGET_WAITKIND_STOPPED
+         && event.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_finish (t, GDB_SIGNAL_0)
+             == DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
+           {
+             /* Add it back to the step-over queue.  */
+             infrun_debug_printf
+               ("displaced-step of %s canceled",
+                target_pid_to_str (t->ptid).c_str ());
+
+             t->control.trap_expected = 0;
+             if (!t->inf->detaching)
+               global_thread_step_over_chain_enqueue (t);
+           }
+       }
+      else
+       {
+         enum gdb_signal sig;
+         struct regcache *regcache;
+
+         infrun_debug_printf
+           ("target_wait %s, saving status for %d.%ld.%ld",
+            target_waitstatus_to_string (&event.ws).c_str (),
+            t->ptid.pid (), t->ptid.lwp (), t->ptid.tid ());
+
+         /* Record for later.  */
+         save_waitstatus (t, &event.ws);
+
+         sig = (event.ws.kind == TARGET_WAITKIND_STOPPED
+                ? event.ws.value.sig : GDB_SIGNAL_0);
+
+         if (displaced_step_finish (t, sig)
+             == DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
+           {
+             /* Add it back to the step-over queue.  */
+             t->control.trap_expected = 0;
+             if (!t->inf->detaching)
+               global_thread_step_over_chain_enqueue (t);
+           }
+
+         regcache = get_thread_regcache (t);
+         t->suspend.stop_pc = regcache_read_pc (regcache);
+
+         infrun_debug_printf ("saved stop_pc=%s for %s "
+                              "(currently_stepping=%d)",
+                              paddress (target_gdbarch (),
+                                        t->suspend.stop_pc),
+                              target_pid_to_str (t->ptid).c_str (),
+                              currently_stepping (t));
+       }
+    }
+
+  return false;
+}
+
 /* See infrun.h.  */
 
 void
@@ -4735,144 +5066,8 @@ stop_all_threads (void)
          for (int i = 0; i < waits_needed; i++)
            {
              wait_one_event event = wait_one ();
-
-             infrun_debug_printf
-               ("%s %s", target_waitstatus_to_string (&event.ws).c_str (),
-                target_pid_to_str (event.ptid).c_str ());
-
-             if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED)
-               {
-                 /* All resumed threads exited.  */
-                 break;
-               }
-             else if (event.ws.kind == TARGET_WAITKIND_THREAD_EXITED
-                      || event.ws.kind == TARGET_WAITKIND_EXITED
-                      || event.ws.kind == TARGET_WAITKIND_SIGNALLED)
-               {
-                 /* One thread/process exited/signalled.  */
-
-                 thread_info *t = nullptr;
-
-                 /* The target may have reported just a pid.  If so, try
-                    the first non-exited thread.  */
-                 if (event.ptid.is_pid ())
-                   {
-                     int pid  = event.ptid.pid ();
-                     inferior *inf = find_inferior_pid (event.target, pid);
-                     for (thread_info *tp : inf->non_exited_threads ())
-                       {
-                         t = tp;
-                         break;
-                       }
-
-                     /* If there is no available thread, the event would
-                        have to be appended to a per-inferior event list,
-                        which does not exist (and if it did, we'd have
-                        to adjust run control command to be able to
-                        resume such an inferior).  We assert here instead
-                        of going into an infinite loop.  */
-                     gdb_assert (t != nullptr);
-
-                     infrun_debug_printf
-                       ("using %s", target_pid_to_str (t->ptid).c_str ());
-                   }
-                 else
-                   {
-                     t = find_thread_ptid (event.target, event.ptid);
-                     /* Check if this is the first time we see this thread.
-                        Don't bother adding if it individually exited.  */
-                     if (t == nullptr
-                         && event.ws.kind != TARGET_WAITKIND_THREAD_EXITED)
-                       t = add_thread (event.target, event.ptid);
-                   }
-
-                 if (t != nullptr)
-                   {
-                     /* Set the threads as non-executing to avoid
-                        another stop attempt on them.  */
-                     switch_to_thread_no_regs (t);
-                     mark_non_executing_threads (event.target, event.ptid,
-                                                 event.ws);
-                     save_waitstatus (t, &event.ws);
-                     t->stop_requested = false;
-                   }
-               }
-             else
-               {
-                 thread_info *t = find_thread_ptid (event.target, event.ptid);
-                 if (t == NULL)
-                   t = add_thread (event.target, event.ptid);
-
-                 t->stop_requested = 0;
-                 t->executing = 0;
-                 t->resumed = false;
-                 t->control.may_range_step = 0;
-
-                 /* This may be the first time we see the inferior report
-                    a stop.  */
-                 inferior *inf = find_inferior_ptid (event.target, event.ptid);
-                 if (inf->needs_setup)
-                   {
-                     switch_to_thread_no_regs (t);
-                     setup_inferior (0);
-                   }
-
-                 if (event.ws.kind == TARGET_WAITKIND_STOPPED
-                     && event.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_finish (t, GDB_SIGNAL_0)
-                         == DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
-                       {
-                         /* Add it back to the step-over queue.  */
-                         infrun_debug_printf
-                           ("displaced-step of %s canceled: adding back to "
-                            "the step-over queue",
-                             target_pid_to_str (t->ptid).c_str ());
-
-                         t->control.trap_expected = 0;
-                         global_thread_step_over_chain_enqueue (t);
-                       }
-                   }
-                 else
-                   {
-                     enum gdb_signal sig;
-                     struct regcache *regcache;
-
-                     infrun_debug_printf
-                       ("target_wait %s, saving status for %d.%ld.%ld",
-                        target_waitstatus_to_string (&event.ws).c_str (),
-                        t->ptid.pid (), t->ptid.lwp (), t->ptid.tid ());
-
-                     /* Record for later.  */
-                     save_waitstatus (t, &event.ws);
-
-                     sig = (event.ws.kind == TARGET_WAITKIND_STOPPED
-                            ? event.ws.value.sig : GDB_SIGNAL_0);
-
-                     if (displaced_step_finish (t, sig)
-                         == DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
-                       {
-                         /* Add it back to the step-over queue.  */
-                         t->control.trap_expected = 0;
-                         global_thread_step_over_chain_enqueue (t);
-                       }
-
-                     regcache = get_thread_regcache (t);
-                     t->suspend.stop_pc = regcache_read_pc (regcache);
-
-                     infrun_debug_printf ("saved stop_pc=%s for %s "
-                                          "(currently_stepping=%d)",
-                                          paddress (target_gdbarch (),
-                                                    t->suspend.stop_pc),
-                                          target_pid_to_str (t->ptid).c_str (),
-                                          currently_stepping (t));
-                   }
-               }
+             if (handle_one (event))
+               break;
            }
        }
     }
@@ -5034,8 +5229,6 @@ handle_inferior_event (struct execution_control_state *ecs)
      end.  */
   scoped_value_mark free_values;
 
-  enum stop_kind stop_soon;
-
   infrun_debug_printf ("%s", target_waitstatus_to_string (&ecs->ws).c_str ());
 
   if (ecs->ws.kind == TARGET_WAITKIND_IGNORE)
@@ -5129,80 +5322,82 @@ handle_inferior_event (struct execution_control_state *ecs)
   switch (ecs->ws.kind)
     {
     case TARGET_WAITKIND_LOADED:
-      context_switch (ecs);
-      /* Ignore gracefully during startup of the inferior, as it might
-        be the shell which has just loaded some objects, otherwise
-        add the symbols for the newly loaded objects.  Also ignore at
-        the beginning of an attach or remote session; we will query
-        the full list of libraries once the connection is
-        established.  */
-
-      stop_soon = get_inferior_stop_soon (ecs);
-      if (stop_soon == NO_STOP_QUIETLY)
-       {
-         struct regcache *regcache;
-
-         regcache = get_thread_regcache (ecs->event_thread);
+      {
+       context_switch (ecs);
+       /* Ignore gracefully during startup of the inferior, as it might
+          be the shell which has just loaded some objects, otherwise
+          add the symbols for the newly loaded objects.  Also ignore at
+          the beginning of an attach or remote session; we will query
+          the full list of libraries once the connection is
+          established.  */
+
+       stop_kind stop_soon = get_inferior_stop_soon (ecs);
+       if (stop_soon == NO_STOP_QUIETLY)
+         {
+           struct regcache *regcache;
 
-         handle_solib_event ();
+           regcache = get_thread_regcache (ecs->event_thread);
 
-         ecs->event_thread->control.stop_bpstat
-           = bpstat_stop_status (regcache->aspace (),
-                                 ecs->event_thread->suspend.stop_pc,
-                                 ecs->event_thread, &ecs->ws);
+           handle_solib_event ();
 
-         if (handle_stop_requested (ecs))
-           return;
+           ecs->event_thread->control.stop_bpstat
+             = bpstat_stop_status (regcache->aspace (),
+                                   ecs->event_thread->suspend.stop_pc,
+                                   ecs->event_thread, &ecs->ws);
 
-         if (bpstat_causes_stop (ecs->event_thread->control.stop_bpstat))
-           {
-             /* A catchpoint triggered.  */
-             process_event_stop_test (ecs);
+           if (handle_stop_requested (ecs))
              return;
-           }
 
-         /* If requested, stop when the dynamic linker notifies
-            gdb of events.  This allows the user to get control
-            and place breakpoints in initializer routines for
-            dynamically loaded objects (among other things).  */
-         ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
-         if (stop_on_solib_events)
-           {
-             /* Make sure we print "Stopped due to solib-event" in
-                normal_stop.  */
-             stop_print_frame = true;
+           if (bpstat_causes_stop (ecs->event_thread->control.stop_bpstat))
+             {
+               /* A catchpoint triggered.  */
+               process_event_stop_test (ecs);
+               return;
+             }
 
-             stop_waiting (ecs);
-             return;
-           }
-       }
+           /* If requested, stop when the dynamic linker notifies
+              gdb of events.  This allows the user to get control
+              and place breakpoints in initializer routines for
+              dynamically loaded objects (among other things).  */
+           ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
+           if (stop_on_solib_events)
+             {
+               /* Make sure we print "Stopped due to solib-event" in
+                  normal_stop.  */
+               stop_print_frame = true;
 
-      /* If we are skipping through a shell, or through shared library
-        loading that we aren't interested in, resume the program.  If
-        we're running the program normally, also resume.  */
-      if (stop_soon == STOP_QUIETLY || stop_soon == NO_STOP_QUIETLY)
-       {
-         /* Loading of shared libraries might have changed breakpoint
-            addresses.  Make sure new breakpoints are inserted.  */
-         if (stop_soon == NO_STOP_QUIETLY)
-           insert_breakpoints ();
-         resume (GDB_SIGNAL_0);
-         prepare_to_wait (ecs);
-         return;
-       }
+               stop_waiting (ecs);
+               return;
+             }
+         }
 
-      /* But stop if we're attaching or setting up a remote
-        connection.  */
-      if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
-         || stop_soon == STOP_QUIETLY_REMOTE)
-       {
-         infrun_debug_printf ("quietly stopped");
-         stop_waiting (ecs);
-         return;
-       }
+       /* If we are skipping through a shell, or through shared library
+          loading that we aren't interested in, resume the program.  If
+          we're running the program normally, also resume.  */
+       if (stop_soon == STOP_QUIETLY || stop_soon == NO_STOP_QUIETLY)
+         {
+           /* Loading of shared libraries might have changed breakpoint
+              addresses.  Make sure new breakpoints are inserted.  */
+           if (stop_soon == NO_STOP_QUIETLY)
+             insert_breakpoints ();
+           resume (GDB_SIGNAL_0);
+           prepare_to_wait (ecs);
+           return;
+         }
 
-      internal_error (__FILE__, __LINE__,
-                     _("unhandled stop_soon: %d"), (int) stop_soon);
+       /* But stop if we're attaching or setting up a remote
+          connection.  */
+       if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
+           || stop_soon == STOP_QUIETLY_REMOTE)
+         {
+           infrun_debug_printf ("quietly stopped");
+           stop_waiting (ecs);
+           return;
+         }
+
+       internal_error (__FILE__, __LINE__,
+                       _("unhandled stop_soon: %d"), (int) stop_soon);
+      }
 
     case TARGET_WAITKIND_SPURIOUS:
       if (handle_stop_requested (ecs))
@@ -5301,17 +5496,20 @@ handle_inferior_event (struct execution_control_state *ecs)
        struct gdbarch *gdbarch = regcache->arch ();
        inferior *parent_inf = find_inferior_ptid (ecs->target, ecs->ptid);
 
-       /* If this is a fork (child gets its own address space copy) and the
-          displaced step buffer was in use at the time of the fork, restore
-          displaced step buffer bytes in the child process.  */
-       if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
-         {
-           displaced_step_inferior_state *displaced
-             = &parent_inf->displaced_step_state;
-
-           if (displaced->step_thread != nullptr)
-             displaced_step_restore (displaced, ecs->ws.value.related_pid);
-         }
+       /* If this is a fork (child gets its own address space copy)
+          and some displaced step buffers were in use at the time of
+          the fork, restore the displaced step buffer bytes in the
+          child process.
+
+          Architectures which support displaced stepping and fork
+          events must supply an implementation of
+          gdbarch_displaced_step_restore_all_in_ptid.  This is not
+          enforced during gdbarch validation to support architectures
+          which support displaced stepping but not forks.  */
+       if (ecs->ws.kind == TARGET_WAITKIND_FORKED
+           && gdbarch_supports_displaced_stepping (gdbarch))
+         gdbarch_displaced_step_restore_all_in_ptid
+           (gdbarch, parent_inf, ecs->ws.value.related_pid);
 
        /* If displaced stepping is supported, and thread ecs->ptid is
           displaced stepping.  */
@@ -5574,6 +5772,13 @@ restart_threads (struct thread_info *event_thread)
 
   for (thread_info *tp : all_non_exited_threads ())
     {
+      if (tp->inf->detaching)
+       {
+         infrun_debug_printf ("restart threads: [%s] inferior detaching",
+                              target_pid_to_str (tp->ptid).c_str ());
+         continue;
+       }
+
       switch_to_thread_no_regs (tp);
 
       if (tp == event_thread)
@@ -5802,13 +6007,16 @@ handle_signal_stop (struct execution_control_state *ecs)
   ecs->event_thread->suspend.stop_pc
     = regcache_read_pc (get_thread_regcache (ecs->event_thread));
 
+  context_switch (ecs);
+
+  if (deprecated_context_hook)
+    deprecated_context_hook (ecs->event_thread->global_num);
+
   if (debug_infrun)
     {
       struct regcache *regcache = get_thread_regcache (ecs->event_thread);
       struct gdbarch *reg_gdbarch = regcache->arch ();
 
-      switch_to_thread (ecs->event_thread);
-
       infrun_debug_printf ("stop_pc=%s",
                           paddress (reg_gdbarch,
                                     ecs->event_thread->suspend.stop_pc));
@@ -5818,7 +6026,8 @@ handle_signal_stop (struct execution_control_state *ecs)
 
          infrun_debug_printf ("stopped by watchpoint");
 
-         if (target_stopped_data_address (current_top_target (), &addr))
+         if (target_stopped_data_address (current_inferior ()->top_target (),
+                                          &addr))
            infrun_debug_printf ("stopped data address=%s",
                                 paddress (reg_gdbarch, addr));
          else
@@ -5831,7 +6040,6 @@ handle_signal_stop (struct execution_control_state *ecs)
   stop_soon = get_inferior_stop_soon (ecs);
   if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
     {
-      context_switch (ecs);
       infrun_debug_printf ("quietly stopped");
       stop_print_frame = true;
       stop_waiting (ecs);
@@ -5869,18 +6077,6 @@ handle_signal_stop (struct execution_control_state *ecs)
       return;
     }
 
-  /* See if something interesting happened to the non-current thread.  If
-     so, then switch to that thread.  */
-  if (ecs->ptid != inferior_ptid)
-    {
-      infrun_debug_printf ("context switch");
-
-      context_switch (ecs);
-
-      if (deprecated_context_hook)
-       deprecated_context_hook (ecs->event_thread->global_num);
-    }
-
   /* At this point, get hold of the now-current thread's frame.  */
   frame = get_current_frame ();
   gdbarch = get_frame_arch (frame);
@@ -6179,7 +6375,6 @@ handle_signal_stop (struct execution_control_state *ecs)
   if (random_signal)
     {
       /* Signal not for debugging purposes.  */
-      struct inferior *inf = find_inferior_ptid (ecs->target, ecs->ptid);
       enum gdb_signal stop_signal = ecs->event_thread->suspend.stop_signal;
 
       infrun_debug_printf ("random signal (%s)",
@@ -6192,8 +6387,7 @@ handle_signal_stop (struct execution_control_state *ecs)
         to remain stopped.  */
       if (stop_soon != NO_STOP_QUIETLY
          || ecs->event_thread->stop_requested
-         || (!inf->detaching
-             && signal_stop_state (ecs->event_thread->suspend.stop_signal)))
+         || signal_stop_state (ecs->event_thread->suspend.stop_signal))
        {
          stop_waiting (ecs);
          return;
@@ -7065,29 +7259,46 @@ process_event_stop_test (struct execution_control_state *ecs)
   bool refresh_step_info = true;
   if ((ecs->event_thread->suspend.stop_pc == stop_pc_sal.pc)
       && (ecs->event_thread->current_line != stop_pc_sal.line
-         || ecs->event_thread->current_symtab != stop_pc_sal.symtab))
+         || ecs->event_thread->current_symtab != stop_pc_sal.symtab))
     {
+      /* We are at a different line.  */
+
       if (stop_pc_sal.is_stmt)
        {
-         /* We are at the start of a different line.  So stop.  Note that
-            we don't stop if we step into the middle of a different line.
-            That is said to make things like for (;;) statements work
-            better.  */
+         /* We are at the start of a statement.
+
+            So stop.  Note that we don't stop if we step into the middle of a
+            statement.  That is said to make things like for (;;) statements
+            work better.  */
          infrun_debug_printf ("stepped to a different line");
          end_stepping_range (ecs);
          return;
        }
       else if (frame_id_eq (get_frame_id (get_current_frame ()),
-                           ecs->event_thread->control.step_frame_id))
+                           ecs->event_thread->control.step_frame_id))
        {
-         /* We are at the start of a different line, however, this line is
-            not marked as a statement, and we have not changed frame.  We
-            ignore this line table entry, and continue stepping forward,
+         /* We are not at the start of a statement, and we have not changed
+            frame.
+
+            We ignore this line table entry, and continue stepping forward,
             looking for a better place to stop.  */
          refresh_step_info = false;
          infrun_debug_printf ("stepped to a different line, but "
                               "it's not the start of a statement");
        }
+      else
+       {
+         /* We are not the start of a statement, and we have changed frame.
+
+            We ignore this line table entry, and continue stepping forward,
+            looking for a better place to stop.  Keep refresh_step_info at
+            true to note that the frame has changed, but ignore the line
+            number to make sure we don't ignore a subsequent entry with the
+            same line number.  */
+         stop_pc_sal.line = 0;
+         infrun_debug_printf ("stepped to a different frame, but "
+                              "it's not the start of a statement");
+       }
     }
 
   /* We aren't done stepping.
@@ -7114,6 +7325,9 @@ process_event_stop_test (struct execution_control_state *ecs)
   keep_going (ecs);
 }
 
+static bool restart_stepped_thread (process_stratum_target *resume_target,
+                                   ptid_t resume_ptid);
+
 /* In all-stop mode, if we're currently stepping but have stopped in
    some other thread, we may need to switch back to the stepped
    thread.  Returns true we set the inferior running, false if we left
@@ -7124,8 +7338,6 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
 {
   if (!target_is_non_stop_p ())
     {
-      struct thread_info *stepping_thread;
-
       /* If any thread is blocked on some internal breakpoint, and we
         simply need to step over that breakpoint to get it going
         again, do that first.  */
@@ -7188,78 +7400,136 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
       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 ())
+      if (restart_stepped_thread (ecs->target, ecs->ptid))
        {
          prepare_to_wait (ecs);
          return true;
        }
 
-      /* Look for the stepping/nexting thread.  */
-      stepping_thread = NULL;
+      switch_to_thread (ecs->event_thread);
+    }
+
+  return false;
+}
 
-      for (thread_info *tp : all_non_exited_threads ())
-       {
-         switch_to_thread_no_regs (tp);
+/* Look for the thread that was stepping, and resume it.
+   RESUME_TARGET / RESUME_PTID indicate the set of threads the caller
+   is resuming.  Return true if a thread was started, false
+   otherwise.  */
 
-         /* Ignore threads of processes the caller is not
-            resuming.  */
-         if (!sched_multi
-             && (tp->inf->process_target () != ecs->target
-                 || tp->inf->pid != ecs->ptid.pid ()))
-           continue;
+static bool
+restart_stepped_thread (process_stratum_target *resume_target,
+                       ptid_t resume_ptid)
+{
+  /* Do all pending step-overs before actually proceeding with
+     step/next/etc.  */
+  if (start_step_over ())
+    return true;
 
-         /* 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.  */
-         if (tp->control.trap_expected)
-           {
-             internal_error (__FILE__, __LINE__,
-                             "[%s] has inconsistent state: "
-                             "trap_expected=%d\n",
-                             target_pid_to_str (tp->ptid).c_str (),
-                             tp->control.trap_expected);
-           }
+  for (thread_info *tp : all_threads_safe ())
+    {
+      if (tp->state == THREAD_EXITED)
+       continue;
 
-         /* Did we find the stepping thread?  */
-         if (tp->control.step_range_end)
-           {
-             /* Yep.  There should only one though.  */
-             gdb_assert (stepping_thread == NULL);
+      if (tp->suspend.waitstatus_pending_p)
+       continue;
 
-             /* The event thread is handled at the top, before we
-                enter this loop.  */
-             gdb_assert (tp != ecs->event_thread);
+      /* Ignore threads of processes the caller is not
+        resuming.  */
+      if (!sched_multi
+         && (tp->inf->process_target () != resume_target
+             || tp->inf->pid != resume_ptid.pid ()))
+       continue;
 
-             /* If some thread other than the event thread is
-                stepping, then scheduler locking can't be in effect,
-                otherwise we wouldn't have resumed the current event
-                thread in the first place.  */
-             gdb_assert (!schedlock_applies (tp));
+      if (tp->control.trap_expected)
+       {
+         infrun_debug_printf ("switching back to stepped thread (step-over)");
 
-             stepping_thread = tp;
-           }
+         if (keep_going_stepped_thread (tp))
+           return true;
        }
+    }
+
+  for (thread_info *tp : all_threads_safe ())
+    {
+      if (tp->state == THREAD_EXITED)
+       continue;
+
+      if (tp->suspend.waitstatus_pending_p)
+       continue;
 
-      if (stepping_thread != NULL)
+      /* Ignore threads of processes the caller is not
+        resuming.  */
+      if (!sched_multi
+         && (tp->inf->process_target () != resume_target
+             || tp->inf->pid != resume_ptid.pid ()))
+       continue;
+
+      /* Did we find the stepping thread?  */
+      if (tp->control.step_range_end)
        {
-         infrun_debug_printf ("switching back to stepped thread");
+         infrun_debug_printf ("switching back to stepped thread (stepping)");
 
-         if (keep_going_stepped_thread (stepping_thread))
-           {
-             prepare_to_wait (ecs);
-             return true;
-           }
+         if (keep_going_stepped_thread (tp))
+           return true;
        }
-
-      switch_to_thread (ecs->event_thread);
     }
 
   return false;
 }
 
+/* See infrun.h.  */
+
+void
+restart_after_all_stop_detach (process_stratum_target *proc_target)
+{
+  /* Note we don't check target_is_non_stop_p() here, because the
+     current inferior may no longer have a process_stratum target
+     pushed, as we just detached.  */
+
+  /* See if we have a THREAD_RUNNING thread that need to be
+     re-resumed.  If we have any thread that is already executing,
+     then we don't need to resume the target -- it is already been
+     resumed.  With the remote target (in all-stop), it's even
+     impossible to issue another resumption if the target is already
+     resumed, until the target reports a stop.  */
+  for (thread_info *thr : all_threads (proc_target))
+    {
+      if (thr->state != THREAD_RUNNING)
+       continue;
+
+      /* If we have any thread that is already executing, then we
+        don't need to resume the target -- it is already been
+        resumed.  */
+      if (thr->executing)
+       return;
+
+      /* If we have a pending event to process, skip resuming the
+        target and go straight to processing it.  */
+      if (thr->resumed && thr->suspend.waitstatus_pending_p)
+       return;
+    }
+
+  /* Alright, we need to re-resume the target.  If a thread was
+     stepping, we need to restart it stepping.  */
+  if (restart_stepped_thread (proc_target, minus_one_ptid))
+    return;
+
+  /* Otherwise, find the first THREAD_RUNNING thread and resume
+     it.  */
+  for (thread_info *thr : all_threads (proc_target))
+    {
+      if (thr->state != THREAD_RUNNING)
+       continue;
+
+      execution_control_state ecs;
+      reset_ecs (&ecs, thr);
+      switch_to_thread (thr);
+      keep_going (&ecs);
+      return;
+    }
+}
+
 /* Set a previously stepped thread back to stepping.  Returns true on
    success, false if the resume is not possible (e.g., the thread
    vanished).  */
@@ -8159,7 +8429,6 @@ maybe_remove_breakpoints (void)
 struct stop_context
 {
   stop_context ();
-  ~stop_context ();
 
   DISABLE_COPY_AND_ASSIGN (stop_context);
 
@@ -8174,7 +8443,7 @@ struct stop_context
 
   /* If stopp for a thread event, this is the thread that caused the
      stop.  */
-  struct thread_info *thread;
+  thread_info_ref thread;
 
   /* The inferior that caused the stop.  */
   int inf_num;
@@ -8193,20 +8462,8 @@ stop_context::stop_context ()
     {
       /* Take a strong reference so that the thread can't be deleted
         yet.  */
-      thread = inferior_thread ();
-      thread->incref ();
+      thread = thread_info_ref::new_reference (inferior_thread ());
     }
-  else
-    thread = NULL;
-}
-
-/* Release a stop context previously created with save_stop_context.
-   Releases the strong reference to the thread as well. */
-
-stop_context::~stop_context ()
-{
-  if (thread != NULL)
-    thread->decref ();
 }
 
 /* Return true if the current context no longer matches the saved stop
@@ -8397,7 +8654,7 @@ normal_stop (void)
      print the stop event.  */
   if (inferior_ptid != null_ptid)
     gdb::observers::normal_stop.notify (inferior_thread ()->control.stop_bpstat,
-                                stop_print_frame);
+                                       stop_print_frame);
   else
     gdb::observers::normal_stop.notify (NULL, stop_print_frame);
 
@@ -8792,7 +9049,8 @@ siginfo_value_read (struct value *v)
   validate_registers_access ();
 
   transferred =
-    target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO,
+    target_read (current_inferior ()->top_target (),
+                TARGET_OBJECT_SIGNAL_INFO,
                 NULL,
                 value_contents_all_raw (v),
                 value_offset (v),
@@ -8814,7 +9072,7 @@ siginfo_value_write (struct value *v, struct value *fromval)
      vice versa.  */
   validate_registers_access ();
 
-  transferred = target_write (current_top_target (),
+  transferred = target_write (current_inferior ()->top_target (),
                              TARGET_OBJECT_SIGNAL_INFO,
                              NULL,
                              value_contents_all_raw (fromval),
@@ -8878,7 +9136,8 @@ public:
 
        siginfo_data.reset ((gdb_byte *) xmalloc (len));
 
-       if (target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
+       if (target_read (current_inferior ()->top_target (),
+                        TARGET_OBJECT_SIGNAL_INFO, NULL,
                         siginfo_data.get (), 0, len) != len)
          {
            /* Errors ignored.  */
@@ -8913,7 +9172,8 @@ public:
        struct type *type = gdbarch_get_siginfo_type (gdbarch);
 
        /* Errors ignored.  */
-       target_write (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
+       target_write (current_inferior ()->top_target (),
+                     TARGET_OBJECT_SIGNAL_INFO, NULL,
                      m_siginfo_data.get (), 0, TYPE_LENGTH (type));
       }
 
@@ -9170,6 +9430,7 @@ static const struct internalvar_funcs siginfo_funcs =
 static void
 infrun_async_inferior_event_handler (gdb_client_data data)
 {
+  clear_async_event_handler (infrun_async_inferior_event_token);
   inferior_event_handler (INF_REG_EVENT);
 }
 
@@ -9251,10 +9512,11 @@ _initialize_infrun ()
     = create_async_event_handler (infrun_async_inferior_event_handler, NULL,
                                  "infrun");
 
-  add_info ("signals", info_signals_command, _("\
+  cmd_list_element *info_signals_cmd
+    = 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);
+  add_info_alias ("handle", info_signals_cmd, 0);
 
   c = add_com ("handle", class_run, handle_command, _("\
 Specify how to handle signals.\n\
@@ -9289,22 +9551,12 @@ There is no `stop' command, but you can set a hook on `stop'.\n\
 This allows you to set a list of commands to be run each time execution\n\
 of the program stops."), &cmdlist);
 
-  add_setshow_zuinteger_cmd ("infrun", class_maintenance, &debug_infrun, _("\
-Set inferior debugging."), _("\
-Show inferior debugging."), _("\
-When non-zero, inferior specific debugging is enabled."),
-                            NULL,
-                            show_debug_infrun,
-                            &setdebuglist, &showdebuglist);
-
-  add_setshow_boolean_cmd ("displaced", class_maintenance,
-                          &debug_displaced, _("\
-Set displaced stepping debugging."), _("\
-Show displaced stepping debugging."), _("\
-When non-zero, displaced stepping specific debugging is enabled."),
-                           NULL,
-                           show_debug_displaced,
-                           &setdebuglist, &showdebuglist);
+  add_setshow_boolean_cmd
+    ("infrun", class_maintenance, &debug_infrun,
+     _("Set inferior debugging."),
+     _("Show inferior debugging."),
+     _("When non-zero, inferior specific debugging is enabled."),
+     NULL, show_debug_infrun, &setdebuglist, &showdebuglist);
 
   add_setshow_boolean_cmd ("non-stop", no_class,
                           &non_stop_1, _("\
@@ -9519,11 +9771,13 @@ enabled by default on some platforms."),
   inferior_ptid = null_ptid;
   target_last_wait_ptid = minus_one_ptid;
 
-  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);
-  gdb::observers::inferior_execd.attach (infrun_inferior_execd);
+  gdb::observers::thread_ptid_changed.attach (infrun_thread_ptid_changed,
+                                             "infrun");
+  gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested,
+                                               "infrun");
+  gdb::observers::thread_exit.attach (infrun_thread_thread_exit, "infrun");
+  gdb::observers::inferior_exit.attach (infrun_inferior_exit, "infrun");
+  gdb::observers::inferior_execd.attach (infrun_inferior_execd, "infrun");
 
   /* 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.050666 seconds and 4 git commands to generate.