From: Pedro Alves Date: Wed, 5 Nov 2008 20:23:07 +0000 (+0000) Subject: * defs.h (add_inferior_continuation) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e0ba674611b77dce4d02d6b08e90b10255ec3e2d;p=binutils-gdb.git * defs.h (add_inferior_continuation) (do_all_inferior_continuations) (discard_all_inferior_continuations): Declare. * utils.c (add_inferior_continuation) (do_all_inferior_continuations) (discard_all_inferior_continuations): New. * inferior.h (struct inferior) : New field. * inferior.c (free_inferior): Discard all the inferior continuations. * inf-loop.c (inferior_event_handler): Do all current inferior continuations. * infcmd.c (attach_command): Register an inferior continuation instead of a thread continuation. * infrun.c (handle_inferior_event): If stop_soon is STOP_QUIETLY_NO_SIGSTOP, also expect a TARGET_SIGNAL_0. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ea9c1d8ac82..5e0413052e0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,21 @@ +2008-11-05 Pedro Alves + + * defs.h (add_inferior_continuation) + (do_all_inferior_continuations) + (discard_all_inferior_continuations): Declare. + * utils.c (add_inferior_continuation) + (do_all_inferior_continuations) + (discard_all_inferior_continuations): New. + * inferior.h (struct inferior) : New field. + * inferior.c (free_inferior): Discard all the inferior + continuations. + * inf-loop.c (inferior_event_handler): Do all current inferior + continuations. + * infcmd.c (attach_command): Register an inferior continuation + instead of a thread continuation. + * infrun.c (handle_inferior_event): If stop_soon is + STOP_QUIETLY_NO_SIGSTOP, also expect a TARGET_SIGNAL_0. + 2008-11-04 Pedro Alves * inf-loop.c (inferior_event_handler): On INF_ERROR and diff --git a/gdb/defs.h b/gdb/defs.h index 8d50f8a824b..b04726693d5 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -701,8 +701,12 @@ extern void free_command_lines (struct command_line **); struct continuation; struct thread_info; +struct inferior; /* From utils.c */ + +/* Thread specific continuations. */ + extern void add_continuation (struct thread_info *, void (*)(void *), void *, void (*)(void *)); @@ -719,6 +723,14 @@ extern void do_all_intermediate_continuations_thread (struct thread_info *); extern void discard_all_intermediate_continuations (void); extern void discard_all_intermediate_continuations_thread (struct thread_info *); +/* Inferior specific (any thread) continuations. */ + +extern void add_inferior_continuation (void (*) (void *), + void *, + void (*) (void *)); +extern void do_all_inferior_continuations (void); +extern void discard_all_inferior_continuations (struct inferior *inf); + /* String containing the current directory (what getwd would return). */ extern char *current_directory; diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c index 2e0f4d26770..95355e8eb73 100644 --- a/gdb/inf-loop.c +++ b/gdb/inf-loop.c @@ -89,6 +89,11 @@ inferior_event_handler (enum inferior_event_type event_type, was_sync = sync_execution; async_enable_stdin (); + /* Do all continuations associated with the whole inferior (not + a particular thread). */ + if (!ptid_equal (inferior_ptid, null_ptid)) + do_all_inferior_continuations (); + /* If we were doing a multi-step (eg: step n, next n), but it got interrupted by a breakpoint, still do the pending continuations. The continuation itself is responsible for diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 50e8fff7460..b3af31fc171 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -2320,9 +2320,8 @@ attach_command (char *args, int from_tty) a->args = xstrdup (args); a->from_tty = from_tty; a->async_exec = async_exec; - add_continuation (inferior_thread (), - attach_command_continuation, a, - attach_command_continuation_free_args); + add_inferior_continuation (attach_command_continuation, a, + attach_command_continuation_free_args); discard_cleanups (back_to); return; } diff --git a/gdb/inferior.c b/gdb/inferior.c index 4233a51dfac..9fec4cc2887 100644 --- a/gdb/inferior.c +++ b/gdb/inferior.c @@ -45,6 +45,7 @@ current_inferior (void) static void free_inferior (struct inferior *inf) { + discard_all_inferior_continuations (inf); xfree (inf->private); xfree (inf); } diff --git a/gdb/inferior.h b/gdb/inferior.h index cc5bf9f5bdd..029dc31a497 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -424,6 +424,11 @@ struct inferior forked. */ int attach_flag; + /* What is left to do for an execution command after any thread of + this inferior stops. For continuations associated with a + specific thread, see `struct thread_info'. */ + struct continuation *continuations; + /* Private data used by the target vector implementation. */ struct private_inferior *private; }; diff --git a/gdb/infrun.c b/gdb/infrun.c index 30d914d49e8..1a954662575 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2834,10 +2834,19 @@ targets should add new threads to the thread list themselves in non-stop mode.") SIGTRAP. Some systems (e.g. Windows), and stubs supporting target extended-remote report it instead of a SIGSTOP (e.g. gdbserver). We already rely on SIGTRAP being our - signal, so this is no exception. */ + signal, so this is no exception. + + Also consider that the attach is complete when we see a + TARGET_SIGNAL_0. In non-stop mode, GDB will explicitly tell + the target to stop all threads of the inferior, in case the + low level attach operation doesn't stop them implicitly. If + they weren't stopped implicitly, then the stub will report a + TARGET_SIGNAL_0, meaning: stopped for no particular reason + other than GDB's request. */ if (stop_soon == STOP_QUIETLY_NO_SIGSTOP && (ecs->event_thread->stop_signal == TARGET_SIGNAL_STOP - || ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)) + || ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP + || ecs->event_thread->stop_signal == TARGET_SIGNAL_0)) { stop_stepping (ecs); ecs->event_thread->stop_signal = TARGET_SIGNAL_0; diff --git a/gdb/utils.c b/gdb/utils.c index 26d79334696..fed2e7e25ad 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -505,6 +505,59 @@ add_continuation (struct thread_info *thread, thread->continuations = (struct continuation *) as_cleanup; } +/* Add a continuation to the continuation list of INFERIOR. The new + continuation will be added at the front. */ + +void +add_inferior_continuation (void (*continuation_hook) (void *), void *args, + void (*continuation_free_args) (void *)) +{ + struct inferior *inf = current_inferior (); + struct cleanup *as_cleanup = &inf->continuations->base; + make_cleanup_ftype *continuation_hook_fn = continuation_hook; + + make_my_cleanup2 (&as_cleanup, + continuation_hook_fn, + args, + continuation_free_args); + + inf->continuations = (struct continuation *) as_cleanup; +} + +/* Do all continuations of the current inferior. */ + +void +do_all_inferior_continuations (void) +{ + struct cleanup *old_chain; + struct cleanup *as_cleanup; + struct inferior *inf = current_inferior (); + + if (inf->continuations == NULL) + return; + + /* Copy the list header into another pointer, and set the global + list header to null, so that the global list can change as a side + effect of invoking the continuations and the processing of the + preexisting continuations will not be affected. */ + + as_cleanup = &inf->continuations->base; + inf->continuations = NULL; + + /* Work now on the list we have set aside. */ + do_my_cleanups (&as_cleanup, NULL); +} + +/* Get rid of all the inferior-wide continuations of INF. */ + +void +discard_all_inferior_continuations (struct inferior *inf) +{ + struct cleanup *continuation_ptr = &inf->continuations->base; + discard_my_cleanups (&continuation_ptr, NULL); + inf->continuations = NULL; +} + static void restore_thread_cleanup (void *arg) {