]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/gdbserver/linux-low.c
Remove usage of find_inferior in linux_stabilize_threads
[thirdparty/binutils-gdb.git] / gdb / gdbserver / linux-low.c
index 3d7cfe31b5a7c929c3a1bc68baff2d661e77ba9b..b4c716c72d081e95bfe4444cee99866dc6b86716 100644 (file)
@@ -279,7 +279,7 @@ static void enqueue_pending_signal (struct lwp_info *lwp, int signal, siginfo_t
 static void complete_ongoing_step_over (void);
 static int linux_low_ptrace_options (int attached);
 static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp);
-static int proceed_one_lwp (struct inferior_list_entry *entry, void *except);
+static int proceed_one_lwp (thread_info *thread, void *except);
 
 /* When the event-loop is doing a step-over, this points at the thread
    being stepped.  */
@@ -414,7 +414,12 @@ delete_lwp (struct lwp_info *lwp)
     debug_printf ("deleting %ld\n", lwpid_of (thr));
 
   remove_thread (thr);
-  free (lwp->arch_private);
+
+  if (the_low_target.delete_thread != NULL)
+    the_low_target.delete_thread (lwp->arch_private);
+  else
+    gdb_assert (lwp->arch_private == NULL);
+
   free (lwp);
 }
 
@@ -570,7 +575,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
 
          clone_all_breakpoints (child_thr, event_thr);
 
-         tdesc = XNEW (struct target_desc);
+         tdesc = allocate_target_description ();
          copy_target_description (tdesc, parent_proc->tdesc);
          child_proc->tdesc = tdesc;
 
@@ -656,6 +661,8 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
          new_lwp->status_pending = status;
        }
 
+      thread_db_notice_clone (event_thr, ptid);
+
       /* Don't report the event.  */
       return 1;
     }
@@ -676,7 +683,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
   else if (event == PTRACE_EVENT_EXEC && report_exec_events)
     {
       struct process_info *proc;
-      VEC (int) *syscalls_to_catch;
+      std::vector<int> syscalls_to_catch;
       ptid_t event_ptid;
       pid_t event_pid;
 
@@ -692,8 +699,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
 
       /* Save the syscall list from the execing process.  */
       proc = get_thread_process (event_thr);
-      syscalls_to_catch = proc->syscalls_to_catch;
-      proc->syscalls_to_catch = NULL;
+      syscalls_to_catch = std::move (proc->syscalls_to_catch);
 
       /* Delete the execing process and all its threads.  */
       linux_mourn (proc);
@@ -724,7 +730,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
       /* Restore the list to catch.  Don't rely on the client, which is free
         to avoid sending a new list when the architecture doesn't change.
         Also, for ANY_SYSCALL, the architecture doesn't really matter.  */
-      proc->syscalls_to_catch = syscalls_to_catch;
+      proc->syscalls_to_catch = std::move (syscalls_to_catch);
 
       /* Report the event.  */
       *orig_event_lwp = event_lwp;
@@ -1241,11 +1247,11 @@ struct counter
 };
 
 static int
-second_thread_of_pid_p (struct inferior_list_entry *entry, void *args)
+second_thread_of_pid_p (thread_info *thread, void *args)
 {
   struct counter *counter = (struct counter *) args;
 
-  if (ptid_get_pid (entry->id) == counter->pid)
+  if (thread->id.pid () == counter->pid)
     {
       if (++counter->count > 1)
        return 1;
@@ -1354,13 +1360,12 @@ kill_wait_lwp (struct lwp_info *lwp)
    except the leader.  */
 
 static int
-kill_one_lwp_callback (struct inferior_list_entry *entry, void *args)
+kill_one_lwp_callback (thread_info *thread, void *args)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
   int pid = * (int *) args;
 
-  if (ptid_get_pid (entry->id) != pid)
+  if (thread->id.pid () != pid)
     return 0;
 
   /* We avoid killing the first thread here, because of a Linux kernel (at
@@ -1372,7 +1377,7 @@ kill_one_lwp_callback (struct inferior_list_entry *entry, void *args)
     {
       if (debug_threads)
        debug_printf ("lkop: is last of process %s\n",
-                     target_pid_to_str (entry->id));
+                     target_pid_to_str (thread->id));
       return 0;
     }
 
@@ -1587,21 +1592,20 @@ linux_detach_one_lwp (struct lwp_info *lwp)
    given process.  */
 
 static int
-linux_detach_lwp_callback (struct inferior_list_entry *entry, void *args)
+linux_detach_lwp_callback (thread_info *thread, void *args)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
   int pid = *(int *) args;
   int lwpid = lwpid_of (thread);
 
   /* Skip other processes.  */
-  if (ptid_get_pid (entry->id) != pid)
+  if (thread->id.pid () != pid)
     return 0;
 
   /* 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 (ptid_get_pid (entry->id) == lwpid)
+  if (thread->id.pid () == lwpid)
     return 0;
 
   linux_detach_one_lwp (lwp);
@@ -1655,9 +1659,8 @@ linux_detach (int pid)
 /* Remove all LWPs that belong to process PROC from the lwp list.  */
 
 static int
-delete_lwp_callback (struct inferior_list_entry *entry, void *proc)
+delete_lwp_callback (thread_info *thread, void *proc)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
   struct process_info *process = (struct process_info *) proc;
 
@@ -1680,7 +1683,10 @@ linux_mourn (struct process_info *process)
 
   /* Freeing all private data.  */
   priv = process->priv;
-  free (priv->arch_private);
+  if (the_low_target.delete_process != NULL)
+    the_low_target.delete_process (priv->arch_private);
+  else
+    gdb_assert (priv->arch_private == NULL);
   free (priv);
   process->priv = NULL;
 
@@ -1804,9 +1810,8 @@ lwp_resumed (struct lwp_info *lwp)
 
 /* Return 1 if this lwp has an interesting status pending.  */
 static int
-status_pending_p_callback (struct inferior_list_entry *entry, void *arg)
+status_pending_p_callback (thread_info *thread, void *arg)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lp = get_thread_lwp (thread);
   ptid_t ptid = * (ptid_t *) arg;
 
@@ -1829,7 +1834,7 @@ status_pending_p_callback (struct inferior_list_entry *entry, void *arg)
 }
 
 static int
-same_lwp (struct inferior_list_entry *entry, void *data)
+same_lwp (thread_info *thread, void *data)
 {
   ptid_t ptid = *(ptid_t *) data;
   int lwp;
@@ -1839,7 +1844,7 @@ same_lwp (struct inferior_list_entry *entry, void *data)
   else
     lwp = ptid_get_pid (ptid);
 
-  if (ptid_get_lwp (entry->id) == lwp)
+  if (thread->id.lwp () == lwp)
     return 1;
 
   return 0;
@@ -1848,13 +1853,12 @@ same_lwp (struct inferior_list_entry *entry, void *data)
 struct lwp_info *
 find_lwp_pid (ptid_t ptid)
 {
-  struct inferior_list_entry *thread
-    = find_inferior (&all_threads, same_lwp, &ptid);
+  thread_info *thread = find_inferior (&all_threads, same_lwp, &ptid);
 
   if (thread == NULL)
     return NULL;
 
-  return get_thread_lwp ((struct thread_info *) thread);
+  return get_thread_lwp (thread);
 }
 
 /* Return the number of known LWPs in the tgid given by PID.  */
@@ -1862,55 +1866,16 @@ find_lwp_pid (ptid_t ptid)
 static int
 num_lwps (int pid)
 {
-  struct inferior_list_entry *inf, *tmp;
   int count = 0;
 
-  ALL_INFERIORS (&all_threads, inf, tmp)
+  for_each_thread (pid, [&] (thread_info *thread)
     {
-      if (ptid_get_pid (inf->id) == pid)
-       count++;
-    }
+      count++;
+    });
 
   return count;
 }
 
-/* The arguments passed to iterate_over_lwps.  */
-
-struct iterate_over_lwps_args
-{
-  /* The FILTER argument passed to iterate_over_lwps.  */
-  ptid_t filter;
-
-  /* The CALLBACK argument passed to iterate_over_lwps.  */
-  iterate_over_lwps_ftype *callback;
-
-  /* The DATA argument passed to iterate_over_lwps.  */
-  void *data;
-};
-
-/* Callback for find_inferior used by iterate_over_lwps to filter
-   calls to the callback supplied to that function.  Returning a
-   nonzero value causes find_inferiors to stop iterating and return
-   the current inferior_list_entry.  Returning zero indicates that
-   find_inferiors should continue iterating.  */
-
-static int
-iterate_over_lwps_filter (struct inferior_list_entry *entry, void *args_p)
-{
-  struct iterate_over_lwps_args *args
-    = (struct iterate_over_lwps_args *) args_p;
-
-  if (ptid_match (entry->id, args->filter))
-    {
-      struct thread_info *thr = (struct thread_info *) entry;
-      struct lwp_info *lwp = get_thread_lwp (thr);
-
-      return (*args->callback) (lwp, args->data);
-    }
-
-  return 0;
-}
-
 /* See nat/linux-nat.h.  */
 
 struct lwp_info *
@@ -1918,14 +1883,17 @@ iterate_over_lwps (ptid_t filter,
                   iterate_over_lwps_ftype callback,
                   void *data)
 {
-  struct iterate_over_lwps_args args = {filter, callback, data};
-  struct inferior_list_entry *entry;
+  thread_info *thread = find_thread (filter, [&] (thread_info *thread)
+    {
+      lwp_info *lwp = get_thread_lwp (thread);
+
+      return callback (lwp, data);
+    });
 
-  entry = find_inferior (&all_threads, iterate_over_lwps_filter, &args);
-  if (entry == NULL)
+  if (thread == NULL)
     return NULL;
 
-  return get_thread_lwp ((struct thread_info *) entry);
+  return get_thread_lwp (thread);
 }
 
 /* Detect zombie thread group leaders, and "exit" them.  We can't reap
@@ -1934,79 +1902,75 @@ iterate_over_lwps (ptid_t filter,
 static void
 check_zombie_leaders (void)
 {
-  struct process_info *proc, *tmp;
+  for_each_process ([] (process_info *proc) {
+    pid_t leader_pid = pid_of (proc);
+    struct lwp_info *leader_lp;
 
-  ALL_PROCESSES (proc, tmp)
-    {
-      pid_t leader_pid = pid_of (proc);
-      struct lwp_info *leader_lp;
-
-      leader_lp = find_lwp_pid (pid_to_ptid (leader_pid));
+    leader_lp = find_lwp_pid (pid_to_ptid (leader_pid));
 
-      if (debug_threads)
-       debug_printf ("leader_pid=%d, leader_lp!=NULL=%d, "
-                     "num_lwps=%d, zombie=%d\n",
-                     leader_pid, leader_lp!= NULL, num_lwps (leader_pid),
-                     linux_proc_pid_is_zombie (leader_pid));
-
-      if (leader_lp != NULL && !leader_lp->stopped
-         /* Check if there are other threads in the group, as we may
-            have raced with the inferior simply exiting.  */
-         && !last_thread_of_process_p (leader_pid)
-         && linux_proc_pid_is_zombie (leader_pid))
-       {
-         /* A leader zombie can mean one of two things:
-
-            - It exited, and there's an exit status pending
-            available, or only the leader exited (not the whole
-            program).  In the latter case, we can't waitpid the
-            leader's exit status until all other threads are gone.
-
-            - There are 3 or more threads in the group, and a thread
-            other than the leader exec'd.  On an exec, the Linux
-            kernel destroys all other threads (except the execing
-            one) in the thread group, and resets the execing thread's
-            tid to the tgid.  No exit notification is sent for the
-            execing thread -- from the ptracer's perspective, it
-            appears as though the execing thread just vanishes.
-            Until we reap all other threads except the leader and the
-            execing thread, the leader will be zombie, and the
-            execing thread will be in `D (disc sleep)'.  As soon as
-            all other threads are reaped, the execing thread changes
-            it's tid to the tgid, and the previous (zombie) leader
-            vanishes, giving place to the "new" leader.  We could try
-            distinguishing the exit and exec cases, by waiting once
-            more, and seeing if something comes out, but it doesn't
-            sound useful.  The previous leader _does_ go away, and
-            we'll re-add the new one once we see the exec event
-            (which is just the same as what would happen if the
-            previous leader did exit voluntarily before some other
-            thread execs).  */
+    if (debug_threads)
+      debug_printf ("leader_pid=%d, leader_lp!=NULL=%d, "
+                   "num_lwps=%d, zombie=%d\n",
+                   leader_pid, leader_lp!= NULL, num_lwps (leader_pid),
+                   linux_proc_pid_is_zombie (leader_pid));
 
-         if (debug_threads)
-           debug_printf ("CZL: Thread group leader %d zombie "
-                         "(it exited, or another thread execd).\n",
-                         leader_pid);
-
-         delete_lwp (leader_lp);
-       }
-    }
+    if (leader_lp != NULL && !leader_lp->stopped
+       /* Check if there are other threads in the group, as we may
+          have raced with the inferior simply exiting.  */
+       && !last_thread_of_process_p (leader_pid)
+       && linux_proc_pid_is_zombie (leader_pid))
+      {
+       /* A leader zombie can mean one of two things:
+
+          - It exited, and there's an exit status pending
+          available, or only the leader exited (not the whole
+          program).  In the latter case, we can't waitpid the
+          leader's exit status until all other threads are gone.
+
+          - There are 3 or more threads in the group, and a thread
+          other than the leader exec'd.  On an exec, the Linux
+          kernel destroys all other threads (except the execing
+          one) in the thread group, and resets the execing thread's
+          tid to the tgid.  No exit notification is sent for the
+          execing thread -- from the ptracer's perspective, it
+          appears as though the execing thread just vanishes.
+          Until we reap all other threads except the leader and the
+          execing thread, the leader will be zombie, and the
+          execing thread will be in `D (disc sleep)'.  As soon as
+          all other threads are reaped, the execing thread changes
+          it's tid to the tgid, and the previous (zombie) leader
+          vanishes, giving place to the "new" leader.  We could try
+          distinguishing the exit and exec cases, by waiting once
+          more, and seeing if something comes out, but it doesn't
+          sound useful.  The previous leader _does_ go away, and
+          we'll re-add the new one once we see the exec event
+          (which is just the same as what would happen if the
+          previous leader did exit voluntarily before some other
+          thread execs).  */
+
+       if (debug_threads)
+         debug_printf ("CZL: Thread group leader %d zombie "
+                       "(it exited, or another thread execd).\n",
+                       leader_pid);
+
+       delete_lwp (leader_lp);
+      }
+    });
 }
 
 /* Callback for `find_inferior'.  Returns the first LWP that is not
    stopped.  ARG is a PTID filter.  */
 
 static int
-not_stopped_callback (struct inferior_list_entry *entry, void *arg)
+not_stopped_callback (thread_info *thread, void *arg)
 {
-  struct thread_info *thr = (struct thread_info *) entry;
   struct lwp_info *lwp;
   ptid_t filter = *(ptid_t *) arg;
 
-  if (!ptid_match (ptid_of (thr), filter))
+  if (!ptid_match (ptid_of (thread), filter))
     return 0;
 
-  lwp = get_thread_lwp (thr);
+  lwp = get_thread_lwp (thread);
   if (!lwp->stopped)
     return 1;
 
@@ -2082,7 +2046,9 @@ handle_tracepoints (struct lwp_info *lwp)
   lwp_suspended_decr (lwp);
 
   gdb_assert (lwp->suspended == 0);
-  gdb_assert (!stabilizing_threads || lwp->collecting_fast_tracepoint);
+  gdb_assert (!stabilizing_threads
+             || (lwp->collecting_fast_tracepoint
+                 != fast_tpoint_collect_result::not_collecting));
 
   if (tpoint_related_event)
     {
@@ -2094,10 +2060,10 @@ handle_tracepoints (struct lwp_info *lwp)
   return 0;
 }
 
-/* Convenience wrapper.  Returns true if LWP is presently collecting a
-   fast tracepoint.  */
+/* Convenience wrapper.  Returns information about LWP's fast tracepoint
+   collection status.  */
 
-static int
+static fast_tpoint_collect_result
 linux_fast_tracepoint_collecting (struct lwp_info *lwp,
                                  struct fast_tpoint_collect_status *status)
 {
@@ -2105,14 +2071,14 @@ linux_fast_tracepoint_collecting (struct lwp_info *lwp,
   struct thread_info *thread = get_lwp_thread (lwp);
 
   if (the_low_target.get_thread_area == NULL)
-    return 0;
+    return fast_tpoint_collect_result::not_collecting;
 
   /* Get the thread area address.  This is used to recognize which
      thread is which when tracing with the in-process agent library.
      We don't read anything from the address, and treat it as opaque;
      it's the address itself that we assume is unique per-thread.  */
   if ((*the_low_target.get_thread_area) (lwpid_of (thread), &thread_area) == -1)
-    return 0;
+    return fast_tpoint_collect_result::not_collecting;
 
   return fast_tracepoint_collecting (thread_area, lwp->stop_pc, status);
 }
@@ -2136,14 +2102,14 @@ maybe_move_out_of_jump_pad (struct lwp_info *lwp, int *wstat)
       && agent_loaded_p ())
     {
       struct fast_tpoint_collect_status status;
-      int r;
 
       if (debug_threads)
        debug_printf ("Checking whether LWP %ld needs to move out of the "
                      "jump pad.\n",
                      lwpid_of (current_thread));
 
-      r = linux_fast_tracepoint_collecting (lwp, &status);
+      fast_tpoint_collect_result r
+       = linux_fast_tracepoint_collecting (lwp, &status);
 
       if (wstat == NULL
          || (WSTOPSIG (*wstat) != SIGILL
@@ -2153,9 +2119,10 @@ maybe_move_out_of_jump_pad (struct lwp_info *lwp, int *wstat)
        {
          lwp->collecting_fast_tracepoint = r;
 
-         if (r != 0)
+         if (r != fast_tpoint_collect_result::not_collecting)
            {
-             if (r == 1 && lwp->exit_jump_pad_bkpt == NULL)
+             if (r == fast_tpoint_collect_result::before_insn
+                 && lwp->exit_jump_pad_bkpt == NULL)
                {
                  /* Haven't executed the original instruction yet.
                     Set breakpoint there, and wait till it's hit,
@@ -2181,9 +2148,10 @@ maybe_move_out_of_jump_pad (struct lwp_info *lwp, int *wstat)
             reporting to GDB.  Otherwise, it's an IPA lib bug: just
             report the signal to GDB, and pray for the best.  */
 
-         lwp->collecting_fast_tracepoint = 0;
+         lwp->collecting_fast_tracepoint
+           = fast_tpoint_collect_result::not_collecting;
 
-         if (r != 0
+         if (r != fast_tpoint_collect_result::not_collecting
              && (status.adjusted_insn_addr <= lwp->stop_pc
                  && lwp->stop_pc < status.adjusted_insn_addr_end))
            {
@@ -2648,9 +2616,8 @@ maybe_hw_step (struct thread_info *thread)
    to report, but are resumed from the core's perspective.  */
 
 static void
-resume_stopped_resumed_lwps (struct inferior_list_entry *entry)
+resume_stopped_resumed_lwps (thread_info *thread)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lp = get_thread_lwp (thread);
 
   if (lp->stopped
@@ -2715,7 +2682,8 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
 
       if (stopping_threads == NOT_STOPPING_THREADS
          && requested_child->status_pending_p
-         && requested_child->collecting_fast_tracepoint)
+         && (requested_child->collecting_fast_tracepoint
+             != fast_tpoint_collect_result::not_collecting))
        {
          enqueue_one_deferred_signal (requested_child,
                                       &requested_child->status_pending);
@@ -2889,9 +2857,8 @@ linux_wait_for_event (ptid_t ptid, int *wstatp, int options)
 /* Count the LWP's that have had events.  */
 
 static int
-count_events_callback (struct inferior_list_entry *entry, void *data)
+count_events_callback (thread_info *thread, void *data)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lp = get_thread_lwp (thread);
   int *count = (int *) data;
 
@@ -2908,9 +2875,8 @@ count_events_callback (struct inferior_list_entry *entry, void *data)
 /* Select the LWP (if any) that is currently being single-stepped.  */
 
 static int
-select_singlestep_lwp_callback (struct inferior_list_entry *entry, void *data)
+select_singlestep_lwp_callback (thread_info *thread, void *data)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lp = get_thread_lwp (thread);
 
   if (thread->last_status.kind == TARGET_WAITKIND_IGNORE
@@ -2924,9 +2890,8 @@ select_singlestep_lwp_callback (struct inferior_list_entry *entry, void *data)
 /* Select the Nth LWP that has had an event.  */
 
 static int
-select_event_lwp_callback (struct inferior_list_entry *entry, void *data)
+select_event_lwp_callback (thread_info *thread, void *data)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lp = get_thread_lwp (thread);
   int *selector = (int *) data;
 
@@ -3004,35 +2969,24 @@ select_event_lwp (struct lwp_info **orig_lp)
     }
 }
 
-/* Decrement the suspend count of an LWP.  */
-
-static int
-unsuspend_one_lwp (struct inferior_list_entry *entry, void *except)
-{
-  struct thread_info *thread = (struct thread_info *) entry;
-  struct lwp_info *lwp = get_thread_lwp (thread);
-
-  /* Ignore EXCEPT.  */
-  if (lwp == except)
-    return 0;
-
-  lwp_suspended_decr (lwp);
-  return 0;
-}
-
 /* Decrement the suspend count of all LWPs, except EXCEPT, if non
    NULL.  */
 
 static void
 unsuspend_all_lwps (struct lwp_info *except)
 {
-  find_inferior (&all_threads, unsuspend_one_lwp, except);
+  for_each_thread ([&] (thread_info *thread)
+    {
+      lwp_info *lwp = get_thread_lwp (thread);
+
+      if (lwp != except)
+       lwp_suspended_decr (lwp);
+    });
 }
 
-static void move_out_of_jump_pad_callback (struct inferior_list_entry *entry);
-static int stuck_in_jump_pad_callback (struct inferior_list_entry *entry,
-                                      void *data);
-static int lwp_running (struct inferior_list_entry *entry, void *data);
+static void move_out_of_jump_pad_callback (thread_info *thread);
+static bool stuck_in_jump_pad_callback (thread_info *thread);
+static int lwp_running (thread_info *thread, void *data);
 static ptid_t linux_wait_1 (ptid_t ptid,
                            struct target_waitstatus *ourstatus,
                            int target_options);
@@ -3070,13 +3024,8 @@ static ptid_t linux_wait_1 (ptid_t ptid,
 static void
 linux_stabilize_threads (void)
 {
-  struct thread_info *saved_thread;
-  struct thread_info *thread_stuck;
+  thread_info *thread_stuck = find_thread (stuck_in_jump_pad_callback);
 
-  thread_stuck
-    = (struct thread_info *) find_inferior (&all_threads,
-                                           stuck_in_jump_pad_callback,
-                                           NULL);
   if (thread_stuck != NULL)
     {
       if (debug_threads)
@@ -3085,7 +3034,7 @@ linux_stabilize_threads (void)
       return;
     }
 
-  saved_thread = current_thread;
+  thread_info *saved_thread = current_thread;
 
   stabilizing_threads = 1;
 
@@ -3128,10 +3077,8 @@ linux_stabilize_threads (void)
 
   if (debug_threads)
     {
-      thread_stuck
-       = (struct thread_info *) find_inferior (&all_threads,
-                                               stuck_in_jump_pad_callback,
-                                               NULL);
+      thread_stuck = find_thread (stuck_in_jump_pad_callback);
+
       if (thread_stuck != NULL)
        debug_printf ("couldn't stabilize, LWP %ld got stuck in jump pad\n",
                      lwpid_of (thread_stuck));
@@ -3185,7 +3132,7 @@ gdb_catching_syscalls_p (struct lwp_info *event_child)
   struct thread_info *thread = get_lwp_thread (event_child);
   struct process_info *proc = get_thread_process (thread);
 
-  return !VEC_empty (int, proc->syscalls_to_catch);
+  return !proc->syscalls_to_catch.empty ();
 }
 
 /* Returns 1 if GDB is interested in the event_child syscall.
@@ -3194,21 +3141,19 @@ gdb_catching_syscalls_p (struct lwp_info *event_child)
 static int
 gdb_catch_this_syscall_p (struct lwp_info *event_child)
 {
-  int i, iter;
   int sysno;
   struct thread_info *thread = get_lwp_thread (event_child);
   struct process_info *proc = get_thread_process (thread);
 
-  if (VEC_empty (int, proc->syscalls_to_catch))
+  if (proc->syscalls_to_catch.empty ())
     return 0;
 
-  if (VEC_index (int, proc->syscalls_to_catch, 0) == ANY_SYSCALL)
+  if (proc->syscalls_to_catch[0] == ANY_SYSCALL)
     return 1;
 
   get_syscall_trapinfo (event_child, &sysno);
-  for (i = 0;
-       VEC_iterate (int, proc->syscalls_to_catch, i, iter);
-       i++)
+
+  for (int iter : proc->syscalls_to_catch)
     if (iter == sysno)
       return 1;
 
@@ -3467,20 +3412,22 @@ linux_wait_1 (ptid_t ptid,
        }
     }
 
-  if (event_child->collecting_fast_tracepoint)
+  if (event_child->collecting_fast_tracepoint
+      != fast_tpoint_collect_result::not_collecting)
     {
       if (debug_threads)
        debug_printf ("LWP %ld was trying to move out of the jump pad (%d). "
                      "Check if we're already there.\n",
                      lwpid_of (current_thread),
-                     event_child->collecting_fast_tracepoint);
+                     (int) event_child->collecting_fast_tracepoint);
 
       trace_event = 1;
 
       event_child->collecting_fast_tracepoint
        = linux_fast_tracepoint_collecting (event_child, NULL);
 
-      if (event_child->collecting_fast_tracepoint != 1)
+      if (event_child->collecting_fast_tracepoint
+         != fast_tpoint_collect_result::before_insn)
        {
          /* No longer need this breakpoint.  */
          if (event_child->exit_jump_pad_bkpt != NULL)
@@ -3507,7 +3454,8 @@ linux_wait_1 (ptid_t ptid,
            }
        }
 
-      if (event_child->collecting_fast_tracepoint == 0)
+      if (event_child->collecting_fast_tracepoint
+         == fast_tpoint_collect_result::not_collecting)
        {
          if (debug_threads)
            debug_printf ("fast tracepoint finished "
@@ -3725,12 +3673,11 @@ linux_wait_1 (ptid_t ptid,
     {
       if (event_child->waitstatus.kind != TARGET_WAITKIND_IGNORE)
        {
-         char *str;
+         std::string str
+           = target_waitstatus_to_string (&event_child->waitstatus);
 
-         str = target_waitstatus_to_string (&event_child->waitstatus);
          debug_printf ("LWP %ld: extended event with waitstatus %s\n",
-                       lwpid_of (get_lwp_thread (event_child)), str);
-         xfree (str);
+                       lwpid_of (get_lwp_thread (event_child)), str.c_str ());
        }
       if (current_thread->last_resume_kind == resume_step)
        {
@@ -3766,18 +3713,16 @@ linux_wait_1 (ptid_t ptid,
        {
          /* In all-stop, a stop reply cancels all previous resume
             requests.  Delete all single-step breakpoints.  */
-         struct inferior_list_entry *inf, *tmp;
 
-         ALL_INFERIORS (&all_threads, inf, tmp)
-           {
-             struct thread_info *thread = (struct thread_info *) inf;
+         find_thread ([&] (thread_info *thread) {
+           if (has_single_step_breakpoints (thread))
+             {
+               remove_single_step_breakpoints_p = 1;
+               return true;
+             }
 
-             if (has_single_step_breakpoints (thread))
-               {
-                 remove_single_step_breakpoints_p = 1;
-                 break;
-               }
-           }
+           return false;
+         });
        }
 
       if (remove_single_step_breakpoints_p)
@@ -3794,15 +3739,10 @@ linux_wait_1 (ptid_t ptid,
            }
          else
            {
-             struct inferior_list_entry *inf, *tmp;
-
-             ALL_INFERIORS (&all_threads, inf, tmp)
-               {
-                 struct thread_info *thread = (struct thread_info *) inf;
-
-                 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);
+             });
            }
 
          unstop_all_lwps (0, event_child);
@@ -4055,9 +3995,8 @@ send_sigstop (struct lwp_info *lwp)
 }
 
 static int
-send_sigstop_callback (struct inferior_list_entry *entry, void *except)
+send_sigstop_callback (thread_info *thread, void *except)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
 
   /* Ignore EXCEPT.  */
@@ -4074,10 +4013,8 @@ send_sigstop_callback (struct inferior_list_entry *entry, void *except)
 /* Increment the suspend count of an LWP, and stop it, if not stopped
    yet.  */
 static int
-suspend_and_send_sigstop_callback (struct inferior_list_entry *entry,
-                                  void *except)
+suspend_and_send_sigstop_callback (thread_info *thread, void *except)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
 
   /* Ignore EXCEPT.  */
@@ -4086,7 +4023,7 @@ suspend_and_send_sigstop_callback (struct inferior_list_entry *entry,
 
   lwp_suspended_inc (lwp);
 
-  return send_sigstop_callback (entry, except);
+  return send_sigstop_callback (thread, except);
 }
 
 static void
@@ -4139,7 +4076,7 @@ wait_for_sigstop (void)
 
   saved_thread = current_thread;
   if (saved_thread != NULL)
-    saved_tid = saved_thread->entry.id;
+    saved_tid = saved_thread->id;
   else
     saved_tid = null_ptid; /* avoid bogus unused warning */
 
@@ -4167,15 +4104,14 @@ wait_for_sigstop (void)
     }
 }
 
-/* Returns true if LWP ENTRY is stopped in a jump pad, and we can't
+/* Returns true if THREAD is stopped in a jump pad, and we can't
    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.  */
 
-static int
-stuck_in_jump_pad_callback (struct inferior_list_entry *entry, void *data)
+static bool
+stuck_in_jump_pad_callback (thread_info *thread)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
 
   if (lwp->suspended != 0)
@@ -4192,13 +4128,13 @@ stuck_in_jump_pad_callback (struct inferior_list_entry *entry, void *data)
          && (gdb_breakpoint_here (lwp->stop_pc)
              || lwp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT
              || thread->last_resume_kind == resume_step)
-         && linux_fast_tracepoint_collecting (lwp, NULL));
+         && (linux_fast_tracepoint_collecting (lwp, NULL)
+             != fast_tpoint_collect_result::not_collecting));
 }
 
 static void
-move_out_of_jump_pad_callback (struct inferior_list_entry *entry)
+move_out_of_jump_pad_callback (thread_info *thread)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct thread_info *saved_thread;
   struct lwp_info *lwp = get_thread_lwp (thread);
   int *wstat;
@@ -4247,9 +4183,8 @@ move_out_of_jump_pad_callback (struct inferior_list_entry *entry)
 }
 
 static int
-lwp_running (struct inferior_list_entry *entry, void *data)
+lwp_running (thread_info *thread, void *data)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
 
   if (lwp_is_marked_dead (lwp))
@@ -4369,7 +4304,8 @@ single_step (struct lwp_info* lwp)
 static int
 lwp_signal_can_be_delivered (struct lwp_info *lwp)
 {
-  return !lwp->collecting_fast_tracepoint;
+  return (lwp->collecting_fast_tracepoint
+         == fast_tpoint_collect_result::not_collecting);
 }
 
 /* Resume execution of LWP.  If STEP is nonzero, single-step it.  If
@@ -4381,7 +4317,6 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
 {
   struct thread_info *thread = get_lwp_thread (lwp);
   struct thread_info *saved_thread;
-  int fast_tp_collecting;
   int ptrace_request;
   struct process_info *proc = get_thread_process (thread);
 
@@ -4397,9 +4332,12 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
 
   gdb_assert (lwp->waitstatus.kind == TARGET_WAITKIND_IGNORE);
 
-  fast_tp_collecting = lwp->collecting_fast_tracepoint;
+  fast_tpoint_collect_result fast_tp_collecting
+    = lwp->collecting_fast_tracepoint;
 
-  gdb_assert (!stabilizing_threads || fast_tp_collecting);
+  gdb_assert (!stabilizing_threads
+             || (fast_tp_collecting
+                 != fast_tpoint_collect_result::not_collecting));
 
   /* Cancel actions that rely on GDB not changing the PC (e.g., the
      user used the "jump" command, or "set $pc = foo").  */
@@ -4455,7 +4393,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
 
       if (can_hardware_single_step ())
        {
-         if (fast_tp_collecting == 0)
+         if (fast_tp_collecting == fast_tpoint_collect_result::not_collecting)
            {
              if (step == 0)
                warning ("BAD - reinserting but not stepping.");
@@ -4468,14 +4406,14 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
       step = maybe_hw_step (thread);
     }
 
-  if (fast_tp_collecting == 1)
+  if (fast_tp_collecting == fast_tpoint_collect_result::before_insn)
     {
       if (debug_threads)
        debug_printf ("lwp %ld wants to get out of fast tracepoint jump pad"
                      " (exit-jump-pad-bkpt)\n",
                      lwpid_of (thread));
     }
-  else if (fast_tp_collecting == 2)
+  else if (fast_tp_collecting == fast_tpoint_collect_result::at_insn)
     {
       if (debug_threads)
        debug_printf ("lwp %ld wants to get out of fast tracepoint jump pad"
@@ -4647,9 +4585,8 @@ struct thread_resume_array
    suspension).  */
 
 static int
-linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
+linux_set_resume_request (thread_info *thread, void *arg)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
   int ndx;
   struct thread_resume_array *r;
@@ -4660,7 +4597,7 @@ linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
     {
       ptid_t ptid = r->resume[ndx].thread;
       if (ptid_equal (ptid, minus_one_ptid)
-         || ptid_equal (ptid, entry->id)
+         || ptid == thread->id
          /* Handle both 'pPID' and 'pPID.-1' as meaning 'all threads
             of PID'.  */
          || (ptid_get_pid (ptid) == pid_of (thread)
@@ -4700,7 +4637,6 @@ linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
             does not yet know are new fork children.  */
          if (lwp->fork_relative != NULL)
            {
-             struct inferior_list_entry *inf, *tmp;
              struct lwp_info *rel = lwp->fork_relative;
 
              if (rel->status_pending_p
@@ -4718,7 +4654,7 @@ linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
             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 (entry->id))
+         if (in_queued_stop_replies (thread->id))
            {
              if (debug_threads)
                debug_printf ("not resuming LWP %ld: has queued stop reply\n",
@@ -4762,9 +4698,8 @@ linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
    Set *FLAG_P if this lwp has an interesting status pending.  */
 
 static int
-resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
+resume_status_pending_p (thread_info *thread, void *flag_p)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
 
   /* LWPs which will not be resumed are not interesting, because
@@ -4784,9 +4719,8 @@ resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
    inferior's regcache.  */
 
 static int
-need_step_over_p (struct inferior_list_entry *entry, void *dummy)
+need_step_over_p (thread_info *thread, void *dummy)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
   struct thread_info *saved_thread;
   CORE_ADDR pc;
@@ -4969,7 +4903,7 @@ start_step_over (struct lwp_info *lwp)
   linux_resume_one_lwp (lwp, step, 0, NULL);
 
   /* Require next event from this LWP.  */
-  step_over_bkpt = thread->entry.id;
+  step_over_bkpt = thread->id;
   return 1;
 }
 
@@ -5062,9 +4996,8 @@ complete_ongoing_step_over (void)
    they should be re-issued if necessary.  */
 
 static int
-linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
+linux_resume_one_thread (thread_info *thread, void *arg)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
   int leave_all_stopped = * (int *) arg;
   int leave_pending;
@@ -5155,7 +5088,7 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
       if (debug_threads)
        debug_printf ("resuming LWP %ld\n", lwpid_of (thread));
 
-      proceed_one_lwp (entry, NULL);
+      proceed_one_lwp (thread, NULL);
     }
   else
     {
@@ -5247,9 +5180,8 @@ linux_resume (struct thread_resume *resume_info, size_t n)
    on that particular thread, and leave all others stopped.  */
 
 static int
-proceed_one_lwp (struct inferior_list_entry *entry, void *except)
+proceed_one_lwp (thread_info *thread, void *except)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
   int step;
 
@@ -5294,7 +5226,8 @@ proceed_one_lwp (struct inferior_list_entry *entry, void *except)
 
   if (thread->last_resume_kind == resume_stop
       && lwp->pending_signals_to_report == NULL
-      && lwp->collecting_fast_tracepoint == 0)
+      && (lwp->collecting_fast_tracepoint
+         == fast_tpoint_collect_result::not_collecting))
     {
       /* We haven't reported this LWP as stopped yet (otherwise, the
         last_status.kind check above would catch it, and we wouldn't
@@ -5345,9 +5278,8 @@ proceed_one_lwp (struct inferior_list_entry *entry, void *except)
 }
 
 static int
-unsuspend_and_proceed_one_lwp (struct inferior_list_entry *entry, void *except)
+unsuspend_and_proceed_one_lwp (thread_info *thread, void *except)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
   struct lwp_info *lwp = get_thread_lwp (thread);
 
   if (lwp == except)
@@ -5355,7 +5287,7 @@ unsuspend_and_proceed_one_lwp (struct inferior_list_entry *entry, void *except)
 
   lwp_suspended_decr (lwp);
 
-  return proceed_one_lwp (entry, except);
+  return proceed_one_lwp (thread, except);
 }
 
 /* When we finish a step-over, set threads running again.  If there's
@@ -6453,35 +6385,6 @@ linux_supports_exec_events (void)
   return linux_supports_traceexec ();
 }
 
-/* Callback for 'find_inferior'.  Set the (possibly changed) ptrace
-   options for the specified lwp.  */
-
-static int
-reset_lwp_ptrace_options_callback (struct inferior_list_entry *entry,
-                                  void *args)
-{
-  struct thread_info *thread = (struct thread_info *) entry;
-  struct lwp_info *lwp = get_thread_lwp (thread);
-
-  if (!lwp->stopped)
-    {
-      /* Stop the lwp so we can modify its ptrace options.  */
-      lwp->must_set_ptrace_flags = 1;
-      linux_stop_lwp (lwp);
-    }
-  else
-    {
-      /* Already stopped; go ahead and set the ptrace options.  */
-      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);
-      lwp->must_set_ptrace_flags = 0;
-    }
-
-  return 0;
-}
-
 /* Target hook for 'handle_new_gdb_connection'.  Causes a reset of the
    ptrace flags for all inferiors.  This is in case the new GDB connection
    doesn't support the same set of events that the previous one did.  */
@@ -6489,10 +6392,27 @@ reset_lwp_ptrace_options_callback (struct inferior_list_entry *entry,
 static void
 linux_handle_new_gdb_connection (void)
 {
-  pid_t pid;
-
   /* Request that all the lwps reset their ptrace options.  */
-  find_inferior (&all_threads, reset_lwp_ptrace_options_callback , &pid);
+  for_each_thread ([] (thread_info *thread)
+    {
+      struct lwp_info *lwp = get_thread_lwp (thread);
+
+      if (!lwp->stopped)
+       {
+         /* Stop the lwp so we can modify its ptrace options.  */
+         lwp->must_set_ptrace_flags = 1;
+         linux_stop_lwp (lwp);
+       }
+      else
+       {
+         /* Already stopped; go ahead and set the ptrace options.  */
+         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);
+         lwp->must_set_ptrace_flags = 0;
+       }
+    });
 }
 
 static int
@@ -7277,7 +7197,6 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
            {
              /* 6x the size for xml_escape_text below.  */
              size_t len = 6 * strlen ((char *) libname);
-             char *name;
 
              if (!header_done)
                {
@@ -7296,12 +7215,11 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
                  p = document + document_len;
                }
 
-             name = xml_escape_text ((char *) libname);
+             std::string name = xml_escape_text ((char *) libname);
              p += sprintf (p, "<library name=\"%s\" lm=\"0x%lx\" "
                            "l_addr=\"0x%lx\" l_ld=\"0x%lx\"/>",
-                           name, (unsigned long) lm_addr,
+                           name.c_str (), (unsigned long) lm_addr,
                            (unsigned long) l_addr, (unsigned long) l_ld);
-             free (name);
            }
        }
 
@@ -7694,6 +7612,11 @@ static struct target_ops linux_target_ops = {
   linux_supports_software_single_step,
   linux_supports_catch_syscall,
   linux_get_ipa_tdesc_idx,
+#if USE_THREAD_DB
+  thread_db_thread_handle,
+#else
+  NULL,
+#endif
 };
 
 #ifdef HAVE_LINUX_REGSETS