diff options
author | Pedro Alves <palves@redhat.com> | 2015-09-09 18:23:24 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2015-09-09 18:24:34 +0100 |
commit | 388a708404618466bbe51b7198de7a64f0a5da9f (patch) | |
tree | 2e85b3d232219ca1c8d9399007360f027df6fc2d /gdb/infrun.c | |
parent | 243a925328f8e3184b2356bee497181049c0174f (diff) | |
download | gdb-388a708404618466bbe51b7198de7a64f0a5da9f.zip gdb-388a708404618466bbe51b7198de7a64f0a5da9f.tar.gz gdb-388a708404618466bbe51b7198de7a64f0a5da9f.tar.bz2 |
Convert infcalls to thread_fsm mechanism
This removes infcall-specific special casing from normal_stop,
simplifying it.
Like the "finish" command's, the FSM is responsible for storing the
function's return value.
gdb/ChangeLog:
2015-09-09 Pedro Alves <palves@redhat.com>
* infcall.c: Include thread_fsm.h.
(struct call_return_meta_info): New.
(get_call_return_value): New function, factored out from
call_function_by_hand_dummy.
(struct call_thread_fsm): New.
(call_thread_fsm_ops): New global.
(new_call_thread_fsm, call_thread_fsm_should_stop)
(call_thread_fsm_should_notify_stop): New functions.
(run_inferior_call): Add 'sm' parameter. Associate the FSM with
the thread.
(call_function_by_hand_dummy): Create a new call_thread_fsm
instance, associate it with the thread, and wait for the FSM to
finish. If finished successfully, fetch the function's result
value out of the FSM.
* infrun.c (fetch_inferior_event): If the FSM says the stop
shouldn't be notified, don't call normal_stop.
(maybe_remove_breakpoints): New function, factored out from ...
(normal_stop): ... here. Simplify.
* infrun.h (maybe_remove_breakpoints): Declare.
* thread-fsm.c (thread_fsm_should_notify_stop): New function.
(thread-fsm.h) <struct thread_fsm_ops>: New field.
(thread_fsm_should_notify_stop): Declare.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 159 |
1 files changed, 70 insertions, 89 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 73ac090..6324fbd 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -3834,6 +3834,7 @@ fetch_inferior_event (void *client_data) struct inferior *inf = find_inferior_ptid (ecs->ptid); int should_stop = 1; struct thread_info *thr = ecs->event_thread; + int should_notify_stop = 1; delete_just_stopped_threads_infrun_breakpoints (); @@ -3853,12 +3854,21 @@ fetch_inferior_event (void *client_data) { clean_up_just_stopped_threads_fsms (ecs); - /* We may not find an inferior if this was a process exit. */ - if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY) - normal_stop (); + if (thr != NULL && thr->thread_fsm != NULL) + { + should_notify_stop + = thread_fsm_should_notify_stop (thr->thread_fsm); + } + + if (should_notify_stop) + { + /* We may not find an inferior if this was a process exit. */ + if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY) + normal_stop (); - inferior_event_handler (INF_EXEC_COMPLETE, NULL); - cmd_done = 1; + inferior_event_handler (INF_EXEC_COMPLETE, NULL); + cmd_done = 1; + } } } @@ -7810,6 +7820,23 @@ print_stop_event (struct ui_out *uiout) } } +/* See infrun.h. */ + +void +maybe_remove_breakpoints (void) +{ + if (!breakpoints_should_be_inserted_now () && target_has_execution) + { + if (remove_breakpoints ()) + { + target_terminal_ours_for_output (); + printf_filtered (_("Cannot remove breakpoints because " + "program is no longer writable.\nFurther " + "execution is probably impossible.\n")); + } + } +} + /* Here to return control to GDB when the inferior stops for real. Print appropriate messages, remove breakpoints, give terminal our modes. @@ -7903,16 +7930,7 @@ normal_stop (void) } /* Note: this depends on the update_thread_list call above. */ - if (!breakpoints_should_be_inserted_now () && target_has_execution) - { - if (remove_breakpoints ()) - { - target_terminal_ours_for_output (); - printf_filtered (_("Cannot remove breakpoints because " - "program is no longer writable.\nFurther " - "execution is probably impossible.\n")); - } - } + maybe_remove_breakpoints (); /* If an auto-display called a function and that got a signal, delete that auto-display to avoid an infinite recursion. */ @@ -7923,87 +7941,50 @@ normal_stop (void) target_terminal_ours (); async_enable_stdin (); - /* Set the current source location. This will also happen if we - display the frame below, but the current SAL will be incorrect - during a user hook-stop function. */ - if (has_stack_frames () && !stop_stack_dummy) - set_current_sal_from_frame (get_current_frame ()); - - /* Let the user/frontend see the threads as stopped, but defer to - call_function_by_hand if the thread finished an infcall - successfully. We may be e.g., evaluating a breakpoint condition. - In that case, the thread had state THREAD_RUNNING before the - infcall, and shall remain marked running, all without informing - the user/frontend about state transition changes. */ - if (target_has_execution - && inferior_thread ()->control.in_infcall - && stop_stack_dummy == STOP_STACK_DUMMY) - discard_cleanups (old_chain); - else - do_cleanups (old_chain); - - /* Look up the hook_stop and run it (CLI internally handles problem - of stop_command's pre-hook not existing). */ - if (stop_command) - catch_errors (hook_stop_stub, stop_command, - "Error while running hook_stop:\n", RETURN_MASK_ALL); + /* Let the user/frontend see the threads as stopped. */ + do_cleanups (old_chain); - if (!has_stack_frames ()) - goto done; + /* Select innermost stack frame - i.e., current frame is frame 0, + and current location is based on that. Handle the case where the + dummy call is returning after being stopped. E.g. the dummy call + previously hit a breakpoint. (If the dummy call returns + normally, we won't reach here.) Do this before the stop hook is + run, so that it doesn't get to see the temporary dummy frame, + which is not where we'll present the stop. */ + if (has_stack_frames ()) + { + if (stop_stack_dummy == STOP_STACK_DUMMY) + { + /* Pop the empty frame that contains the stack dummy. This + also restores inferior state prior to the call (struct + infcall_suspend_state). */ + struct frame_info *frame = get_current_frame (); - if (last.kind == TARGET_WAITKIND_SIGNALLED - || last.kind == TARGET_WAITKIND_EXITED) - goto done; + gdb_assert (get_frame_type (frame) == DUMMY_FRAME); + frame_pop (frame); + /* frame_pop calls reinit_frame_cache as the last thing it + does which means there's now no selected frame. */ + } - /* Select innermost stack frame - i.e., current frame is frame 0, - and current location is based on that. - Don't do this on return from a stack dummy routine, - or if the program has exited. */ - - if (!stop_stack_dummy) - select_frame (get_current_frame ()); - - if (stop_stack_dummy == STOP_STACK_DUMMY) - { - /* Pop the empty frame that contains the stack dummy. - This also restores inferior state prior to the call - (struct infcall_suspend_state). */ - struct frame_info *frame = get_current_frame (); - - gdb_assert (get_frame_type (frame) == DUMMY_FRAME); - frame_pop (frame); - /* frame_pop() calls reinit_frame_cache as the last thing it - does which means there's currently no selected frame. We - don't need to re-establish a selected frame if the dummy call - returns normally, that will be done by - restore_infcall_control_state. However, we do have to handle - the case where the dummy call is returning after being - stopped (e.g. the dummy call previously hit a breakpoint). - We can't know which case we have so just always re-establish - a selected frame here. */ select_frame (get_current_frame ()); - } - -done: - /* Suppress the stop observer if we're in the middle of: + /* Set the current source location. */ + set_current_sal_from_frame (get_current_frame ()); + } - - calling an inferior function, as we pretend we inferior didn't - run at all. The return value of the call is handled by the - expression evaluator, through call_function_by_hand. */ + /* Look up the hook_stop and run it (CLI internally handles problem + of stop_command's pre-hook not existing). */ + if (stop_command) + catch_errors (hook_stop_stub, stop_command, + "Error while running hook_stop:\n", RETURN_MASK_ALL); - if (!target_has_execution - || last.kind == TARGET_WAITKIND_SIGNALLED - || last.kind == TARGET_WAITKIND_EXITED - || last.kind == TARGET_WAITKIND_NO_RESUMED - || !inferior_thread ()->control.in_infcall) - { - if (!ptid_equal (inferior_ptid, null_ptid)) - observer_notify_normal_stop (inferior_thread ()->control.stop_bpstat, - stop_print_frame); - else - observer_notify_normal_stop (NULL, stop_print_frame); - } + /* Notify observers about the stop. This is where the interpreters + print the stop event. */ + if (!ptid_equal (inferior_ptid, null_ptid)) + observer_notify_normal_stop (inferior_thread ()->control.stop_bpstat, + stop_print_frame); + else + observer_notify_normal_stop (NULL, stop_print_frame); annotate_stopped (); |