[v3,2/3] gdbserver: introduce 'introdusive_list' type

Message ID 20241018152052.1509373-3-stephan.rohr@intel.com
State New
Headers
Series gdbserver: add thread map |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Test passed

Commit Message

Rohr, Stephan Oct. 18, 2024, 3:20 p.m. UTC
  This patch replaces the 'std::list' type of 'all_processes' and
'all_threads' with the more lightweight 'intrusive_list' type.
---
 gdbserver/dll.cc           |   4 +-
 gdbserver/gdbthread.h      |  18 ++--
 gdbserver/inferiors.cc     | 116 +++++++++-------------
 gdbserver/inferiors.h      |  10 +-
 gdbserver/linux-low.cc     | 196 ++++++++++++++++++-------------------
 gdbserver/linux-low.h      |   2 +-
 gdbserver/linux-x86-low.cc |   4 +-
 gdbserver/regcache.cc      |  12 +--
 gdbserver/regcache.h       |   2 +-
 gdbserver/server.cc        | 114 ++++++++++-----------
 10 files changed, 228 insertions(+), 250 deletions(-)
  

Comments

Simon Marchi Oct. 18, 2024, 5:48 p.m. UTC | #1
On 2024-10-18 11:20, Stephan Rohr wrote:
> @@ -101,10 +95,11 @@ remove_thread (struct thread_info *thread)
>      target_disable_btrace (thread->btrace);
>  
>    discard_queued_stop_replies (ptid_of (thread));
> -  all_threads.remove (thread);
> +  auto it = all_threads.iterator_to (*thread);
> +  all_threads.erase (it);

I'd suggest getting rid of the `it` variable:

  all_threads.erase (all_threads.iterator_to (*thread));

>  void *
> @@ -128,8 +123,10 @@ set_thread_regcache_data (struct thread_info *thread, struct regcache *data)
>  void
>  clear_inferiors (void)
>  {
> -  for_each_thread (free_one_thread);
> -  all_threads.clear ();
> +  all_threads.clear_and_dispose ([=] (thread_info *thr)
> +    {
> +      delete thr;
> +    });

If all_threads is the owner of the thread_info objects (it seems like
it), you can switch to using owning_intrusive_list.  Erasing an object
from the list will delete it automatically.  I don't think the rest of
the code will change, except the insertion, from:

  thread_info *new_thread = new thread_info (thread_id, target_data);

  all_threads.push_back (*new_thread);

to something like:

  auto &new_thread = all_threads.emplace_back (thread_id, target_data);

>  /* See gdbthread.h.  */
>  
>  void
> -for_each_thread (gdb::function_view<void (thread_info *)> func)
> +for_each_thread (gdb::function_view<void (thread_info &)> func)

I had forgotten that switching to intrusive_list means that iterating on
the list now yields references instead of pointers.

There are more calls to for_each_thread in arch-specific code that would
need updating, for instance in linux-arm-low.cc.

I think the safer option for now (and less work for you) would be to
keep the existing signature for for_each_thread (and other similar
functions).  You would need to replace

  func (*cur);

with

  func (&*cur);

Callers would not need to change.  And it would make the patch more
focused.

Switching functions from taking pointers to taking references is good,
but at this scale it's better kept as separate patch (which is entirely
optional, I'm not forcing you to do it).

Simon
  
Tom Tromey Oct. 25, 2024, 7:01 p.m. UTC | #2
>>>>> "Stephan" == Stephan Rohr <stephan.rohr@intel.com> writes:

Stephan> This patch replaces the 'std::list' type of 'all_processes' and
Stephan> 'all_threads' with the more lightweight 'intrusive_list' type.

This patch uses the word "introdusive" in its Subject line, but it
should be "intrusive", or maybe even just rewritten?

thanks,
Tom
  

Patch

diff --git a/gdbserver/dll.cc b/gdbserver/dll.cc
index ff637a03fed..f3f062316d7 100644
--- a/gdbserver/dll.cc
+++ b/gdbserver/dll.cc
@@ -93,8 +93,8 @@  unloaded_dll (process_info *proc, const char *name, CORE_ADDR base_addr)
 void
 clear_dlls (void)
 {
-  for_each_process ([] (process_info *proc)
+  for_each_process ([] (process_info &proc)
     {
-      proc->all_dlls.clear ();
+      proc.all_dlls.clear ();
     });
 }
diff --git a/gdbserver/gdbthread.h b/gdbserver/gdbthread.h
index adc5857abfd..8e6f81afad2 100644
--- a/gdbserver/gdbthread.h
+++ b/gdbserver/gdbthread.h
@@ -23,12 +23,10 @@ 
 #include "gdbsupport/function-view.h"
 #include "inferiors.h"
 
-#include <list>
-
 struct btrace_target_info;
 struct regcache;
 
-struct thread_info
+struct thread_info : public intrusive_list_node<thread_info>
 {
   thread_info (ptid_t id, void *target_data)
     : id (id), target_data (target_data)
@@ -86,7 +84,7 @@  struct thread_info
   gdb_thread_options thread_options = 0;
 };
 
-extern std::list<thread_info *> all_threads;
+extern intrusive_list<thread_info> all_threads;
 
 void remove_thread (struct thread_info *thread);
 struct thread_info *add_thread (ptid_t ptid, void *target_data);
@@ -105,34 +103,34 @@  struct thread_info *find_any_thread_of_pid (int pid);
    satisfying FUNC is found.  */
 
 thread_info *
-find_thread (gdb::function_view<bool (thread_info *)> func);
+find_thread (gdb::function_view<bool (thread_info &)> func);
 
 /* Like the above, but only consider threads with pid PID.  */
 
 thread_info *
-find_thread (int pid, gdb::function_view<bool (thread_info *)> func);
+find_thread (int pid, gdb::function_view<bool (thread_info &)> func);
 
 /* Find the first thread that matches FILTER for which FUNC returns true.
    Return NULL if no thread satisfying these conditions is found.  */
 
 thread_info *
-find_thread (ptid_t filter, gdb::function_view<bool (thread_info *)> func);
+find_thread (ptid_t filter, gdb::function_view<bool (thread_info &)> func);
 
 /* Invoke FUNC for each thread.  */
 
 void
-for_each_thread (gdb::function_view<void (thread_info *)> func);
+for_each_thread (gdb::function_view<void (thread_info &)> func);
 
 /* Like the above, but only consider threads with pid PID.  */
 
 void
-for_each_thread (int pid, gdb::function_view<void (thread_info *)> func);
+for_each_thread (int pid, gdb::function_view<void (thread_info &)> func);
 
 /* Find the a random thread for which FUNC (THREAD) returns true.  If
    no entry is found then return NULL.  */
 
 thread_info *
-find_thread_in_random (gdb::function_view<bool (thread_info *)> func);
+find_thread_in_random (gdb::function_view<bool (thread_info &)> func);
 
 /* Get current thread ID (Linux task ID).  */
 #define current_ptid (current_thread->id)
diff --git a/gdbserver/inferiors.cc b/gdbserver/inferiors.cc
index 5621db377fb..1a2109ef9c8 100644
--- a/gdbserver/inferiors.cc
+++ b/gdbserver/inferiors.cc
@@ -22,8 +22,8 @@ 
 #include "gdbthread.h"
 #include "dll.h"
 
-std::list<process_info *> all_processes;
-std::list<thread_info *> all_threads;
+intrusive_list<process_info> all_processes;
+intrusive_list<thread_info> all_threads;
 
 /* The current process.  */
 static process_info *current_process_;
@@ -42,7 +42,7 @@  add_thread (ptid_t thread_id, void *target_data)
 {
   thread_info *new_thread = new thread_info (thread_id, target_data);
 
-  all_threads.push_back (new_thread);
+  all_threads.push_back (*new_thread);
 
   if (current_thread == NULL)
     switch_to_thread (new_thread);
@@ -56,7 +56,7 @@  struct thread_info *
 get_first_thread (void)
 {
   if (!all_threads.empty ())
-    return all_threads.front ();
+    return &(all_threads.front ());
   else
     return NULL;
 }
@@ -64,8 +64,8 @@  get_first_thread (void)
 struct thread_info *
 find_thread_ptid (ptid_t ptid)
 {
-  return find_thread ([&] (thread_info *thread) {
-    return thread->id == ptid;
+  return find_thread ([&] (thread_info &thread) {
+    return thread.id == ptid;
   });
 }
 
@@ -83,17 +83,11 @@  find_thread_process (const struct process_info *const process)
 struct thread_info *
 find_any_thread_of_pid (int pid)
 {
-  return find_thread (pid, [] (thread_info *thread) {
+  return find_thread (pid, [] (thread_info &thread) {
     return true;
   });
 }
 
-static void
-free_one_thread (thread_info *thread)
-{
-  delete thread;
-}
-
 void
 remove_thread (struct thread_info *thread)
 {
@@ -101,10 +95,11 @@  remove_thread (struct thread_info *thread)
     target_disable_btrace (thread->btrace);
 
   discard_queued_stop_replies (ptid_of (thread));
-  all_threads.remove (thread);
+  auto it = all_threads.iterator_to (*thread);
+  all_threads.erase (it);
   if (current_thread == thread)
     switch_to_thread (nullptr);
-  free_one_thread (thread);
+  delete thread;
 }
 
 void *
@@ -128,8 +123,10 @@  set_thread_regcache_data (struct thread_info *thread, struct regcache *data)
 void
 clear_inferiors (void)
 {
-  for_each_thread (free_one_thread);
-  all_threads.clear ();
+  all_threads.clear_and_dispose ([=] (thread_info *thr)
+    {
+      delete thr;
+    });
 
   clear_dlls ();
 
@@ -142,7 +139,7 @@  add_process (int pid, int attached)
 {
   process_info *process = new process_info (pid, attached);
 
-  all_processes.push_back (process);
+  all_processes.push_back (*process);
 
   return process;
 }
@@ -157,7 +154,8 @@  remove_process (struct process_info *process)
   clear_symbol_cache (&process->symbol_cache);
   free_all_breakpoints (process);
   gdb_assert (find_thread_process (process) == NULL);
-  all_processes.remove (process);
+  auto it = all_processes.iterator_to (*process);
+  all_processes.erase (it);
   if (current_process () == process)
     switch_to_process (nullptr);
   delete process;
@@ -166,8 +164,8 @@  remove_process (struct process_info *process)
 process_info *
 find_process_pid (int pid)
 {
-  return find_process ([&] (process_info *process) {
-    return process->pid == pid;
+  return find_process ([&] (process_info &process) {
+    return process.pid == pid;
   });
 }
 
@@ -177,7 +175,7 @@  process_info *
 get_first_process (void)
 {
   if (!all_processes.empty ())
-    return all_processes.front ();
+    return &(all_processes.front ());
   else
     return NULL;
 }
@@ -188,8 +186,8 @@  get_first_process (void)
 int
 have_started_inferiors_p (void)
 {
-  return find_process ([] (process_info *process) {
-    return !process->attached;
+  return find_process ([] (process_info &process) {
+    return !process.attached;
   }) != NULL;
 }
 
@@ -198,8 +196,8 @@  have_started_inferiors_p (void)
 int
 have_attached_inferiors_p (void)
 {
-  return find_process ([] (process_info *process) {
-    return process->attached;
+  return find_process ([] (process_info &process) {
+    return process.attached;
   }) != NULL;
 }
 
@@ -218,9 +216,9 @@  current_process (void)
 /* See inferiors.h.  */
 
 void
-for_each_process (gdb::function_view<void (process_info *)> func)
+for_each_process (gdb::function_view<void (process_info &)> func)
 {
-  std::list<process_info *>::iterator next, cur = all_processes.begin ();
+  intrusive_list<process_info>::iterator next, cur = all_processes.begin ();
 
   while (cur != all_processes.end ())
     {
@@ -234,20 +232,11 @@  for_each_process (gdb::function_view<void (process_info *)> func)
 /* See inferiors.h.  */
 
 process_info *
-find_process (gdb::function_view<bool (process_info *)> func)
+find_process (gdb::function_view<bool (process_info &)> func)
 {
-  std::list<process_info *>::iterator next, cur = all_processes.begin ();
-
-  while (cur != all_processes.end ())
-    {
-      next = cur;
-      next++;
-
-      if (func (*cur))
-	return *cur;
-
-      cur = next;
-    }
+  for (process_info &process : all_processes)
+    if (func (process))
+      return &process;
 
   return NULL;
 }
@@ -255,20 +244,11 @@  find_process (gdb::function_view<bool (process_info *)> func)
 /* See gdbthread.h.  */
 
 thread_info *
-find_thread (gdb::function_view<bool (thread_info *)> func)
+find_thread (gdb::function_view<bool (thread_info &)> func)
 {
-  std::list<thread_info *>::iterator next, cur = all_threads.begin ();
-
-  while (cur != all_threads.end ())
-    {
-      next = cur;
-      next++;
-
-      if (func (*cur))
-	return *cur;
-
-      cur = next;
-    }
+  for (thread_info &thread : all_threads)
+    if (func (thread))
+      return &thread;
 
   return NULL;
 }
@@ -276,30 +256,30 @@  find_thread (gdb::function_view<bool (thread_info *)> func)
 /* See gdbthread.h.  */
 
 thread_info *
-find_thread (int pid, gdb::function_view<bool (thread_info *)> func)
+find_thread (int pid, gdb::function_view<bool (thread_info &)> func)
 {
-  return find_thread ([&] (thread_info *thread)
+  return find_thread ([&] (thread_info &thread)
     {
-      return thread->id.pid () == pid && func (thread);
+      return thread.id.pid () == pid && func (thread);
     });
 }
 
 /* See gdbthread.h.  */
 
 thread_info *
-find_thread (ptid_t filter, gdb::function_view<bool (thread_info *)> func)
+find_thread (ptid_t filter, gdb::function_view<bool (thread_info &)> func)
 {
-  return find_thread ([&] (thread_info *thread) {
-    return thread->id.matches (filter) && func (thread);
+  return find_thread ([&] (thread_info &thread) {
+    return thread.id.matches (filter) && func (thread);
   });
 }
 
 /* See gdbthread.h.  */
 
 void
-for_each_thread (gdb::function_view<void (thread_info *)> func)
+for_each_thread (gdb::function_view<void (thread_info &)> func)
 {
-  std::list<thread_info *>::iterator next, cur = all_threads.begin ();
+  intrusive_list<thread_info>::iterator next, cur = all_threads.begin ();
 
   while (cur != all_threads.end ())
     {
@@ -313,11 +293,11 @@  for_each_thread (gdb::function_view<void (thread_info *)> func)
 /* See gdbthread.h.  */
 
 void
-for_each_thread (int pid, gdb::function_view<void (thread_info *)> func)
+for_each_thread (int pid, gdb::function_view<void (thread_info &)> func)
 {
-  for_each_thread ([&] (thread_info *thread)
+  for_each_thread ([&] (thread_info &thread)
     {
-      if (pid == thread->id.pid ())
+      if (pid == thread.id.pid ())
 	func (thread);
     });
 }
@@ -325,13 +305,13 @@  for_each_thread (int pid, gdb::function_view<void (thread_info *)> func)
 /* See gdbthread.h.  */
 
 thread_info *
-find_thread_in_random (gdb::function_view<bool (thread_info *)> func)
+find_thread_in_random (gdb::function_view<bool (thread_info &)> func)
 {
   int count = 0;
   int random_selector;
 
   /* First count how many interesting entries we have.  */
-  for_each_thread ([&] (thread_info *thread) {
+  for_each_thread ([&] (thread_info &thread) {
     if (func (thread))
       count++;
   });
@@ -343,7 +323,7 @@  find_thread_in_random (gdb::function_view<bool (thread_info *)> func)
   random_selector = (int)
     ((count * (double) rand ()) / (RAND_MAX + 1.0));
 
-  thread_info *thread = find_thread ([&] (thread_info *thr_arg) {
+  thread_info *thread = find_thread ([&] (thread_info &thr_arg) {
     return func (thr_arg) && (random_selector-- == 0);
   });
 
diff --git a/gdbserver/inferiors.h b/gdbserver/inferiors.h
index 5f865fa860a..7605cb675d0 100644
--- a/gdbserver/inferiors.h
+++ b/gdbserver/inferiors.h
@@ -20,8 +20,8 @@ 
 #define GDBSERVER_INFERIORS_H
 
 #include "gdbsupport/gdb_vecs.h"
+#include "gdbsupport/intrusive_list.h"
 #include "dll.h"
-#include <list>
 
 struct thread_info;
 struct regcache;
@@ -32,7 +32,7 @@  struct raw_breakpoint;
 struct fast_tracepoint_jump;
 struct process_info_private;
 
-struct process_info
+struct process_info : public intrusive_list_node<process_info>
 {
   process_info (int pid_, int attached_)
   : pid (pid_), attached (attached_)
@@ -99,17 +99,17 @@  pid_of (const process_info *proc)
 struct process_info *current_process (void);
 struct process_info *get_thread_process (const struct thread_info *);
 
-extern std::list<process_info *> all_processes;
+extern intrusive_list<process_info> all_processes;
 
 /* Invoke FUNC for each process.  */
 
-void for_each_process (gdb::function_view<void (process_info *)> func);
+void for_each_process (gdb::function_view<void (process_info &)> func);
 
 /* Find the first process for which FUNC returns true.  Return NULL if no
    process satisfying FUNC is found.  */
 
 process_info *
-find_process (gdb::function_view<bool (process_info *)> func);
+find_process (gdb::function_view<bool (process_info &)> func);
 
 extern struct thread_info *current_thread;
 
diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc
index 79512c07a22..ceb47aef583 100644
--- a/gdbserver/linux-low.cc
+++ b/gdbserver/linux-low.cc
@@ -1249,7 +1249,7 @@  last_thread_of_process_p (int pid)
 {
   bool seen_one = false;
 
-  thread_info *thread = find_thread (pid, [&] (thread_info *thr_arg)
+  thread_info *thread = find_thread (pid, [&] (thread_info &thr_arg)
     {
       if (!seen_one)
 	{
@@ -1357,19 +1357,19 @@  kill_wait_lwp (struct lwp_info *lwp)
    except the leader.  */
 
 static void
-kill_one_lwp_callback (thread_info *thread, int pid)
+kill_one_lwp_callback (thread_info &thread, int pid)
 {
-  struct lwp_info *lwp = get_thread_lwp (thread);
+  struct lwp_info *lwp = get_thread_lwp (&thread);
 
   /* We avoid killing the first thread here, because of a Linux kernel (at
      least 2.6.0-test7 through 2.6.8-rc4) bug; if we kill the parent before
      the children get a chance to be reaped, it will remain a zombie
      forever.  */
 
-  if (lwpid_of (thread) == pid)
+  if (lwpid_of (&thread) == pid)
     {
       threads_debug_printf ("is last of process %s",
-			    target_pid_to_str (thread->id).c_str ());
+			    target_pid_to_str (thread.id).c_str ());
       return;
     }
 
@@ -1385,7 +1385,7 @@  linux_process_target::kill (process_info *process)
      first, as PTRACE_KILL will not work otherwise.  */
   stop_all_lwps (0, NULL);
 
-  for_each_thread (pid, [&] (thread_info *thread)
+  for_each_thread (pid, [&] (thread_info &thread)
     {
       kill_one_lwp_callback (thread, pid);
     });
@@ -1509,7 +1509,7 @@  linux_process_target::detach_one_lwp (lwp_info *lwp)
   try
     {
       /* Flush any pending changes to the process's registers.  */
-      regcache_invalidate_thread (thread);
+      regcache_invalidate_thread (*thread);
 
       /* Finally, let it resume.  */
       low_prepare_to_resume (lwp);
@@ -1588,15 +1588,15 @@  linux_process_target::detach (process_info *process)
   /* Detach from the clone lwps first.  If the thread group exits just
      while we're detaching, we must reap the clone lwps before we're
      able to reap the leader.  */
-  for_each_thread (process->pid, [this] (thread_info *thread)
+  for_each_thread (process->pid, [this] (thread_info &thread)
     {
       /* We don't actually detach from the thread group leader just yet.
 	 If the thread group exits, we must reap the zombie clone lwps
 	 before we're able to reap the leader.  */
-      if (thread->id.pid () == thread->id.lwp ())
+      if (thread.id.pid () == thread.id.lwp ())
 	return;
 
-      lwp_info *lwp = get_thread_lwp (thread);
+      lwp_info *lwp = get_thread_lwp (&thread);
       detach_one_lwp (lwp);
     });
 
@@ -1621,9 +1621,9 @@  linux_process_target::mourn (process_info *process)
   thread_db_mourn (process);
 #endif
 
-  for_each_thread (process->pid, [this] (thread_info *thread)
+  for_each_thread (process->pid, [this] (thread_info &thread)
     {
-      delete_lwp (get_thread_lwp (thread));
+      delete_lwp (get_thread_lwp (&thread));
     });
 
   this->remove_linux_process (process);
@@ -1745,9 +1745,9 @@  struct lwp_info *
 find_lwp_pid (ptid_t ptid)
 {
   long lwp = ptid.lwp () != 0 ? ptid.lwp () : ptid.pid ();
-  thread_info *thread = find_thread ([lwp] (thread_info *thr_arg)
+  thread_info *thread = find_thread ([lwp] (thread_info &thr_arg)
     {
-      return thr_arg->id.lwp () == lwp;
+      return thr_arg.id.lwp () == lwp;
     });
 
   if (thread == NULL)
@@ -1763,7 +1763,7 @@  num_lwps (int pid)
 {
   int count = 0;
 
-  for_each_thread (pid, [&] (thread_info *thread)
+  for_each_thread (pid, [&] (thread_info &thread)
     {
       count++;
     });
@@ -1777,9 +1777,9 @@  struct lwp_info *
 iterate_over_lwps (ptid_t filter,
 		   gdb::function_view<iterate_over_lwps_ftype> callback)
 {
-  thread_info *thread = find_thread (filter, [&] (thread_info *thr_arg)
+  thread_info *thread = find_thread (filter, [&] (thread_info &thr_arg)
     {
-      lwp_info *lwp = get_thread_lwp (thr_arg);
+      lwp_info *lwp = get_thread_lwp (&thr_arg);
 
       return callback (lwp);
     });
@@ -1795,9 +1795,9 @@  linux_process_target::check_zombie_leaders ()
 {
   bool new_pending_event = false;
 
-  for_each_process ([&] (process_info *proc)
+  for_each_process ([&] (process_info &proc)
     {
-      pid_t leader_pid = pid_of (proc);
+      pid_t leader_pid = pid_of (&proc);
       lwp_info *leader_lp = find_lwp_pid (ptid_t (leader_pid));
 
       threads_debug_printf ("leader_pid=%d, leader_lp!=NULL=%d, "
@@ -1883,12 +1883,12 @@  linux_process_target::check_zombie_leaders ()
    stopped.  */
 
 static bool
-not_stopped_callback (thread_info *thread, ptid_t filter)
+not_stopped_callback (thread_info &thread, ptid_t filter)
 {
-  if (!thread->id.matches (filter))
+  if (!thread.id.matches (filter))
     return false;
 
-  lwp_info *lwp = get_thread_lwp (thread);
+  lwp_info *lwp = get_thread_lwp (&thread);
 
   return !lwp->stopped;
 }
@@ -2291,9 +2291,9 @@  linux_process_target::filter_event (int lwpid, int wstat)
 	     forked and then it exits.  However, note that we may have
 	     earlier deleted a leader of an inferior we're debugging,
 	     in check_zombie_leaders.  Re-add it back here if so.  */
-	  find_process ([&] (process_info *proc)
+	  find_process ([&] (process_info &proc)
 	    {
-	      if (proc->pid == lwpid)
+	      if (proc.pid == lwpid)
 		{
 		  threads_debug_printf
 		    ("Re-adding thread group leader LWP %d after exit.",
@@ -2522,9 +2522,9 @@  linux_process_target::wait_for_event_filtered (ptid_t wait_ptid,
 
   if (filter_ptid == minus_one_ptid || filter_ptid.is_pid ())
     {
-      event_thread = find_thread_in_random ([&] (thread_info *thread)
+      event_thread = find_thread_in_random ([&] (thread_info &thread)
 	{
-	  return status_pending_p_callback (thread, filter_ptid);
+	  return status_pending_p_callback (&thread, filter_ptid);
 	});
 
       if (event_thread != NULL)
@@ -2631,16 +2631,16 @@  linux_process_target::wait_for_event_filtered (ptid_t wait_ptid,
       /* Now that we've pulled all events out of the kernel, resume
 	 LWPs that don't have an interesting event to report.  */
       if (stopping_threads == NOT_STOPPING_THREADS)
-	for_each_thread ([this] (thread_info *thread)
+	for_each_thread ([this] (thread_info &thread)
 	  {
-	    resume_stopped_resumed_lwps (thread);
+	    resume_stopped_resumed_lwps (&thread);
 	  });
 
       /* ... and find an LWP with a status to report to the core, if
 	 any.  */
-      event_thread = find_thread_in_random ([&] (thread_info *thread)
+      event_thread = find_thread_in_random ([&] (thread_info &thread)
 	{
-	  return status_pending_p_callback (thread, filter_ptid);
+	  return status_pending_p_callback (&thread, filter_ptid);
 	});
 
       if (event_thread != NULL)
@@ -2657,7 +2657,7 @@  linux_process_target::wait_for_event_filtered (ptid_t wait_ptid,
       if (check_zombie_leaders ())
 	goto retry;
 
-      auto not_stopped = [&] (thread_info *thread)
+      auto not_stopped = [&] (thread_info &thread)
 	{
 	  return not_stopped_callback (thread, wait_ptid);
 	};
@@ -2724,12 +2724,12 @@  select_event_lwp (struct lwp_info **orig_lp)
      would report it to the user as a random signal.  */
   if (!non_stop)
     {
-      event_thread = find_thread ([] (thread_info *thread)
+      event_thread = find_thread ([] (thread_info &thread)
 	{
-	  lwp_info *lp = get_thread_lwp (thread);
+	  lwp_info *lp = get_thread_lwp (&thread);
 
-	  return (thread->last_status.kind () == TARGET_WAITKIND_IGNORE
-		  && thread->last_resume_kind == resume_step
+	  return (thread.last_status.kind () == TARGET_WAITKIND_IGNORE
+		  && thread.last_resume_kind == resume_step
 		  && lp->status_pending_p);
 	});
 
@@ -2743,12 +2743,12 @@  select_event_lwp (struct lwp_info **orig_lp)
       /* No single-stepping LWP.  Select one at random, out of those
 	 which have had events.  */
 
-      event_thread = find_thread_in_random ([&] (thread_info *thread)
+      event_thread = find_thread_in_random ([&] (thread_info &thread)
 	{
-	  lwp_info *lp = get_thread_lwp (thread);
+	  lwp_info *lp = get_thread_lwp (&thread);
 
 	  /* Only resumed LWPs that have an event pending. */
-	  return (thread->last_status.kind () == TARGET_WAITKIND_IGNORE
+	  return (thread.last_status.kind () == TARGET_WAITKIND_IGNORE
 		  && lp->status_pending_p);
 	});
     }
@@ -2768,16 +2768,16 @@  select_event_lwp (struct lwp_info **orig_lp)
 static void
 unsuspend_all_lwps (struct lwp_info *except)
 {
-  for_each_thread ([&] (thread_info *thread)
+  for_each_thread ([&] (thread_info &thread)
     {
-      lwp_info *lwp = get_thread_lwp (thread);
+      lwp_info *lwp = get_thread_lwp (&thread);
 
       if (lwp != except)
 	lwp_suspended_decr (lwp);
     });
 }
 
-static bool lwp_running (thread_info *thread);
+static bool lwp_running (thread_info &thread);
 
 /* Stabilize threads (move out of jump pads).
 
@@ -2812,7 +2812,7 @@  static bool lwp_running (thread_info *thread);
 void
 linux_process_target::stabilize_threads ()
 {
-  thread_info *thread_stuck = find_thread ([this] (thread_info *thread)
+  thread_info *thread_stuck = find_thread ([this] (thread_info &thread)
 				{
 				  return stuck_in_jump_pad (thread);
 				});
@@ -2829,9 +2829,9 @@  linux_process_target::stabilize_threads ()
   stabilizing_threads = 1;
 
   /* Kick 'em all.  */
-  for_each_thread ([this] (thread_info *thread)
+  for_each_thread ([this] (thread_info &thread)
     {
-      move_out_of_jump_pad (thread);
+      move_out_of_jump_pad (&thread);
     });
 
   /* Loop until all are stopped out of the jump pads.  */
@@ -2868,7 +2868,7 @@  linux_process_target::stabilize_threads ()
 
   if (debug_threads)
     {
-      thread_stuck = find_thread ([this] (thread_info *thread)
+      thread_stuck = find_thread ([this] (thread_info &thread)
 		       {
 			 return stuck_in_jump_pad (thread);
 		       });
@@ -3461,8 +3461,8 @@  linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
 	  /* In all-stop, a stop reply cancels all previous resume
 	     requests.  Delete all single-step breakpoints.  */
 
-	  find_thread ([&] (thread_info *thread) {
-	    if (has_single_step_breakpoints (thread))
+	  find_thread ([&] (thread_info &thread) {
+	    if (has_single_step_breakpoints (&thread))
 	      {
 		remove_single_step_breakpoints_p = 1;
 		return true;
@@ -3486,9 +3486,9 @@  linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
 	    }
 	  else
 	    {
-	      for_each_thread ([] (thread_info *thread){
-		if (has_single_step_breakpoints (thread))
-		  delete_single_step_breakpoints (thread);
+	      for_each_thread ([] (thread_info &thread){
+		if (has_single_step_breakpoints (&thread))
+		  delete_single_step_breakpoints (&thread);
 	      });
 	    }
 
@@ -3839,14 +3839,14 @@  linux_process_target::wait_for_sigstop ()
 }
 
 bool
-linux_process_target::stuck_in_jump_pad (thread_info *thread)
+linux_process_target::stuck_in_jump_pad (thread_info &thread)
 {
-  struct lwp_info *lwp = get_thread_lwp (thread);
+  struct lwp_info *lwp = get_thread_lwp (&thread);
 
   if (lwp->suspended != 0)
     {
       internal_error ("LWP %ld is suspended, suspended=%d\n",
-		      lwpid_of (thread), lwp->suspended);
+		      lwpid_of (&thread), lwp->suspended);
     }
   gdb_assert (lwp->stopped);
 
@@ -3855,7 +3855,7 @@  linux_process_target::stuck_in_jump_pad (thread_info *thread)
 	  && agent_loaded_p ()
 	  && (gdb_breakpoint_here (lwp->stop_pc)
 	      || lwp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT
-	      || thread->last_resume_kind == resume_step)
+	      || thread.last_resume_kind == resume_step)
 	  && (linux_fast_tracepoint_collecting (lwp, NULL)
 	      != fast_tpoint_collect_result::not_collecting));
 }
@@ -3904,9 +3904,9 @@  linux_process_target::move_out_of_jump_pad (thread_info *thread)
 }
 
 static bool
-lwp_running (thread_info *thread)
+lwp_running (thread_info &thread)
 {
-  struct lwp_info *lwp = get_thread_lwp (thread);
+  struct lwp_info *lwp = get_thread_lwp (&thread);
 
   if (lwp_is_marked_dead (lwp))
     return false;
@@ -3933,14 +3933,14 @@  linux_process_target::stop_all_lwps (int suspend, lwp_info *except)
 		      : STOPPING_THREADS);
 
   if (suspend)
-    for_each_thread ([&] (thread_info *thread)
+    for_each_thread ([&] (thread_info &thread)
       {
-	suspend_and_send_sigstop (thread, except);
+	suspend_and_send_sigstop (&thread, except);
       });
   else
-    for_each_thread ([&] (thread_info *thread)
+    for_each_thread ([&] (thread_info &thread)
       {
-	 send_sigstop (thread, except);
+	 send_sigstop (&thread, except);
       });
 
   wait_for_sigstop ();
@@ -4169,7 +4169,7 @@  linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step,
 
   low_prepare_to_resume (lwp);
 
-  regcache_invalidate_thread (thread);
+  regcache_invalidate_thread (*thread);
   errno = 0;
   lwp->stepping = step;
   if (step)
@@ -4277,29 +4277,29 @@  linux_process_target::resume_one_lwp (lwp_info *lwp, int step, int signal,
    suspension).  */
 
 static void
-linux_set_resume_request (thread_info *thread, thread_resume *resume, size_t n)
+linux_set_resume_request (thread_info &thread, thread_resume *resume, size_t n)
 {
-  struct lwp_info *lwp = get_thread_lwp (thread);
+  struct lwp_info *lwp = get_thread_lwp (&thread);
 
   for (int ndx = 0; ndx < n; ndx++)
     {
       ptid_t ptid = resume[ndx].thread;
       if (ptid == minus_one_ptid
-	  || ptid == thread->id
+	  || ptid == thread.id
 	  /* Handle both 'pPID' and 'pPID.-1' as meaning 'all threads
 	     of PID'.  */
-	  || (ptid.pid () == pid_of (thread)
+	  || (ptid.pid () == pid_of (&thread)
 	      && (ptid.is_pid ()
 		  || ptid.lwp () == -1)))
 	{
 	  if (resume[ndx].kind == resume_stop
-	      && thread->last_resume_kind == resume_stop)
+	      && thread.last_resume_kind == resume_stop)
 	    {
 	      threads_debug_printf
 		("already %s LWP %ld at GDB's request",
-		 (thread->last_status.kind () == TARGET_WAITKIND_STOPPED
+		 (thread.last_status.kind () == TARGET_WAITKIND_STOPPED
 		  ? "stopped" : "stopping"),
-		  lwpid_of (thread));
+		  lwpid_of (&thread));
 
 	      continue;
 	    }
@@ -4307,13 +4307,13 @@  linux_set_resume_request (thread_info *thread, thread_resume *resume, size_t n)
 	  /* Ignore (wildcard) resume requests for already-resumed
 	     threads.  */
 	  if (resume[ndx].kind != resume_stop
-	      && thread->last_resume_kind != resume_stop)
+	      && thread.last_resume_kind != resume_stop)
 	    {
 	      threads_debug_printf
 		("already %s LWP %ld at GDB's request",
-		 (thread->last_resume_kind == resume_step
+		 (thread.last_resume_kind == resume_step
 		  ? "stepping" : "continuing"),
-		 lwpid_of (thread));
+		 lwpid_of (&thread));
 	      continue;
 	    }
 
@@ -4328,7 +4328,7 @@  linux_set_resume_request (thread_info *thread, thread_resume *resume, size_t n)
 		{
 		  threads_debug_printf
 		    ("not resuming LWP %ld: has queued stop reply",
-		     lwpid_of (thread));
+		     lwpid_of (&thread));
 		  continue;
 		}
 	    }
@@ -4337,16 +4337,16 @@  linux_set_resume_request (thread_info *thread, thread_resume *resume, size_t n)
 	     reported to GDBserver core, but GDB has not pulled the
 	     event out of the vStopped queue yet, likewise, ignore the
 	     (wildcard) resume request.  */
-	  if (in_queued_stop_replies (thread->id))
+	  if (in_queued_stop_replies (thread.id))
 	    {
 	      threads_debug_printf
 		("not resuming LWP %ld: has queued stop reply",
-		 lwpid_of (thread));
+		 lwpid_of (&thread));
 	      continue;
 	    }
 
 	  lwp->resume = &resume[ndx];
-	  thread->last_resume_kind = lwp->resume->kind;
+	  thread.last_resume_kind = lwp->resume->kind;
 
 	  lwp->step_range_start = lwp->resume->step_range_start;
 	  lwp->step_range_end = lwp->resume->step_range_end;
@@ -4364,7 +4364,7 @@  linux_set_resume_request (thread_info *thread, thread_resume *resume, size_t n)
 		("Dequeueing deferred signal %d for LWP %ld, "
 		 "leaving status pending.",
 		 WSTOPSIG (lwp->status_pending),
-		 lwpid_of (thread));
+		 lwpid_of (&thread));
 	    }
 
 	  return;
@@ -4737,7 +4737,7 @@  linux_process_target::resume (thread_resume *resume_info, size_t n)
 
  THREADS_SCOPED_DEBUG_ENTER_EXIT;
 
-  for_each_thread ([&] (thread_info *thread)
+  for_each_thread ([&] (thread_info &thread)
     {
       linux_set_resume_request (thread, resume_info, n);
     });
@@ -4750,9 +4750,9 @@  linux_process_target::resume (thread_resume *resume_info, size_t n)
      before considering to start a step-over (in all-stop).  */
   bool any_pending = false;
   if (!non_stop)
-    any_pending = find_thread ([this] (thread_info *thread)
+    any_pending = find_thread ([this] (thread_info &thread)
 		    {
-		      return resume_status_pending (thread);
+		      return resume_status_pending (&thread);
 		    }) != nullptr;
 
   /* If there is a thread which would otherwise be resumed, which is
@@ -4762,9 +4762,9 @@  linux_process_target::resume (thread_resume *resume_info, size_t n)
      to queue any signals that would otherwise be delivered or
      queued.  */
   if (!any_pending && low_supports_breakpoints ())
-    need_step_over = find_thread ([this] (thread_info *thread)
+    need_step_over = find_thread ([this] (thread_info &thread)
 		       {
-			 return thread_needs_step_over (thread);
+			 return thread_needs_step_over (&thread);
 		       });
 
   bool leave_all_stopped = (need_step_over != NULL || any_pending);
@@ -4779,9 +4779,9 @@  linux_process_target::resume (thread_resume *resume_info, size_t n)
 
   /* Even if we're leaving threads stopped, queue all signals we'd
      otherwise deliver.  */
-  for_each_thread ([&] (thread_info *thread)
+  for_each_thread ([&] (thread_info &thread)
     {
-      resume_one_thread (thread, leave_all_stopped);
+      resume_one_thread (&thread, leave_all_stopped);
     });
 
   if (need_step_over)
@@ -4908,9 +4908,9 @@  linux_process_target::proceed_all_lwps ()
 
   if (low_supports_breakpoints ())
     {
-      need_step_over = find_thread ([this] (thread_info *thread)
+      need_step_over = find_thread ([this] (thread_info &thread)
 			 {
-			   return thread_needs_step_over (thread);
+			   return thread_needs_step_over (&thread);
 			 });
 
       if (need_step_over != NULL)
@@ -4925,9 +4925,9 @@  linux_process_target::proceed_all_lwps ()
 
   threads_debug_printf ("Proceeding, no step-over needed");
 
-  for_each_thread ([this] (thread_info *thread)
+  for_each_thread ([this] (thread_info &thread)
     {
-      proceed_one_lwp (thread, NULL);
+      proceed_one_lwp (&thread, NULL);
     });
 }
 
@@ -4943,14 +4943,14 @@  linux_process_target::unstop_all_lwps (int unsuspend, lwp_info *except)
     threads_debug_printf ("except=nullptr");
 
   if (unsuspend)
-    for_each_thread ([&] (thread_info *thread)
+    for_each_thread ([&] (thread_info &thread)
       {
-	unsuspend_and_proceed_one_lwp (thread, except);
+	unsuspend_and_proceed_one_lwp (&thread, except);
       });
   else
-    for_each_thread ([&] (thread_info *thread)
+    for_each_thread ([&] (thread_info &thread)
       {
-	proceed_one_lwp (thread, except);
+	proceed_one_lwp (&thread, except);
       });
 }
 
@@ -5975,9 +5975,9 @@  void
 linux_process_target::handle_new_gdb_connection ()
 {
   /* Request that all the lwps reset their ptrace options.  */
-  for_each_thread ([] (thread_info *thread)
+  for_each_thread ([] (thread_info &thread)
     {
-      struct lwp_info *lwp = get_thread_lwp (thread);
+      struct lwp_info *lwp = get_thread_lwp (&thread);
 
       if (!lwp->stopped)
 	{
@@ -5988,10 +5988,10 @@  linux_process_target::handle_new_gdb_connection ()
       else
 	{
 	  /* Already stopped; go ahead and set the ptrace options.  */
-	  struct process_info *proc = find_process_pid (pid_of (thread));
+	  struct process_info *proc = find_process_pid (pid_of (&thread));
 	  int options = linux_low_ptrace_options (proc->attached);
 
-	  linux_enable_event_reporting (lwpid_of (thread), options);
+	  linux_enable_event_reporting (lwpid_of (&thread), options);
 	  lwp->must_set_ptrace_flags = 0;
 	}
     });
@@ -6206,12 +6206,12 @@  linux_process_target::any_resumed ()
 {
   bool any_resumed;
 
-  auto status_pending_p_any = [&] (thread_info *thread)
+  auto status_pending_p_any = [&] (thread_info &thread)
     {
-      return status_pending_p_callback (thread, minus_one_ptid);
+      return status_pending_p_callback (&thread, minus_one_ptid);
     };
 
-  auto not_stopped = [&] (thread_info *thread)
+  auto not_stopped = [&] (thread_info &thread)
     {
       return not_stopped_callback (thread, minus_one_ptid);
     };
diff --git a/gdbserver/linux-low.h b/gdbserver/linux-low.h
index 273c04626b8..0e82e06cd48 100644
--- a/gdbserver/linux-low.h
+++ b/gdbserver/linux-low.h
@@ -590,7 +590,7 @@  class linux_process_target : public process_stratum_target
      move it out, because we need to report the stop event to GDB.  For
      example, if the user puts a breakpoint in the jump pad, it's
      because she wants to debug it.  */
-  bool stuck_in_jump_pad (thread_info *thread);
+  bool stuck_in_jump_pad (thread_info &thread);
 
   /* Convenience wrapper.  Returns information about LWP's fast tracepoint
      collection status.  */
diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc
index afb1954a1b3..8295cc21e93 100644
--- a/gdbserver/linux-x86-low.cc
+++ b/gdbserver/linux-x86-low.cc
@@ -918,8 +918,8 @@  x86_target::update_xmltarget ()
      release the current regcache objects.  */
   regcache_release ();
 
-  for_each_process ([this] (process_info *proc) {
-    int pid = proc->pid;
+  for_each_process ([this] (process_info &proc) {
+    int pid = proc.pid;
 
     /* Look up any thread of this process.  */
     switch_to_thread (find_any_thread_of_pid (pid));
diff --git a/gdbserver/regcache.cc b/gdbserver/regcache.cc
index 1bb71d10328..974b549106e 100644
--- a/gdbserver/regcache.cc
+++ b/gdbserver/regcache.cc
@@ -72,11 +72,11 @@  get_thread_regcache_for_ptid (ptid_t ptid)
 }
 
 void
-regcache_invalidate_thread (struct thread_info *thread)
+regcache_invalidate_thread (struct thread_info &thread)
 {
   struct regcache *regcache;
 
-  regcache = thread_regcache_data (thread);
+  regcache = thread_regcache_data (&thread);
 
   if (regcache == NULL)
     return;
@@ -85,7 +85,7 @@  regcache_invalidate_thread (struct thread_info *thread)
     {
       scoped_restore_current_thread restore_thread;
 
-      switch_to_thread (thread);
+      switch_to_thread (&thread);
       store_inferior_registers (regcache, -1);
     }
 
@@ -273,15 +273,15 @@  find_regno (const struct target_desc *tdesc, const char *name)
 }
 
 static void
-free_register_cache_thread (struct thread_info *thread)
+free_register_cache_thread (struct thread_info &thread)
 {
-  struct regcache *regcache = thread_regcache_data (thread);
+  struct regcache *regcache = thread_regcache_data (&thread);
 
   if (regcache != NULL)
     {
       regcache_invalidate_thread (thread);
       free_register_cache (regcache);
-      set_thread_regcache_data (thread, NULL);
+      set_thread_regcache_data (&thread, NULL);
     }
 }
 
diff --git a/gdbserver/regcache.h b/gdbserver/regcache.h
index 1752c3979d3..90915f2c967 100644
--- a/gdbserver/regcache.h
+++ b/gdbserver/regcache.h
@@ -77,7 +77,7 @@  void free_register_cache (struct regcache *regcache);
 
 /* Invalidate cached registers for one thread.  */
 
-void regcache_invalidate_thread (struct thread_info *);
+void regcache_invalidate_thread (struct thread_info &);
 
 /* Invalidate cached registers for all threads of the given process.  */
 
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index 69ffb722be7..6733ddee886 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -1005,10 +1005,10 @@  handle_general_set (char *own_buf)
 	  if (ptid.lwp () == -1)
 	    ptid = ptid_t (ptid.pid ());
 
-	  for_each_thread ([&] (thread_info *thread)
+	  for_each_thread ([&] (thread_info &thread)
 	    {
-	      if (ptid_of (thread).matches (ptid))
-		set_options[thread] = options;
+	      if (ptid_of (&thread).matches (ptid))
+		set_options[&thread] = options;
 	    });
 	}
 
@@ -1355,15 +1355,15 @@  handle_detach (char *own_buf)
      another process might delete the next thread in the iteration, which is
      the one saved by the safe iterator.  We will never delete the currently
      iterated on thread, so standard iteration should be safe.  */
-  for (thread_info *thread : all_threads)
+  for (thread_info &thread : all_threads)
     {
       /* Only threads that are of the process we are detaching.  */
-      if (thread->id.pid () != pid)
+      if (thread.id.pid () != pid)
 	continue;
 
       /* Only threads that have a pending fork event.  */
       target_waitkind kind;
-      thread_info *child = target_thread_pending_child (thread, &kind);
+      thread_info *child = target_thread_pending_child (&thread, &kind);
       if (child == nullptr || kind == TARGET_WAITKIND_THREAD_CLONED)
 	continue;
 
@@ -1375,7 +1375,7 @@  handle_detach (char *own_buf)
       if (detach_inferior (fork_child_process) != 0)
 	warning (_("Failed to detach fork child %s, child of %s"),
 		 target_pid_to_str (ptid_t (fork_child_pid)).c_str (),
-		 target_pid_to_str (thread->id).c_str ());
+		 target_pid_to_str (thread.id).c_str ());
     }
 
   if (detach_inferior (process) != 0)
@@ -2002,9 +2002,9 @@  handle_qxfer_statictrace (const char *annex,
    Emit the XML to describe the thread of INF.  */
 
 static void
-handle_qxfer_threads_worker (thread_info *thread, std::string *buffer)
+handle_qxfer_threads_worker (thread_info &thread, std::string *buffer)
 {
-  ptid_t ptid = ptid_of (thread);
+  ptid_t ptid = ptid_of (&thread);
   char ptid_s[100];
   int core = target_core_of_thread (ptid);
   char core_s[21];
@@ -2017,7 +2017,7 @@  handle_qxfer_threads_worker (thread_info *thread, std::string *buffer)
      GDB does not yet know about this thread, and must not know about
      it until it gets the corresponding (v)fork/clone event.  Exclude
      this thread from the list.  */
-  if (target_thread_pending_parent (thread) != nullptr)
+  if (target_thread_pending_parent (&thread) != nullptr)
     return;
 
   write_ptid (ptid_s, ptid);
@@ -2061,7 +2061,7 @@  handle_qxfer_threads_proper (std::string *buffer)
   if (non_stop)
     target_pause_all (true);
 
-  for_each_thread ([&] (thread_info *thread)
+  for_each_thread ([&] (thread_info &thread)
     {
       handle_qxfer_threads_worker (thread, buffer);
     });
@@ -2523,7 +2523,7 @@  static void
 handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 {
   client_state &cs = get_client_state ();
-  static std::list<thread_info *>::const_iterator thread_iter;
+  static intrusive_list<thread_info>::iterator thread_iter;
 
   /* Reply the current thread id.  */
   if (strcmp ("qC", own_buf) == 0 && !disable_packet_qC)
@@ -2536,7 +2536,7 @@  handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       else
 	{
 	  thread_iter = all_threads.begin ();
-	  ptid = (*thread_iter)->id;
+	  ptid = thread_iter->id;
 	}
 
       sprintf (own_buf, "QC");
@@ -2599,7 +2599,7 @@  handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 	  thread_iter = all_threads.begin ();
 
 	  *own_buf++ = 'm';
-	  ptid_t ptid = (*thread_iter)->id;
+	  ptid_t ptid = thread_iter->id;
 	  write_ptid (own_buf, ptid);
 	  thread_iter++;
 	  return;
@@ -2611,7 +2611,7 @@  handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 	  if (thread_iter != all_threads.end ())
 	    {
 	      *own_buf++ = 'm';
-	      ptid_t ptid = (*thread_iter)->id;
+	      ptid_t ptid = thread_iter->id;
 	      write_ptid (own_buf, ptid);
 	      thread_iter++;
 	      return;
@@ -3093,7 +3093,7 @@  typedef int (visit_actioned_threads_callback_ftype)
    Note: This function is itself a callback for find_thread.  */
 
 static bool
-visit_actioned_threads (thread_info *thread,
+visit_actioned_threads (thread_info &thread,
 			const struct thread_resume *actions,
 			size_t num_actions,
 			visit_actioned_threads_callback_ftype *callback)
@@ -3103,12 +3103,12 @@  visit_actioned_threads (thread_info *thread,
       const struct thread_resume *action = &actions[i];
 
       if (action->thread == minus_one_ptid
-	  || action->thread == thread->id
+	  || action->thread == thread.id
 	  || ((action->thread.pid ()
-	       == thread->id.pid ())
+	       == thread.id.pid ())
 	      && action->thread.lwp () == -1))
 	{
-	  if ((*callback) (action, thread))
+	  if ((*callback) (action, &thread))
 	    return true;
 	}
     }
@@ -3258,7 +3258,7 @@  resume (struct thread_resume *actions, size_t num_actions)
 	 resuming/stopping and report the pending event
 	 immediately.  */
 
-      thread_info *thread_with_status = find_thread ([&] (thread_info *thread)
+      thread_info *thread_with_status = find_thread ([&] (thread_info &thread)
 	{
 	  return visit_actioned_threads (thread, actions, num_actions,
 					 handle_pending_status);
@@ -3640,7 +3640,7 @@  myresume (char *own_buf, int step, int sig)
    stopped thread.  */
 
 static void
-queue_stop_reply_callback (thread_info *thread)
+queue_stop_reply_callback (thread_info &thread)
 {
   /* For now, assume targets that don't have this callback also don't
      manage the thread's last_status field.  */
@@ -3648,26 +3648,26 @@  queue_stop_reply_callback (thread_info *thread)
     {
       struct vstop_notif *new_notif = new struct vstop_notif;
 
-      new_notif->ptid = thread->id;
-      new_notif->status = thread->last_status;
+      new_notif->ptid = thread.id;
+      new_notif->status = thread.last_status;
       /* Pass the last stop reply back to GDB, but don't notify
 	 yet.  */
       notif_event_enque (&notif_stop, new_notif);
     }
   else
     {
-      if (target_thread_stopped (thread))
+      if (target_thread_stopped (&thread))
 	{
 	  threads_debug_printf
 	    ("Reporting thread %s as already stopped with %s",
-	     target_pid_to_str (thread->id).c_str (),
-	     thread->last_status.to_string ().c_str ());
+	     target_pid_to_str (thread.id).c_str (),
+	     thread.last_status.to_string ().c_str ());
 
-	  gdb_assert (thread->last_status.kind () != TARGET_WAITKIND_IGNORE);
+	  gdb_assert (thread.last_status.kind () != TARGET_WAITKIND_IGNORE);
 
 	  /* Pass the last stop reply back to GDB, but don't notify
 	     yet.  */
-	  queue_stop_reply (thread->id, thread->last_status);
+	  queue_stop_reply (thread.id, thread.last_status);
 	}
     }
 }
@@ -3677,15 +3677,15 @@  queue_stop_reply_callback (thread_info *thread)
    it.  */
 
 static void
-gdb_wants_thread_stopped (thread_info *thread)
+gdb_wants_thread_stopped (thread_info &thread)
 {
-  thread->last_resume_kind = resume_stop;
+  thread.last_resume_kind = resume_stop;
 
-  if (thread->last_status.kind () == TARGET_WAITKIND_IGNORE)
+  if (thread.last_status.kind () == TARGET_WAITKIND_IGNORE)
     {
       /* Most threads are stopped implicitly (all-stop); tag that with
 	 signal 0.  */
-      thread->last_status.set_stopped (GDB_SIGNAL_0);
+      thread.last_status.set_stopped (GDB_SIGNAL_0);
     }
 }
 
@@ -3701,18 +3701,18 @@  gdb_wants_all_threads_stopped (void)
    interesting event, mark it as having a pending event.  */
 
 static void
-set_pending_status_callback (thread_info *thread)
+set_pending_status_callback (thread_info &thread)
 {
-  if (thread->last_status.kind () != TARGET_WAITKIND_STOPPED
-      || (thread->last_status.sig () != GDB_SIGNAL_0
+  if (thread.last_status.kind () != TARGET_WAITKIND_STOPPED
+      || (thread.last_status.sig () != GDB_SIGNAL_0
 	  /* A breakpoint, watchpoint or finished step from a previous
 	     GDB run isn't considered interesting for a new GDB run.
 	     If we left those pending, the new GDB could consider them
 	     random SIGTRAPs.  This leaves out real async traps.  We'd
 	     have to peek into the (target-specific) siginfo to
 	     distinguish those.  */
-	  && thread->last_status.sig () != GDB_SIGNAL_TRAP))
-    thread->status_pending_p = 1;
+	  && thread.last_status.sig () != GDB_SIGNAL_TRAP))
+    thread.status_pending_p = 1;
 }
 
 /* Status handler for the '?' packet.  */
@@ -3723,8 +3723,8 @@  handle_status (char *own_buf)
   client_state &cs = get_client_state ();
 
   /* GDB is connected, don't forward events to the target anymore.  */
-  for_each_process ([] (process_info *process) {
-    process->gdb_detached = 0;
+  for_each_process ([] (process_info &process) {
+    process.gdb_detached = 0;
   });
 
   /* In non-stop mode, we must send a stop reply for each stopped
@@ -3766,9 +3766,9 @@  handle_status (char *own_buf)
       /* If the last event thread is not found for some reason, look
 	 for some other thread that might have an event to report.  */
       if (thread == NULL)
-	thread = find_thread ([] (thread_info *thr_arg)
+	thread = find_thread ([] (thread_info &thr_arg)
 	  {
-	    return thr_arg->status_pending_p;
+	    return thr_arg.status_pending_p;
 	  });
 
       /* If we're still out of luck, simply pick the first thread in
@@ -3913,10 +3913,10 @@  start_event_loop ()
 }
 
 static void
-kill_inferior_callback (process_info *process)
+kill_inferior_callback (process_info &process)
 {
-  kill_inferior (process);
-  discard_queued_stop_replies (ptid_t (process->pid));
+  kill_inferior (&process);
+  discard_queued_stop_replies (ptid_t (process.pid));
 }
 
 /* Call this when exiting gdbserver with possible inferiors that need
@@ -3934,9 +3934,9 @@  detach_or_kill_for_exit (void)
     {
       fprintf (stderr, "Killing process(es):");
 
-      for_each_process ([] (process_info *process) {
-	if (!process->attached)
-	  fprintf (stderr, " %d", process->pid);
+      for_each_process ([] (process_info &process) {
+	if (!process.attached)
+	  fprintf (stderr, " %d", process.pid);
       });
 
       fprintf (stderr, "\n");
@@ -3945,22 +3945,22 @@  detach_or_kill_for_exit (void)
     {
       fprintf (stderr, "Detaching process(es):");
 
-      for_each_process ([] (process_info *process) {
-	if (process->attached)
-	  fprintf (stderr, " %d", process->pid);
+      for_each_process ([] (process_info &process) {
+	if (process.attached)
+	  fprintf (stderr, " %d", process.pid);
       });
 
       fprintf (stderr, "\n");
     }
 
   /* Now we can kill or detach the inferiors.  */
-  for_each_process ([] (process_info *process) {
-    int pid = process->pid;
+  for_each_process ([] (process_info &process) {
+    int pid = process.pid;
 
-    if (process->attached)
-      detach_inferior (process);
+    if (process.attached)
+      detach_inferior (&process);
     else
-      kill_inferior (process);
+      kill_inferior (&process);
 
     discard_queued_stop_replies (ptid_t (pid));
   });
@@ -4434,9 +4434,9 @@  captured_main (int argc, char *argv[])
 	     (by the same GDB instance or another) will refresh all its
 	     state from scratch.  */
 	  discard_queued_stop_replies (minus_one_ptid);
-	  for_each_thread ([] (thread_info *thread)
+	  for_each_thread ([] (thread_info &thread)
 	    {
-	      thread->status_pending_p = 0;
+	      thread.status_pending_p = 0;
 	    });
 
 	  if (tracing)