gdb: use intrusive_list for linux-nat lwp_list

Replace the manually maintained linked list of lwp_info objects with
intrusive_list.  Replace the ALL_LWPS macro with all_lwps, which returns
a range.  Add all_lwps_safe as well, for use in iterate_over_lwps, which
currently iterates in a safe manner.

Change-Id: I355313502510acc0103f5eaf2fbde80897d6376c
This commit is contained in:
Simon Marchi 2021-08-28 10:58:45 -04:00
parent 676362df18
commit 901b98215e
5 changed files with 46 additions and 53 deletions

View file

@ -589,7 +589,6 @@ ia64_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type, enum target_hw_bp_type type,
struct expression *cond) struct expression *cond)
{ {
struct lwp_info *lp;
int idx; int idx;
long dbr_addr, dbr_mask; long dbr_addr, dbr_mask;
int max_watchpoints = 4; int max_watchpoints = 4;
@ -630,7 +629,8 @@ ia64_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
debug_registers[2 * idx] = dbr_addr; debug_registers[2 * idx] = dbr_addr;
debug_registers[2 * idx + 1] = dbr_mask; debug_registers[2 * idx + 1] = dbr_mask;
ALL_LWPS (lp)
for (const lwp_info *lp : all_lwps ())
{ {
store_debug_register_pair (lp->ptid, idx, &dbr_addr, &dbr_mask); store_debug_register_pair (lp->ptid, idx, &dbr_addr, &dbr_mask);
enable_watchpoints_in_psr (lp->ptid); enable_watchpoints_in_psr (lp->ptid);
@ -657,14 +657,12 @@ ia64_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
dbr_mask = debug_registers[2 * idx + 1]; dbr_mask = debug_registers[2 * idx + 1];
if ((dbr_mask & (0x3UL << 62)) && addr == (CORE_ADDR) dbr_addr) if ((dbr_mask & (0x3UL << 62)) && addr == (CORE_ADDR) dbr_addr)
{ {
struct lwp_info *lp;
debug_registers[2 * idx] = 0; debug_registers[2 * idx] = 0;
debug_registers[2 * idx + 1] = 0; debug_registers[2 * idx + 1] = 0;
dbr_addr = 0; dbr_addr = 0;
dbr_mask = 0; dbr_mask = 0;
ALL_LWPS (lp) for (const lwp_info *lp : all_lwps ())
store_debug_register_pair (lp->ptid, idx, &dbr_addr, &dbr_mask); store_debug_register_pair (lp->ptid, idx, &dbr_addr, &dbr_mask);
return 0; return 0;

View file

@ -421,9 +421,8 @@ static int
num_lwps (int pid) num_lwps (int pid)
{ {
int count = 0; int count = 0;
struct lwp_info *lp;
for (lp = lwp_list; lp; lp = lp->next) for (const lwp_info *lp ATTRIBUTE_UNUSED : all_lwps ())
if (lp->ptid.pid () == pid) if (lp->ptid.pid () == pid)
count++; count++;
@ -700,17 +699,31 @@ lwp_lwpid_htab_add_lwp (struct lwp_info *lp)
creation order. This order is assumed in some cases. E.g., creation order. This order is assumed in some cases. E.g.,
reaping status after killing alls lwps of a process: the leader LWP reaping status after killing alls lwps of a process: the leader LWP
must be reaped last. */ must be reaped last. */
struct lwp_info *lwp_list;
static intrusive_list<lwp_info> lwp_list;
/* See linux-nat.h. */
lwp_info_range
all_lwps ()
{
return lwp_info_range (lwp_list.begin ());
}
/* See linux-nat.h. */
lwp_info_safe_range
all_lwps_safe ()
{
return lwp_info_safe_range (lwp_list.begin ());
}
/* Add LP to sorted-by-reverse-creation-order doubly-linked list. */ /* Add LP to sorted-by-reverse-creation-order doubly-linked list. */
static void static void
lwp_list_add (struct lwp_info *lp) lwp_list_add (struct lwp_info *lp)
{ {
lp->next = lwp_list; lwp_list.push_front (*lp);
if (lwp_list != NULL)
lwp_list->prev = lp;
lwp_list = lp;
} }
/* Remove LP from sorted-by-reverse-creation-order doubly-linked /* Remove LP from sorted-by-reverse-creation-order doubly-linked
@ -720,12 +733,7 @@ static void
lwp_list_remove (struct lwp_info *lp) lwp_list_remove (struct lwp_info *lp)
{ {
/* Remove from sorted-by-creation-order list. */ /* Remove from sorted-by-creation-order list. */
if (lp->next != NULL) lwp_list.erase (lwp_list.iterator_to (*lp));
lp->next->prev = lp->prev;
if (lp->prev != NULL)
lp->prev->next = lp->next;
if (lp == lwp_list)
lwp_list = lp->next;
} }
@ -922,12 +930,8 @@ struct lwp_info *
iterate_over_lwps (ptid_t filter, iterate_over_lwps (ptid_t filter,
gdb::function_view<iterate_over_lwps_ftype> callback) gdb::function_view<iterate_over_lwps_ftype> callback)
{ {
struct lwp_info *lp, *lpnext; for (lwp_info *lp : all_lwps_safe ())
for (lp = lwp_list; lp; lp = lpnext)
{ {
lpnext = lp->next;
if (lp->ptid.matches (filter)) if (lp->ptid.matches (filter))
{ {
if (callback (lp) != 0) if (callback (lp) != 0)
@ -3715,8 +3719,6 @@ linux_nat_target::thread_alive (ptid_t ptid)
void void
linux_nat_target::update_thread_list () linux_nat_target::update_thread_list ()
{ {
struct lwp_info *lwp;
/* We add/delete threads from the list as clone/exit events are /* We add/delete threads from the list as clone/exit events are
processed, so just try deleting exited threads still in the processed, so just try deleting exited threads still in the
thread list. */ thread list. */
@ -3724,7 +3726,7 @@ linux_nat_target::update_thread_list ()
/* Update the processor core that each lwp/thread was last seen /* Update the processor core that each lwp/thread was last seen
running on. */ running on. */
ALL_LWPS (lwp) for (lwp_info *lwp : all_lwps ())
{ {
/* Avoid accessing /proc if the thread hasn't run since we last /* Avoid accessing /proc if the thread hasn't run since we last
time we fetched the thread's core. Accessing /proc becomes time we fetched the thread's core. Accessing /proc becomes
@ -3948,7 +3950,7 @@ linux_proc_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
/* Iterate over LWPs of the current inferior, trying to access /* Iterate over LWPs of the current inferior, trying to access
memory through one of them. */ memory through one of them. */
for (lwp_info *lp = lwp_list; lp != nullptr; lp = lp->next) for (lwp_info *lp : all_lwps ())
{ {
if (lp->ptid.pid () != cur_pid) if (lp->ptid.pid () != cur_pid)
continue; continue;

View file

@ -196,11 +196,9 @@ extern linux_nat_target *linux_target;
struct arch_lwp_info; struct arch_lwp_info;
/* Structure describing an LWP. This is public only for the purposes /* Structure describing an LWP. */
of ALL_LWPS; target-specific code should generally not access it
directly. */
struct lwp_info struct lwp_info : intrusive_list_node<lwp_info>
{ {
lwp_info (ptid_t ptid) lwp_info (ptid_t ptid)
: ptid (ptid) : ptid (ptid)
@ -283,27 +281,26 @@ struct lwp_info
/* Arch-specific additions. */ /* Arch-specific additions. */
struct arch_lwp_info *arch_private = nullptr; struct arch_lwp_info *arch_private = nullptr;
/* Previous and next pointers in doubly-linked list of known LWPs,
sorted by reverse creation order. */
struct lwp_info *prev = nullptr;
struct lwp_info *next = nullptr;
}; };
/* The global list of LWPs, for ALL_LWPS. Unlike the threads list, /* lwp_info iterator and range types. */
there is always at least one LWP on the list while the GNU/Linux
native target is active. */ using lwp_info_iterator
extern struct lwp_info *lwp_list; = reference_to_pointer_iterator<intrusive_list<lwp_info>::iterator>;
using lwp_info_range = iterator_range<lwp_info_iterator>;
using lwp_info_safe_range = basic_safe_range<lwp_info_range>;
/* Get an iterable range over all lwps. */
lwp_info_range all_lwps ();
/* Same as the above, but safe against deletion while iterating. */
lwp_info_safe_range all_lwps_safe ();
/* Does the current host support PTRACE_GETREGSET? */ /* Does the current host support PTRACE_GETREGSET? */
extern enum tribool have_ptrace_getregset; extern enum tribool have_ptrace_getregset;
/* Iterate over each active thread (light-weight process). */
#define ALL_LWPS(LP) \
for ((LP) = lwp_list; \
(LP) != NULL; \
(LP) = (LP)->next)
/* Called from the LWP layer to inform the thread_db layer that PARENT /* Called from the LWP layer to inform the thread_db layer that PARENT
spawned CHILD. Both LWPs are currently stopped. This function spawned CHILD. Both LWPs are currently stopped. This function
does whatever is required to have the child LWP under the does whatever is required to have the child LWP under the

View file

@ -920,13 +920,12 @@ try_thread_db_load_1 (struct thread_db_info *info)
if (info->td_ta_thr_iter_p == NULL) if (info->td_ta_thr_iter_p == NULL)
{ {
struct lwp_info *lp;
int pid = inferior_ptid.pid (); int pid = inferior_ptid.pid ();
thread_info *curr_thread = inferior_thread (); thread_info *curr_thread = inferior_thread ();
linux_stop_and_wait_all_lwps (); linux_stop_and_wait_all_lwps ();
ALL_LWPS (lp) for (const lwp_info *lp : all_lwps ())
if (lp->ptid.pid () == pid) if (lp->ptid.pid () == pid)
thread_from_lwp (curr_thread, lp->ptid); thread_from_lwp (curr_thread, lp->ptid);

View file

@ -632,12 +632,9 @@ mips_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
static int static int
write_watchpoint_regs (void) write_watchpoint_regs (void)
{ {
struct lwp_info *lp; for (const lwp_info *lp : all_lwps ())
int tid;
ALL_LWPS (lp)
{ {
tid = lp->ptid.lwp (); int tid = lp->ptid.lwp ();
if (ptrace (PTRACE_SET_WATCH_REGS, tid, &watch_mirror, NULL) == -1) if (ptrace (PTRACE_SET_WATCH_REGS, tid, &watch_mirror, NULL) == -1)
perror_with_name (_("Couldn't write debug register")); perror_with_name (_("Couldn't write debug register"));
} }