This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC/WIP PATCH v2 10/14] Parallel steps, wait for all threads to reach their goal


Something I mentioned in previous patches.  This makes it so that with e.g.,

	(gdb) step -p t1,t2

	you only get the prompt back when both t1 and t2 finished
	stepping.

2011-12-16  Pedro Alves  <pedro@codesourcery.com>

	* breakpoint.c (until_break_command): Adjust.
	* gdbthread.h (struct itset): Forward declare.
	(struct thread_info) <apply_set, waiting_for_apply_set_siblings>:
	New fields.
	* infcmd.c (apply_execution_command): New parameter
	`want_parallel'.  Handle it.
	(continue_command, step_1, jump_command, signal_command)
	(until_next_command, finish_command): Adjust.
	* infrun.c (clear_proceed_status_thread): Clear the thread's apply
	set and waiting_for_apply_set_siblings flag.
	(all_in_apply_set_done_p): New.
	(handle_inferior_event): Check if there are other thread's in the
	even thread's apply set.  If so, wait for them to finish before
	considering the execution command done with.
---
 gdb/breakpoint.c |    3 ++-
 gdb/gdbthread.h  |    4 +++
 gdb/infcmd.c     |   16 +++++++++-----
 gdb/infrun.c     |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 9df16b6..92929db 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -9709,6 +9709,7 @@ char *parse_execution_args (char *args, int step,
 typedef void (*aec_callback_func) (struct thread_info *thr, void *data);
 void apply_execution_command (struct itset *apply_itset,
 			      struct itset *run_free_itset,
+			      int want_parallel,
 			      aec_callback_func callback, void *callback_data);
 
 void ensure_runnable (struct thread_info *thr);
@@ -9797,7 +9798,7 @@ until_break_command (char *arg, int from_tty, int anywhere)
     }
 
   cb_data.from_tty = from_tty;
-  apply_execution_command (apply_itset, run_free_itset,
+  apply_execution_command (apply_itset, run_free_itset, 1,
 			   until_break_aec_callback, NULL);
 
   do_cleanups (old_chain);
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 4b628c9..378d425 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -23,6 +23,7 @@
 #define GDBTHREAD_H
 
 struct symtab;
+struct itset;
 
 #include "breakpoint.h"
 #include "frame.h"
@@ -246,6 +247,9 @@ struct thread_info
   /* Data used by the execution command in effect.  */
   void *cmd_data;
 
+  struct itset *apply_set;
+  int waiting_for_apply_set_siblings;
+
   /* Private data used by the target vector implementation.  */
   struct private_thread_info *private;
 
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index bec876e..96ab8d9 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -92,6 +92,7 @@ int follow_fork (int should_resume);
 void
 apply_execution_command (struct itset *apply_itset,
 			 struct itset *run_free_itset,
+			 int want_parallel,
 			 aec_callback_func callback, void *callback_data)
 {
   if (target_is_non_stop_p ())
@@ -133,6 +134,9 @@ apply_execution_command (struct itset *apply_itset,
 	    {
 	      switch_to_thread (t->ptid);
 	      (*callback) (t, callback_data);
+	      gdb_assert (t->apply_set == NULL);
+	      if (want_parallel)
+		t->apply_set = itset_reference (apply_itset);
 	    }
 	  else if (t->state == THREAD_STOPPED
 		   && itset_contains_thread (run_free_itset, t))
@@ -1056,7 +1060,7 @@ continue_command (char *args, int from_tty)
   if (from_tty)
     printf_filtered (_("Continuing.\n"));
 
-  apply_execution_command (apply_itset, run_free_itset,
+  apply_execution_command (apply_itset, run_free_itset, 0,
 			   continue_aec_callback, NULL);
 
   do_cleanups (old_chain);
@@ -1207,7 +1211,7 @@ step_1 (int skip_subroutines, int single_inst, char *args)
   step_args.count = count;
   step_args.thread = -1;
 
-  apply_execution_command (apply_itset, run_free_itset,
+  apply_execution_command (apply_itset, run_free_itset, 1,
 			   step_1_aec_callback, &step_args);
 
   do_cleanups (old_chain);
@@ -1551,7 +1555,7 @@ jump_command (char *arg, int from_tty)
     }
 
   cb_data.from_tty = from_tty;
-  apply_execution_command (apply_itset, run_free_itset,
+  apply_execution_command (apply_itset, run_free_itset, 1,
 			   jump_aec_callback, &cb_data);
 
   do_cleanups (old_chain);
@@ -1661,7 +1665,7 @@ signal_command (char *arg, int from_tty)
     }
 
   cb_data.oursig = oursig;
-  apply_execution_command (apply_itset, run_free_itset,
+  apply_execution_command (apply_itset, run_free_itset, 0,
 			   signal_aec_callback, &cb_data);
 
   do_cleanups (old_chain);
@@ -1779,7 +1783,7 @@ until_next_command (char *arg, int from_tty)
 	error (_("The program is not being run."));
     }
 
-  apply_execution_command (apply_itset, run_free_itset,
+  apply_execution_command (apply_itset, run_free_itset, 1,
 			   until_next_aec_callback, NULL);
 
   do_cleanups (old_chain);
@@ -2198,7 +2202,7 @@ finish_command (char *arg, int from_tty)
     }
 
   cb_data.from_tty = from_tty;
-  apply_execution_command (apply_itset, run_free_itset,
+  apply_execution_command (apply_itset, run_free_itset, 1,
 			   finish_aec_callback, &cb_data);
 
   do_cleanups (old_chain);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index a4a2bc9..f77ecd7 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2198,6 +2198,10 @@ clear_proceed_status_thread (struct thread_info *tp)
       return;
     }
 
+  itset_free (tp->apply_set);
+  tp->apply_set = NULL;
+  tp->waiting_for_apply_set_siblings = 0;
+
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
 			"infrun: clear_proceed_status_thread (%s)\n",
@@ -3902,6 +3906,43 @@ stop_all_threads (struct itset *stop_set)
     fprintf_unfiltered (gdb_stdlog, "infrun.c: stop_all_threads done\n");
 }
 
+static int
+all_in_apply_set_done_p (struct execution_control_state *ecs)
+{
+  if (ecs->event_thread->apply_set != NULL)
+    {
+      struct itset *set;
+      struct thread_info *thr;
+
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog, "infrun: thread has an apply-set\n");
+
+      update_thread_list ();
+
+      ecs->event_thread->waiting_for_apply_set_siblings = 1;
+
+      ALL_THREADS (thr)
+	if (itset_contains_thread (ecs->event_thread->apply_set, thr))
+	  {
+	    if (!thr->waiting_for_apply_set_siblings)
+	      {
+		if (debug_infrun)
+		  fprintf_unfiltered (gdb_stdlog,
+				      "infrun: at least thread %s has not reached its goal yet\n",
+				      target_pid_to_str (thr->ptid));
+
+		prepare_to_wait (ecs);
+		return 0;
+	      }
+	  }
+
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog, "infrun: all in apply-set are done\n");
+    }
+
+  return 1;
+}
+
 /* Given an execution control state that has been freshly filled in
    by an event from the inferior, figure out what it means and take
    appropriate action.  */
@@ -5870,6 +5911,10 @@ process_event_stop_test:
          one instruction.  */
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog, "infrun: stepi/nexti\n");
+
+      if (!all_in_apply_set_done_p (ecs))
+	return;
+
       ecs->event_thread->control.stop_step = 1;
       print_end_stepping_range_reason ();
       stop_stepping (ecs);
@@ -5884,6 +5929,10 @@ process_event_stop_test:
          or can this happen as a result of a return or longjmp?).  */
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n");
+
+      if (!all_in_apply_set_done_p (ecs))
+	return;
+
       ecs->event_thread->control.stop_step = 1;
       print_end_stepping_range_reason ();
       stop_stepping (ecs);
@@ -5917,6 +5966,9 @@ process_event_stop_test:
 	      && call_sal.symtab == ecs->event_thread->current_symtab)
 	    step_into_inline_frame (ecs->ptid);
 
+	  if (!all_in_apply_set_done_p (ecs))
+	    return;
+
 	  ecs->event_thread->control.stop_step = 1;
 	  print_end_stepping_range_reason ();
 	  stop_stepping (ecs);
@@ -5932,6 +5984,9 @@ process_event_stop_test:
 	    keep_going (ecs);
 	  else
 	    {
+	      if (!all_in_apply_set_done_p (ecs))
+		return;
+
 	      ecs->event_thread->control.stop_step = 1;
 	      print_end_stepping_range_reason ();
 	      stop_stepping (ecs);
@@ -5959,6 +6014,9 @@ process_event_stop_test:
 	keep_going (ecs);
       else
 	{
+	  if (!all_in_apply_set_done_p (ecs))
+	    return;
+
 	  ecs->event_thread->control.stop_step = 1;
 	  print_end_stepping_range_reason ();
 	  stop_stepping (ecs);
@@ -5977,6 +6035,10 @@ process_event_stop_test:
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog,
 			     "infrun: stepped to a different line\n");
+
+      if (!all_in_apply_set_done_p (ecs))
+	return;
+
       ecs->event_thread->control.stop_step = 1;
       print_end_stepping_range_reason ();
       stop_stepping (ecs);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]