+ /* 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'. */
+
+struct thread_control_state
+{
+ /* User/external stepping state. */
+
+ /* Step-resume or longjmp-resume breakpoint. */
+ struct breakpoint *step_resume_breakpoint = nullptr;
+
+ /* 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.
+
+ If this is nonzero, respond to a single-step signal by continuing
+ to step if the pc is in this range.
+
+ If step_range_start and step_range_end are both 1, it means to
+ step for a single instruction (FIXME: it might clean up
+ 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 = 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
+ single-stepping it without GDB core involvement as long as the
+ 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 = 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 {};
+
+ /* 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.
+
+ 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 = 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 = 0;
+
+ /* Nonzero if the thread is being proceeded for an inferior function
+ call. */
+ int in_infcall = 0;
+
+ enum step_over_calls_kind step_over_calls = STEP_OVER_NONE;
+
+ /* Nonzero if stopped due to a step command. */
+ int stop_step = 0;
+
+ /* Chain containing status of breakpoint(s) the thread stopped
+ at. */
+ 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 = 0;
+};
+
+/* Inferior thread specific part of `struct infcall_suspend_state'. */
+
+struct thread_suspend_state
+{
+ /* 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, this is set to -1, to avoid leaving
+ it with a stale value, to make it easier to catch bugs. */
+ CORE_ADDR stop_pc = 0;
+};
+
+/* 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
+ 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. */
+
+class thread_info : public refcounted_object
+{
+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);
+
+ struct thread_info *next = NULL;