gdb: fix python/lib/gdb/__init__.py formatting
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 6ec269adaa8c5b127197ff85615f26ea15de9d15..9469b74af397dac9a3d47e362a49107e4e25cd67 100644 (file)
@@ -426,7 +426,7 @@ follow_fork_inferior (bool follow_child, bool detach_fork)
 Can not resume the parent process over vfork in the foreground while\n\
 holding the child stopped.  Try \"set detach-on-fork\" or \
 \"set schedule-multiple\".\n"));
-      return 1;
+      return true;
     }
 
   if (!follow_child)
@@ -477,7 +477,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          set_current_inferior (child_inf);
          switch_to_no_thread ();
          child_inf->symfile_flags = SYMFILE_NO_READ;
-         push_target (parent_inf->process_target ());
+         child_inf->push_target (parent_inf->process_target ());
          thread_info *child_thr
            = add_thread_silent (child_inf->process_target (), child_ptid);
 
@@ -521,6 +521,9 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
                 breakpoint.  If a "cloned-VM" event was propagated
                 better throughout the core, this wouldn't be
                 required.  */
+             scoped_restore restore_in_initial_library_scan
+               = make_scoped_restore (&child_inf->in_initial_library_scan,
+                                      true);
              solib_create_inferior_hook (0);
            }
        }
@@ -627,7 +630,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
           informing the solib layer about this new process.  */
 
        set_current_inferior (child_inf);
-       push_target (target);
+       child_inf->push_target (target);
       }
 
       thread_info *child_thr = add_thread_silent (target, child_ptid);
@@ -656,13 +659,17 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
             shared libraries, and install the solib event breakpoint.
             If a "cloned-VM" event was propagated better throughout
             the core, this wouldn't be required.  */
+         scoped_restore restore_in_initial_library_scan
+           = make_scoped_restore (&child_inf->in_initial_library_scan, true);
          solib_create_inferior_hook (0);
        }
 
       switch_to_thread (child_thr);
     }
 
-  return target_follow_fork (follow_child, detach_fork);
+  target_follow_fork (follow_child, detach_fork);
+
+  return false;
 }
 
 /* Tell the target to follow the fork we're stopped at.  Returns true
@@ -1062,7 +1069,6 @@ show_follow_exec_mode_string (struct ui_file *file, int from_tty,
 static void
 follow_exec (ptid_t ptid, const char *exec_file_target)
 {
-  struct inferior *inf = current_inferior ();
   int pid = ptid.pid ();
   ptid_t process_ptid;
 
@@ -1165,6 +1171,8 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
      previous incarnation of this process.  */
   no_shared_libraries (NULL, 0);
 
+  struct inferior *inf = current_inferior ();
+
   if (follow_exec_mode_string == follow_exec_mode_new)
     {
       /* The user wants to keep the old inferior and program spaces
@@ -1174,18 +1182,16 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
         inferior's pid.  Having two inferiors with the same pid would confuse
         find_inferior_p(t)id.  Transfer the terminal state and info from the
          old to the new inferior.  */
-      inf = add_inferior_with_spaces ();
-      swap_terminal_info (inf, current_inferior ());
-      exit_inferior_silent (current_inferior ());
+      inferior *new_inferior = add_inferior_with_spaces ();
 
-      inf->pid = pid;
-      target_follow_exec (inf, exec_file_target);
+      swap_terminal_info (new_inferior, inf);
+      exit_inferior_silent (inf);
 
-      inferior *org_inferior = current_inferior ();
-      switch_to_inferior_no_thread (inf);
-      push_target (org_inferior->process_target ());
-      thread_info *thr = add_thread (inf->process_target (), ptid);
-      switch_to_thread (thr);
+      new_inferior->pid = pid;
+      target_follow_exec (new_inferior, ptid, exec_file_target);
+
+      /* We continue with the new inferior.  */
+      inf = new_inferior;
     }
   else
     {
@@ -1196,8 +1202,10 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
         around (its description is later cleared/refetched on
         restart).  */
       target_clear_description ();
+      target_follow_exec (inf, ptid, exec_file_target);
     }
 
+  gdb_assert (current_inferior () == inf);
   gdb_assert (current_program_space == inf->pspace);
 
   /* Attempt to open the exec file.  SYMFILE_DEFER_BP_RESET is used
@@ -1777,7 +1785,7 @@ displaced_step_finish (thread_info *event_thread, enum gdb_signal signal)
   /* Fixup may need to read memory/registers.  Switch to the thread
      that we're fixing up.  Also, target_stopped_by_watchpoint checks
      the current thread, and displaced_step_restore performs ptid-dependent
-     memory accesses using current_inferior() and current_top_target().  */
+     memory accesses using current_inferior().  */
   switch_to_thread (event_thread);
 
   displaced_step_reset_cleanup cleanup (displaced);
@@ -2030,7 +2038,8 @@ set_schedlock_func (const char *args, int from_tty, struct cmd_list_element *c)
   if (!target_can_lock_scheduler ())
     {
       scheduler_mode = schedlock_off;
-      error (_("Target '%s' cannot support this command."), target_shortname);
+      error (_("Target '%s' cannot support this command."),
+            target_shortname ());
     }
 }
 
@@ -2172,8 +2181,6 @@ do_target_resume (ptid_t resume_ptid, bool step, enum gdb_signal sig)
 
   target_resume (resume_ptid, step, sig);
 
-  target_commit_resume ();
-
   if (target_can_async_p ())
     target_async (1);
 }
@@ -2760,28 +2767,220 @@ schedlock_applies (struct thread_info *tp)
                                            execution_direction)));
 }
 
-/* Calls target_commit_resume on all targets.  */
+/* Set process_stratum_target::COMMIT_RESUMED_STATE in all target
+   stacks that have threads executing and don't have threads with
+   pending events.  */
 
 static void
-commit_resume_all_targets ()
+maybe_set_commit_resumed_all_targets ()
 {
   scoped_restore_current_thread restore_thread;
 
-  /* Map between process_target and a representative inferior.  This
-     is to avoid committing a resume in the same target more than
-     once.  Resumptions must be idempotent, so this is an
-     optimization.  */
-  std::unordered_map<process_stratum_target *, inferior *> conn_inf;
-
   for (inferior *inf : all_non_exited_inferiors ())
-    if (inf->has_execution ())
-      conn_inf[inf->process_target ()] = inf;
+    {
+      process_stratum_target *proc_target = inf->process_target ();
+
+      if (proc_target->commit_resumed_state)
+       {
+         /* We already set this in a previous iteration, via another
+            inferior sharing the process_stratum target.  */
+         continue;
+       }
 
-  for (const auto &ci : conn_inf)
+      /* If the target has no resumed threads, it would be useless to
+        ask it to commit the resumed threads.  */
+      if (!proc_target->threads_executing)
+       {
+         infrun_debug_printf ("not requesting commit-resumed for target "
+                              "%s, no resumed threads",
+                              proc_target->shortname ());
+         continue;
+       }
+
+      /* As an optimization, if a thread from this target has some
+        status to report, handle it before requiring the target to
+        commit its resumed threads: handling the status might lead to
+        resuming more threads.  */
+      bool has_thread_with_pending_status = false;
+      for (thread_info *thread : all_non_exited_threads (proc_target))
+       if (thread->resumed && thread->suspend.waitstatus_pending_p)
+         {
+           has_thread_with_pending_status = true;
+           break;
+         }
+
+      if (has_thread_with_pending_status)
+       {
+         infrun_debug_printf ("not requesting commit-resumed for target %s, a"
+                              " thread has a pending waitstatus",
+                              proc_target->shortname ());
+         continue;
+       }
+
+      switch_to_inferior_no_thread (inf);
+
+      if (target_has_pending_events ())
+       {
+         infrun_debug_printf ("not requesting commit-resumed for target %s, "
+                              "target has pending events",
+                              proc_target->shortname ());
+         continue;
+       }
+
+      infrun_debug_printf ("enabling commit-resumed for target %s",
+                          proc_target->shortname ());
+
+      proc_target->commit_resumed_state = true;
+    }
+}
+
+/* See infrun.h.  */
+
+void
+maybe_call_commit_resumed_all_targets ()
+{
+  scoped_restore_current_thread restore_thread;
+
+  for (inferior *inf : all_non_exited_inferiors ())
     {
-      inferior *inf = ci.second;
+      process_stratum_target *proc_target = inf->process_target ();
+
+      if (!proc_target->commit_resumed_state)
+       continue;
+
       switch_to_inferior_no_thread (inf);
-      target_commit_resume ();
+
+      infrun_debug_printf ("calling commit_resumed for target %s",
+                          proc_target->shortname());
+
+      target_commit_resumed ();
+    }
+}
+
+/* To track nesting of scoped_disable_commit_resumed objects, ensuring
+   that only the outermost one attempts to re-enable
+   commit-resumed.  */
+static bool enable_commit_resumed = true;
+
+/* See infrun.h.  */
+
+scoped_disable_commit_resumed::scoped_disable_commit_resumed
+  (const char *reason)
+  : m_reason (reason),
+    m_prev_enable_commit_resumed (enable_commit_resumed)
+{
+  infrun_debug_printf ("reason=%s", m_reason);
+
+  enable_commit_resumed = false;
+
+  for (inferior *inf : all_non_exited_inferiors ())
+    {
+      process_stratum_target *proc_target = inf->process_target ();
+
+      if (m_prev_enable_commit_resumed)
+       {
+         /* This is the outermost instance: force all
+            COMMIT_RESUMED_STATE to false.  */
+         proc_target->commit_resumed_state = false;
+       }
+      else
+       {
+         /* This is not the outermost instance, we expect
+            COMMIT_RESUMED_STATE to have been cleared by the
+            outermost instance.  */
+         gdb_assert (!proc_target->commit_resumed_state);
+       }
+    }
+}
+
+/* See infrun.h.  */
+
+void
+scoped_disable_commit_resumed::reset ()
+{
+  if (m_reset)
+    return;
+  m_reset = true;
+
+  infrun_debug_printf ("reason=%s", m_reason);
+
+  gdb_assert (!enable_commit_resumed);
+
+  enable_commit_resumed = m_prev_enable_commit_resumed;
+
+  if (m_prev_enable_commit_resumed)
+    {
+      /* This is the outermost instance, re-enable
+         COMMIT_RESUMED_STATE on the targets where it's possible.  */
+      maybe_set_commit_resumed_all_targets ();
+    }
+  else
+    {
+      /* This is not the outermost instance, we expect
+        COMMIT_RESUMED_STATE to still be false.  */
+      for (inferior *inf : all_non_exited_inferiors ())
+       {
+         process_stratum_target *proc_target = inf->process_target ();
+         gdb_assert (!proc_target->commit_resumed_state);
+       }
+    }
+}
+
+/* See infrun.h.  */
+
+scoped_disable_commit_resumed::~scoped_disable_commit_resumed ()
+{
+  reset ();
+}
+
+/* See infrun.h.  */
+
+void
+scoped_disable_commit_resumed::reset_and_commit ()
+{
+  reset ();
+  maybe_call_commit_resumed_all_targets ();
+}
+
+/* See infrun.h.  */
+
+scoped_enable_commit_resumed::scoped_enable_commit_resumed
+  (const char *reason)
+  : m_reason (reason),
+    m_prev_enable_commit_resumed (enable_commit_resumed)
+{
+  infrun_debug_printf ("reason=%s", m_reason);
+
+  if (!enable_commit_resumed)
+    {
+      enable_commit_resumed = true;
+
+      /* Re-enable COMMIT_RESUMED_STATE on the targets where it's
+        possible.  */
+      maybe_set_commit_resumed_all_targets ();
+
+      maybe_call_commit_resumed_all_targets ();
+    }
+}
+
+/* See infrun.h.  */
+
+scoped_enable_commit_resumed::~scoped_enable_commit_resumed ()
+{
+  infrun_debug_printf ("reason=%s", m_reason);
+
+  gdb_assert (enable_commit_resumed);
+
+  enable_commit_resumed = m_prev_enable_commit_resumed;
+
+  if (!enable_commit_resumed)
+    {
+      /* Force all COMMIT_RESUMED_STATE back to false.  */
+      for (inferior *inf : all_non_exited_inferiors ())
+       {
+         process_stratum_target *proc_target = inf->process_target ();
+         proc_target->commit_resumed_state = false;
+       }
     }
 }
 
@@ -2809,7 +3008,7 @@ check_multi_target_resumption (process_stratum_target *resume_target)
         always-non-stop mode.  */
       inferior *first_not_non_stop = nullptr;
 
-      for (inferior *inf : all_non_exited_inferiors (resume_target))
+      for (inferior *inf : all_non_exited_inferiors ())
        {
          switch_to_inferior_no_thread (inf);
 
@@ -3005,7 +3204,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
   cur_thr->prev_pc = regcache_read_pc_protected (regcache);
 
   {
-    scoped_restore save_defer_tc = make_scoped_defer_target_commit_resume ();
+    scoped_disable_commit_resumed disable_commit_resumed ("proceeding");
 
     started = start_step_over ();
 
@@ -3073,9 +3272,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
        if (!ecs->wait_some_more)
          error (_("Command aborted."));
       }
-  }
 
-  commit_resume_all_targets ();
+    disable_commit_resumed.reset_and_commit ();
+  }
 
   finish_state.release ();
 
@@ -3471,8 +3670,7 @@ do_target_wait_1 (inferior *inf, ptid_t ptid,
    more events.  Polls for events from all inferiors/targets.  */
 
 static bool
-do_target_wait (ptid_t wait_ptid, execution_control_state *ecs,
-               target_wait_flags options)
+do_target_wait (execution_control_state *ecs, target_wait_flags options)
 {
   int num_inferiors = 0;
   int random_selector;
@@ -3482,10 +3680,9 @@ do_target_wait (ptid_t wait_ptid, execution_control_state *ecs,
      polling the rest of the inferior list starting from that one in a
      circular fashion until the whole list is polled once.  */
 
-  auto inferior_matches = [&wait_ptid] (inferior *inf)
+  auto inferior_matches = [] (inferior *inf)
     {
-      return (inf->process_target () != NULL
-             && ptid_t (inf->pid).matches (wait_ptid));
+      return inf->process_target () != nullptr;
     };
 
   /* First see how many matching inferiors we have.  */
@@ -3524,7 +3721,7 @@ do_target_wait (ptid_t wait_ptid, execution_control_state *ecs,
 
   auto do_wait = [&] (inferior *inf)
   {
-    ecs->ptid = do_target_wait_1 (inf, wait_ptid, &ecs->ws, options);
+    ecs->ptid = do_target_wait_1 (inf, minus_one_ptid, &ecs->ws, options);
     ecs->target = inf->process_target ();
     return (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
   };
@@ -3877,8 +4074,16 @@ fetch_inferior_event ()
       = make_scoped_restore (&execution_direction,
                             target_execution_direction ());
 
-    if (!do_target_wait (minus_one_ptid, ecs, TARGET_WNOHANG))
-      return;
+    /* Allow targets to pause their resumed threads while we handle
+       the event.  */
+    scoped_disable_commit_resumed disable_commit_resumed ("handling event");
+
+    if (!do_target_wait (ecs, TARGET_WNOHANG))
+      {
+       infrun_debug_printf ("do_target_wait returned no event");
+       disable_commit_resumed.reset_and_commit ();
+       return;
+      }
 
     gdb_assert (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
 
@@ -3969,6 +4174,8 @@ fetch_inferior_event ()
     /* No error, don't finish the thread states yet.  */
     finish_state.release ();
 
+    disable_commit_resumed.reset_and_commit ();
+
     /* This scope is used to ensure that readline callbacks are
        reinstalled here.  */
   }
@@ -4500,12 +4707,11 @@ save_waitstatus (struct thread_info *tp, const target_waitstatus *ws)
   tp->suspend.waitstatus = *ws;
   tp->suspend.waitstatus_pending_p = 1;
 
-  struct regcache *regcache = get_thread_regcache (tp);
-  const address_space *aspace = regcache->aspace ();
-
   if (ws->kind == TARGET_WAITKIND_STOPPED
       && ws->value.sig == GDB_SIGNAL_TRAP)
     {
+      struct regcache *regcache = get_thread_regcache (tp);
+      const address_space *aspace = regcache->aspace ();
       CORE_ADDR pc = regcache_read_pc (regcache);
 
       adjust_pc_after_break (tp, &tp->suspend.waitstatus);
@@ -5290,10 +5496,18 @@ handle_inferior_event (struct execution_control_state *ecs)
        struct gdbarch *gdbarch = regcache->arch ();
        inferior *parent_inf = find_inferior_ptid (ecs->target, ecs->ptid);
 
-       /* If this is a fork (child gets its own address space copy) and some
-          displaced step buffers were in use at the time of the fork, restore
-          the displaced step buffer bytes in the child process.  */
-       if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
+       /* If this is a fork (child gets its own address space copy)
+          and some displaced step buffers were in use at the time of
+          the fork, restore the displaced step buffer bytes in the
+          child process.
+
+          Architectures which support displaced stepping and fork
+          events must supply an implementation of
+          gdbarch_displaced_step_restore_all_in_ptid.  This is not
+          enforced during gdbarch validation to support architectures
+          which support displaced stepping but not forks.  */
+       if (ecs->ws.kind == TARGET_WAITKIND_FORKED
+           && gdbarch_supports_displaced_stepping (gdbarch))
          gdbarch_displaced_step_restore_all_in_ptid
            (gdbarch, parent_inf, ecs->ws.value.related_pid);
 
@@ -5812,7 +6026,8 @@ handle_signal_stop (struct execution_control_state *ecs)
 
          infrun_debug_printf ("stopped by watchpoint");
 
-         if (target_stopped_data_address (current_top_target (), &addr))
+         if (target_stopped_data_address (current_inferior ()->top_target (),
+                                          &addr))
            infrun_debug_printf ("stopped data address=%s",
                                 paddress (reg_gdbarch, addr));
          else
@@ -7044,7 +7259,7 @@ process_event_stop_test (struct execution_control_state *ecs)
   bool refresh_step_info = true;
   if ((ecs->event_thread->suspend.stop_pc == stop_pc_sal.pc)
       && (ecs->event_thread->current_line != stop_pc_sal.line
-         || ecs->event_thread->current_symtab != stop_pc_sal.symtab))
+         || ecs->event_thread->current_symtab != stop_pc_sal.symtab))
     {
       /* We are at a different line.  */
 
@@ -8834,7 +9049,8 @@ siginfo_value_read (struct value *v)
   validate_registers_access ();
 
   transferred =
-    target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO,
+    target_read (current_inferior ()->top_target (),
+                TARGET_OBJECT_SIGNAL_INFO,
                 NULL,
                 value_contents_all_raw (v),
                 value_offset (v),
@@ -8856,7 +9072,7 @@ siginfo_value_write (struct value *v, struct value *fromval)
      vice versa.  */
   validate_registers_access ();
 
-  transferred = target_write (current_top_target (),
+  transferred = target_write (current_inferior ()->top_target (),
                              TARGET_OBJECT_SIGNAL_INFO,
                              NULL,
                              value_contents_all_raw (fromval),
@@ -8920,7 +9136,8 @@ public:
 
        siginfo_data.reset ((gdb_byte *) xmalloc (len));
 
-       if (target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
+       if (target_read (current_inferior ()->top_target (),
+                        TARGET_OBJECT_SIGNAL_INFO, NULL,
                         siginfo_data.get (), 0, len) != len)
          {
            /* Errors ignored.  */
@@ -8955,7 +9172,8 @@ public:
        struct type *type = gdbarch_get_siginfo_type (gdbarch);
 
        /* Errors ignored.  */
-       target_write (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
+       target_write (current_inferior ()->top_target (),
+                     TARGET_OBJECT_SIGNAL_INFO, NULL,
                      m_siginfo_data.get (), 0, TYPE_LENGTH (type));
       }
 
@@ -9212,6 +9430,7 @@ static const struct internalvar_funcs siginfo_funcs =
 static void
 infrun_async_inferior_event_handler (gdb_client_data data)
 {
+  clear_async_event_handler (infrun_async_inferior_event_token);
   inferior_event_handler (INF_REG_EVENT);
 }
 
@@ -9293,10 +9512,11 @@ _initialize_infrun ()
     = create_async_event_handler (infrun_async_inferior_event_handler, NULL,
                                  "infrun");
 
-  add_info ("signals", info_signals_command, _("\
+  cmd_list_element *info_signals_cmd
+    = add_info ("signals", info_signals_command, _("\
 What debugger does when program gets various signals.\n\
 Specify a signal as argument to print info on that signal only."));
-  add_info_alias ("handle", "signals", 0);
+  add_info_alias ("handle", info_signals_cmd, 0);
 
   c = add_com ("handle", class_run, handle_command, _("\
 Specify how to handle signals.\n\
@@ -9551,11 +9771,13 @@ enabled by default on some platforms."),
   inferior_ptid = null_ptid;
   target_last_wait_ptid = minus_one_ptid;
 
-  gdb::observers::thread_ptid_changed.attach (infrun_thread_ptid_changed);
-  gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested);
-  gdb::observers::thread_exit.attach (infrun_thread_thread_exit);
-  gdb::observers::inferior_exit.attach (infrun_inferior_exit);
-  gdb::observers::inferior_execd.attach (infrun_inferior_execd);
+  gdb::observers::thread_ptid_changed.attach (infrun_thread_ptid_changed,
+                                             "infrun");
+  gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested,
+                                               "infrun");
+  gdb::observers::thread_exit.attach (infrun_thread_thread_exit, "infrun");
+  gdb::observers::inferior_exit.attach (infrun_inferior_exit, "infrun");
+  gdb::observers::inferior_execd.attach (infrun_inferior_execd, "infrun");
 
   /* Explicitly create without lookup, since that tries to create a
      value with a void typed value, and when we get here, gdbarch
This page took 0.03038 seconds and 4 git commands to generate.