This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFC/WIP PATCH v2 10/14] Parallel steps, wait for all threads to reach their goal
- From: Pedro Alves <pedro at codesourcery dot com>
- To: gdb-patches at sourceware dot org
- Date: Sat, 17 Dec 2011 12:38:10 +0000
- Subject: [RFC/WIP PATCH v2 10/14] Parallel steps, wait for all threads to reach their goal
- References: <20111217025904.22456.50717.stgit@localhost6.localdomain6>
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);