/* Multi-process/thread control defs for GDB, the GNU debugger.
- Copyright (C) 1987-2017 Free Software Foundation, Inc.
+ Copyright (C) 1987-2018 Free Software Foundation, Inc.
Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
/* 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. */
+ 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;
};
-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
{
/* 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));
+ return (refcount () == 0 && ptid != inferior_ptid);
}
+ /* 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
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 these are
non-NULL. If only a single thread is in the chain, then these
struct thread_info *step_over_next = NULL;
};
+/* A gdb::ref_ptr pointer to a thread_info. */
+
+using thread_info_ref
+ = gdb::ref_ptr<struct thread_info, refcounted_object_ref_policy>;
+
/* Create an empty thread list, or empty the existing one. */
extern void init_thread_list (void);
struct private_thread_info *);
/* Delete an existing thread list entry. */
-extern void delete_thread (ptid_t);
+extern void delete_thread (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);
+extern void delete_thread_silent (struct thread_info *thread);
/* Delete a step_resume_breakpoint from the thread database. */
extern void delete_step_resume_breakpoint (struct thread_info *);
/* 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. */
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). */
+/* Boolean test for an already-known ptid. */
extern int in_thread_list (ptid_t ptid);
/* Boolean test for an already-known global thread id (GDB's homegrown
struct thread_info *find_thread_by_handle (struct value *thread_handle,
struct inferior *inf);
-/* 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);
+/* Finds the first thread of the specified inferior. */
+extern struct thread_info *first_thread_of_inferior (inferior *inf);
-/* Returns any thread of process PID, giving preference to the current
- thread. */
-extern struct thread_info *any_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 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);
extern int thread_count (void);
-/* Switch from one thread to another. Does not read registers and
- sets STOP_PC to -1. */
+/* Switch context to thread THR. Also sets the STOP_PC global. */
+extern void switch_to_thread (struct thread_info *thr);
+
+/* Switch context to no thread selected. */
+extern void switch_to_no_thread ();
+
+/* Switch from one thread to another. Does not read registers. */
extern void switch_to_thread_no_regs (struct thread_info *thread);
/* Marks or clears thread(s) PTID as resumed. If PTID is
thread_info. */
extern void set_executing (ptid_t ptid, int executing);
-/* Reports if thread PTID is executing. */
-extern int is_executing (ptid_t ptid);
-
/* True if any (known or unknown) thread is or may be executing. */
extern int threads_are_executing (void);
Notifications are only emitted if the thread state did change. */
extern void finish_thread_state (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. */
+class scoped_finish_thread_state
+{
+public:
+ explicit scoped_finish_thread_state (ptid_t ptid)
+ : m_ptid (ptid)
+ {}
+
+ ~scoped_finish_thread_state ()
+ {
+ if (!m_released)
+ finish_thread_state (m_ptid);
+ }
+
+ /* Disengage. */
+ void release ()
+ {
+ m_released = true;
+ }
+
+ DISABLE_COPY_AND_ASSIGN (scoped_finish_thread_state);
+
+private:
+ bool m_released = false;
+ ptid_t m_ptid;
+};
/* Commands with a prefix of `thread'. */
extern struct cmd_list_element *thread_cmd_list;
DISABLE_COPY_AND_ASSIGN (scoped_restore_current_thread);
private:
- thread_info *m_thread;
+ /* Use the "class" keyword here, because of a clash with a "thread_info"
+ function in the Darwin API. */
+ class thread_info *m_thread;
inferior *m_inf;
frame_id m_selected_frame_id;
int m_selected_frame_level;
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. */
+
+class enable_thread_stack_temporaries
+{
+public:
+
+ explicit enable_thread_stack_temporaries (struct thread_info *thr)
+ : m_thr (thr)
+ {
+ gdb_assert (m_thr != NULL);
+
+ m_thr->incref ();
+
+ 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 ();
+
+ m_thr->decref ();
+ }
+
+ DISABLE_COPY_AND_ASSIGN (enable_thread_stack_temporaries);
+
+private:
+
+ struct thread_info *m_thr;
+};
-extern int thread_stack_temporaries_enabled_p (ptid_t ptid);
+extern bool thread_stack_temporaries_enabled_p (struct thread_info *tp);
-extern void push_thread_stack_temporary (ptid_t ptid, struct value *v);
+extern void push_thread_stack_temporary (struct thread_info *tp, struct value *v);
-extern struct value *get_last_thread_stack_temporary (ptid_t);
+extern value *get_last_thread_stack_temporary (struct thread_info *tp);
-extern int value_in_thread_stack_temporaries (struct value *, ptid_t);
+extern bool value_in_thread_stack_temporaries (struct value *,
+ struct thread_info *thr);
/* Add TP to the end of its inferior's pending step-over chain. */
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
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, thread_info *thr);
+extern void thread_select (const char *tidstr, class thread_info *thr);
extern struct thread_info *thread_list;