Automatic date update in version.in
[binutils-gdb.git] / gdb / gdbthread.h
index 7bf2070338b06611fbe09e282f34354fefafacd5..1a33eb612213648359fb287deeea54c80b4ade56 100644 (file)
@@ -1,5 +1,5 @@
 /* Multi-process/thread control defs for GDB, the GNU debugger.
-   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   Copyright (C) 1987-2022 Free Software Foundation, Inc.
    Contributed by Lynx Real-Time Systems, Inc.  Los Gatos, CA.
    
 
@@ -26,22 +26,70 @@ struct symtab;
 #include "breakpoint.h"
 #include "frame.h"
 #include "ui-out.h"
-#include "inferior.h"
 #include "btrace.h"
-#include "common/vec.h"
 #include "target/waitstatus.h"
 #include "cli/cli-utils.h"
-#include "common/refcounted-object.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'.  */
@@ -51,17 +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;
+  struct breakpoint *single_step_breakpoints = nullptr;
 
   /* Range to single step within.
 
@@ -73,11 +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;
+  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
@@ -85,62 +133,44 @@ 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;
+  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.
-
-     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 return value should be printed.  */
-  int proceed_to_finish;
+  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;
 
   /* 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;
+  int stepping_command = 0;
 };
 
 /* Inferior thread specific part of `struct infcall_suspend_state'.  */
@@ -154,29 +184,43 @@ struct thread_suspend_state
      "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;
+  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;
+  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;
+  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").  This is
-     used in coordination with stop_reason and waitstatus_pending_p:
-     if the thread's PC is changed since it last stopped, a pending
-     breakpoint waitstatus is discarded.  */
-  CORE_ADDR stop_pc;
+     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;
 };
 
-typedef struct value *value_ptr;
-DEF_VEC_P (value_ptr);
-typedef VEC (value_ptr) value_vec;
+/* Base class for target-specific thread data.  */
+struct private_thread_info
+{
+  virtual ~private_thread_info () = 0;
+};
 
 /* Threads are intrusively refcounted objects.  Being the
    user-selected thread is normally considered an implicit strong
@@ -189,26 +233,26 @@ typedef VEC (value_ptr) value_vec;
    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 make_cleanup_restore_current_thread and
+   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.  */
+   refcount.
 
-class thread_info : public refcounted_object
+   The intrusive_list_node base links threads in a per-inferior list.  */
+
+class thread_info : public refcounted_object,
+                   public intrusive_list_node<thread_info>
 {
 public:
   explicit thread_info (inferior *inf, ptid_t ptid);
   ~thread_info ();
 
-  bool deletable () const
-  {
-    /* If this is the current thread, or there's code out there that
-       relies on it existing (refcount > 0) we can't delete yet.  */
-    return (refcount () == 0 && !ptid_equal (ptid, inferior_ptid));
-  }
+  bool deletable () const;
+
+  /* Mark this thread as running and notify observers.  */
+  void set_running (bool running);
 
-  struct thread_info *next = NULL;
   ptid_t ptid;                 /* "Actual process id";
                                    In fact, this may be overloaded with 
                                    kernel thread id, etc.  */
@@ -217,14 +261,14 @@ public:
 
      a) The thread ID (Id).  This consists of the pair of:
 
-        - the number of the thread's inferior and,
+       - 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.
+       - 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.
+       between all inferiors.
 
      E.g.:
 
@@ -253,24 +297,36 @@ public:
   /* The inferior this thread belongs to.  */
   struct inferior *inf;
 
-  /* 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 = NULL;
+  /* The user-given name of the thread.
 
-  /* 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 = 0;
+     Returns nullptr if the thread does not have a user-given name.  */
+  const char *name () const
+  {
+    return m_name.get ();
+  }
 
-  /* Non-zero 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.  */
-  int resumed = 0;
+  /* 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
@@ -281,11 +337,138 @@ public:
 
   /* State of GDB control of inferior thread execution.
      See `struct thread_control_state'.  */
-  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'.  */
-  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.
+
+     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;
@@ -324,11 +507,6 @@ public:
      when GDB gets back SIGTRAP from step_resume_breakpoint.  */
   int step_after_step_resume_breakpoint = 0;
 
-  /* 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.  */
-  struct thread_fsm *thread_fsm = NULL;
-
   /* 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
      resume of the thread, and not immediately.  */
@@ -344,30 +522,82 @@ public:
   struct frame_id initiating_frame = null_frame_id;
 
   /* Private data used by the target vector implementation.  */
-  struct private_thread_info *priv = NULL;
-
-  /* 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 *) = NULL;
+  std::unique_ptr<private_thread_info> priv;
 
   /* Branch trace information for this thread.  */
   struct btrace_thread_info btrace {};
 
   /* Flag which indicates that the stack temporaries should be stored while
      evaluating expressions.  */
-  int stack_temporaries_enabled = 0;
+  bool stack_temporaries_enabled = false;
 
   /* Values that are stored as temporaries on stack while evaluating
      expressions.  */
-  value_vec *stack_temporaries = NULL;
+  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;
 
-  /* Step-over chain.  A thread is in the step-over queue if these are
-     non-NULL.  If only a single thread is in the chain, then these
-     fields point to self.  */
-  struct thread_info *step_over_prev = NULL;
-  struct thread_info *step_over_next = NULL;
+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);
 
@@ -375,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 *);
@@ -409,19 +647,9 @@ 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,
-                                                  struct address_space *aspace,
+                                                  const address_space *aspace,
                                                   CORE_ADDR addr);
 
-/* Translate the global 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 global_thread_id_to_ptid (int num);
-
-/* Translate a 'pid' (which may be overloaded with extra thread
-   information) into the global integer thread id (GDB's homegrown id,
-   not the system's).  */
-extern int ptid_to_global_thread_id (ptid_t ptid);
-
 /* 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.  */
@@ -433,154 +661,179 @@ extern int show_inferior_qualified_tids (void);
    circular static buffer, NUMCELLS deep.  */
 const char *print_thread_id (struct thread_info *thr);
 
-/* 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 ptid.  */
+extern bool in_thread_list (process_stratum_target *targ, 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);
 
-/* Search function to lookup a thread by 'pid'.  */
-extern struct thread_info *find_thread_ptid (ptid_t ptid);
+/* Find (non-exited) thread PTID of inferior INF.  */
+extern thread_info *find_thread_ptid (inferior *inf, 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 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, giving preference to the current
-   thread.  */
-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 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 process PID, giving preference to
+/* 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_process (int pid);
+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.  */
-#define ALL_THREADS(T)                         \
-  for (T = thread_list; T; T = T->next)                \
+/* Pull in the internals of the inferiors/threads ranges and
+   iterators.  Must be done after struct thread_info is defined.  */
+#include "thread-iter.h"
 
-/* Traverse over all threads, sorted by inferior.  */
-#define ALL_THREADS_BY_INFERIOR(inf, tp) \
-  ALL_INFERIORS (inf) \
-    ALL_THREADS (tp) \
-      if (inf == tp->inf)
+/* Return a range that can be used to walk over threads, with
+   range-for.
 
-/* Traverse all threads, except those that have THREAD_EXITED
-   state.  */
+   Used like this, it walks over all threads of all inferiors of all
+   targets:
 
-#define ALL_NON_EXITED_THREADS(T)                              \
-  for (T = thread_list; T; T = T->next) \
-    if ((T)->state != THREAD_EXITED)
+       for (thread_info *thr : all_threads ())
+        { .... }
 
-/* Traverse all threads, including those that have THREAD_EXITED
-   state.  Allows deleting the currently iterated thread.  */
-#define ALL_THREADS_SAFE(T, TMP)       \
-  for ((T) = thread_list;                      \
-       (T) != NULL ? ((TMP) = (T)->next, 1): 0;        \
-       (T) = (TMP))
+   FILTER_PTID can be used to filter out threads that don't match.
+   FILTER_PTID can be:
 
-extern int thread_count (void);
+   - minus_one_ptid, meaning walk all threads of all inferiors of
+     PROC_TARGET.  If PROC_TARGET is NULL, then of all targets.
 
-/* Switch from one thread to another.  Also sets the STOP_PC
-   global.  */
-extern void switch_to_thread (ptid_t ptid);
+   - A process ptid, in which case walk all threads of the specified
+     process.  PROC_TARGET must be non-NULL in this case.
 
-/* Switch from one thread to another.  Does not read registers and
-   sets STOP_PC to -1.  */
-extern void switch_to_thread_no_regs (struct thread_info *thread);
-
-/* Marks or clears thread(s) PTID as resumed.  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.  */
-extern void set_resumed (ptid_t ptid, int resumed);
+   - A thread ptid, in which case walk that thread only.  PROC_TARGET
+     must be non-NULL in this case.
+*/
 
-/* Marks thread PTID is running, or stopped. 
-   If PTID is minus_one_ptid, marks all threads.  */
-extern void set_running (ptid_t ptid, int running);
+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);
+}
 
-/* 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);
+/* 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.  */
 
-/* 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,
+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);
+}
 
-    use (good):
+/* 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:
 
-     if (is_stopped (ptid))
+     for (thread_info *t : all_threads_safe ())
+       if (some_condition ())
+        delete f;
+*/
 
-    instead of (bad):
+inline all_threads_safe_range
+all_threads_safe ()
+{
+  return all_threads_safe_range (all_threads_iterator::begin_t {});
+}
 
-     if (!is_running (ptid))
+extern int thread_count (process_stratum_target *proc_target);
 
-   The latter also returns true on exited threads, most likelly not
-   what you want.  */
+/* Return true if we have any thread in any inferior.  */
+extern bool any_thread_p ();
 
-/* Reports if in the frontend's perpective, thread PTID is running.  */
-extern int is_running (ptid_t ptid);
+/* Switch context to thread THR.  Also sets the STOP_PC global.  */
+extern void switch_to_thread (struct thread_info *thr);
 
-/* 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 no thread selected.  */
+extern void switch_to_no_thread ();
 
-/* In the frontend's perpective, is this thread stopped?  */
-extern int is_stopped (ptid_t ptid);
+/* 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 is minus_one_ptid,
-   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);
-
-/* Reports if thread PTID is executing.  */
-extern int is_executing (ptid_t ptid);
+extern void set_executing (process_stratum_target *targ,
+                          ptid_t ptid, bool executing);
 
-/* True if any (known or unknown) thread is or may be executing.  */
-extern int threads_are_executing (void);
+/* 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 is minus_one_ptid, 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 (char *tidstr, int from_tty);
+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 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
@@ -589,7 +842,8 @@ extern int print_thread_events;
    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, char *requested_threads,
+extern void print_thread_info (struct ui_out *uiout,
+                              const char *requested_threads,
                               int pid);
 
 /* Save/restore current inferior/thread/frame.  */
@@ -600,18 +854,25 @@ public:
   scoped_restore_current_thread ();
   ~scoped_restore_current_thread ();
 
-  /* Disable copy.  */
-  scoped_restore_current_thread
-    (const scoped_restore_current_thread &) = delete;
-  void operator=
-    (const scoped_restore_current_thread &) = delete;
+  DISABLE_COPY_AND_ASSIGN (scoped_restore_current_thread);
+
+  /* Cancel restoring on scope exit.  */
+  void dont_restore () { m_dont_restore = true; }
 
 private:
-  thread_info *m_thread;
-  inferior *m_inf;
+  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
@@ -633,33 +894,91 @@ extern void delete_exited_threads (void);
 
 int pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread);
 
-extern struct cleanup *enable_thread_stack_temporaries (ptid_t ptid);
+/* Enable storing stack temporaries for thread THR and disable and
+   clear the stack temporaries on destruction.  Holds a strong
+   reference to THR.  */
 
-extern int thread_stack_temporaries_enabled_p (ptid_t ptid);
+class enable_thread_stack_temporaries
+{
+public:
 
-extern void push_thread_stack_temporary (ptid_t ptid, struct value *v);
+  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 ();
+  }
 
-extern struct value *get_last_thread_stack_temporary (ptid_t);
+  DISABLE_COPY_AND_ASSIGN (enable_thread_stack_temporaries);
 
-extern int value_in_thread_stack_temporaries (struct value *, ptid_t);
+private:
+
+  thread_info_ref m_thr;
+};
 
-/* Add TP to the end of its inferior's pending step-over chain.  */
+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 ()));
+}
 
-extern void thread_step_over_chain_enqueue (struct thread_info *tp);
+/* Add TP to the end of the global pending step-over chain.  */
 
-/* Remove TP from its inferior's pending step-over chain.  */
+extern void global_thread_step_over_chain_enqueue (thread_info *tp);
 
-extern void thread_step_over_chain_remove (struct thread_info *tp);
+/* Append the thread step over list LIST to the global thread step over
+   chain. */
 
-/* Return the next thread in the step-over chain starting at TP.  NULL
-   if TP is the last entry in the chain.  */
+extern void global_thread_step_over_chain_enqueue_chain
+  (thread_step_over_list &&list);
 
-extern struct thread_info *thread_step_over_chain_next (struct thread_info *tp);
+/* Remove TP from the global pending step-over chain.  */
 
-/* Return true if TP is in the 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);
@@ -669,9 +988,9 @@ extern void thread_cancel_execution_command (struct thread_info *thr);
    executing).  */
 extern void validate_registers_access (void);
 
-/* Check whether it makes sense to access a register of PTID at this point.
+/* 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_ptid (ptid_t ptid);
+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
@@ -682,6 +1001,37 @@ extern int show_thread_that_caused_stop (void);
 extern void print_selected_thread_frame (struct ui_out *uiout,
                                         user_selected_what selection);
 
-extern struct thread_info *thread_list;
+/* 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 */