[PATCH] gdb: make iterate_over_threads a template function

Andrew Burgess andrew.burgess@embecosm.com
Sat May 22 16:51:46 GMT 2021


This started off as changing the return type of the callback function
that iterate_over_threads takes from int to bool.

But then I thought, why not make the whole thing templated, and remove
the need to pass void* arguments around.

So now we can do:

  bool
  callback_1 (struct thread_info *tp)
  { ... }

  bool
  callback_2 (struct thread_info *tp, const struct some_type &obj)
  { ... }

  void
  some_other_part_of_gdb ()
  {
    iterate_over_threads (callback_1);

    iterate_over_threads (callback_2, object_of_some_type);
  }

Which seems much nicer to me.

While updating all the callback functions I took this opportunity to
remove a code construct I really hate:

  if (condition)
    return true;
  return false;

This has now become:

  return (condition);

There should be no user visible changes after this commit.

gdb/ChangeLog:

	* aix-thread.c (giter_count): Update argument types and return
	type, update implementation to match.
	(giter_accum): Likewise.
	(iter_tid): Likewise.
	(pd_update): Update call to iterate_over_threads.
	* breakpoint.c (bpstat_remove_breakpoint_callback): Update
	argument types and return type, update implementation to match.
	* fbsd-tdep.c (find_signalled_thread): Likewise.
	(fbsd_make_corefile_notes): Update call to iterate_over_threads.
	* gdbthread.h (thread_callback_func): Delete typedef.
	(iterate_over_threads): Delete declaration, rewrite as templated
	function.
	* infcmd.c (proceed_thread_callback): Update argument types and
	return type, update implementation to match.
	(continue_1): Update call to iterate_over_threads.
	* infrun.c (proceed_after_vfork_done): Update argument types and
	return type, update implementation to match.
	(handle_vfork_child_exec_or_exit): Update call to
	iterate_over_threads.
	(resumed_thread_with_pending_status): Update argument types and
	return type, update implementation to match.
	(finish_step_over): Update call to iterate_over_threads.
	* mi/mi-main.c (proceed_thread_callback): Update argument types
	and return type, update implementation to match.
	(exec_continue): Update call to iterate_over_threads.
	(interrupt_thread_callback): Update argument types and return
	type, update implementation to match.
	(mi_cmd_exec_interrupt): Update call to iterate_over_threads.
	(find_thread_of_process): Update argument types and return type,
	update implementation to match.
	(mi_cmd_target_detach): Update call to iterate_over_threads.
	(collect_cores): Update argument types and return type, update
	implementation to match.
	* procfs.c (find_signalled_thread): Update argument types and
	return type, update implementation to match.
	(find_stop_signal): Update call to iterate_over_threads.
	* sol-thread.c (thread_db_find_thread_from_tid): Update argument
	types and return type, update implementation to match.
	(sol_thread_target::get_ada_task_ptid): Update call to
	iterate_over_threads.
	* thread.c (iterate_over_threads): Delete implementation, this has
	now moved into gdbthread.h.
---
 gdb/ChangeLog    | 45 +++++++++++++++++++++++++++++++++++++++++++++
 gdb/aix-thread.c | 25 ++++++++++++-------------
 gdb/breakpoint.c |  9 ++++-----
 gdb/fbsd-tdep.c  | 13 +++++--------
 gdb/gdbthread.h  | 28 +++++++++++++++++++++++-----
 gdb/infcmd.c     | 12 ++++++------
 gdb/infrun.c     | 22 ++++++++--------------
 gdb/mi/mi-main.c | 45 +++++++++++++++++----------------------------
 gdb/procfs.c     | 13 +++++--------
 gdb/sol-thread.c | 15 +++++----------
 gdb/thread.c     | 25 -------------------------
 11 files changed, 130 insertions(+), 122 deletions(-)

diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c
index 889cb65fdcd..abab6dc5da9 100644
--- a/gdb/aix-thread.c
+++ b/gdb/aix-thread.c
@@ -639,12 +639,12 @@ pcmp (const void *p1v, const void *p2v)
    does not include that main thread either, and thus allows us
    to compare the two lists.  */
 
-static int
-giter_count (struct thread_info *thread, void *countp)
+static bool
+giter_count (struct thread_info *thread, int *countp)
 {
   if (PD_TID (thread->ptid))
-    (*(int *) countp)++;
-  return 0;
+    (*countp)++;
+  return false;
 }
 
 /* iterate_over_threads() callback for accumulating GDB thread pids.
@@ -654,15 +654,15 @@ giter_count (struct thread_info *thread, void *countp)
    does not include that main thread either, and thus allows us
    to compare the two lists.  */
 
-static int
-giter_accum (struct thread_info *thread, void *bufp)
+static bool
+giter_accum (struct thread_info *thread, struct thread_info ***bufp)
 {
   if (PD_TID (thread->ptid))
     {
-      **(struct thread_info ***) bufp = thread;
-      (*(struct thread_info ***) bufp)++;
+      **bufp = thread;
+      (*bufp)++;
     }
-  return 0;
+  return false;
 }
 
 /* ptid comparison function */
@@ -861,10 +861,9 @@ sync_threadlists (void)
 /* Iterate_over_threads() callback for locating a thread, using
    the TID of its associated kernel thread.  */
 
-static int
-iter_tid (struct thread_info *thread, void *tidp)
+static bool
+iter_tid (struct thread_info *thread, const pthdb_tid_t &tid)
 {
-  const pthdb_tid_t tid = *(pthdb_tid_t *)tidp;
   aix_thread_info *priv = get_aix_thread_info (thread);
 
   return priv->tid == tid;
@@ -895,7 +894,7 @@ pd_update (int set_infpid)
 
   tid = get_signaled_thread ();
   if (tid != 0)
-    thread = iterate_over_threads (iter_tid, &tid);
+    thread = iterate_over_threads (iter_tid, tid);
   if (!thread)
     ptid = inferior_ptid;
   else
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index d479f008948..b1df9c52369 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -12304,13 +12304,12 @@ bpstat_remove_bp_location (bpstat bps, struct breakpoint *bpt)
 }
 
 /* Callback for iterate_over_threads.  */
-static int
-bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
+static bool
+bpstat_remove_breakpoint_callback (struct thread_info *th,
+				   struct breakpoint *bpt)
 {
-  struct breakpoint *bpt = (struct breakpoint *) data;
-
   bpstat_remove_bp_location (th->control.stop_bpstat, bpt);
-  return 0;
+  return false;
 }
 
 /* Helper for breakpoint and tracepoint breakpoint_ops->mention
diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c
index 6cab31dde82..8f1a008566a 100644
--- a/gdb/fbsd-tdep.c
+++ b/gdb/fbsd-tdep.c
@@ -574,14 +574,11 @@ fbsd_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf,
   return len;
 }
 
-static int
-find_signalled_thread (struct thread_info *info, void *data)
+static bool
+find_signalled_thread (struct thread_info *info)
 {
-  if (info->suspend.stop_signal != GDB_SIGNAL_0
-      && info->ptid.pid () == inferior_ptid.pid ())
-    return 1;
-
-  return 0;
+  return (info->suspend.stop_signal != GDB_SIGNAL_0
+	  && info->ptid.pid () == inferior_ptid.pid ());
 }
 
 /* Return a byte_vector containing the contents of a core dump note
@@ -655,7 +652,7 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
     signalled_thr = curr_thr;
   else
     {
-      signalled_thr = iterate_over_threads (find_signalled_thread, NULL);
+      signalled_thr = iterate_over_threads (find_signalled_thread);
       if (signalled_thr == NULL)
 	signalled_thr = curr_thr;
     }
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index eef37f79e6a..bdd6310c3cd 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -505,11 +505,6 @@ extern struct thread_info *any_live_thread_of_inferior (inferior *inf);
 void thread_change_ptid (process_stratum_target *targ,
 			 ptid_t old_ptid, ptid_t new_ptid);
 
-/* Iterator function to call a user-provided callback function
-   once for each known thread.  */
-typedef int (*thread_callback_func) (struct thread_info *, void *);
-extern struct thread_info *iterate_over_threads (thread_callback_func, void *);
-
 /* Pull in the internals of the inferiors/threads ranges and
    iterators.  Must be done after struct thread_info is defined.  */
 #include "thread-iter.h"
@@ -570,6 +565,29 @@ all_threads_safe ()
   return {};
 }
 
+/* Iterator function to call a user-provided CALLBACK function once for
+   each known thread.  The function CALLBACK must take the thread_info as
+   its first argument, but can then take zero or more additional arguments
+   of any type.
+
+   Call CALLBACK once for each thread, so long as the callback function
+   returns false.  If CALLBACK returns true, the iteration will end and the
+   current thread will be returned.  This can be useful for implementing a
+   search for a thread with arbitrary attributes, or for applying some
+   operation to every thread.  */
+
+template<typename... Types>
+struct thread_info *
+iterate_over_threads (bool (*callback) (struct thread_info *, Types...),
+		      Types... args)
+{
+  for (thread_info *tp : all_threads_safe ())
+    if (callback (tp, args...))
+      return tp;
+
+  return nullptr;
+}
+
 extern int thread_count (process_stratum_target *proc_target);
 
 /* Return true if we have any thread in any inferior.  */
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 4351409af50..cf3a89c6d00 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -577,8 +577,8 @@ starti_command (const char *args, int from_tty)
   run_command_1 (args, from_tty, RUN_STOP_AT_FIRST_INSN);
 } 
 
-static int
-proceed_thread_callback (struct thread_info *thread, void *arg)
+static bool
+proceed_thread_callback (struct thread_info *thread)
 {
   /* We go through all threads individually instead of compressing
      into a single target `resume_all' request, because some threads
@@ -590,15 +590,15 @@ proceed_thread_callback (struct thread_info *thread, void *arg)
      thread stopped until I say otherwise', then we can optimize
      this.  */
   if (thread->state != THREAD_STOPPED)
-    return 0;
+    return false;
 
   if (!thread->inf->has_execution ())
-    return 0;
+    return false;
 
   switch_to_thread (thread);
   clear_proceed_status (0);
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
-  return 0;
+  return false;
 }
 
 static void
@@ -653,7 +653,7 @@ continue_1 (int all_threads)
 	 exit.  */
       scoped_restore_current_thread restore_thread;
 
-      iterate_over_threads (proceed_thread_callback, NULL);
+      iterate_over_threads (proceed_thread_callback);
 
       if (current_ui->prompt_state == PROMPT_BLOCKED)
 	{
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 7fc56dc51f0..a4f9b5102e1 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -884,12 +884,9 @@ follow_inferior_reset_breakpoints (void)
 /* The child has exited or execed: resume threads of the parent the
    user wanted to be executing.  */
 
-static int
-proceed_after_vfork_done (struct thread_info *thread,
-			  void *arg)
+static bool
+proceed_after_vfork_done (struct thread_info *thread, int pid)
 {
-  int pid = * (int *) arg;
-
   if (thread->ptid.pid () == pid
       && thread->state == THREAD_RUNNING
       && !thread->executing
@@ -904,7 +901,7 @@ proceed_after_vfork_done (struct thread_info *thread,
       proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
     }
 
-  return 0;
+  return false;
 }
 
 /* Called whenever we notice an exec or exit event, to handle
@@ -1035,7 +1032,7 @@ handle_vfork_child_exec_or_exit (int exec)
 	  infrun_debug_printf ("resuming vfork parent process %d",
 			       resume_parent);
 
-	  iterate_over_threads (proceed_after_vfork_done, &resume_parent);
+	  iterate_over_threads (proceed_after_vfork_done, resume_parent);
 	}
     }
 }
@@ -5845,12 +5842,10 @@ restart_threads (struct thread_info *event_thread)
 /* Callback for iterate_over_threads.  Find a resumed thread that has
    a pending waitstatus.  */
 
-static int
-resumed_thread_with_pending_status (struct thread_info *tp,
-				    void *arg)
+static bool
+resumed_thread_with_pending_status (struct thread_info *tp)
 {
-  return (tp->resumed
-	  && tp->suspend.waitstatus_pending_p);
+  return (tp->resumed && tp->suspend.waitstatus_pending_p);
 }
 
 /* Called when we get an event that may finish an in-line or
@@ -5918,8 +5913,7 @@ finish_step_over (struct execution_control_state *ecs)
       if (ecs->event_thread->stepping_over_watchpoint)
 	return 0;
 
-      pending = iterate_over_threads (resumed_thread_with_pending_status,
-				      NULL);
+      pending = iterate_over_threads (resumed_thread_with_pending_status);
       if (pending != NULL)
 	{
 	  struct thread_info *tp = ecs->event_thread;
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 9d205f0208b..0f6919045a8 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -252,13 +252,11 @@ proceed_thread (struct thread_info *thread, int pid)
   proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
 }
 
-static int
-proceed_thread_callback (struct thread_info *thread, void *arg)
+static bool
+proceed_thread_callback (struct thread_info *thread, int pid)
 {
-  int pid = *(int *)arg;
-
   proceed_thread (thread, pid);
-  return 0;
+  return false;
 }
 
 static void
@@ -288,7 +286,7 @@ exec_continue (char **argv, int argc)
 
 	      pid = inf->pid;
 	    }
-	  iterate_over_threads (proceed_thread_callback, &pid);
+	  iterate_over_threads (proceed_thread_callback, pid);
 	}
       else
 	{
@@ -342,19 +340,17 @@ mi_cmd_exec_continue (const char *command, char **argv, int argc)
     exec_continue (argv, argc);
 }
 
-static int
-interrupt_thread_callback (struct thread_info *thread, void *arg)
+static bool
+interrupt_thread_callback (struct thread_info *thread, int pid)
 {
-  int pid = *(int *)arg;
-
   if (thread->state != THREAD_RUNNING)
-    return 0;
+    return false;
 
   if (thread->ptid.pid () != pid)
-    return 0;
+    return false;
 
   target_stop (thread->ptid);
-  return 0;
+  return false;
 }
 
 /* Interrupt the execution of the target.  Note how we must play
@@ -383,7 +379,7 @@ mi_cmd_exec_interrupt (const char *command, char **argv, int argc)
     {
       struct inferior *inf = find_inferior_id (current_context->thread_group);
 
-      iterate_over_threads (interrupt_thread_callback, &inf->pid);
+      iterate_over_threads (interrupt_thread_callback, inf->pid);
     }
   else
     {
@@ -477,15 +473,10 @@ mi_cmd_exec_run (const char *command, char **argv, int argc)
 }
 
 
-static int
-find_thread_of_process (struct thread_info *ti, void *p)
+static bool
+find_thread_of_process (struct thread_info *ti, int pid)
 {
-  int pid = *(int *)p;
-
-  if (ti->ptid.pid () == pid && ti->state != THREAD_EXITED)
-    return 1;
-
-  return 0;
+  return (ti->ptid.pid () == pid && ti->state != THREAD_EXITED);
 }
 
 void
@@ -526,7 +517,7 @@ mi_cmd_target_detach (const char *command, char **argv, int argc)
 
       /* Pick any thread in the desired process.  Current
 	 target_detach detaches from the parent of inferior_ptid.  */
-      tp = iterate_over_threads (find_thread_of_process, &pid);
+      tp = iterate_over_threads (find_thread_of_process, pid);
       if (!tp)
 	error (_("Thread group is empty"));
 
@@ -612,11 +603,9 @@ struct collect_cores_data
   std::set<int> cores;
 };
 
-static int
-collect_cores (struct thread_info *ti, void *xdata)
+static bool
+collect_cores (struct thread_info *ti, struct collect_cores_data *data)
 {
-  struct collect_cores_data *data = (struct collect_cores_data *) xdata;
-
   if (ti->ptid.pid () == data->pid)
     {
       int core = target_core_of_thread (ti->ptid);
@@ -625,7 +614,7 @@ collect_cores (struct thread_info *ti, void *xdata)
 	data->cores.insert (core);
     }
 
-  return 0;
+  return false;
 }
 
 struct print_one_inferior_data
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 23c0aa22a7a..705d77f6c42 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -3574,21 +3574,18 @@ procfs_corefile_thread_callback (procinfo *pi, procinfo *thread, void *data)
   return 0;
 }
 
-static int
-find_signalled_thread (struct thread_info *info, void *data)
+static bool
+find_signalled_thread (struct thread_info *info)
 {
-  if (info->suspend.stop_signal != GDB_SIGNAL_0
-      && info->ptid.pid () == inferior_ptid.pid ())
-    return 1;
-
-  return 0;
+  return (info->suspend.stop_signal != GDB_SIGNAL_0
+	  && info->ptid.pid () == inferior_ptid.pid ());
 }
 
 static enum gdb_signal
 find_stop_signal (void)
 {
   struct thread_info *info =
-    iterate_over_threads (find_signalled_thread, NULL);
+    iterate_over_threads (find_signalled_thread);
 
   if (info)
     return info->suspend.stop_signal;
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index 18eacf1062a..14568729437 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -1117,22 +1117,17 @@ info_solthreads (const char *args, int from_tty)
 /* Callback routine used to find a thread based on the TID part of
    its PTID.  */
 
-static int
-thread_db_find_thread_from_tid (struct thread_info *thread, void *data)
+static bool
+thread_db_find_thread_from_tid (struct thread_info *thread, long tid)
 {
-  long *tid = (long *) data;
-
-  if (thread->ptid.tid () == *tid)
-    return 1;
-
-  return 0;
+  return (thread->ptid.tid () == tid);
 }
 
 ptid_t
 sol_thread_target::get_ada_task_ptid (long lwp, long thread)
 {
   struct thread_info *thread_info =
-    iterate_over_threads (thread_db_find_thread_from_tid, &thread);
+    iterate_over_threads (thread_db_find_thread_from_tid, thread);
 
   if (thread_info == NULL)
     {
@@ -1140,7 +1135,7 @@ sol_thread_target::get_ada_task_ptid (long lwp, long thread)
 	 thread that is missing from the list, and try again.  */
       update_thread_list ();
       thread_info = iterate_over_threads (thread_db_find_thread_from_tid,
-					  &thread);
+					  thread);
     }
 
   gdb_assert (thread_info != NULL);
diff --git a/gdb/thread.c b/gdb/thread.c
index 40051013c0a..0205bd3b18c 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -557,31 +557,6 @@ find_thread_by_handle (gdb::array_view<const gdb_byte> handle,
 					      inf);
 }
 
-/*
- * Thread iterator function.
- *
- * Calls a callback function once for each thread, so long as
- * the callback function returns false.  If the callback function
- * returns true, the iteration will end and the current thread
- * will be returned.  This can be useful for implementing a
- * search for a thread with arbitrary attributes, or for applying
- * some operation to every thread.
- *
- * FIXME: some of the existing functionality, such as
- * "Thread apply all", might be rewritten using this functionality.
- */
-
-struct thread_info *
-iterate_over_threads (int (*callback) (struct thread_info *, void *),
-		      void *data)
-{
-  for (thread_info *tp : all_threads_safe ())
-    if ((*callback) (tp, data))
-      return tp;
-
-  return NULL;
-}
-
 /* See gdbthread.h.  */
 
 bool
-- 
2.25.4



More information about the Gdb-patches mailing list