Automatic date update in version.in
[binutils-gdb.git] / gdb / gdbthread.h
index 81dc7edb6b7e0cc9c3332e14914f12b4768cbb67..1a33eb612213648359fb287deeea54c80b4ade56 100644 (file)
@@ -1,5 +1,5 @@
 /* Multi-process/thread control defs for GDB, the GNU debugger.
-   Copyright (C) 1987-2013 Free Software Foundation, Inc.
+   Copyright (C) 1987-2022 Free Software Foundation, Inc.
    Contributed by Lynx Real-Time Systems, Inc.  Los Gatos, CA.
    
 
@@ -26,18 +26,70 @@ struct symtab;
 #include "breakpoint.h"
 #include "frame.h"
 #include "ui-out.h"
-#include "inferior.h"
 #include "btrace.h"
+#include "target/waitstatus.h"
+#include "cli/cli-utils.h"
+#include "gdbsupport/refcounted-object.h"
+#include "gdbsupport/common-gdbthread.h"
+#include "gdbsupport/forward-scope-exit.h"
+#include "displaced-stepping.h"
+#include "gdbsupport/intrusive_list.h"
+#include "thread-fsm.h"
+
+struct inferior;
+struct process_stratum_target;
+
+/* When true, print debug messages related to GDB thread creation and
+   deletion.  */
+
+extern bool debug_threads;
+
+/* Print a "threads" debug statement.  */
+
+#define threads_debug_printf(fmt, ...) \
+  debug_prefixed_printf_cond (debug_threads, "threads", fmt, ##__VA_ARGS__)
 
 /* Frontend view of the thread state.  Possible extensions: stepping,
-   finishing, until(ling),...  */
+   finishing, until(ling),...
+
+   NOTE: Since the thread state is not a boolean, most times, you do
+   not want to check it with negation.  If you really want to check if
+   the thread is stopped,
+
+    use (good):
+
+     if (tp->state == THREAD_STOPPED)
+
+    instead of (bad):
+
+     if (tp->state != THREAD_RUNNING)
+
+   The latter is also true for exited threads, most likely not what
+   you want.  */
 enum thread_state
 {
+  /* In the frontend's perpective, the thread is stopped.  */
   THREAD_STOPPED,
+
+  /* In the frontend's perpective, the thread is running.  */
   THREAD_RUNNING,
+
+  /* The thread is listed, but known to have exited.  We keep it
+     listed (but not visible) until it's safe to delete it.  */
   THREAD_EXITED,
 };
 
+/* STEP_OVER_ALL means step over all subroutine calls.
+   STEP_OVER_UNDEBUGGABLE means step over calls to undebuggable functions.
+   STEP_OVER_NONE means don't step over any subroutine calls.  */
+
+enum step_over_calls_kind
+  {
+    STEP_OVER_NONE,
+    STEP_OVER_ALL,
+    STEP_OVER_UNDEBUGGABLE
+  };
+
 /* Inferior thread specific part of `struct infcall_control_state'.
 
    Inferior process counterpart is `struct inferior_control_state'.  */
@@ -47,10 +99,17 @@ struct thread_control_state
   /* User/external stepping state.  */
 
   /* Step-resume or longjmp-resume breakpoint.  */
-  struct breakpoint *step_resume_breakpoint;
+  struct breakpoint *step_resume_breakpoint = nullptr;
 
   /* Exception-resume breakpoint.  */
-  struct breakpoint *exception_resume_breakpoint;
+  struct breakpoint *exception_resume_breakpoint = nullptr;
+
+  /* Breakpoints used for software single stepping.  Plural, because
+     it may have multiple locations.  E.g., if stepping over a
+     conditional branch instruction we can't decode the condition for,
+     we'll need to put a breakpoint at the branch destination, and
+     another at the instruction after the branch.  */
+  struct breakpoint *single_step_breakpoints = nullptr;
 
   /* Range to single step within.
 
@@ -62,8 +121,11 @@ struct thread_control_state
      wait_for_inferior in a minor way if this were changed to the
      address of the instruction and that address plus one.  But maybe
      not).  */
-  CORE_ADDR step_range_start;  /* Inclusive */
-  CORE_ADDR step_range_end;    /* Exclusive */
+  CORE_ADDR step_range_start = 0;      /* Inclusive */
+  CORE_ADDR step_range_end = 0;                /* Exclusive */
+
+  /* Function the thread was in as of last it started stepping.  */
+  struct symbol *step_start_function = nullptr;
 
   /* If GDB issues a target step request, and this is nonzero, the
      target should single-step this thread once, and then continue
@@ -71,122 +133,368 @@ struct thread_control_state
      thread stops in the step range above.  If this is zero, the
      target should ignore the step range, and only issue one single
      step.  */
-  int may_range_step;
+  int may_range_step = 0;
 
   /* Stack frame address as of when stepping command was issued.
      This is how we know when we step into a subroutine call, and how
      to set the frame for the breakpoint used to step out.  */
-  struct frame_id step_frame_id;
+  struct frame_id step_frame_id {};
 
   /* Similarly, the frame ID of the underlying stack frame (skipping
      any inlined frames).  */
-  struct frame_id step_stack_frame_id;
-
-  /* Nonzero if we are presently stepping over a breakpoint.
-
-     If we hit a breakpoint or watchpoint, and then continue, we need
-     to single step the current thread with breakpoints disabled, to
-     avoid hitting the same breakpoint or watchpoint again.  And we
-     should step just a single thread and keep other threads stopped,
-     so that other threads don't miss breakpoints while they are
-     removed.
-
-     So, this variable simultaneously means that we need to single
-     step the current thread, keep other threads stopped, and that
-     breakpoints should be removed while we step.
-
-     This variable is set either:
-     - in proceed, when we resume inferior on user's explicit request
-     - in keep_going, if handle_inferior_event decides we need to
-     step over breakpoint.
+  struct frame_id step_stack_frame_id {};
 
-     The variable is cleared in normal_stop.  The proceed calls
-     wait_for_inferior, which calls handle_inferior_event in a loop,
-     and until wait_for_inferior exits, this variable is changed only
-     by keep_going.  */
-  int trap_expected;
+  /* True if the the thread is presently stepping over a breakpoint or
+     a watchpoint, either with an inline step over or a displaced (out
+     of line) step, and we're now expecting it to report a trap for
+     the finished single step.  */
+  int trap_expected = 0;
 
   /* Nonzero if the thread is being proceeded for a "finish" command
-     or a similar situation when stop_registers should be saved.  */
-  int proceed_to_finish;
+     or a similar situation when return value should be printed.  */
+  int proceed_to_finish = 0;
 
   /* Nonzero if the thread is being proceeded for an inferior function
      call.  */
-  int in_infcall;
+  int in_infcall = 0;
 
-  enum step_over_calls_kind step_over_calls;
+  enum step_over_calls_kind step_over_calls = STEP_OVER_NONE;
 
   /* Nonzero if stopped due to a step command.  */
-  int stop_step;
+  int stop_step = 0;
 
   /* Chain containing status of breakpoint(s) the thread stopped
      at.  */
-  bpstat stop_bpstat;
-};
+  bpstat *stop_bpstat = nullptr;
 
-/* Inferior thread specific part of `struct infcall_suspend_state'.
+  /* Whether the command that started the thread was a stepping
+     command.  This is used to decide whether "set scheduler-locking
+     step" behaves like "on" or "off".  */
+  int stepping_command = 0;
+};
 
-   Inferior process counterpart is `struct inferior_suspend_state'.  */
+/* Inferior thread specific part of `struct infcall_suspend_state'.  */
 
 struct thread_suspend_state
 {
-  /* Last signal that the inferior received (why it stopped).  */
-  enum gdb_signal stop_signal;
+  /* Last signal that the inferior received (why it stopped).  When
+     the thread is resumed, this signal is delivered.  Note: the
+     target should not check whether the signal is in pass state,
+     because the signal may have been explicitly passed with the
+     "signal" command, which overrides "handle nopass".  If the signal
+     should be suppressed, the core will take care of clearing this
+     before the target is resumed.  */
+  enum gdb_signal stop_signal = GDB_SIGNAL_0;
+
+  /* The reason the thread last stopped, if we need to track it
+     (breakpoint, watchpoint, etc.)  */
+  enum target_stop_reason stop_reason = TARGET_STOPPED_BY_NO_REASON;
+
+  /* The waitstatus for this thread's last event.  */
+  struct target_waitstatus waitstatus;
+  /* If true WAITSTATUS hasn't been handled yet.  */
+  int waitstatus_pending_p = 0;
+
+  /* Record the pc of the thread the last time it stopped.  (This is
+     not the current thread's PC as that may have changed since the
+     last stop, e.g., "return" command, or "p $pc = 0xf000").
+
+     - If the thread's PC has not changed since the thread last
+       stopped, then proceed skips a breakpoint at the current PC,
+       otherwise we let the thread run into the breakpoint.
+
+     - If the thread has an unprocessed event pending, as indicated by
+       waitstatus_pending_p, this is used in coordination with
+       stop_reason: if the thread's PC has changed since the thread
+       last stopped, a pending breakpoint waitstatus is discarded.
+
+     - If the thread is running, then this field has its value removed by
+       calling stop_pc.reset() (see thread_info::set_executing()).
+       Attempting to read a gdb::optional with no value is undefined
+       behaviour and will trigger an assertion error when _GLIBCXX_DEBUG is
+       defined, which should make error easier to track down.  */
+  gdb::optional<CORE_ADDR> stop_pc;
+};
+
+/* Base class for target-specific thread data.  */
+struct private_thread_info
+{
+  virtual ~private_thread_info () = 0;
 };
 
-struct thread_info
+/* Threads are intrusively refcounted objects.  Being the
+   user-selected thread is normally considered an implicit strong
+   reference and is thus not accounted in the refcount, unlike
+   inferior objects.  This is necessary, because there's no "current
+   thread" pointer.  Instead the current thread is inferred from the
+   inferior_ptid global.  However, when GDB needs to remember the
+   selected thread to later restore it, GDB bumps the thread object's
+   refcount, to prevent something deleting the thread object before
+   reverting back (e.g., due to a "kill" command).  If the thread
+   meanwhile exits before being re-selected, then the thread object is
+   left listed in the thread list, but marked with state
+   THREAD_EXITED.  (See scoped_restore_current_thread and
+   delete_thread).  All other thread references are considered weak
+   references.  Placing a thread in the thread list is an implicit
+   strong reference, and is thus not accounted for in the thread's
+   refcount.
+
+   The intrusive_list_node base links threads in a per-inferior list.  */
+
+class thread_info : public refcounted_object,
+                   public intrusive_list_node<thread_info>
 {
-  struct thread_info *next;
+public:
+  explicit thread_info (inferior *inf, ptid_t ptid);
+  ~thread_info ();
+
+  bool deletable () const;
+
+  /* Mark this thread as running and notify observers.  */
+  void set_running (bool running);
+
   ptid_t ptid;                 /* "Actual process id";
                                    In fact, this may be overloaded with 
                                    kernel thread id, etc.  */
-  int num;                     /* Convenient handle (GDB thread id) */
 
-  /* The name of the thread, as specified by the user.  This is NULL
-     if the thread does not have a user-given name.  */
-  char *name;
+  /* Each thread has two GDB IDs.
 
-  /* Non-zero means the thread is executing.  Note: this is different
-     from saying that there is an active target and we are stopped at
-     a breakpoint, for instance.  This is a real indicator whether the
-     thread is off and running.  */
-  int executing;
-
-  /* Frontend view of the thread state.  Note that the RUNNING/STOPPED
-     states are different from EXECUTING.  When the thread is stopped
-     internally while handling an internal event, like a software
-     single-step breakpoint, EXECUTING will be false, but running will
-     still be true.  As a possible future extension, this could turn
-     into enum { stopped, exited, stepping, finishing, until(ling),
-     running ... }  */
-  int state;
-
-  /* If this is > 0, then it means there's code out there that relies
-     on this thread being listed.  Don't delete it from the lists even
-     if we detect it exiting.  */
-  int refcount;
+     a) The thread ID (Id).  This consists of the pair of:
+
+       - the number of the thread's inferior and,
+
+       - the thread's thread number in its inferior, aka, the
+         per-inferior thread number.  This number is unique in the
+         inferior but not unique between inferiors.
+
+     b) The global ID (GId).  This is a a single integer unique
+       between all inferiors.
+
+     E.g.:
+
+      (gdb) info threads -gid
+       Id    GId   Target Id   Frame
+      * 1.1   1     Thread A    0x16a09237 in foo () at foo.c:10
+       1.2   3     Thread B    0x15ebc6ed in bar () at foo.c:20
+       1.3   5     Thread C    0x15ebc6ed in bar () at foo.c:20
+       2.1   2     Thread A    0x16a09237 in foo () at foo.c:10
+       2.2   4     Thread B    0x15ebc6ed in bar () at foo.c:20
+       2.3   6     Thread C    0x15ebc6ed in bar () at foo.c:20
+
+     Above, both inferiors 1 and 2 have threads numbered 1-3, but each
+     thread has its own unique global ID.  */
+
+  /* The thread's global GDB thread number.  This is exposed to MI,
+     Python/Scheme, visible with "info threads -gid", and is also what
+     the $_gthread convenience variable is bound to.  */
+  int global_num;
+
+  /* The per-inferior thread number.  This is unique in the inferior
+     the thread belongs to, but not unique between inferiors.  This is
+     what the $_thread convenience variable is bound to.  */
+  int per_inf_num;
+
+  /* The inferior this thread belongs to.  */
+  struct inferior *inf;
+
+  /* The user-given name of the thread.
+
+     Returns nullptr if the thread does not have a user-given name.  */
+  const char *name () const
+  {
+    return m_name.get ();
+  }
+
+  /* Set the user-given name of the thread.
+
+     Pass nullptr to clear the name.  */
+  void set_name (gdb::unique_xmalloc_ptr<char> name)
+  {
+    m_name = std::move (name);
+  }
+
+  bool executing () const
+  { return m_executing; }
+
+  /* Set the thread's 'm_executing' field from EXECUTING, and if EXECUTING
+     is true also clears the thread's stop_pc.  */
+  void set_executing (bool executing);
+
+  bool resumed () const
+  { return m_resumed; }
+
+  /* Set the thread's 'm_resumed' field from RESUMED.  The thread may also
+     be added to (when RESUMED is true), or removed from (when RESUMED is
+     false), the list of threads with a pending wait status.  */
+  void set_resumed (bool resumed);
+
+  /* Frontend view of the thread state.  Note that the THREAD_RUNNING/
+     THREAD_STOPPED states are different from EXECUTING.  When the
+     thread is stopped internally while handling an internal event,
+     like a software single-step breakpoint, EXECUTING will be false,
+     but STATE will still be THREAD_RUNNING.  */
+  enum thread_state state = THREAD_STOPPED;
 
   /* State of GDB control of inferior thread execution.
      See `struct thread_control_state'.  */
-  struct thread_control_state control;
+  thread_control_state control;
 
-  /* State of inferior thread to restore after GDB is done with an inferior
-     call.  See `struct thread_suspend_state'.  */
-  struct thread_suspend_state suspend;
+  /* Save M_SUSPEND to SUSPEND.  */
+
+  void save_suspend_to (thread_suspend_state &suspend) const
+  {
+    suspend = m_suspend;
+  }
+
+  /* Restore M_SUSPEND from SUSPEND.  */
+
+  void restore_suspend_from (const thread_suspend_state &suspend)
+  {
+    m_suspend = suspend;
+  }
+
+  /* Return this thread's stop PC.  This should only be called when it is
+     known that stop_pc has a value.  If this function is being used in a
+     situation where a thread may not have had a stop_pc assigned, then
+     stop_pc_p() can be used to check if the stop_pc is defined.  */
+
+  CORE_ADDR stop_pc () const
+  {
+    gdb_assert (m_suspend.stop_pc.has_value ());
+    return *m_suspend.stop_pc;
+  }
+
+  /* Set this thread's stop PC.  */
+
+  void set_stop_pc (CORE_ADDR stop_pc)
+  {
+    m_suspend.stop_pc = stop_pc;
+  }
+
+  /* Remove the stop_pc stored on this thread.  */
+
+  void clear_stop_pc ()
+  {
+    m_suspend.stop_pc.reset ();
+  }
+
+  /* Return true if this thread has a cached stop pc value, otherwise
+     return false.  */
+
+  bool stop_pc_p () const
+  {
+    return m_suspend.stop_pc.has_value ();
+  }
+
+  /* Return true if this thread has a pending wait status.  */
+
+  bool has_pending_waitstatus () const
+  {
+    return m_suspend.waitstatus_pending_p;
+  }
+
+  /* Get this thread's pending wait status.
+
+     May only be called if has_pending_waitstatus returns true.  */
+
+  const target_waitstatus &pending_waitstatus () const
+  {
+    gdb_assert (this->has_pending_waitstatus ());
+
+    return m_suspend.waitstatus;
+  }
+
+  /* Set this thread's pending wait status.
 
-  int current_line;
-  struct symtab *current_symtab;
+     May only be called if has_pending_waitstatus returns false.  */
+
+  void set_pending_waitstatus (const target_waitstatus &ws);
+
+  /* Clear this thread's pending wait status.
+
+     May only be called if has_pending_waitstatus returns true.  */
+
+  void clear_pending_waitstatus ();
+
+  /* Return this thread's stop signal.  */
+
+  gdb_signal stop_signal () const
+  {
+    return m_suspend.stop_signal;
+  }
+
+  /* Set this thread's stop signal.  */
+
+  void set_stop_signal (gdb_signal sig)
+  {
+    m_suspend.stop_signal = sig;
+  }
+
+  /* Return this thread's stop reason.  */
+
+  target_stop_reason stop_reason () const
+  {
+    return m_suspend.stop_reason;
+  }
+
+  /* Set this thread's stop reason.  */
+
+  void set_stop_reason (target_stop_reason reason)
+  {
+    m_suspend.stop_reason = reason;
+  }
+
+  /* Get the FSM associated with the thread.  */
+
+  struct thread_fsm *thread_fsm () const
+  {
+    return m_thread_fsm.get ();
+  }
+
+  /* Get the owning reference to the FSM associated with the thread.
+
+     After a call to this method, "thread_fsm () == nullptr".  */
+
+  std::unique_ptr<struct thread_fsm> release_thread_fsm ()
+  {
+    return std::move (m_thread_fsm);
+  }
+
+  /* Set the FSM associated with the current thread.
+
+     It is invalid to set the FSM if another FSM is already installed.  */
+
+  void set_thread_fsm (std::unique_ptr<struct thread_fsm> fsm)
+  {
+    gdb_assert (m_thread_fsm == nullptr);
+    m_thread_fsm = std::move (fsm);
+  }
+
+  int current_line = 0;
+  struct symtab *current_symtab = NULL;
 
   /* Internal stepping state.  */
 
-  /* Record the pc of the thread the last time it stopped.  This is
-     maintained by proceed and keep_going, and used in
+  /* Record the pc of the thread the last time it was resumed.  (It
+     can't be done on stop as the PC may change since the last stop,
+     e.g., "return" command, or "p $pc = 0xf000").  This is maintained
+     by proceed and keep_going, and among other things, it's used in
      adjust_pc_after_break to distinguish a hardware single-step
      SIGTRAP from a breakpoint SIGTRAP.  */
-  CORE_ADDR prev_pc;
+  CORE_ADDR prev_pc = 0;
+
+  /* Did we set the thread stepping a breakpoint instruction?  This is
+     used in conjunction with PREV_PC to decide whether to adjust the
+     PC.  */
+  int stepped_breakpoint = 0;
 
   /* Should we step over breakpoint next time keep_going is called?  */
-  int stepping_over_breakpoint;
+  int stepping_over_breakpoint = 0;
+
+  /* Should we step over a watchpoint next time keep_going is called?
+     This is needed on targets with non-continuable, non-steppable
+     watchpoints.  */
+  int stepping_over_watchpoint = 0;
 
   /* Set to TRUE if we should finish single-stepping over a breakpoint
      after hitting the current step-resume breakpoint.  The context here
@@ -197,23 +505,7 @@ struct thread_info
      step_after_step_resume_breakpoint is set to TRUE at this moment in
      order to keep GDB in mind that there is still a breakpoint to step over
      when GDB gets back SIGTRAP from step_resume_breakpoint.  */
-  int step_after_step_resume_breakpoint;
-
-  /* Per-thread command support.  */
-
-  /* Pointer to what is left to do for an execution command after the
-     target stops.  Used only in asynchronous mode, by targets that
-     support async execution.  Several execution commands use it.  */
-  struct continuation *continuations;
-
-  /* Similar to the above, but used when a single execution command
-     requires several resume/stop iterations.  Used by the step
-     command.  */
-  struct continuation *intermediate_continuations;
-
-  /* If stepping, nonzero means step count is > 1 so don't print frame
-     next time inferior stops if it stops due to stepping.  */
-  int step_multi;
+  int step_after_step_resume_breakpoint = 0;
 
   /* This is used to remember when a fork or vfork event was caught by
      a catchpoint, and thus the event is to be followed at the next
@@ -221,25 +513,91 @@ struct thread_info
   struct target_waitstatus pending_follow;
 
   /* True if this thread has been explicitly requested to stop.  */
-  int stop_requested;
+  int stop_requested = 0;
 
   /* The initiating frame of a nexting operation, used for deciding
      which exceptions to intercept.  If it is null_frame_id no
      bp_longjmp or bp_exception but longjmp has been caught just for
      bp_longjmp_call_dummy.  */
-  struct frame_id initiating_frame;
+  struct frame_id initiating_frame = null_frame_id;
 
   /* Private data used by the target vector implementation.  */
-  struct private_thread_info *private;
-
-  /* Function that is called to free PRIVATE.  If this is NULL, then
-     xfree will be called on PRIVATE.  */
-  void (*private_dtor) (struct private_thread_info *);
+  std::unique_ptr<private_thread_info> priv;
 
   /* Branch trace information for this thread.  */
-  struct btrace_thread_info btrace;
+  struct btrace_thread_info btrace {};
+
+  /* Flag which indicates that the stack temporaries should be stored while
+     evaluating expressions.  */
+  bool stack_temporaries_enabled = false;
+
+  /* Values that are stored as temporaries on stack while evaluating
+     expressions.  */
+  std::vector<struct value *> stack_temporaries;
+
+  /* Step-over chain.  A thread is in the step-over queue if this node is
+     linked.  */
+  intrusive_list_node<thread_info> step_over_list_node;
+
+  /* Node for list of threads that are resumed and have a pending wait status.
+
+     The list head for this is in process_stratum_target, hence all threads in
+     this list belong to that process target.  */
+  intrusive_list_node<thread_info> resumed_with_pending_wait_status_node;
+
+  /* Displaced-step state for this thread.  */
+  displaced_step_thread_state displaced_step_state;
+
+private:
+  /* True if this thread is resumed from infrun's perspective.
+     Note that a thread can be marked both as not-executing and
+     resumed at the same time.  This happens if we try to resume a
+     thread that has a wait status pending.  We shouldn't let the
+     thread really run until that wait status has been processed, but
+     we should not process that wait status if we didn't try to let
+     the thread run.  */
+  bool m_resumed = false;
+
+  /* True means the thread is executing.  Note: this is different
+     from saying that there is an active target and we are stopped at
+     a breakpoint, for instance.  This is a real indicator whether the
+     thread is off and running.  */
+  bool m_executing = false;
+
+  /* State of inferior thread to restore after GDB is done with an inferior
+     call.  See `struct thread_suspend_state'.  */
+  thread_suspend_state m_suspend;
+
+  /* The user-given name of the thread.
+
+     Nullptr if the thread does not have a user-given name.  */
+  gdb::unique_xmalloc_ptr<char> m_name;
+
+  /* Pointer to the state machine manager object that handles what is
+     left to do for the thread's execution command after the target
+     stops.  Several execution commands use it.  */
+  std::unique_ptr<struct thread_fsm> m_thread_fsm;
 };
 
+using thread_info_resumed_with_pending_wait_status_node
+  = intrusive_member_node<thread_info,
+                         &thread_info::resumed_with_pending_wait_status_node>;
+using thread_info_resumed_with_pending_wait_status_list
+  = intrusive_list<thread_info,
+                  thread_info_resumed_with_pending_wait_status_node>;
+
+/* A gdb::ref_ptr pointer to a thread_info.  */
+
+using thread_info_ref
+  = gdb::ref_ptr<struct thread_info, refcounted_object_ref_policy>;
+
+/* A gdb::ref_ptr pointer to an inferior.  This would ideally be in
+   inferior.h, but it can't due to header dependencies (inferior.h
+   includes gdbthread.h).  */
+
+using inferior_ref
+  = gdb::ref_ptr<struct inferior, refcounted_object_ref_policy>;
+
 /* Create an empty thread list, or empty the existing one.  */
 extern void init_thread_list (void);
 
@@ -247,23 +605,31 @@ extern void init_thread_list (void);
    that a new thread is found, and return the pointer to
    the new thread.  Caller my use this pointer to 
    initialize the private thread data.  */
-extern struct thread_info *add_thread (ptid_t ptid);
+extern struct thread_info *add_thread (process_stratum_target *targ,
+                                      ptid_t ptid);
 
-/* Same as add_thread, but does not print a message
-   about new thread.  */
-extern struct thread_info *add_thread_silent (ptid_t ptid);
+/* Same as add_thread, but does not print a message about new
+   thread.  */
+extern struct thread_info *add_thread_silent (process_stratum_target *targ,
+                                             ptid_t ptid);
 
 /* Same as add_thread, and sets the private info.  */
-extern struct thread_info *add_thread_with_info (ptid_t ptid,
-                                                struct private_thread_info *);
+extern struct thread_info *add_thread_with_info (process_stratum_target *targ,
+                                                ptid_t ptid,
+                                                private_thread_info *);
+
+/* Delete thread THREAD and notify of thread exit.  If the thread is
+   currently not deletable, don't actually delete it but still tag it
+   as exited and do the notification.  */
+extern void delete_thread (struct thread_info *thread);
 
-/* Delete an existing thread list entry.  */
-extern void delete_thread (ptid_t);
+/* Like delete_thread, but be quiet about it.  Used when the process
+   this thread belonged to has already exited, for example.  */
+extern void delete_thread_silent (struct thread_info *thread);
 
-/* Delete an existing thread list entry, and be quiet about it.  Used
-   after the process this thread having belonged to having already
-   exited, for example.  */
-extern void delete_thread_silent (ptid_t);
+/* Mark the thread exited, but don't delete it or remove it from the
+   inferior thread list.  */
+extern void set_thread_exited (thread_info *tp, bool silent);
 
 /* Delete a step_resume_breakpoint from the thread database.  */
 extern void delete_step_resume_breakpoint (struct thread_info *);
@@ -271,135 +637,243 @@ extern void delete_step_resume_breakpoint (struct thread_info *);
 /* Delete an exception_resume_breakpoint from the thread database.  */
 extern void delete_exception_resume_breakpoint (struct thread_info *);
 
-/* Translate the integer thread id (GDB's homegrown id, not the system's)
-   into a "pid" (which may be overloaded with extra thread information).  */
-extern ptid_t thread_id_to_pid (int);
+/* Delete the single-step breakpoints of thread TP, if any.  */
+extern void delete_single_step_breakpoints (struct thread_info *tp);
+
+/* Check if the thread has software single stepping breakpoints
+   set.  */
+extern int thread_has_single_step_breakpoints_set (struct thread_info *tp);
+
+/* Check whether the thread has software single stepping breakpoints
+   set at PC.  */
+extern int thread_has_single_step_breakpoint_here (struct thread_info *tp,
+                                                  const address_space *aspace,
+                                                  CORE_ADDR addr);
+
+/* Returns whether to show inferior-qualified thread IDs, or plain
+   thread numbers.  Inferior-qualified IDs are shown whenever we have
+   multiple inferiors, or the only inferior left has number > 1.  */
+extern int show_inferior_qualified_tids (void);
+
+/* Return a string version of THR's thread ID.  If there are multiple
+   inferiors, then this prints the inferior-qualifier form, otherwise
+   it only prints the thread number.  The result is stored in a
+   circular static buffer, NUMCELLS deep.  */
+const char *print_thread_id (struct thread_info *thr);
 
-/* Translate a 'pid' (which may be overloaded with extra thread information) 
-   into the integer thread id (GDB's homegrown id, not the system's).  */
-extern int pid_to_thread_id (ptid_t ptid);
+/* Boolean test for an already-known ptid.  */
+extern bool in_thread_list (process_stratum_target *targ, ptid_t ptid);
 
-/* Boolean test for an already-known pid (which may be overloaded with
-   extra thread information).  */
-extern int in_thread_list (ptid_t ptid);
+/* Boolean test for an already-known global thread id (GDB's homegrown
+   global id, not the system's).  */
+extern int valid_global_thread_id (int global_id);
 
-/* Boolean test for an already-known thread id (GDB's homegrown id, 
-   not the system's).  */
-extern int valid_thread_id (int thread);
+/* Find (non-exited) thread PTID of inferior INF.  */
+extern thread_info *find_thread_ptid (inferior *inf, ptid_t ptid);
 
-/* Search function to lookup a thread by 'pid'.  */
-extern struct thread_info *find_thread_ptid (ptid_t ptid);
+/* Search function to lookup a (non-exited) thread by 'ptid'.  */
+extern struct thread_info *find_thread_ptid (process_stratum_target *targ,
+                                            ptid_t ptid);
 
-/* Find thread by GDB user-visible thread number.  */
-struct thread_info *find_thread_id (int num);
+/* Find thread by GDB global thread ID.  */
+struct thread_info *find_thread_global_id (int global_id);
 
-/* Finds the first thread of the inferior given by PID.  If PID is -1,
-   returns the first thread in the list.  */
-struct thread_info *first_thread_of_process (int pid);
+/* Find thread by thread library specific handle in inferior INF.  */
+struct thread_info *find_thread_by_handle
+  (gdb::array_view<const gdb_byte> handle, struct inferior *inf);
 
-/* Returns any thread of process PID.  */
-extern struct thread_info *any_thread_of_process (int pid);
+/* Finds the first thread of the specified inferior.  */
+extern struct thread_info *first_thread_of_inferior (inferior *inf);
 
-/* Returns any non-exited thread of process PID, giving preference for
-   not executing threads.  */
-extern struct thread_info *any_live_thread_of_process (int pid);
+/* Returns any thread of inferior INF, giving preference to the
+   current thread.  */
+extern struct thread_info *any_thread_of_inferior (inferior *inf);
+
+/* Returns any non-exited thread of inferior INF, giving preference to
+   the current thread, and to not executing threads.  */
+extern struct thread_info *any_live_thread_of_inferior (inferior *inf);
 
 /* Change the ptid of thread OLD_PTID to NEW_PTID.  */
-void thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid);
+void thread_change_ptid (process_stratum_target *targ,
+                        ptid_t old_ptid, ptid_t new_ptid);
 
 /* Iterator function to call a user-provided callback function
    once for each known thread.  */
 typedef int (*thread_callback_func) (struct thread_info *, void *);
 extern struct thread_info *iterate_over_threads (thread_callback_func, void *);
 
-/* Traverse all threads.  */
+/* Pull in the internals of the inferiors/threads ranges and
+   iterators.  Must be done after struct thread_info is defined.  */
+#include "thread-iter.h"
 
-#define ALL_THREADS(T)                         \
-  for (T = thread_list; T; T = T->next)
+/* Return a range that can be used to walk over threads, with
+   range-for.
 
-extern int thread_count (void);
+   Used like this, it walks over all threads of all inferiors of all
+   targets:
 
-/* Switch from one thread to another.  */
-extern void switch_to_thread (ptid_t ptid);
+       for (thread_info *thr : all_threads ())
+        { .... }
 
-/* Marks thread PTID is running, or stopped. 
-   If ptid_get_pid (PTID) is -1, marks all threads.  */
-extern void set_running (ptid_t ptid, int running);
+   FILTER_PTID can be used to filter out threads that don't match.
+   FILTER_PTID can be:
 
-/* Marks or clears thread(s) PTID as having been requested to stop.
-   If PTID is MINUS_ONE_PTID, applies to all threads.  If
-   ptid_is_pid(PTID) is true, applies to all threads of the process
-   pointed at by PTID.  If STOP, then the THREAD_STOP_REQUESTED
-   observer is called with PTID as argument.  */
-extern void set_stop_requested (ptid_t ptid, int stop);
+   - minus_one_ptid, meaning walk all threads of all inferiors of
+     PROC_TARGET.  If PROC_TARGET is NULL, then of all targets.
 
-/* NOTE: Since the thread state is not a boolean, most times, you do
-   not want to check it with negation.  If you really want to check if
-   the thread is stopped,
+   - A process ptid, in which case walk all threads of the specified
+     process.  PROC_TARGET must be non-NULL in this case.
 
-    use (good):
+   - A thread ptid, in which case walk that thread only.  PROC_TARGET
+     must be non-NULL in this case.
+*/
+
+inline all_matching_threads_range
+all_threads (process_stratum_target *proc_target = nullptr,
+            ptid_t filter_ptid = minus_one_ptid)
+{
+  return all_matching_threads_range (proc_target, filter_ptid);
+}
 
-     if (is_stopped (ptid))
+/* Return a range that can be used to walk over all non-exited threads
+   of all inferiors, with range-for.  Arguments are like all_threads
+   above.  */
 
-    instead of (bad):
+inline all_non_exited_threads_range
+all_non_exited_threads (process_stratum_target *proc_target = nullptr,
+                       ptid_t filter_ptid = minus_one_ptid)
+{
+  return all_non_exited_threads_range (proc_target, filter_ptid);
+}
 
-     if (!is_running (ptid))
+/* Return a range that can be used to walk over all threads of all
+   inferiors, with range-for, safely.  I.e., it is safe to delete the
+   currently-iterated thread.  When combined with range-for, this
+   allow convenient patterns like this:
+
+     for (thread_info *t : all_threads_safe ())
+       if (some_condition ())
+        delete f;
+*/
+
+inline all_threads_safe_range
+all_threads_safe ()
+{
+  return all_threads_safe_range (all_threads_iterator::begin_t {});
+}
 
-   The latter also returns true on exited threads, most likelly not
-   what you want.  */
+extern int thread_count (process_stratum_target *proc_target);
 
-/* Reports if in the frontend's perpective, thread PTID is running.  */
-extern int is_running (ptid_t ptid);
+/* Return true if we have any thread in any inferior.  */
+extern bool any_thread_p ();
 
-/* Is this thread listed, but known to have exited?  We keep it listed
-   (but not visible) until it's safe to delete.  */
-extern int is_exited (ptid_t ptid);
+/* Switch context to thread THR.  Also sets the STOP_PC global.  */
+extern void switch_to_thread (struct thread_info *thr);
 
-/* In the frontend's perpective, is this thread stopped?  */
-extern int is_stopped (ptid_t ptid);
+/* Switch context to no thread selected.  */
+extern void switch_to_no_thread ();
 
-/* In the frontend's perpective is there any thread running?  */
-extern int any_running (void);
+/* Switch from one thread to another.  Does not read registers.  */
+extern void switch_to_thread_no_regs (struct thread_info *thread);
 
-/* Marks thread PTID as executing, or not.  If ptid_get_pid (PTID) is -1,
-   marks all threads.
+/* Marks or clears thread(s) PTID of TARG as resumed.  If PTID is
+   MINUS_ONE_PTID, applies to all threads of TARG.  If
+   ptid_is_pid(PTID) is true, applies to all threads of the process
+   pointed at by {TARG,PTID}.  */
+extern void set_resumed (process_stratum_target *targ,
+                        ptid_t ptid, bool resumed);
+
+/* Marks thread PTID of TARG as running, or as stopped.  If PTID is
+   minus_one_ptid, marks all threads of TARG.  */
+extern void set_running (process_stratum_target *targ,
+                        ptid_t ptid, bool running);
+
+/* Marks or clears thread(s) PTID of TARG as having been requested to
+   stop.  If PTID is MINUS_ONE_PTID, applies to all threads of TARG.
+   If ptid_is_pid(PTID) is true, applies to all threads of the process
+   pointed at by {TARG, PTID}.  If STOP, then the
+   THREAD_STOP_REQUESTED observer is called with PTID as argument.  */
+extern void set_stop_requested (process_stratum_target *targ,
+                               ptid_t ptid, bool stop);
+
+/* Marks thread PTID of TARG as executing, or not.  If PTID is
+   minus_one_ptid, marks all threads of TARG.
 
    Note that this is different from the running state.  See the
    description of state and executing fields of struct
    thread_info.  */
-extern void set_executing (ptid_t ptid, int executing);
+extern void set_executing (process_stratum_target *targ,
+                          ptid_t ptid, bool executing);
 
-/* Reports if thread PTID is executing.  */
-extern int is_executing (ptid_t ptid);
+/* True if any (known or unknown) thread of TARG is or may be
+   executing.  */
+extern bool threads_are_executing (process_stratum_target *targ);
 
-/* Merge the executing property of thread PTID over to its thread
-   state property (frontend running/stopped view).
+/* Merge the executing property of thread PTID of TARG over to its
+   thread state property (frontend running/stopped view).
 
    "not executing" -> "stopped"
    "executing"     -> "running"
    "exited"        -> "exited"
 
-   If ptid_get_pid (PTID) is -1, go over all threads.
+   If PTID is minus_one_ptid, go over all threads of TARG.
 
    Notifications are only emitted if the thread state did change.  */
-extern void finish_thread_state (ptid_t ptid);
+extern void finish_thread_state (process_stratum_target *targ, ptid_t ptid);
 
-/* Same as FINISH_THREAD_STATE, but with an interface suitable to be
-   registered as a cleanup.  PTID_P points to the ptid_t that is
-   passed to FINISH_THREAD_STATE.  */
-extern void finish_thread_state_cleanup (void *ptid_p);
+/* Calls finish_thread_state on scope exit, unless release() is called
+   to disengage.  */
+using scoped_finish_thread_state
+  = FORWARD_SCOPE_EXIT (finish_thread_state);
 
 /* Commands with a prefix of `thread'.  */
 extern struct cmd_list_element *thread_cmd_list;
 
+extern void thread_command (const char *tidstr, int from_tty);
+
 /* Print notices on thread events (attach, detach, etc.), set with
    `set print thread-events'.  */
-extern int print_thread_events;
-
-extern void print_thread_info (struct ui_out *uiout, char *threads,
+extern bool print_thread_events;
+
+/* Prints the list of threads and their details on UIOUT.  If
+   REQUESTED_THREADS, a list of GDB ids/ranges, is not NULL, only
+   print threads whose ID is included in the list.  If PID is not -1,
+   only print threads from the process PID.  Otherwise, threads from
+   all attached PIDs are printed.  If both REQUESTED_THREADS is not
+   NULL and PID is not -1, then the thread is printed if it belongs to
+   the specified process.  Otherwise, an error is raised.  */
+extern void print_thread_info (struct ui_out *uiout,
+                              const char *requested_threads,
                               int pid);
 
-extern struct cleanup *make_cleanup_restore_current_thread (void);
+/* Save/restore current inferior/thread/frame.  */
+
+class scoped_restore_current_thread
+{
+public:
+  scoped_restore_current_thread ();
+  ~scoped_restore_current_thread ();
+
+  DISABLE_COPY_AND_ASSIGN (scoped_restore_current_thread);
+
+  /* Cancel restoring on scope exit.  */
+  void dont_restore () { m_dont_restore = true; }
+
+private:
+  void restore ();
+
+  bool m_dont_restore = false;
+  thread_info_ref m_thread;
+  inferior_ref m_inf;
+
+  frame_id m_selected_frame_id;
+  int m_selected_frame_level;
+  bool m_was_stopped;
+  /* Save/restore the language as well, because selecting a frame
+     changes the current language to the frame's language if "set
+     language auto".  */
+  enum language m_lang;
+};
 
 /* Returns a pointer into the thread_info corresponding to
    INFERIOR_PTID.  INFERIOR_PTID *must* be in the thread list.  */
@@ -407,10 +881,157 @@ extern struct thread_info* inferior_thread (void);
 
 extern void update_thread_list (void);
 
+/* Delete any thread the target says is no longer alive.  */
+
+extern void prune_threads (void);
+
+/* Delete threads marked THREAD_EXITED.  Unlike prune_threads, this
+   does not consult the target about whether the thread is alive right
+   now.  */
+extern void delete_exited_threads (void);
+
 /* Return true if PC is in the stepping range of THREAD.  */
 
 int pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread);
 
-extern struct thread_info *thread_list;
+/* Enable storing stack temporaries for thread THR and disable and
+   clear the stack temporaries on destruction.  Holds a strong
+   reference to THR.  */
+
+class enable_thread_stack_temporaries
+{
+public:
+
+  explicit enable_thread_stack_temporaries (struct thread_info *thr)
+    : m_thr (thread_info_ref::new_reference (thr))
+  {
+    m_thr->stack_temporaries_enabled = true;
+    m_thr->stack_temporaries.clear ();
+  }
+
+  ~enable_thread_stack_temporaries ()
+  {
+    m_thr->stack_temporaries_enabled = false;
+    m_thr->stack_temporaries.clear ();
+  }
+
+  DISABLE_COPY_AND_ASSIGN (enable_thread_stack_temporaries);
+
+private:
+
+  thread_info_ref m_thr;
+};
+
+extern bool thread_stack_temporaries_enabled_p (struct thread_info *tp);
+
+extern void push_thread_stack_temporary (struct thread_info *tp, struct value *v);
+
+extern value *get_last_thread_stack_temporary (struct thread_info *tp);
+
+extern bool value_in_thread_stack_temporaries (struct value *,
+                                              struct thread_info *thr);
+
+/* Thread step-over list type.  */
+using thread_step_over_list_node
+  = intrusive_member_node<thread_info, &thread_info::step_over_list_node>;
+using thread_step_over_list
+  = intrusive_list<thread_info, thread_step_over_list_node>;
+using thread_step_over_list_iterator
+  = reference_to_pointer_iterator<thread_step_over_list::iterator>;
+using thread_step_over_list_safe_iterator
+  = basic_safe_iterator<thread_step_over_list_iterator>;
+using thread_step_over_list_safe_range
+  = iterator_range<thread_step_over_list_safe_iterator>;
+
+static inline thread_step_over_list_safe_range
+make_thread_step_over_list_safe_range (thread_step_over_list &list)
+{
+  return thread_step_over_list_safe_range
+    (thread_step_over_list_safe_iterator (list.begin (),
+                                         list.end ()),
+     thread_step_over_list_safe_iterator (list.end (),
+                                         list.end ()));
+}
+
+/* Add TP to the end of the global pending step-over chain.  */
+
+extern void global_thread_step_over_chain_enqueue (thread_info *tp);
+
+/* Append the thread step over list LIST to the global thread step over
+   chain. */
+
+extern void global_thread_step_over_chain_enqueue_chain
+  (thread_step_over_list &&list);
+
+/* Remove TP from the global pending step-over chain.  */
+
+extern void global_thread_step_over_chain_remove (thread_info *tp);
+
+/* Return true if TP is in any step-over chain.  */
+
+extern int thread_is_in_step_over_chain (struct thread_info *tp);
+
+/* Return the length of the the step over chain TP is in.
+
+   If TP is non-nullptr, the thread must be in a step over chain.
+   TP may be nullptr, in which case it denotes an empty list, so a length of
+   0.  */
+
+extern int thread_step_over_chain_length (const thread_step_over_list &l);
+
+/* Cancel any ongoing execution command.  */
+
+extern void thread_cancel_execution_command (struct thread_info *thr);
+
+/* Check whether it makes sense to access a register of the current
+   thread at this point.  If not, throw an error (e.g., the thread is
+   executing).  */
+extern void validate_registers_access (void);
+
+/* Check whether it makes sense to access a register of THREAD at this point.
+   Returns true if registers may be accessed; false otherwise.  */
+extern bool can_access_registers_thread (struct thread_info *thread);
+
+/* Returns whether to show which thread hit the breakpoint, received a
+   signal, etc. and ended up causing a user-visible stop.  This is
+   true iff we ever detected multiple threads.  */
+extern int show_thread_that_caused_stop (void);
+
+/* Print the message for a thread or/and frame selected.  */
+extern void print_selected_thread_frame (struct ui_out *uiout,
+                                        user_selected_what selection);
+
+/* Helper for the CLI's "thread" command and for MI's -thread-select.
+   Selects thread THR.  TIDSTR is the original string the thread ID
+   was parsed from.  This is used in the error message if THR is not
+   alive anymore.  */
+extern void thread_select (const char *tidstr, class thread_info *thr);
+
+/* Return THREAD's name.
+
+   If THREAD has a user-given name, return it.  Otherwise, query the thread's
+   target to get the name.  May return nullptr.  */
+extern const char *thread_name (thread_info *thread);
+
+/* Switch to thread TP if it is alive.  Returns true if successfully
+   switched, false otherwise.  */
+
+extern bool switch_to_thread_if_alive (thread_info *thr);
+
+/* Assuming that THR is the current thread, execute CMD.
+   If ADA_TASK is not empty, it is the Ada task ID, and will
+   be printed instead of the thread information.
+   FLAGS.QUIET controls the printing of the thread information.
+   FLAGS.CONT and FLAGS.SILENT control how to handle errors.  Can throw an
+   exception if !FLAGS.SILENT and !FLAGS.CONT and CMD fails.  */
+
+extern void thread_try_catch_cmd (thread_info *thr,
+                                 gdb::optional<int> ada_task,
+                                 const char *cmd, int from_tty,
+                                 const qcs_flags &flags);
+
+/* Return a string representation of STATE.  */
+
+extern const char *thread_state_string (enum thread_state state);
 
 #endif /* GDBTHREAD_H */