From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6774 invoked by alias); 17 Dec 2011 12:38:30 -0000 Received: (qmail 6765 invoked by uid 22791); 17 Dec 2011 12:38:28 -0000 X-SWARE-Spam-Status: No, hits=-0.2 required=5.0 tests=AWL,BAYES_50,FROM_12LTRDOM X-Spam-Check-By: sourceware.org Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 17 Dec 2011 12:38:14 +0000 Received: from nat-ies.mentorg.com ([192.94.31.2] helo=EU1-MAIL.mgc.mentorg.com) by relay1.mentorg.com with esmtp id 1RbtWo-0005U0-3g from pedro_alves@mentor.com for gdb-patches@sourceware.org; Sat, 17 Dec 2011 04:38:14 -0800 Received: from scottsdale.localnet ([172.16.63.104]) by EU1-MAIL.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.1830); Sat, 17 Dec 2011 12:38:11 +0000 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [RFC/WIP PATCH v2 10/14] Parallel steps, wait for all threads to reach their goal Date: Sat, 17 Dec 2011 14:05:00 -0000 User-Agent: KMail/1.13.6 (Linux/2.6.38-13-generic; KDE/4.7.2; x86_64; ; ) References: <20111217025904.22456.50717.stgit@localhost6.localdomain6> In-Reply-To: <20111217025904.22456.50717.stgit@localhost6.localdomain6> MIME-Version: 1.0 Content-Type: Text/Plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <201112171238.10751.pedro@codesourcery.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-12/txt/msg00569.txt.bz2 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 * breakpoint.c (until_break_command): Adjust. * gdbthread.h (struct itset): Forward declare. (struct thread_info) : 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);