+ /* Chain containing status of breakpoint(s) the thread stopped
+ at. */
+ bpstat stop_bpstat;
+
+ /* 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;
+};
+
+/* 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;
+
+ /* The reason the thread last stopped, if we need to track it
+ (breakpoint, watchpoint, etc.) */
+ enum target_stop_reason stop_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;
+
+ /* 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;
+};
+
+/* 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 make_cleanup_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
+ {
+ /* 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));
+ }
+
+ struct thread_info *next = NULL;
+ ptid_t ptid; /* "Actual process id";
+ In fact, this may be overloaded with
+ kernel thread id, etc. */
+
+ /* Each thread has two GDB IDs.
+
+ 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 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;
+
+ /* 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;
+
+ /* 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;
+
+ /* 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'. */
+ 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 {};
+
+ int current_line = 0;
+ struct symtab *current_symtab = NULL;
+
+ /* Internal stepping state. */
+
+ /* 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 = 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 = 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
+ is that GDB is to do `next' or `step' while signal arrives.
+ When stepping over a breakpoint and signal arrives, GDB will attempt
+ to skip signal handler, so it inserts a step_resume_breakpoint at the
+ signal return address, and resume inferior.
+ 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 = 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;