* defs.h (add_inferior_continuation)
authorPedro Alves <palves@redhat.com>
Wed, 5 Nov 2008 20:23:07 +0000 (20:23 +0000)
committerPedro Alves <palves@redhat.com>
Wed, 5 Nov 2008 20:23:07 +0000 (20:23 +0000)
(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) <continuations>: 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.

gdb/ChangeLog
gdb/defs.h
gdb/inf-loop.c
gdb/infcmd.c
gdb/inferior.c
gdb/inferior.h
gdb/infrun.c
gdb/utils.c

index ea9c1d8..5e04130 100644 (file)
@@ -1,3 +1,21 @@
+2008-11-05  Pedro Alves  <pedro@codesourcery.com>
+
+       * 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) <continuations>: 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  <pedro@codesourcery.com>
 
        * inf-loop.c (inferior_event_handler): On INF_ERROR and
index 8d50f8a..b047266 100644 (file)
@@ -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;
index 2e0f4d2..95355e8 100644 (file)
@@ -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
index 50e8fff..b3af31f 100644 (file)
@@ -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;
        }
index 4233a51..9fec4cc 100644 (file)
@@ -45,6 +45,7 @@ current_inferior (void)
 static void
 free_inferior (struct inferior *inf)
 {
+  discard_all_inferior_continuations (inf);
   xfree (inf->private);
   xfree (inf);
 }
index cc5bf9f..029dc31 100644 (file)
@@ -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;
 };
index 30d914d..1a95466 100644 (file)
@@ -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;
index 26d7933..fed2e7e 100644 (file)
@@ -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)
 {