From patchwork Wed Aug 12 17:01:54 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 8153 Received: (qmail 20091 invoked by alias); 12 Aug 2015 17:02:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 20066 invoked by uid 89); 12 Aug 2015 17:02:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.0 required=5.0 tests=AWL, BAYES_50, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 12 Aug 2015 17:02:04 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id 03A9891DB5 for ; Wed, 12 Aug 2015 17:02:03 +0000 (UTC) Received: from brno.lan (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t7CH1vbY024215 for ; Wed, 12 Aug 2015 13:02:02 -0400 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 4/7] Convert the until/advance commands to thread_fsm mechanism Date: Wed, 12 Aug 2015 18:01:54 +0100 Message-Id: <1439398917-22761-5-git-send-email-palves@redhat.com> In-Reply-To: <1439398917-22761-1-git-send-email-palves@redhat.com> References: <1439398917-22761-1-git-send-email-palves@redhat.com> gdb/ChangeLog: 2015-08-12 Pedro Alves * breakpoint.c: Include "thread-fsm.h". (struct until_break_command_continuation_args): Delete. (struct until_break_fsm): New. (until_break_fsm_ops): New global. (new_until_break_fsm, until_break_fsm_should_stop): New functions. (until_break_command_continuation): Delete. (until_break_fsm_clean_up): New function. (until_break_fsm_async_reply_reason): New function. (until_break_command): Adjust to create an until_break_fsm instead of a continuation. (momentary_bkpt_print_it): No longer print MI's async-stop-reason here. * infcmd.c (struct until_next_fsm): New. (until_next_fsm_ops): New global. (new_until_next_fsm, until_next_fsm_should_stop): New function. (until_next_continuation): Delete. (until_next_fsm_clean_up, until_next_fsm_async_reply_reason): New functions. (until_next_command): Adjust to create a new until_next_fsm instead of a continuation. --- gdb/breakpoint.c | 181 +++++++++++++++++++++++++++++++++++-------------------- gdb/infcmd.c | 92 ++++++++++++++++++++++------ 2 files changed, 188 insertions(+), 85 deletions(-) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index ef04bde..eb15e58 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -68,6 +68,7 @@ #include "interps.h" #include "format.h" #include "location.h" +#include "thread-fsm.h" /* readline include files */ #include "readline/readline.h" @@ -11467,29 +11468,109 @@ awatch_command (char *arg, int from_tty) } -/* Helper routines for the until_command routine in infcmd.c. Here - because it uses the mechanisms of breakpoints. */ +/* Data for the FSM that manages the until(location)/advance commands + in infcmd.c. Here because it uses the mechanisms of + breakpoints. */ -struct until_break_command_continuation_args +struct until_break_fsm { - struct breakpoint *breakpoint; - struct breakpoint *breakpoint2; - int thread_num; + /* The base class. */ + struct thread_fsm thread_fsm; + + /* The thread that as current when the command was executed. */ + int thread; + + /* The breakpoint set at the destination location. */ + struct breakpoint *location_breakpoint; + + /* Breakpoint set at the return address in the caller frame. May be + NULL. */ + struct breakpoint *caller_breakpoint; }; -/* This function is called by fetch_inferior_event via the - cmd_continuation pointer, to complete the until command. It takes - care of cleaning up the temporary breakpoints set up by the until - command. */ +static void until_break_fsm_clean_up (struct thread_fsm *self); +static int until_break_fsm_should_stop (struct thread_fsm *self); +static enum async_reply_reason + until_break_fsm_async_reply_reason (struct thread_fsm *self); + +/* until_break_fsm's vtable. */ + +static struct thread_fsm_ops until_break_fsm_ops = +{ + NULL, /* dtor */ + until_break_fsm_clean_up, + until_break_fsm_should_stop, + NULL, /* return_value */ + until_break_fsm_async_reply_reason, +}; + +/* Allocate a new until_break_command_fsm. */ + +static struct until_break_fsm * +new_until_break_fsm (int thread, + struct breakpoint *location_breakpoint, + struct breakpoint *caller_breakpoint) +{ + struct until_break_fsm *sm; + + sm = XCNEW (struct until_break_fsm); + thread_fsm_ctor (&sm->thread_fsm, &until_break_fsm_ops); + + sm->thread = thread; + sm->location_breakpoint = location_breakpoint; + sm->caller_breakpoint = caller_breakpoint; + + return sm; +} + +/* Implementation of the 'should_stop' FSM method for the + until(location)/advance commands. */ + +static int +until_break_fsm_should_stop (struct thread_fsm *self) +{ + struct until_break_fsm *sm = (struct until_break_fsm *) self; + struct thread_info *tp = inferior_thread (); + + if (bpstat_find_breakpoint (tp->control.stop_bpstat, + sm->location_breakpoint) != NULL + || (sm->caller_breakpoint != NULL + && bpstat_find_breakpoint (tp->control.stop_bpstat, + sm->caller_breakpoint) != NULL)) + thread_fsm_set_finished (self); + + return 1; +} + +/* Implementation of the 'clean_up' FSM method for the + until(location)/advance commands. */ + static void -until_break_command_continuation (void *arg, int err) +until_break_fsm_clean_up (struct thread_fsm *self) { - struct until_break_command_continuation_args *a = arg; + struct until_break_fsm *sm = (struct until_break_fsm *) self; - delete_breakpoint (a->breakpoint); - if (a->breakpoint2) - delete_breakpoint (a->breakpoint2); - delete_longjmp_breakpoint (a->thread_num); + /* Clean up our temporary breakpoints. */ + if (sm->location_breakpoint != NULL) + { + delete_breakpoint (sm->location_breakpoint); + sm->location_breakpoint = NULL; + } + if (sm->caller_breakpoint != NULL) + { + delete_breakpoint (sm->caller_breakpoint); + sm->caller_breakpoint = NULL; + } + delete_longjmp_breakpoint (sm->thread); +} + +/* Implementation of the 'async_reply_reason' FSM method for the + until(location)/advance commands. */ + +static enum async_reply_reason +until_break_fsm_async_reply_reason (struct thread_fsm *self) +{ + return EXEC_ASYNC_LOCATION_REACHED; } void @@ -11501,12 +11582,13 @@ until_break_command (char *arg, int from_tty, int anywhere) struct gdbarch *frame_gdbarch; struct frame_id stack_frame_id; struct frame_id caller_frame_id; - struct breakpoint *breakpoint; - struct breakpoint *breakpoint2 = NULL; + struct breakpoint *location_breakpoint; + struct breakpoint *caller_breakpoint = NULL; struct cleanup *old_chain, *cleanup; int thread; struct thread_info *tp; struct event_location *location; + struct until_break_fsm *sm; clear_proceed_status (0); @@ -11556,14 +11638,16 @@ until_break_command (char *arg, int from_tty, int anywhere) if (frame_id_p (caller_frame_id)) { struct symtab_and_line sal2; + struct gdbarch *caller_gdbarch; sal2 = find_pc_line (frame_unwind_caller_pc (frame), 0); sal2.pc = frame_unwind_caller_pc (frame); - breakpoint2 = set_momentary_breakpoint (frame_unwind_caller_arch (frame), - sal2, - caller_frame_id, - bp_until); - make_cleanup_delete_breakpoint (breakpoint2); + caller_gdbarch = frame_unwind_caller_arch (frame); + caller_breakpoint = set_momentary_breakpoint (caller_gdbarch, + sal2, + caller_frame_id, + bp_until); + make_cleanup_delete_breakpoint (caller_breakpoint); set_longjmp_breakpoint (tp, caller_frame_id); make_cleanup (delete_longjmp_breakpoint_cleanup, &thread); @@ -11575,38 +11659,21 @@ until_break_command (char *arg, int from_tty, int anywhere) if (anywhere) /* If the user told us to continue until a specified location, we don't specify a frame at which we need to stop. */ - breakpoint = set_momentary_breakpoint (frame_gdbarch, sal, - null_frame_id, bp_until); + location_breakpoint = set_momentary_breakpoint (frame_gdbarch, sal, + null_frame_id, bp_until); else /* Otherwise, specify the selected frame, because we want to stop only at the very same frame. */ - breakpoint = set_momentary_breakpoint (frame_gdbarch, sal, - stack_frame_id, bp_until); - make_cleanup_delete_breakpoint (breakpoint); + location_breakpoint = set_momentary_breakpoint (frame_gdbarch, sal, + stack_frame_id, bp_until); + make_cleanup_delete_breakpoint (location_breakpoint); - proceed (-1, GDB_SIGNAL_DEFAULT); + sm = new_until_break_fsm (tp->num, location_breakpoint, caller_breakpoint); + tp->thread_fsm = &sm->thread_fsm; - /* If we are running asynchronously, and proceed call above has - actually managed to start the target, arrange for breakpoints to - be deleted when the target stops. Otherwise, we're already - stopped and delete breakpoints via cleanup chain. */ - - if (is_running (inferior_ptid)) - { - struct until_break_command_continuation_args *args; - args = xmalloc (sizeof (*args)); - - args->breakpoint = breakpoint; - args->breakpoint2 = breakpoint2; - args->thread_num = thread; + discard_cleanups (old_chain); - discard_cleanups (old_chain); - add_continuation (inferior_thread (), - until_break_command_continuation, args, - xfree); - } - else - do_cleanups (old_chain); + proceed (-1, GDB_SIGNAL_DEFAULT); do_cleanups (cleanup); } @@ -13198,22 +13265,6 @@ momentary_bkpt_check_status (bpstat bs) static enum print_stop_action momentary_bkpt_print_it (bpstat bs) { - struct ui_out *uiout = current_uiout; - - if (ui_out_is_mi_like_p (uiout)) - { - struct breakpoint *b = bs->breakpoint_at; - - switch (b->type) - { - case bp_until: - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED)); - break; - } - } - return PRINT_UNKNOWN; } diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 67b5df0..e5d01ff 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1388,22 +1388,81 @@ queue_signal_command (char *signum_exp, int from_tty) tp->suspend.stop_signal = oursig; } -/* Continuation args to be passed to the "until" command - continuation. */ -struct until_next_continuation_args +/* Data for the FSM that manages the until (with no argument) + command. */ + +struct until_next_fsm { - /* The thread that was current when the command was executed. */ + /* The base class. */ + struct thread_fsm thread_fsm; + + /* The thread that as current when the command was executed. */ int thread; }; -/* A continuation callback for until_next_command. */ +static int until_next_fsm_should_stop (struct thread_fsm *self); +static void until_next_fsm_clean_up (struct thread_fsm *self); +static enum async_reply_reason + until_next_fsm_async_reply_reason (struct thread_fsm *self); + +/* until_next_fsm's vtable. */ + +static struct thread_fsm_ops until_next_fsm_ops = +{ + NULL, /* dtor */ + until_next_fsm_clean_up, + until_next_fsm_should_stop, + NULL, /* return_value */ + until_next_fsm_async_reply_reason, +}; + +/* Allocate a new until_next_fsm. */ + +static struct until_next_fsm * +new_until_next_fsm (int thread) +{ + struct until_next_fsm *sm; + + sm = XCNEW (struct until_next_fsm); + thread_fsm_ctor (&sm->thread_fsm, &until_next_fsm_ops); + + sm->thread = thread; + + return sm; +} + +/* Implementation of the 'should_stop' FSM method for the until (with + no arg) command. */ + +static int +until_next_fsm_should_stop (struct thread_fsm *self) +{ + struct thread_info *tp = inferior_thread (); + + if (tp->control.stop_step) + thread_fsm_set_finished (self); + + return 1; +} + +/* Implementation of the 'clean_up' FSM method for the until (with no + arg) command. */ static void -until_next_continuation (void *arg, int err) +until_next_fsm_clean_up (struct thread_fsm *self) { - struct until_next_continuation_args *a = arg; + struct until_next_fsm *sm = (struct until_next_fsm *) self; - delete_longjmp_breakpoint (a->thread); + delete_longjmp_breakpoint (sm->thread); +} + +/* Implementation of the 'async_reply_reason' FSM method for the until + (with no arg) command. */ + +static enum async_reply_reason +until_next_fsm_async_reply_reason (struct thread_fsm *self) +{ + return EXEC_ASYNC_END_STEPPING_RANGE; } /* Proceed until we reach a different source line with pc greater than @@ -1424,6 +1483,7 @@ until_next_command (int from_tty) struct thread_info *tp = inferior_thread (); int thread = tp->num; struct cleanup *old_chain; + struct until_next_fsm *sm; clear_proceed_status (0); set_step_frame (); @@ -1463,20 +1523,12 @@ until_next_command (int from_tty) set_longjmp_breakpoint (tp, get_frame_id (frame)); old_chain = make_cleanup (delete_longjmp_breakpoint_cleanup, &thread); - proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); - - if (is_running (inferior_ptid)) - { - struct until_next_continuation_args *cont_args; + sm = new_until_next_fsm (tp->num); + tp->thread_fsm = &sm->thread_fsm; + discard_cleanups (old_chain); - discard_cleanups (old_chain); - cont_args = XNEW (struct until_next_continuation_args); - cont_args->thread = inferior_thread ()->num; + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); - add_continuation (tp, until_next_continuation, cont_args, xfree); - } - else - do_cleanups (old_chain); } static void