Merge remote-tracking branch 'origin/master' into amd-common
authorLaurent Morichetti <laurent.morichetti@amd.com>
Sat, 11 Jan 2020 23:23:46 +0000 (15:23 -0800)
committerLaurent Morichetti <laurent.morichetti@amd.com>
Sat, 11 Jan 2020 23:23:46 +0000 (15:23 -0800)
Change-Id: I96a19b82dab210c7d98d33c5cd889b0a6f47806d

1  2 
gdb/Makefile.in
gdb/breakpoint.c
gdb/infrun.c
gdb/inline-frame.c

diff --combined gdb/Makefile.in
index 084c83dcef7ef25458f7a71796e0c2cef6bc22df,6df0f46b5ed91d4abcb0a59d73bcee7ec7cd3b02..e852b140e7acd0306e77347694ed59e95231226f
@@@ -1,5 -1,4 +1,5 @@@
  # Copyright (C) 1989-2020 Free Software Foundation, Inc.
 +# Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
  
  # This file is part of GDB.
  
@@@ -610,7 -609,7 +610,7 @@@ INTERNAL_LDFLAGS = 
  CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(LIBCTF) $(ZLIB) \
          $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \
        $(XM_CLIBS) $(GDBTKLIBS) \
 -      @LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
 +      @LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ @ROCM_DBGAPI_LIBS@ \
        $(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \
        $(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) $(LIBICONV) $(LIBMPFR) \
        $(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS)
@@@ -1141,6 -1140,7 +1141,7 @@@ COMMON_SFILES = 
        symmisc.c \
        symtab.c \
        target.c \
+       target-connection.c \
        target-dcache.c \
        target-descriptions.c \
        target-memory.c \
@@@ -1220,7 -1220,6 +1221,7 @@@ HFILES_NO_SRCDIR = 
        amd64-linux-tdep.h \
        amd64-nat.h \
        amd64-tdep.h \
 +      amdgcn-rocm-tdep.h \
        annotate.h \
        arc-tdep.h \
        arch-utils.h \
        riscv-fbsd-tdep.h \
        riscv-ravenscar-thread.h \
        riscv-tdep.h \
 +      rocm-tdep.h \
        rs6000-aix-tdep.h \
        rs6000-tdep.h \
        run-on-main-thread.h \
@@@ -2188,7 -2186,6 +2189,7 @@@ ALLDEPFILES = 
        amd64-obsd-tdep.c \
        amd64-sol2-tdep.c \
        amd64-tdep.c \
 +      amdgcn-rocm-tdep.c \
        arc-tdep.c \
        arm.c \
        arm-bsd-tdep.c \
        riscv-linux-tdep.c \
        riscv-ravenscar-thread.c \
        riscv-tdep.c \
 +      rocm-tdep.c \
        rl78-tdep.c \
        rs6000-lynx178-tdep.c \
        rs6000-nat.c \
        sh-tdep.c \
        sol2-tdep.c \
        solib-aix.c \
 +      solib-rocm.c \
        solib-svr4.c \
        sparc-linux-nat.c \
        sparc-linux-tdep.c \
diff --combined gdb/breakpoint.c
index 75b45c3db8657cafec63b6c040d7636ab39b758b,5b734abf1c161b41001b428782a0f27d19f13edb..9e8291b4af0d2084731d801ec3990899ba633d13
@@@ -1,7 -1,6 +1,7 @@@
  /* Everything about breakpoints, for GDB.
  
     Copyright (C) 1986-2020 Free Software Foundation, Inc.
 +   Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
  
     This file is part of GDB.
  
@@@ -368,10 -367,7 +368,10 @@@ show_automatic_hardware_breakpoints (st
     breakpoints until the next resume, and removes them again when the
     target fully stops.  This is a bit safer in case GDB crashes while
     processing user input.  */
 -static bool always_inserted_mode = false;
 +/* FIXME: this is a temporary workaround to make sure waves created while
 +   all known threads are stopped, and the gdb prompt is presented, do not
 +   execute past the enabled breakpoints.  */
 +static bool always_inserted_mode = true;
  
  static void
  show_always_inserted_mode (struct ui_file *file, int from_tty,
@@@ -393,7 -389,7 +393,7 @@@ breakpoints_should_be_inserted_now (voi
         no threads under GDB's control yet.  */
        return 1;
      }
-   else if (target_has_execution)
+   else
      {
        if (always_inserted_mode)
        {
          return 1;
        }
  
-       if (threads_are_executing ())
-       return 1;
+       for (inferior *inf : all_inferiors ())
+       if (inf->has_execution ()
+           && threads_are_executing (inf->process_target ()))
+         return 1;
  
        /* Don't remove breakpoints yet if, even though all threads are
         stopped, we still have events to process.  */
@@@ -2891,7 -2889,7 +2893,7 @@@ update_inserted_breakpoint_locations (v
         if we aren't attached to any process yet, we should still
         insert breakpoints.  */
        if (!gdbarch_has_global_breakpoints (target_gdbarch ())
-         && inferior_ptid == null_ptid)
+         && (inferior_ptid == null_ptid || !target_has_execution))
        continue;
  
        val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
@@@ -2947,7 -2945,7 +2949,7 @@@ insert_breakpoint_locations (void
         if we aren't attached to any process yet, we should still
         insert breakpoints.  */
        if (!gdbarch_has_global_breakpoints (target_gdbarch ())
-         && inferior_ptid == null_ptid)
+         && (inferior_ptid == null_ptid || !target_has_execution))
        continue;
  
        val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
@@@ -8513,9 -8511,7 +8515,9 @@@ static voi
  mention (struct breakpoint *b)
  {
    b->ops->print_mention (b);
 -  current_uiout->text ("\n");
 +  if (current_uiout->is_mi_like_p ())
 +    return;
 +  printf_filtered ("\n");
  }
  \f
  
@@@ -11909,7 -11905,18 +11911,18 @@@ update_global_location_list (enum ugll_
                 around.  We simply always ignore hardware watchpoint
                 traps we can no longer explain.  */
  
-             old_loc->events_till_retirement = 3 * (thread_count () + 1);
+             process_stratum_target *proc_target = nullptr;
+             for (inferior *inf : all_inferiors ())
+               if (inf->pspace == old_loc->pspace)
+                 {
+                   proc_target = inf->process_target ();
+                   break;
+                 }
+             if (proc_target != nullptr)
+               old_loc->events_till_retirement
+                 = 3 * (thread_count (proc_target) + 1);
+             else
+               old_loc->events_till_retirement = 1;
              old_loc->owner = NULL;
  
              moribund_locations.push_back (old_loc);
diff --combined gdb/infrun.c
index fe479967cd4d5a9d85c45ba2e6c7303ffacf9764,a0583a8e65868ecdcc63d324908ea2c4df339a50..8209b08d0834acb1ecc169ff824188d8e2ba62db
@@@ -2,7 -2,6 +2,7 @@@
     process.
  
     Copyright (C) 1986-2020 Free Software Foundation, Inc.
 +   Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
  
     This file is part of GDB.
  
@@@ -29,6 -28,7 +29,7 @@@
  #include "gdbcore.h"
  #include "gdbcmd.h"
  #include "target.h"
+ #include "target-connection.h"
  #include "gdbthread.h"
  #include "annotate.h"
  #include "symfile.h"
@@@ -64,6 -64,8 +65,8 @@@
  #include "arch-utils.h"
  #include "gdbsupport/scope-exit.h"
  #include "gdbsupport/forward-scope-exit.h"
+ #include "gdb_select.h"
+ #include <unordered_map>
  
  /* Prototypes for local functions */
  
@@@ -79,8 -81,6 +82,6 @@@ static void follow_inferior_reset_break
  
  static int currently_stepping (struct thread_info *tp);
  
- void nullify_last_target_wait_ptid (void);
  static void insert_hp_step_resume_breakpoint_at_frame (struct frame_info *);
  
  static void insert_step_resume_breakpoint_at_caller (struct frame_info *);
@@@ -91,6 -91,8 +92,8 @@@ static int maybe_software_singlestep (s
  
  static void resume (gdb_signal sig);
  
+ static void wait_for_inferior (inferior *inf);
  /* 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;
@@@ -373,9 -375,10 +376,10 @@@ show_stop_on_solib_events (struct ui_fi
  
  static int stop_print_frame;
  
- /* This is a cached copy of the pid/waitstatus of the last event
-    returned by target_wait()/deprecated_target_wait_hook().  This
-    information is returned by get_last_target_status().  */
+ /* This is a cached copy of the target/ptid/waitstatus of the last
+    event returned by target_wait()/deprecated_target_wait_hook().
+    This information is returned by get_last_target_status().  */
+ static process_stratum_target *target_last_proc_target;
  static ptid_t target_last_wait_ptid;
  static struct target_waitstatus target_last_waitstatus;
  
@@@ -481,10 -484,12 +485,12 @@@ holding the child stopped.  Try \"set d
  
          scoped_restore_current_pspace_and_thread restore_pspace_thread;
  
-         inferior_ptid = child_ptid;
-         add_thread_silent (inferior_ptid);
          set_current_inferior (child_inf);
+         switch_to_no_thread ();
          child_inf->symfile_flags = SYMFILE_NO_READ;
+         push_target (parent_inf->process_target ());
+         add_thread_silent (child_inf->process_target (), child_ptid);
+         inferior_ptid = child_ptid;
  
          /* If this is a vfork child, then the address-space is
             shared with the parent.  */
              child_inf->pspace = parent_inf->pspace;
              child_inf->aspace = parent_inf->aspace;
  
+             exec_on_vfork ();
              /* The parent will be frozen until the child is done
                 with the shared region.  Keep track of the
                 parent.  */
  
        parent_pspace = parent_inf->pspace;
  
-       /* If we're vforking, we want to hold on to the parent until the
-        child exits or execs.  At child exec or exit time we can
-        remove the old breakpoints from the parent and detach or
-        resume debugging it.  Otherwise, detach the parent now; we'll
-        want to reuse it's program/address spaces, but we can't set
-        them to the child before removing breakpoints from the
-        parent, otherwise, the breakpoints module could decide to
-        remove breakpoints from the wrong process (since they'd be
-        assigned to the same address space).  */
+       process_stratum_target *target = parent_inf->process_target ();
  
-       if (has_vforked)
-       {
-         gdb_assert (child_inf->vfork_parent == NULL);
-         gdb_assert (parent_inf->vfork_child == NULL);
-         child_inf->vfork_parent = parent_inf;
-         child_inf->pending_detach = 0;
-         parent_inf->vfork_child = child_inf;
-         parent_inf->pending_detach = detach_fork;
-         parent_inf->waiting_for_vfork_done = 0;
-       }
-       else if (detach_fork)
-       {
-         if (print_inferior_events)
-           {
-             /* Ensure that we have a process ptid.  */
-             ptid_t process_ptid = ptid_t (parent_ptid.pid ());
+       {
+       /* Hold a strong reference to the target while (maybe)
+          detaching the parent.  Otherwise detaching could close the
+          target.  */
+       auto target_ref = target_ops_ref::new_reference (target);
+       /* If we're vforking, we want to hold on to the parent until
+          the child exits or execs.  At child exec or exit time we
+          can remove the old breakpoints from the parent and detach
+          or resume debugging it.  Otherwise, detach the parent now;
+          we'll want to reuse it's program/address spaces, but we
+          can't set them to the child before removing breakpoints
+          from the parent, otherwise, the breakpoints module could
+          decide to remove breakpoints from the wrong process (since
+          they'd be assigned to the same address space).  */
+       if (has_vforked)
+         {
+           gdb_assert (child_inf->vfork_parent == NULL);
+           gdb_assert (parent_inf->vfork_child == NULL);
+           child_inf->vfork_parent = parent_inf;
+           child_inf->pending_detach = 0;
+           parent_inf->vfork_child = child_inf;
+           parent_inf->pending_detach = detach_fork;
+           parent_inf->waiting_for_vfork_done = 0;
+         }
+       else if (detach_fork)
+         {
+           if (print_inferior_events)
+             {
+               /* Ensure that we have a process ptid.  */
+               ptid_t process_ptid = ptid_t (parent_ptid.pid ());
+               target_terminal::ours_for_output ();
+               fprintf_filtered (gdb_stdlog,
+                                 _("[Detaching after fork from "
+                                   "parent %s]\n"),
+                                 target_pid_to_str (process_ptid).c_str ());
+             }
  
-             target_terminal::ours_for_output ();
-             fprintf_filtered (gdb_stdlog,
-                               _("[Detaching after fork from "
-                                 "parent %s]\n"),
-                               target_pid_to_str (process_ptid).c_str ());
-           }
+           target_detach (parent_inf, 0);
+           parent_inf = NULL;
+         }
  
-         target_detach (parent_inf, 0);
-       }
+       /* Note that the detach above makes PARENT_INF dangling.  */
  
-       /* Note that the detach above makes PARENT_INF dangling.  */
+       /* Add the child thread to the appropriate lists, and switch
+          to this new thread, before cloning the program space, and
+          informing the solib layer about this new process.  */
  
-       /* Add the child thread to the appropriate lists, and switch to
-        this new thread, before cloning the program space, and
-        informing the solib layer about this new process.  */
+       set_current_inferior (child_inf);
+       push_target (target);
+       }
  
+       add_thread_silent (target, child_ptid);
        inferior_ptid = child_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
        {
          child_inf->pspace = parent_pspace;
          child_inf->aspace = child_inf->pspace->aspace;
+         exec_on_vfork ();
        }
        else
        {
@@@ -668,11 -689,12 +690,12 @@@ follow_fork (void
  
    if (!non_stop)
      {
+       process_stratum_target *wait_target;
        ptid_t wait_ptid;
        struct target_waitstatus wait_status;
  
        /* Get the last target status returned by target_wait().  */
-       get_last_target_status (&wait_ptid, &wait_status);
+       get_last_target_status (&wait_target, &wait_ptid, &wait_status);
  
        /* If not stopped at a fork event, then there's nothing else to
         do.  */
        /* Check if we switched over from WAIT_PTID, since the event was
         reported.  */
        if (wait_ptid != minus_one_ptid
-         && inferior_ptid != wait_ptid)
+         && (current_inferior ()->process_target () != wait_target
+             || inferior_ptid != wait_ptid))
        {
          /* We did.  Switch back to WAIT_PTID thread, to tell the
             target to follow it (in either direction).  We'll
             afterwards refuse to resume, and inform the user what
             happened.  */
-         thread_info *wait_thread
-           = find_thread_ptid (wait_ptid);
+         thread_info *wait_thread = find_thread_ptid (wait_target, wait_ptid);
          switch_to_thread (wait_thread);
          should_resume = 0;
        }
        parent = inferior_ptid;
        child = tp->pending_follow.value.related_pid;
  
+       process_stratum_target *parent_targ = tp->inf->process_target ();
        /* Set up inferior(s) as specified by the caller, and tell the
           target to do whatever is necessary to follow either parent
           or child.  */
               or another.  The previous selected thread may be gone
               from the lists by now, but if it is still around, need
               to clear the pending follow request.  */
-           tp = find_thread_ptid (parent);
+           tp = find_thread_ptid (parent_targ, parent);
            if (tp)
              tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
  
            /* If we followed the child, switch to it...  */
            if (follow_child)
              {
-               thread_info *child_thr = find_thread_ptid (child);
+               thread_info *child_thr = find_thread_ptid (parent_targ, child);
                switch_to_thread (child_thr);
  
                /* ... and preserve the stepping state, in case the
@@@ -1191,9 -1214,11 +1215,11 @@@ follow_exec (ptid_t ptid, const char *e
        inf->pid = pid;
        target_follow_exec (inf, exec_file_target);
  
-       set_current_inferior (inf);
-       set_current_program_space (inf->pspace);
-       add_thread (ptid);
+       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);
      }
    else
      {
@@@ -1887,6 -1912,7 +1913,7 @@@ displaced_step_fixup (thread_info *even
     discarded between events.  */
  struct execution_control_state
  {
+   process_stratum_target *target;
    ptid_t ptid;
    /* The thread that got the event, if this was a thread event; NULL
       otherwise.  */
@@@ -2143,6 -2169,16 +2170,16 @@@ user_visible_resume_ptid (int step
    return resume_ptid;
  }
  
+ /* See infrun.h.  */
+ process_stratum_target *
+ user_visible_resume_target (ptid_t resume_ptid)
+ {
+   return (resume_ptid == minus_one_ptid && sched_multi
+         ? NULL
+         : current_inferior ()->process_target ());
+ }
  /* 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
@@@ -2207,6 -2243,9 +2244,9 @@@ do_target_resume (ptid_t resume_ptid, i
    target_resume (resume_ptid, step, sig);
  
    target_commit_resume ();
+   if (target_can_async_p ())
+     target_async (1);
  }
  
  /* Resume the inferior.  SIG is the signal to give the inferior
@@@ -2250,6 -2289,7 +2290,7 @@@ resume_1 (enum gdb_signal sig
                              currently_stepping (tp));
        }
  
+       tp->inf->process_target ()->threads_executing = true;
        tp->resumed = 1;
  
        /* FIXME: What should we do if we are supposed to resume this
@@@ -2735,10 -2775,12 +2776,12 @@@ clear_proceed_status (int step
    if (!non_stop && inferior_ptid != null_ptid)
      {
        ptid_t resume_ptid = user_visible_resume_ptid (step);
+       process_stratum_target *resume_target
+       = user_visible_resume_target (resume_ptid);
  
        /* In all-stop mode, delete the per-thread status of all threads
         we're about to resume, implicitly and explicitly.  */
-       for (thread_info *tp : all_non_exited_threads (resume_ptid))
+       for (thread_info *tp : all_non_exited_threads (resume_target, resume_ptid))
        clear_proceed_status_thread (tp);
      }
  
@@@ -2815,6 -2857,86 +2858,86 @@@ schedlock_applies (struct thread_info *
                                            execution_direction)));
  }
  
+ /* Calls target_commit_resume on all targets.  */
+ static void
+ commit_resume_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;
+   for (const auto &ci : conn_inf)
+     {
+       inferior *inf = ci.second;
+       switch_to_inferior_no_thread (inf);
+       target_commit_resume ();
+     }
+ }
+ /* Check that all the targets we're about to resume are in non-stop
+    mode.  Ideally, we'd only care whether all targets support
+    target-async, but we're not there yet.  E.g., stop_all_threads
+    doesn't know how to handle all-stop targets.  Also, the remote
+    protocol in all-stop mode is synchronous, irrespective of
+    target-async, which means that things like a breakpoint re-set
+    triggered by one target would try to read memory from all targets
+    and fail.  */
+ static void
+ check_multi_target_resumption (process_stratum_target *resume_target)
+ {
+   if (!non_stop && resume_target == nullptr)
+     {
+       scoped_restore_current_thread restore_thread;
+       /* This is used to track whether we're resuming more than one
+        target.  */
+       process_stratum_target *first_connection = nullptr;
+       /* The first inferior we see with a target that does not work in
+        always-non-stop mode.  */
+       inferior *first_not_non_stop = nullptr;
+       for (inferior *inf : all_non_exited_inferiors (resume_target))
+       {
+         switch_to_inferior_no_thread (inf);
+         if (!target_has_execution)
+           continue;
+         process_stratum_target *proc_target
+           = current_inferior ()->process_target();
+         if (!target_is_non_stop_p ())
+           first_not_non_stop = inf;
+         if (first_connection == nullptr)
+           first_connection = proc_target;
+         else if (first_connection != proc_target
+                  && first_not_non_stop != nullptr)
+           {
+             switch_to_inferior_no_thread (first_not_non_stop);
+             proc_target = current_inferior ()->process_target();
+             error (_("Connection %d (%s) does not support "
+                      "multi-target resumption."),
+                    proc_target->connection_number,
+                    make_target_connection_string (proc_target).c_str ());
+           }
+       }
+     }
+ }
  /* Basic routine for continuing the program in various fashions.
  
     ADDR is the address to resume at, or -1 for resume where stopped.
@@@ -2829,7 -2951,6 +2952,6 @@@ proceed (CORE_ADDR addr, enum gdb_signa
    struct regcache *regcache;
    struct gdbarch *gdbarch;
    CORE_ADDR pc;
-   ptid_t resume_ptid;
    struct execution_control_state ecss;
    struct execution_control_state *ecs = &ecss;
    int started;
  
    gdb_assert (!thread_is_in_step_over_chain (cur_thr));
  
+   ptid_t resume_ptid
+     = user_visible_resume_ptid (cur_thr->control.stepping_command);
+   process_stratum_target *resume_target
+     = user_visible_resume_target (resume_ptid);
+   check_multi_target_resumption (resume_target);
    if (addr == (CORE_ADDR) -1)
      {
        if (pc == cur_thr->suspend.stop_pc
    if (siggnal != GDB_SIGNAL_DEFAULT)
      cur_thr->suspend.stop_signal = siggnal;
  
-   resume_ptid = user_visible_resume_ptid (cur_thr->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);
+   scoped_finish_thread_state finish_state (resume_target, 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
       inferior function, as in that case we pretend the inferior
       doesn't run at all.  */
    if (!cur_thr->control.in_infcall)
-    set_running (resume_ptid, 1);
+     set_running (resume_target, resume_ptid, 1);
  
    if (debug_infrun)
      fprintf_unfiltered (gdb_stdlog,
       threads.  */
    if (!non_stop && !schedlock_applies (cur_thr))
      {
-       for (thread_info *tp : all_non_exited_threads (resume_ptid))
+       for (thread_info *tp : all_non_exited_threads (resume_target,
+                                                    resume_ptid))
        {
+         switch_to_thread_no_regs (tp);
          /* Ignore the current thread here.  It's handled
             afterwards.  */
          if (tp == cur_thr)
  
          thread_step_over_chain_enqueue (tp);
        }
+       switch_to_thread (cur_thr);
      }
  
    /* Enqueue the current thread last, so that we move all other
        {
        /* 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_ptid))
-         {
+       for (thread_info *tp : all_non_exited_threads (resume_target,
+                                                      resume_ptid))
+         {
+           switch_to_thread_no_regs (tp);
+         if (!tp->inf->has_execution ())
+           {
+             if (debug_infrun)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "infrun: proceed: [%s] target has "
+                                   "no execution\n",
+                                   target_pid_to_str (tp->ptid).c_str ());
+             continue;
+           }
          if (tp->resumed)
            {
              if (debug_infrun)
        }
    }
  
-   target_commit_resume ();
+   commit_resume_all_targets ();
  
    finish_state.release ();
  
+   /* If we've switched threads above, switch back to the previously
+      current thread.  We don't want the user to see a different
+      selected thread.  */
+   switch_to_thread (cur_thr);
    /* Tell the event loop to wait for it to stop.  If the target
       supports asynchronous execution, it'll do this from within
       target_resume.  */
  void
  start_remote (int from_tty)
  {
-   struct inferior *inferior;
-   inferior = current_inferior ();
-   inferior->control.stop_soon = STOP_QUIETLY_REMOTE;
+   inferior *inf = current_inferior ();
+   inf->control.stop_soon = STOP_QUIETLY_REMOTE;
  
    /* Always go on waiting for the target, regardless of the mode.  */
    /* FIXME: cagney/1999-09-23: At present it isn't possible to
       target_open() return to the caller an indication that the target
       is currently running and GDB state should be set to the same as
       for an async run.  */
-   wait_for_inferior ();
+   wait_for_inferior (inf);
  
    /* Now that the inferior has stopped, do any bookkeeping like
       loading shared libraries.  We want to do this before normal_stop,
@@@ -3093,7 -3240,7 +3241,7 @@@ init_wait_for_inferior (void
  
    clear_proceed_status (0);
  
-   target_last_wait_ptid = minus_one_ptid;
+   nullify_last_target_wait_ptid ();
  
    previous_inferior_ptid = inferior_ptid;
  }
@@@ -3123,11 -3270,13 +3271,13 @@@ static int switch_back_to_stepped_threa
  static void
  infrun_thread_stop_requested (ptid_t ptid)
  {
+   process_stratum_target *curr_target = current_inferior ()->process_target ();
    /* 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.  */
-   for (thread_info *tp : all_threads (ptid))
+   for (thread_info *tp : all_threads (curr_target, ptid))
      {
        if (tp->state != THREAD_RUNNING)
        continue;
  
        /* Clear the inline-frame state, since we're re-processing the
         stop.  */
-       clear_inline_frame_state (tp->ptid);
+       clear_inline_frame_state (tp);
  
        /* If this thread was paused because some other thread was
         doing an inline-step over, let that finish first.  Once
  static void
  infrun_thread_thread_exit (struct thread_info *tp, int silent)
  {
-   if (target_last_wait_ptid == tp->ptid)
+   if (target_last_proc_target == tp->inf->process_target ()
+       && target_last_wait_ptid == tp->ptid)
      nullify_last_target_wait_ptid ();
  }
  
@@@ -3268,19 -3418,20 +3419,20 @@@ print_target_wait_results (ptid_t waito
     had events.  */
  
  static struct thread_info *
- random_pending_event_thread (ptid_t waiton_ptid)
+ random_pending_event_thread (inferior *inf, ptid_t waiton_ptid)
  {
    int num_events = 0;
  
-   auto has_event = [] (thread_info *tp)
+   auto has_event = [&] (thread_info *tp)
      {
-       return (tp->resumed
+       return (tp->ptid.matches (waiton_ptid)
+             && tp->resumed
              && tp->suspend.waitstatus_pending_p);
      };
  
    /* First see how many events we have.  Count only resumed threads
       that have an event pending.  */
-   for (thread_info *tp : all_non_exited_threads (waiton_ptid))
+   for (thread_info *tp : inf->non_exited_threads ())
      if (has_event (tp))
        num_events++;
  
                        num_events, random_selector);
  
    /* Select the Nth thread that has had an event.  */
-   for (thread_info *tp : all_non_exited_threads (waiton_ptid))
+   for (thread_info *tp : inf->non_exited_threads ())
      if (has_event (tp))
        if (random_selector-- == 0)
        return tp;
  
  /* Wrapper for target_wait that first checks whether threads have
     pending statuses to report before actually asking the target for
-    more events.  */
+    more events.  INF is the inferior we're using to call target_wait
+    on.  */
  
  static ptid_t
- do_target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
+ do_target_wait_1 (inferior *inf, ptid_t ptid,
+                 target_waitstatus *status, int options)
  {
    ptid_t event_ptid;
    struct thread_info *tp;
       pending.  */
    if (ptid == minus_one_ptid || ptid.is_pid ())
      {
-       tp = random_pending_event_thread (ptid);
+       tp = random_pending_event_thread (inf, ptid);
      }
    else
      {
                            target_pid_to_str (ptid).c_str ());
  
        /* We have a specific thread to check.  */
-       tp = find_thread_ptid (ptid);
+       tp = find_thread_ptid (inf, ptid);
        gdb_assert (tp != NULL);
        if (!tp->suspend.waitstatus_pending_p)
        tp = NULL;
    return event_ptid;
  }
  
+ /* Returns true if INF has any resumed thread with a status
+    pending.  */
+ static bool
+ threads_are_resumed_pending_p (inferior *inf)
+ {
+   for (thread_info *tp : inf->non_exited_threads ())
+     if (tp->resumed
+       && tp->suspend.waitstatus_pending_p)
+       return true;
+   return false;
+ }
+ /* Wrapper for target_wait that first checks whether threads have
+    pending statuses to report before actually asking the target for
+    more events. Polls for events from all inferiors/targets.  */
+ static bool
+ do_target_wait (ptid_t wait_ptid, execution_control_state *ecs, int options)
+ {
+   int num_inferiors = 0;
+   int random_selector;
+   /* For fairness, we pick the first inferior/target to poll at
+      random, and then continue 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)
+     {
+       return (inf->process_target () != NULL
+             && (threads_are_executing (inf->process_target ())
+                 || threads_are_resumed_pending_p (inf))
+             && ptid_t (inf->pid).matches (wait_ptid));
+     };
+   /* First see how many resumed inferiors we have.  */
+   for (inferior *inf : all_inferiors ())
+     if (inferior_matches (inf))
+       num_inferiors++;
+   if (num_inferiors == 0)
+     {
+       ecs->ws.kind = TARGET_WAITKIND_IGNORE;
+       return false;
+     }
+   /* Now randomly pick an inferior out of those that were resumed.  */
+   random_selector = (int)
+     ((num_inferiors * (double) rand ()) / (RAND_MAX + 1.0));
+   if (debug_infrun && num_inferiors > 1)
+     fprintf_unfiltered (gdb_stdlog,
+                       "infrun: Found %d inferiors, starting at #%d\n",
+                       num_inferiors, random_selector);
+   /* Select the Nth inferior that was resumed.  */
+   inferior *selected = nullptr;
+   for (inferior *inf : all_inferiors ())
+     if (inferior_matches (inf))
+       if (random_selector-- == 0)
+       {
+         selected = inf;
+         break;
+       }
+   /* Now poll for events out of each of the resumed inferior's
+      targets, starting from the selected one.  */
+   auto do_wait = [&] (inferior *inf)
+   {
+     switch_to_inferior_no_thread (inf);
+     ecs->ptid = do_target_wait_1 (inf, wait_ptid, &ecs->ws, options);
+     ecs->target = inf->process_target ();
+     return (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
+   };
+   /* Needed in all-stop+target-non-stop mode, because we end up here
+      spuriously after the target is all stopped and we've already
+      reported the stop to the user, polling for events.  */
+   scoped_restore_current_thread restore_thread;
+   int inf_num = selected->num;
+   for (inferior *inf = selected; inf != NULL; inf = inf->next)
+     if (inferior_matches (inf))
+       if (do_wait (inf))
+       return true;
+   for (inferior *inf = inferior_list;
+        inf != NULL && inf->num < inf_num;
+        inf = inf->next)
+     if (inferior_matches (inf))
+       if (do_wait (inf))
+       return true;
+   ecs->ws.kind = TARGET_WAITKIND_IGNORE;
+   return false;
+ }
  /* 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
@@@ -3475,7 -3731,7 +3732,7 @@@ prepare_for_detach (void
         don't get any event.  */
        target_dcache_invalidate ();
  
-       ecs->ptid = do_target_wait (pid_ptid, &ecs->ws, 0);
+       do_target_wait (pid_ptid, ecs, 0);
  
        if (debug_infrun)
        print_target_wait_results (pid_ptid, ecs->ptid, &ecs->ws);
        /* 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 (minus_one_ptid);
+       scoped_finish_thread_state finish_state (inf->process_target (),
+                                              minus_one_ptid);
  
        /* Now figure out what to do with the result of the result.  */
        handle_inferior_event (ecs);
     When this function actually returns it means the inferior
     should be left stopped and GDB should read more commands.  */
  
- void
- wait_for_inferior (void)
static void
+ wait_for_inferior (inferior *inf)
  {
    if (debug_infrun)
      fprintf_unfiltered
    /* 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 (minus_one_ptid);
+   scoped_finish_thread_state finish_state
+     (inf->process_target (), minus_one_ptid);
  
    while (1)
      {
        struct execution_control_state ecss;
        struct execution_control_state *ecs = &ecss;
-       ptid_t waiton_ptid = minus_one_ptid;
  
        memset (ecs, 0, sizeof (*ecs));
  
         don't get any event.  */
        target_dcache_invalidate ();
  
-       ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, 0);
+       ecs->ptid = do_target_wait_1 (inf, minus_one_ptid, &ecs->ws, 0);
+       ecs->target = inf->process_target ();
  
        if (debug_infrun)
-       print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
+       print_target_wait_results (minus_one_ptid, ecs->ptid, &ecs->ws);
  
        /* Now figure out what to do with the result of the result.  */
        handle_inferior_event (ecs);
@@@ -3670,7 -3928,6 +3929,6 @@@ fetch_inferior_event (void *client_data
    struct execution_control_state ecss;
    struct execution_control_state *ecs = &ecss;
    int cmd_done = 0;
-   ptid_t waiton_ptid = minus_one_ptid;
  
    memset (ecs, 0, sizeof (*ecs));
  
        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.  */
-       maybe_restore_thread.emplace ();
+     /* The user/frontend should not notice a thread switch due to
+        internal events.  Make sure we revert to the user selected
+        thread and frame after handling the event and running any
+        breakpoint commands.  */
+     scoped_restore_current_thread restore_thread;
  
      overlay_cache_invalid = 1;
      /* Flush target cache before starting to handle each event.  Target
        = make_scoped_restore (&execution_direction,
                             target_execution_direction ());
  
-     ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws,
-                               target_can_async_p () ? TARGET_WNOHANG : 0);
+     if (!do_target_wait (minus_one_ptid, ecs, TARGET_WNOHANG))
+       return;
+     gdb_assert (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
+     /* Switch to the target that generated the event, so we can do
+        target calls.  Any inferior bound to the target will do, so we
+        just switch to the first we find.  */
+     for (inferior *inf : all_inferiors (ecs->target))
+       {
+       switch_to_inferior_no_thread (inf);
+       break;
+       }
  
      if (debug_infrun)
-       print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
+       print_target_wait_results (minus_one_ptid, ecs->ptid, &ecs->ws);
  
      /* If an error happens while handling the event, propagate GDB's
         knowledge of the executing state to the frontend/user running
         state.  */
      ptid_t finish_ptid = !target_is_non_stop_p () ? minus_one_ptid : ecs->ptid;
-     scoped_finish_thread_state finish_state (finish_ptid);
+     scoped_finish_thread_state finish_state (ecs->target, finish_ptid);
  
      /* Get executed before scoped_restore_current_thread above to apply
         still for the thread which has thrown the exception.  */
  
      if (!ecs->wait_some_more)
        {
-       struct inferior *inf = find_inferior_ptid (ecs->ptid);
+       struct inferior *inf = find_inferior_ptid (ecs->target, ecs->ptid);
        int should_stop = 1;
        struct thread_info *thr = ecs->event_thread;
  
                inferior_event_handler (INF_EXEC_COMPLETE, NULL);
                cmd_done = 1;
              }
+           /* If we got a TARGET_WAITKIND_NO_RESUMED event, then the
+              previously selected thread is gone.  We have two
+              choices - switch to no thread selected, or restore the
+              previously selected thread (now exited).  We chose the
+              later, just because that's what GDB used to do.  After
+              this, "info threads" says "The current thread <Thread
+              ID 2> has terminated." instead of "No thread
+              selected.".  */
+           if (!non_stop
+               && cmd_done
+               && ecs->ws.kind != TARGET_WAITKIND_NO_RESUMED)
+             restore_thread.dont_restore ();
          }
        }
  
@@@ -3827,31 -4105,39 +4106,39 @@@ init_thread_stepping_state (struct thre
    tss->step_after_step_resume_breakpoint = 0;
  }
  
- /* Set the cached copy of the last ptid/waitstatus.  */
+ /* See infrun.h.  */
  
  void
- set_last_target_status (ptid_t ptid, struct target_waitstatus status)
+ set_last_target_status (process_stratum_target *target, ptid_t ptid,
+                       target_waitstatus status)
  {
+   target_last_proc_target = target;
    target_last_wait_ptid = ptid;
    target_last_waitstatus = status;
  }
  
- /* Return the cached copy of the last pid/waitstatus returned by
-    target_wait()/deprecated_target_wait_hook().  The data is actually
-    cached by handle_inferior_event(), which gets called immediately
-    after target_wait()/deprecated_target_wait_hook().  */
+ /* See infrun.h.  */
  
  void
- get_last_target_status (ptid_t *ptidp, struct target_waitstatus *status)
+ get_last_target_status (process_stratum_target **target, ptid_t *ptid,
+                       target_waitstatus *status)
  {
-   *ptidp = target_last_wait_ptid;
-   *status = target_last_waitstatus;
+   if (target != nullptr)
+     *target = target_last_proc_target;
+   if (ptid != nullptr)
+     *ptid = target_last_wait_ptid;
+   if (status != nullptr)
+     *status = target_last_waitstatus;
  }
  
+ /* See infrun.h.  */
  void
  nullify_last_target_wait_ptid (void)
  {
+   target_last_proc_target = nullptr;
    target_last_wait_ptid = minus_one_ptid;
+   target_last_waitstatus = {};
  }
  
  /* Switch thread contexts.  */
@@@ -3861,7 -4147,8 +4148,8 @@@ context_switch (execution_control_stat
  {
    if (debug_infrun
        && ecs->ptid != inferior_ptid
-       && ecs->event_thread != inferior_thread ())
+       && (inferior_ptid == null_ptid
+         || ecs->event_thread != inferior_thread ()))
      {
        fprintf_unfiltered (gdb_stdlog, "infrun: Switching context from %s ",
                          target_pid_to_str (inferior_ptid).c_str ());
@@@ -4186,20 -4473,19 +4474,19 @@@ fill_in_stop_func (struct gdbarch *gdba
  static enum stop_kind
  get_inferior_stop_soon (execution_control_state *ecs)
  {
-   struct inferior *inf = find_inferior_ptid (ecs->ptid);
+   struct inferior *inf = find_inferior_ptid (ecs->target, ecs->ptid);
  
    gdb_assert (inf != NULL);
    return inf->control.stop_soon;
  }
  
- /* Wait for one event.  Store the resulting waitstatus in WS, and
-    return the event ptid.  */
+ /* Poll for one event out of the current target.  Store the resulting
+    waitstatus in WS, and return the event ptid.  Does not block.  */
  
  static ptid_t
wait_one (struct target_waitstatus *ws)
poll_one_curr_target (struct target_waitstatus *ws)
  {
    ptid_t event_ptid;
-   ptid_t wait_ptid = minus_one_ptid;
  
    overlay_cache_invalid = 1;
  
    target_dcache_invalidate ();
  
    if (deprecated_target_wait_hook)
-     event_ptid = deprecated_target_wait_hook (wait_ptid, ws, 0);
+     event_ptid = deprecated_target_wait_hook (minus_one_ptid, ws, TARGET_WNOHANG);
    else
-     event_ptid = target_wait (wait_ptid, ws, 0);
+     event_ptid = target_wait (minus_one_ptid, ws, TARGET_WNOHANG);
  
    if (debug_infrun)
-     print_target_wait_results (wait_ptid, event_ptid, ws);
+     print_target_wait_results (minus_one_ptid, event_ptid, 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
+ wait_one ()
+ {
+   while (1)
+     {
+       for (inferior *inf : all_inferiors ())
+       {
+         process_stratum_target *target = inf->process_target ();
+         if (target == NULL
+             || !target->is_async_p ()
+             || !target->threads_executing)
+           continue;
+         switch_to_inferior_no_thread (inf);
+         wait_one_event event;
+         event.target = target;
+         event.ptid = poll_one_curr_target (&event.ws);
+         if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED)
+           {
+             /* If nothing is resumed, remove the target from the
+                event loop.  */
+             target_async (0);
+           }
+         else if (event.ws.kind != TARGET_WAITKIND_IGNORE)
+           return event;
+       }
+       /* Block waiting for some event.  */
+       fd_set readfds;
+       int nfds = 0;
+       FD_ZERO (&readfds);
+       for (inferior *inf : all_inferiors ())
+       {
+         process_stratum_target *target = inf->process_target ();
+         if (target == NULL
+             || !target->is_async_p ()
+             || !target->threads_executing)
+           continue;
+         int fd = target->async_wait_fd ();
+         FD_SET (fd, &readfds);
+         if (nfds <= fd)
+           nfds = fd + 1;
+       }
+       if (nfds == 0)
+       {
+         /* No waitable targets left.  All must be stopped.  */
+         return {NULL, minus_one_ptid, {TARGET_WAITKIND_NO_RESUMED}};
+       }
+       QUIT;
+       int numfds = interruptible_select (nfds, &readfds, 0, NULL, 0);
+       if (numfds < 0)
+       {
+         if (errno == EINTR)
+           continue;
+         else
+           perror_with_name ("interruptible_select");
+       }
+     }
+ }
  /* Generate a wrapper for target_stopped_by_REASON that works on PTID
     instead of the current thread.  */
  #define THREAD_STOPPED_BY(REASON)             \
@@@ -4242,7 -4613,7 +4614,7 @@@ THREAD_STOPPED_BY (hw_breakpoint
  /* Save the thread's event and stop reason to process it later.  */
  
  static void
- save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws)
+ save_waitstatus (struct thread_info *tp, const target_waitstatus *ws)
  {
    if (debug_infrun)
      {
@@@ -4342,8 -4713,6 +4714,6 @@@ stop_all_threads (void
                            "iterations=%d\n", pass, iterations);
        while (1)
        {
-         ptid_t event_ptid;
-         struct target_waitstatus ws;
          int need_wait = 0;
  
          update_thread_list ();
                                            "infrun:   %s executing, "
                                            "need stop\n",
                                            target_pid_to_str (t->ptid).c_str ());
+                     switch_to_thread_no_regs (t);
                      target_stop (t->ptid);
                      t->stop_requested = 1;
                    }
          if (pass > 0)
            pass = -1;
  
-         event_ptid = wait_one (&ws);
+         wait_one_event event = wait_one ();
          if (debug_infrun)
            {
              fprintf_unfiltered (gdb_stdlog,
                                  "infrun: stop_all_threads %s %s\n",
-                                 target_waitstatus_to_string (&ws).c_str (),
-                                 target_pid_to_str (event_ptid).c_str ());
+                                 target_waitstatus_to_string (&event.ws).c_str (),
+                                 target_pid_to_str (event.ptid).c_str ());
            }
  
-         if (ws.kind == TARGET_WAITKIND_NO_RESUMED
-             || ws.kind == TARGET_WAITKIND_THREAD_EXITED
-             || ws.kind == TARGET_WAITKIND_EXITED
-             || ws.kind == TARGET_WAITKIND_SIGNALLED)
+         if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED
+             || event.ws.kind == TARGET_WAITKIND_THREAD_EXITED
+             || event.ws.kind == TARGET_WAITKIND_EXITED
+             || event.ws.kind == TARGET_WAITKIND_SIGNALLED)
            {
              /* All resumed threads exited
                 or one thread/process exited/signalled.  */
            }
          else
            {
-             thread_info *t = find_thread_ptid (event_ptid);
+             thread_info *t = find_thread_ptid (event.target, event.ptid);
              if (t == NULL)
-               t = add_thread (event_ptid);
+               t = add_thread (event.target, event.ptid);
  
              t->stop_requested = 0;
              t->executing = 0;
  
              /* This may be the first time we see the inferior report
                 a stop.  */
-             inferior *inf = find_inferior_ptid (event_ptid);
+             inferior *inf = find_inferior_ptid (event.target, 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)
+             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.  */
  
                  if (debug_infrun)
                    {
-                     std::string statstr = target_waitstatus_to_string (&ws);
+                     std::string statstr = target_waitstatus_to_string (&event.ws);
  
                      fprintf_unfiltered (gdb_stdlog,
                                          "infrun: target_wait %s, saving "
                    }
  
                  /* Record for later.  */
-                 save_waitstatus (t, &ws);
+                 save_waitstatus (t, &event.ws);
  
-                 sig = (ws.kind == TARGET_WAITKIND_STOPPED
-                        ? ws.value.sig : GDB_SIGNAL_0);
+                 sig = (event.ws.kind == TARGET_WAITKIND_STOPPED
+                        ? event.ws.value.sig : GDB_SIGNAL_0);
  
                  if (displaced_step_fixup (t, sig) < 0)
                    {
@@@ -4580,7 -4951,7 +4952,7 @@@ handle_no_resumed (struct execution_con
       the synchronous command show "no unwaited-for " to the user.  */
    update_thread_list ();
  
-   for (thread_info *thread : all_non_exited_threads ())
+   for (thread_info *thread : all_non_exited_threads (ecs->target))
      {
        if (thread->executing
          || thread->suspend.waitstatus_pending_p)
       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.  */
-   for (inferior *inf : all_inferiors ())
+   for (inferior *inf : all_non_exited_inferiors (ecs->target))
      {
-       if (inf->pid == 0)
-       continue;
        thread_info *thread = any_live_thread_of_inferior (inf);
        if (thread == NULL)
        {
@@@ -4673,8 -5041,8 +5042,8 @@@ handle_inferior_event (struct execution
        && handle_no_resumed (ecs))
      return;
  
-   /* Cache the last pid/waitstatus.  */
-   set_last_target_status (ecs->ptid, ecs->ws);
+   /* Cache the last target/ptid/waitstatus.  */
+   set_last_target_status (ecs->target, ecs->ptid, ecs->ws);
  
    /* Always clear state belonging to the previous time we stopped.  */
    stop_stack_dummy = STOP_NONE;
    if (ecs->ws.kind != TARGET_WAITKIND_EXITED
        && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED)
      {
-       ecs->event_thread = find_thread_ptid (ecs->ptid);
+       ecs->event_thread = find_thread_ptid (ecs->target, ecs->ptid);
        /* If it's a new thread, add it to the thread database.  */
        if (ecs->event_thread == NULL)
-       ecs->event_thread = add_thread (ecs->ptid);
+       ecs->event_thread = add_thread (ecs->target, ecs->ptid);
  
        /* Disable range stepping.  If the next step request could use a
         range, this will be end up re-enabled then.  */
      else
        mark_ptid = ecs->ptid;
  
-     set_executing (mark_ptid, 0);
+     set_executing (ecs->target, mark_ptid, 0);
  
      /* Likewise the resumed flag.  */
-     set_resumed (mark_ptid, 0);
+     set_resumed (ecs->target, mark_ptid, 0);
    }
  
    switch (ecs->ws.kind)
      case TARGET_WAITKIND_EXITED:
      case TARGET_WAITKIND_SIGNALLED:
        inferior_ptid = ecs->ptid;
-       set_current_inferior (find_inferior_ptid (ecs->ptid));
+       set_current_inferior (find_inferior_ptid (ecs->target, 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.  */
@@@ -4943,7 -5311,7 +5312,7 @@@ Cannot fill $_exitsignal with the corre
        if (displaced_step_in_progress_thread (ecs->event_thread))
          {
            struct inferior *parent_inf
-             = find_inferior_ptid (ecs->ptid);
+             = find_inferior_ptid (ecs->target, ecs->ptid);
            struct regcache *child_regcache;
            CORE_ADDR parent_pc;
  
               list yet at this point.  */
  
            child_regcache
-             = get_thread_arch_aspace_regcache (ecs->ws.value.related_pid,
+             = get_thread_arch_aspace_regcache (parent_inf->process_target (),
+                                                ecs->ws.value.related_pid,
                                                 gdbarch,
                                                 parent_inf->aspace);
            /* Read PC value of parent process.  */
  
          ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
  
+         process_stratum_target *targ
+           = ecs->event_thread->inf->process_target ();
          should_resume = follow_fork ();
  
+         /* Note that one of these may be an invalid pointer,
+            depending on detach_fork.  */
          thread_info *parent = ecs->event_thread;
-         thread_info *child = find_thread_ptid (ecs->ws.value.related_pid);
+         thread_info *child
+           = find_thread_ptid (targ, ecs->ws.value.related_pid);
  
          /* At this point, the parent is marked running, and the
             child is marked stopped.  */
@@@ -5207,6 -5582,8 +5583,8 @@@ restart_threads (struct thread_info *ev
  
    for (thread_info *tp : all_non_exited_threads ())
      {
+       switch_to_thread_no_regs (tp);
        if (tp == event_thread)
        {
          if (debug_infrun)
@@@ -5360,12 -5737,7 +5738,12 @@@ finish_step_over (struct execution_cont
        context_switch (ecs);
        insert_breakpoints ();
  
 -      restart_threads (ecs->event_thread);
 +      {
 +        scoped_restore save_defer_tc
 +          = make_scoped_defer_target_commit_resume ();
 +        restart_threads (ecs->event_thread);
 +      }
 +      target_commit_resume ();
  
        /* If we have events pending, go through handle_inferior_event
         again, picking up a pending event at random.  This avoids
@@@ -5470,9 -5842,8 +5848,8 @@@ handle_signal_stop (struct execution_co
      {
        struct regcache *regcache = get_thread_regcache (ecs->event_thread);
        struct gdbarch *reg_gdbarch = regcache->arch ();
-       scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
  
-       inferior_ptid = ecs->ptid;
+       switch_to_thread (ecs->event_thread);
  
        fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n",
                          paddress (reg_gdbarch,
    if (random_signal)
      {
        /* Signal not for debugging purposes.  */
-       struct inferior *inf = find_inferior_ptid (ecs->ptid);
+       struct inferior *inf = find_inferior_ptid (ecs->target, ecs->ptid);
        enum gdb_signal stop_signal = ecs->event_thread->suspend.stop_signal;
  
        if (debug_infrun)
@@@ -6915,10 -7286,13 +7292,13 @@@ switch_back_to_stepped_thread (struct e
  
        for (thread_info *tp : all_non_exited_threads ())
          {
+         switch_to_thread_no_regs (tp);
          /* Ignore threads of processes the caller is not
             resuming.  */
          if (!sched_multi
-             && tp->ptid.pid () != ecs->ptid.pid ())
+             && (tp->inf->process_target () != ecs->target
+                 || tp->inf->pid != ecs->ptid.pid ()))
            continue;
  
          /* When stepping over a breakpoint, we lock all threads
              return 1;
            }
        }
+       switch_to_thread (ecs->event_thread);
      }
  
    return 0;
@@@ -7855,10 -8231,9 +8237,9 @@@ voi
  print_stop_event (struct ui_out *uiout, bool displays)
  {
    struct target_waitstatus last;
-   ptid_t last_ptid;
    struct thread_info *tp;
  
-   get_last_target_status (&last_ptid, &last);
+   get_last_target_status (nullptr, nullptr, &last);
  
    {
      scoped_restore save_uiout = make_scoped_restore (&current_uiout, uiout);
@@@ -7977,9 -8352,8 +8358,8 @@@ in
  normal_stop (void)
  {
    struct target_waitstatus last;
-   ptid_t last_ptid;
  
-   get_last_target_status (&last_ptid, &last);
+   get_last_target_status (nullptr, nullptr, &last);
  
    new_stop_id ();
  
       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;
+   ptid_t finish_ptid = null_ptid;
  
    if (!non_stop)
-     maybe_finish_thread_state.emplace (minus_one_ptid);
+     finish_ptid = minus_one_ptid;
    else if (last.kind == TARGET_WAITKIND_SIGNALLED
           || last.kind == TARGET_WAITKIND_EXITED)
      {
         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 ()));
+       finish_ptid = ptid_t (inferior_ptid.pid ());
      }
    else if (last.kind != TARGET_WAITKIND_NO_RESUMED)
-     maybe_finish_thread_state.emplace (inferior_ptid);
+     finish_ptid = inferior_ptid;
+   gdb::optional<scoped_finish_thread_state> maybe_finish_thread_state;
+   if (finish_ptid != null_ptid)
+     {
+       maybe_finish_thread_state.emplace
+       (user_visible_resume_target (finish_ptid), finish_ptid);
+     }
  
    /* As we're presenting a stop, and potentially removing breakpoints,
       update the thread list so we can tell whether there are threads
diff --combined gdb/inline-frame.c
index 2ba57b06dfdc9e68deea938858847b400e4b1377,0ee1de3a1f1c6a423eec4486e5beb7090520d2f5..ae0af2e5a523797b1c1c1ca27bcebe9559fde726
@@@ -1,7 -1,6 +1,7 @@@
  /* Inline frame unwinder for GDB.
  
     Copyright (C) 2008-2020 Free Software Foundation, Inc.
 +   Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
  
     This file is part of GDB.
  
@@@ -96,37 -95,54 +96,54 @@@ find_inline_frame_state (thread_info *t
    return &state;
  }
  
- /* Forget about any hidden inlined functions in PTID, which is new or
-    about to be resumed.  PTID may be minus_one_ptid (all processes)
-    or a PID (all threads in this process).  */
+ /* See inline-frame.h.  */
  
  void
- clear_inline_frame_state (ptid_t ptid)
+ clear_inline_frame_state (process_stratum_target *target, ptid_t filter_ptid)
  {
-   if (ptid == minus_one_ptid)
-     {
-       inline_states.clear ();
-       return;
-     }
+   gdb_assert (target != NULL);
  
-   if (ptid.is_pid ())
+   if (filter_ptid == minus_one_ptid || filter_ptid.is_pid ())
      {
-       int pid = ptid.pid ();
+       auto matcher = [target, &filter_ptid] (const inline_state &state)
+       {
+         thread_info *t = state.thread;
+         return (t->inf->process_target () == target
+                 && t->ptid.matches (filter_ptid));
+       };
        auto it = std::remove_if (inline_states.begin (), inline_states.end (),
-                               [pid] (const inline_state &state)
-                                 {
-                                   return pid == state.thread->inf->pid;
-                                 });
+                               matcher);
  
        inline_states.erase (it, inline_states.end ());
  
        return;
      }
  
+   auto matcher = [target, &filter_ptid] (const inline_state &state)
+     {
+       thread_info *t = state.thread;
+       return (t->inf->process_target () == target
+             && filter_ptid == t->ptid);
+     };
+   auto it = std::find_if (inline_states.begin (), inline_states.end (),
+                         matcher);
+   if (it != inline_states.end ())
+     unordered_remove (inline_states, it);
+ }
+ /* See inline-frame.h.  */
+ void
+ clear_inline_frame_state (thread_info *thread)
+ {
    auto it = std::find_if (inline_states.begin (), inline_states.end (),
-                         [&ptid] (const inline_state &state)
+                         [thread] (const inline_state &state)
                            {
-                             return ptid == state.thread->ptid;
+                             return thread == state.thread;
                            });
  
    if (it != inline_states.end ())
@@@ -155,6 -171,10 +172,6 @@@ inline_frame_this_id (struct frame_inf
       frame").  This will take work.  */
    gdb_assert (frame_id_p (*this_id));
  
 -  /* For now, require we don't match outer_frame_id either (see
 -     comment above).  */
 -  gdb_assert (!frame_id_eq (*this_id, outer_frame_id));
 -
    /* Future work NOTE: Alexandre Oliva applied a patch to GCC 4.3
       which generates DW_AT_entry_pc for inlined functions when
       possible.  If this attribute is available, we should use it
This page took 0.055938 seconds and 4 git commands to generate.