]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
thread_info::executing+resumed -> thread_info::internal_state
authorPedro Alves <pedro@palves.net>
Wed, 19 Feb 2025 14:37:39 +0000 (14:37 +0000)
committerPedro Alves <pedro@palves.net>
Mon, 9 Jun 2025 17:09:11 +0000 (18:09 +0100)
While working on Windows non-stop support, I ran into a
very-hard-to-track-down bug.

The problem turned out to be that
infrun.c:proceed_resume_thread_checked resumed an already-executing
thread because the thread was marked as "executing=true,
resumed=false", and that function only skips resuming threads that are
marked resumed=true.  The consequence was that GDB corrupted the
registers of the Windows DLL loader threads, eventually leading to a
GDB+inferior deadlock.

Originally, the "resumed" flag was only ever set when infrun decided
is was ready to process a thread's pending wait status.  infrun has
since evolved to set the resumed flag when we set a thread's executing
flag too.  We are not always consistent throughout in guaranteeing
that a thread is marked resumed=true whenever it is marked
executing=true, though.  For instance, no target code that supports
non-stop mode (linux-nat, remote, and windows-nat with this series) is
making sure that new threads are marked resumed=true when they are
added to the thread list.  They are only marked as {state=running,
executing=true}, the "resumed" flag is not touched.

Making proceed_resume_thread_checked check thr->executing() in
addition to thr->resumed(), feels like papering over a combination of
states that shouldn't happen nowadays.

OTOH, having to have the target backends mark new threads as
resumed=true just feels like too many different states (three) to set:

  add_thread (...);
  set_running (...);
  set_executing (...);
  set_resumed (...);

Yuck.  I think we can do better.

We really have too many "state tracking" flags in a thread.
Basically:

 - whether a thread is "running/stopped/exited" (from the user's
   perspective).  This is the thread_info::state field.

 - whether a thread is "executing" (infrun asked the target to set the
   thread executing).  This is thread_info::executing().

 - whether a thread is "resumed" (infrun wants the thread to be
   resumed, but maybe can't yet because the thread has a pending wait
   status).  This is thread_info::resumed()

"running", "executing", and "resumed" are almost synonyms, so this can
be highly confusing English-wise too.

For "running" vs "executing", in comments, we tipically need to
explain that "running/stopped/exited" is for the user/frontend
perspective, while "executing true/false" is for gdb's internal run
control.

(Also, "executing or not" can also mean something else in GDB's
codebase -- "target has execution" does not mean that threads are
actually running right now -- it's a test for whether we have a live
process vs a core dump!)

One simplification we can do that avoids this running vs executing
ambiguity is to replace the "executing" field with an "internal_state"
field, similar to the thread_info::state field, and make that new
internal_state field reuse the same enum thread_state type that is
used by thread_info::state.  Like:

  struct thread_info
  {
  ...
    /* Frontend/public/external/user view of the thread state.  */
    enum thread_state m_state = THREAD_STOPPED;

    /* The thread's internal state.  When the thread is stopped
       internally while handling an internal event, like a software
       single-step breakpoint, the internal state will be
       THREAD_STOPPED, but the external state will still be
       THREAD_RUNNING.  */
    enum thread_state m_internal_state = THREAD_STOPPED;
  };

(Assume we'd add state() and internal_state() getters.)

With that, every check for thr->executing() is replaced with a
'thr->internal_state() == THREAD_RUNNING' check, and the code is
clearer by design.  There is no confusion between "running" vs
"executing" any more, because they now mean the exact same thing.
Instead, we say e.g., 'thread has (user) state "running", and internal
state "stopped"'.  Or simpler, 'thread is running (from the user's
perspective), but internally stopped'.  That is after all what we
would way in comments today already.

That still leaves the 'resumed' flag, though.  That's the least
obvious one.  Turns out we can get rid of it, and make it a new state
tracked by thread_info::internal_state.  That is, we make
internal_state have its own enumeration type (decoupled from
thread_info::state's type), and convert the resumed true/false flag to
a new enumerator of this new enumeration.  Like so:

  enum thread_int_state
  {
    THREAD_INT_STOPPED,
    THREAD_INT_RUNNING,
 +   THREAD_INT_RESUMED_PENDING_STATUS,
    THREAD_INT_EXITED,
  };

That is what this patch does.  So in summary, we go from:

 thread_info::state {THREAD_STOPPED, THREAD_RUNNING, THREAD_EXITED}
 thread_info::executing {false, true}
 thread_info::resumed {false, true}

to:

 thread_info::state {THREAD_STOPPED, THREAD_RUNNING, THREAD_EXITED}
 thread_info::internal_state {THREAD_INT_STOPPED, THREAD_INT_RUNNING,
                              THREAD_INT_RESUMED_PENDING_STATUS,
      THREAD_INT_EXITED}

The patch adds getters/setters for both (user) state and
internal_state, and adds assertions around state transitions, ensuring
that internal_state doesn't get out of sync with
thread::have_pending_wait_status().  It also adds an assertion to
clear_proceed_status_thread, making sure that we don't try to proceed
a thread that is already running.  Turns out that catches
attach_command calling init_wait_for_inferior too late, after
attaching has already created already-running threads.

The code that adds/removes threads from the proc_target's
resumed_with_pending_wait_status list is all centralized within
thread_info::set_internal_state, when we switch to/from the
resumed-pending-status state.  With the assertions in place, it should
be impossible to end up with a THREAD_INT_RUNNING thread with a
pending status.

The thread.c:set_running, thread.c:set_executing, thread.c:set_resumed
global functions are all gone, replaced with new thread.c:set_state
and thread.c:set_internal_state functions.

Tested on x86_64-linux-gnu, native and gdbserver.

Change-Id: I4f5097d68f4694d44e1ae23fea3e9bce45fb078c

33 files changed:
gdb/aarch64-tdep.c
gdb/amd-dbgapi-target.c
gdb/breakpoint.c
gdb/bsd-uthread.c
gdb/fork-child.c
gdb/frame.c
gdb/gcore.c
gdb/gdbthread.h
gdb/i386-tdep.c
gdb/inf-ptrace.c
gdb/infcall.c
gdb/infcmd.c
gdb/inferior.h
gdb/inflow.c
gdb/infrun.c
gdb/infrun.h
gdb/linux-fork.c
gdb/linux-nat.c
gdb/linux-thread-db.c
gdb/mi/mi-cmd-var.c
gdb/mi/mi-interp.c
gdb/mi/mi-main.c
gdb/process-stratum-target.c
gdb/python/py-infthread.c
gdb/record-btrace.c
gdb/record-full.c
gdb/regcache.c
gdb/remote.c
gdb/sol-thread.c
gdb/target.c
gdb/thread-iter.h
gdb/thread.c
gdb/top.c

index 8d54e59f332a76e1ae768ba7e12b765b24054f27..8e1908452c5ba2c2329db1782731ee4f0886fdcc 100644 (file)
@@ -4265,7 +4265,7 @@ aarch64_remove_non_address_bits (struct gdbarch *gdbarch, CORE_ADDR pointer)
 
       /* If the thread is running, we will not be able to fetch the mask
         registers.  */
-      if (thread != nullptr && thread->state != THREAD_RUNNING)
+      if (thread != nullptr && thread->state () != THREAD_RUNNING)
        {
          /* Otherwise, fetch the register cache and the masks.  */
          struct regcache *regs
index 819b373da3210de656bf82dc20d0fd3b5e5738df..b976cb75d06bb4bfe3d3121fc8a07614fc44c81d 100644 (file)
@@ -907,7 +907,7 @@ amd_dbgapi_target::stop (ptid_t ptid)
     /* Use the threads_safe iterator since stop_one_thread may delete the
        thread if it has exited.  */
     for (auto *thread : inf->threads_safe ())
-      if (thread->state != THREAD_EXITED && thread->ptid.matches (ptid)
+      if (thread->state () != THREAD_EXITED && thread->ptid.matches (ptid)
          && ptid_is_gpu (thread->ptid))
        stop_one_thread (thread);
 }
@@ -1130,8 +1130,8 @@ add_gpu_thread (inferior *inf, ptid_t wave_ptid)
   /* Create new GPU threads silently to avoid spamming the terminal
      with thousands of "[New Thread ...]" messages.  */
   thread_info *thread = add_thread_silent (proc_target, wave_ptid);
-  set_running (proc_target, wave_ptid, true);
-  set_executing (proc_target, wave_ptid, true);
+  set_state (proc_target, wave_ptid, THREAD_RUNNING);
+  set_internal_state (proc_target, wave_ptid, THREAD_INT_RUNNING);
   return thread;
 }
 
@@ -1872,7 +1872,7 @@ amd_dbgapi_target::update_thread_list ()
         which does not have a corresponding wave_id represents a wave which
         is gone at this point and should be deleted.  */
       for (thread_info *tp : inf->threads_safe ())
-       if (ptid_is_gpu (tp->ptid) && tp->state != THREAD_EXITED)
+       if (ptid_is_gpu (tp->ptid) && tp->state () != THREAD_EXITED)
          {
            auto it = threads.find (tp->ptid.tid ());
 
index dab52f1fae720828786b2a8938bb95c8251659a6..a86be54e81ae59f5cc889c4b4cbebb95c236cad3 100644 (file)
@@ -624,9 +624,9 @@ breakpoints_should_be_inserted_now (void)
          return 1;
 
       /* Don't remove breakpoints yet if, even though all threads are
-        stopped, we still have events to process.  */
+        stopped, some still have pending events to process.  */
       for (thread_info *tp : all_non_exited_threads ())
-       if (tp->resumed () && tp->has_pending_waitstatus ())
+       if (tp->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS)
          return 1;
     }
   return 0;
@@ -2049,7 +2049,7 @@ watchpoint_in_thread_scope (struct watchpoint *b)
   return (b->pspace == current_program_space
          && (b->watchpoint_thread == null_ptid
              || (inferior_ptid == b->watchpoint_thread
-                 && !inferior_thread ()->executing ())));
+                 && inferior_thread ()->internal_state () != THREAD_INT_RUNNING)));
 }
 
 /* Set watchpoint B to disp_del_at_next_stop, even including its possible
@@ -4990,7 +4990,8 @@ get_bpstat_thread ()
     return NULL;
 
   thread_info *tp = inferior_thread ();
-  if (tp->state == THREAD_EXITED || tp->executing ())
+  if (tp->internal_state () == THREAD_INT_EXITED
+      || tp->internal_state () == THREAD_INT_RUNNING)
     return NULL;
   return tp;
 }
index a493b0c6ae4545b031a495bfa5a9a5e7ba490148..6ca7acb03e0d73687e68e49ee87c5ab4a323d3d1 100644 (file)
@@ -416,7 +416,7 @@ bsd_uthread_target::wait (ptid_t ptid, struct target_waitstatus *status,
 
   /* Don't let the core see a ptid without a corresponding thread.  */
   thread_info *thread = beneath->find_thread (ptid);
-  if (thread == NULL || thread->state == THREAD_EXITED)
+  if (thread == NULL || thread->state () == THREAD_EXITED)
     add_thread (beneath, ptid);
 
   return ptid;
@@ -467,7 +467,7 @@ bsd_uthread_target::update_thread_list ()
       process_stratum_target *proc_target
        = as_process_stratum_target (this->beneath ());
       thread_info *thread = proc_target->find_thread (ptid);
-      if (thread == nullptr || thread->state == THREAD_EXITED)
+      if (thread == nullptr || thread->state () == THREAD_EXITED)
        {
          /* If INFERIOR_PTID doesn't have a tid member yet, then ptid
             is still the initial thread of the process.  Notify GDB
index 8abfbda2b784bd44657bf113223fe6e0534c8ecc..0913435fb801069d67b64a24edf44d83d63f6964 100644 (file)
@@ -130,8 +130,8 @@ gdb_startup_inferior (pid_t pid, int num_traps)
 
   ptid_t ptid = startup_inferior (proc_target, pid, num_traps, NULL, NULL);
 
-  /* Mark all threads non-executing.  */
-  set_executing (proc_target, ptid, false);
+  /* Mark all threads internally stopped.  */
+  set_internal_state (proc_target, ptid, THREAD_INT_STOPPED);
 
   return ptid;
 }
index fe5336f24012ad7a8790cd9f69b90648e04cc3d7..59e72ec37d85e4301ec806319f996d748ecb58ee 100644 (file)
@@ -1873,11 +1873,11 @@ has_stack_frames ()
 
       thread_info *tp = inferior_thread ();
       /* Don't try to read from a dead thread.  */
-      if (tp->state == THREAD_EXITED)
+      if (tp->internal_state () == THREAD_INT_EXITED)
        return false;
 
       /* ... or from a spinning thread.  */
-      if (tp->executing ())
+      if (tp->internal_state () == THREAD_INT_RUNNING)
        return false;
     }
 
index fa15d06796b43389469f29696d22de1d49efaff9..b9ed7991efb0d2122443a0d8e4a8fbb721dfa9c8 100644 (file)
@@ -846,7 +846,7 @@ thread_info *
 gcore_find_signalled_thread ()
 {
   thread_info *curr_thr = inferior_thread ();
-  if (curr_thr->state != THREAD_EXITED
+  if (curr_thr->state () != THREAD_EXITED
       && curr_thr->stop_signal () != GDB_SIGNAL_0)
     return curr_thr;
 
@@ -855,7 +855,7 @@ gcore_find_signalled_thread ()
       return thr;
 
   /* Default to the current thread, unless it has exited.  */
-  if (curr_thr->state != THREAD_EXITED)
+  if (curr_thr->state () != THREAD_EXITED)
     return curr_thr;
 
   return nullptr;
index a8fd967c7029b81478a2ebd95abeaff2e7a36cbb..344c808e9cb69506ad449e991ab1500931e23a67 100644 (file)
@@ -51,8 +51,8 @@ extern bool debug_threads;
 #define threads_debug_printf(fmt, ...) \
   debug_prefixed_printf_cond (debug_threads, "threads", fmt, ##__VA_ARGS__)
 
-/* Frontend view of the thread state.  Possible extensions: stepping,
-   finishing, until(ling),...
+/* User/frontend view of the thread state.  Possible extensions:
+   stepping, finishing, until(ling),...
 
    NOTE: Since the thread state is not a boolean, most times, you do
    not want to check it with negation.  If you really want to check if
@@ -81,6 +81,34 @@ enum thread_state
   THREAD_EXITED,
 };
 
+/* Internal view of the thread's running state.  When a thread is
+   running from the user's perspective, it will still occasionally
+   stop, due to breakpoint hits, single-stepping, etc.  Often those
+   stops are not meant to be user-visible.  In such situations, the
+   user state will be THREAD_RUNNING, while the internal state
+   transitions between stopped, running, etc.  */
+
+enum thread_int_state
+{
+  /* The thread is stopped.  If the thread has a pending wait status,
+     we should not process it until we try to let the thread run, in
+     which case we switch the thread to
+     THREAD_INT_RESUMED_PENDING_STATUS state.  */
+  THREAD_INT_STOPPED,
+
+  /* The thread is running.  */
+  THREAD_INT_RUNNING,
+
+  /* infrun wants the thread to be resumed, but didn't set it running
+     yet, because the thread has a pending wait status to process.  We
+     shouldn't let the thread really run until that wait status has
+     been processed.  */
+  THREAD_INT_RESUMED_PENDING_STATUS,
+
+  /* The thread is listed, but known to have exited.  */
+  THREAD_INT_EXITED,
+};
+
 /* STEP_OVER_ALL means step over all subroutine calls.
    STEP_OVER_UNDEBUGGABLE means step over calls to undebuggable functions.
    STEP_OVER_NONE means don't step over any subroutine calls.  */
@@ -218,10 +246,10 @@ struct thread_suspend_state
        last stopped, a pending breakpoint waitstatus is discarded.
 
      - If the thread is running, then this field has its value removed by
-       calling stop_pc.reset() (see thread_info::set_executing()).
+       calling stop_pc.reset() (see thread_info::set_internal_state()).
        Attempting to read a std::optional with no value is undefined
        behavior and will trigger an assertion error when _GLIBCXX_DEBUG is
-       defined, which should make error easier to track down.  */
+       defined, which should make errors easier to track down.  */
   std::optional<CORE_ADDR> stop_pc;
 };
 
@@ -263,8 +291,23 @@ public:
 
   bool deletable () const;
 
-  /* Mark this thread as running and notify observers.  */
-  void set_running (bool running);
+  /* Get the thread's (user-visible) state.  */
+  thread_state state () const { return m_state; }
+
+  /* Set this thread's (user-visible) state.  If the thread is set
+     running, notify observers.  */
+  void set_state (thread_state state) { set_state (state, false); }
+
+  /* Get the thread's internal state.  */
+  thread_int_state internal_state () const { return m_internal_state; }
+
+  /* Set the thread's internal state from STATE.  If the state
+     switches to THREAD_INT_RUNNING, also clears the thread's stop_pc.
+     The thread may also be added to (when switching to
+     THREAD_INT_RESUMED_PENDING_STATUS), or removed from (when
+     switching from THREAD_INT_RESUMED_PENDING_STATUS), the list of
+     threads with a pending wait status.  */
+  void set_internal_state (thread_int_state state);
 
   ptid_t ptid;                 /* "Actual process id";
                                    In fact, this may be overloaded with 
@@ -326,28 +369,6 @@ public:
     m_name = std::move (name);
   }
 
-  bool executing () const
-  { return m_executing; }
-
-  /* Set the thread's 'm_executing' field from EXECUTING, and if EXECUTING
-     is true also clears the thread's stop_pc.  */
-  void set_executing (bool executing);
-
-  bool resumed () const
-  { return m_resumed; }
-
-  /* Set the thread's 'm_resumed' field from RESUMED.  The thread may also
-     be added to (when RESUMED is true), or removed from (when RESUMED is
-     false), the list of threads with a pending wait status.  */
-  void set_resumed (bool resumed);
-
-  /* Frontend view of the thread state.  Note that the THREAD_RUNNING/
-     THREAD_STOPPED states are different from EXECUTING.  When the
-     thread is stopped internally while handling an internal event,
-     like a software single-step breakpoint, EXECUTING will be false,
-     but STATE will still be THREAD_RUNNING.  */
-  enum thread_state state = THREAD_STOPPED;
-
   /* State of GDB control of inferior thread execution.
      See `struct thread_control_state'.  */
   thread_control_state control;
@@ -573,20 +594,22 @@ public:
   displaced_step_thread_state displaced_step_state;
 
 private:
-  /* True if this thread is resumed from infrun's perspective.
-     Note that a thread can be marked both as not-executing and
-     resumed at the same time.  This happens if we try to resume a
-     thread that has a wait status pending.  We shouldn't let the
-     thread really run until that wait status has been processed, but
-     we should not process that wait status if we didn't try to let
-     the thread run.  */
-  bool m_resumed = false;
-
-  /* True means the thread is executing.  Note: this is different
-     from saying that there is an active target and we are stopped at
-     a breakpoint, for instance.  This is a real indicator whether the
-     thread is off and running.  */
-  bool m_executing = false;
+  /* Set this thread's (user-visible) state.  If the thread is set
+     running, notify observers, unless SUPPRESS_NOTIFICATION is true.
+     Returns the thread's previous state.  */
+  thread_state set_state (thread_state state, bool suppress_notification);
+  friend void set_state (process_stratum_target *targ,
+                        ptid_t ptid,
+                        thread_state state);
+  friend void finish_thread_state (process_stratum_target *targ,
+                                  ptid_t ptid);
+
+  /* User view of the thread's stopped/running/exited state.  */
+  enum thread_state m_state = THREAD_STOPPED;
+
+  /* The thread's internal state.  See definition of
+     thread_int_state.  */
+  enum thread_int_state m_internal_state = THREAD_INT_STOPPED;
 
   /* State of inferior thread to restore after GDB is done with an inferior
      call.  See `struct thread_suspend_state'.  */
@@ -815,17 +838,15 @@ extern void switch_to_no_thread ();
 /* Switch from one thread to another.  Does not read registers.  */
 extern void switch_to_thread_no_regs (struct thread_info *thread);
 
-/* Marks or clears thread(s) PTID of TARG as resumed.  If PTID is
-   MINUS_ONE_PTID, applies to all threads of TARG.  If
-   ptid_is_pid(PTID) is true, applies to all threads of the process
-   pointed at by {TARG,PTID}.  */
-extern void set_resumed (process_stratum_target *targ,
-                        ptid_t ptid, bool resumed);
+/* Marks thread PTID of TARG with user state STATE.  If PTID is
+   minus_one_ptid, marks all threads of TARG.  */
+extern void set_state (process_stratum_target *targ,
+                      ptid_t ptid, thread_state state);
 
-/* Marks thread PTID of TARG as running, or as stopped.  If PTID is
+/* Marks thread PTID of TARG with internal state STATE.  If PTID is
    minus_one_ptid, marks all threads of TARG.  */
-extern void set_running (process_stratum_target *targ,
-                        ptid_t ptid, bool running);
+extern void set_internal_state (process_stratum_target *targ,
+                               ptid_t ptid, thread_int_state state);
 
 /* Marks or clears thread(s) PTID of TARG as having been requested to
    stop.  If PTID is MINUS_ONE_PTID, applies to all threads of TARG.
@@ -835,25 +856,19 @@ extern void set_running (process_stratum_target *targ,
 extern void set_stop_requested (process_stratum_target *targ,
                                ptid_t ptid, bool stop);
 
-/* Marks thread PTID of TARG as executing, or not.  If PTID is
-   minus_one_ptid, marks all threads of TARG.
-
-   Note that this is different from the running state.  See the
-   description of state and executing fields of struct
-   thread_info.  */
-extern void set_executing (process_stratum_target *targ,
-                          ptid_t ptid, bool executing);
-
 /* True if any (known or unknown) thread of TARG is or may be
    executing.  */
 extern bool threads_are_executing (process_stratum_target *targ);
 
-/* Merge the executing property of thread PTID of TARG over to its
-   thread state property (frontend running/stopped view).
+/* Propagate the internal thread state of thread PTID of TARG over to
+   its (user) thread state.
 
-   "not executing" -> "stopped"
-   "executing"     -> "running"
-   "exited"        -> "exited"
+     user    <- internal
+    -------     ------------------------
+    stopped  <- stopped
+    running  <- running
+    running  <- continued-pending-status
+    exited   <- exited
 
    If PTID is minus_one_ptid, go over all threads of TARG.
 
@@ -1074,5 +1089,6 @@ extern void thread_try_catch_cmd (thread_info *thr,
 /* Return a string representation of STATE.  */
 
 extern const char *thread_state_string (enum thread_state state);
+extern const char *thread_int_state_string (enum thread_int_state state);
 
 #endif /* GDB_GDBTHREAD_H */
index 23788b44e92f6a48b5f926af4410314f2b47c991..a37eb132f47686efbd51806d23f8818d96e3bc14 100644 (file)
@@ -4811,8 +4811,8 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
   /* Since we are reading pseudo registers, we need to tell GDB that it is
      safe to do so, by saying we aren't _really_ running the inferior right
      now.  */
-  SCOPE_EXIT { inferior_thread ()->set_executing (true); };
-  inferior_thread () -> set_executing (false);
+  SCOPE_EXIT { inferior_thread ()->set_internal_state (THREAD_INT_RUNNING); };
+  inferior_thread ()->set_internal_state (THREAD_INT_STOPPED);
 
   switch (opcode)
     {
index efa269cbe238b0374995d7063535a4a18c36ea6c..d39f2e5b015c4df08c5bde09922682ae63b95842 100644 (file)
@@ -175,7 +175,7 @@ inf_ptrace_target::attach (const char *args, int from_tty)
 
   /* Don't consider the thread stopped until we've processed its
      initial SIGSTOP stop.  */
-  set_executing (this, thr->ptid, true);
+  set_internal_state (this, thr->ptid, THREAD_INT_RUNNING);
 
   unpusher.release ();
 }
index 098072dfd2aae491ff725800a8bde29808c3fcb8..697bbbacc5a6589cb79f1b53523a6e01f986feed 100644 (file)
@@ -797,7 +797,7 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
 
   struct gdb_exception caught_error;
   ptid_t call_thread_ptid = call_thread->ptid;
-  int was_running = call_thread->state == THREAD_RUNNING;
+  int was_running = call_thread->state () == THREAD_RUNNING;
   *timed_out_p = false;
 
   infcall_debug_printf ("call function at %s in thread %s, was_running = %d",
@@ -928,7 +928,7 @@ run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
      of error out of resume()), then we wouldn't need this.  */
   if (caught_error.reason < 0)
     {
-      if (call_thread->state != THREAD_EXITED)
+      if (call_thread->state () != THREAD_EXITED)
        breakpoint_auto_delete (call_thread->control.stop_bpstat);
     }
 
@@ -1565,7 +1565,7 @@ call_function_by_hand_dummy (struct value *function,
       infcall_debug_printf ("after inferior call, exception (%d): %s",
                            e.reason, e.what ());
     infcall_debug_printf ("after inferior call, thread state is: %s",
-                         thread_state_string (call_thread->state));
+                         thread_state_string (call_thread->state ()));
 
     gdb::observers::inferior_call_post.notify (call_thread_ptid, funaddr);
 
@@ -1576,7 +1576,7 @@ call_function_by_hand_dummy (struct value *function,
        threads appear after GDB has reported a stop.  */
     update_thread_list ();
 
-    if (call_thread->state != THREAD_EXITED)
+    if (call_thread->state () != THREAD_EXITED)
       {
        /* The FSM should still be the same.  */
        gdb_assert (call_thread->thread_fsm () == sm);
index e9b58ce55210499c77a4b5835d9830698c4b3a44..6c07e07619ce314cd44f94852e9f56ce1f1c4460 100644 (file)
@@ -537,12 +537,12 @@ proceed_thread_callback (struct thread_info *thread)
      into a single target `resume_all' request, because some threads
      may be stopped in internal breakpoints/events, or stopped waiting
      for its turn in the displaced stepping queue (that is, they are
-     running && !executing).  The target side has no idea about why
-     the thread is stopped, so a `resume_all' command would resume too
-     much.  If/when GDB gains a way to tell the target `hold this
-     thread stopped until I say otherwise', then we can optimize
-     this.  */
-  if (thread->state != THREAD_STOPPED)
+     running from the user's perspective but internally stopped).  The
+     target side has no idea about why the thread is stopped, so a
+     `resume_all' command would resume too much.  If/when GDB gains a
+     way to tell the target `hold this thread stopped until I say
+     otherwise', then we can optimize this.  */
+  if (thread->state () != THREAD_STOPPED)
     return false;
 
   if (!thread->inf->has_execution ())
@@ -558,7 +558,7 @@ static void
 ensure_valid_thread (void)
 {
   if (inferior_ptid == null_ptid
-      || inferior_thread ()->state == THREAD_EXITED)
+      || inferior_thread ()->state () == THREAD_EXITED)
     error (_("Cannot execute this command without a live selected thread."));
 }
 
@@ -587,7 +587,7 @@ error_is_running (void)
 static void
 ensure_not_running (void)
 {
-  if (inferior_thread ()->state == THREAD_RUNNING)
+  if (inferior_thread ()->state () == THREAD_RUNNING)
     error_is_running ();
 }
 
@@ -945,7 +945,8 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
 
              /* Pretend that we've ran.  */
              resume_ptid = user_visible_resume_ptid (1);
-             set_running (tp->inf->process_target (), resume_ptid, true);
+             set_state (tp->inf->process_target (), resume_ptid,
+                        THREAD_RUNNING);
 
              step_into_inline_frame (tp);
 
@@ -1921,12 +1922,12 @@ info_program_command (const char *args, int from_tty)
                  print_thread_id (tp),
                  target_pid_to_str (tp->ptid).c_str ());
 
-      if (tp->state == THREAD_EXITED)
+      if (tp->state () == THREAD_EXITED)
        {
          gdb_printf (_("Selected thread has exited.\n"));
          return;
        }
-      else if (tp->state == THREAD_RUNNING)
+      else if (tp->state () == THREAD_RUNNING)
        {
          gdb_printf (_("Selected thread is running.\n"));
          return;
@@ -1948,13 +1949,13 @@ info_program_command (const char *args, int from_tty)
                  print_thread_id (tp),
                  target_pid_to_str (tp->ptid).c_str ());
 
-      if (tp->state == THREAD_EXITED)
+      if (tp->state () == THREAD_EXITED)
        {
          gdb_printf (_("Thread has since exited.\n"));
          return;
        }
 
-      if (tp->state == THREAD_RUNNING)
+      if (tp->state () == THREAD_RUNNING)
        {
          gdb_printf (_("Thread is now running.\n"));
          return;
@@ -2473,7 +2474,7 @@ proceed_after_attach (inferior *inf)
   scoped_restore_current_thread restore_thread;
 
   for (thread_info *thread : inf->non_exited_threads ())
-    if (!thread->executing ()
+    if (thread->internal_state () != THREAD_INT_RUNNING
        && !thread->stop_requested
        && thread->stop_signal () == GDB_SIGNAL_0)
       {
@@ -2628,6 +2629,10 @@ attach_command (const char *args, int from_tty)
      this function should probably be moved into target_pre_inferior.  */
   target_pre_inferior ();
 
+  /* Set up execution context to know that we should return from
+     wait_for_inferior as soon as the target reports a stop.  */
+  init_wait_for_inferior ();
+
   gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
   args = stripped.get ();
 
@@ -2670,10 +2675,6 @@ attach_command (const char *args, int from_tty)
        finished.  */
   target_terminal::inferior ();
 
-  /* Set up execution context to know that we should return from
-     wait_for_inferior as soon as the target reports a stop.  */
-  init_wait_for_inferior ();
-
   inferior->needs_setup = true;
 
   if (target_is_non_stop_p ())
@@ -2753,7 +2754,7 @@ notice_new_inferior (thread_info *thr, bool leave_running, int from_tty)
   /* When we "notice" a new inferior we need to do all the things we
      would normally do if we had just attached to it.  */
 
-  if (thr->executing ())
+  if (thr->internal_state () == THREAD_INT_RUNNING)
     {
       struct inferior *inferior = current_inferior ();
 
index 54f5229b420fad16f26a95132b471b644d2bcd33..301a78f9ebbb65ae8605c7a18be84fb39ba3d39b 100644 (file)
@@ -201,8 +201,8 @@ extern void child_interrupt (struct target_ops *self);
 /* From fork-child.c */
 
 /* Helper function to call STARTUP_INFERIOR with PID and NUM_TRAPS.
-   This function already calls set_executing.  Return the ptid_t from
-   STARTUP_INFERIOR.  */
+   This function already sets the threads' internal state to
+   THREAD_STOPPED.  Return the ptid_t from STARTUP_INFERIOR.  */
 extern ptid_t gdb_startup_inferior (pid_t pid, int num_traps);
 
 /* From infcmd.c */
index f5ae6cd982fec6d4612ce5d9a66860d39b9bc79d..aef3c8c708191a40cb9d962e1a80c1a86d89144d 100644 (file)
@@ -525,7 +525,7 @@ child_interrupt (struct target_ops *self)
   thread_info *resumed = NULL;
   for (thread_info *thr : all_non_exited_threads ())
     {
-      if (thr->executing ())
+      if (thr->internal_state () == THREAD_INT_RUNNING)
        {
          resumed = thr;
          break;
index 70a799a8269aa68219cc066257943de2dd2791df..52e526361e43abd7f85d17ec355a7c132b199761 100644 (file)
@@ -990,14 +990,14 @@ follow_inferior_reset_breakpoints (void)
   insert_breakpoints ();
 }
 
-/* The child has exited or execed: resume THREAD, a thread of the parent,
-   if it was meant to be executing.  */
+/* The child has exited or execed: resume THREAD, a thread of the
+   parent, if it was meant to be running.  */
 
 static void
 proceed_after_vfork_done (thread_info *thread)
 {
-  if (thread->state == THREAD_RUNNING
-      && !thread->executing ()
+  if (thread->state () == THREAD_RUNNING
+      && thread->internal_state () != THREAD_INT_RUNNING
       && !thread->stop_requested
       && thread->stop_signal () == GDB_SIGNAL_0)
     {
@@ -2226,15 +2226,14 @@ start_step_over (void)
        }
 
       if (tp->control.trap_expected
-         || tp->resumed ()
-         || tp->executing ())
+         || tp->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS
+         || tp->internal_state () == THREAD_INT_RUNNING)
        {
          internal_error ("[%s] has inconsistent state: "
-                         "trap_expected=%d, resumed=%d, executing=%d\n",
+                         "trap_expected=%d, internal_state=%s\n",
                          tp->ptid.to_string ().c_str (),
                          tp->control.trap_expected,
-                         tp->resumed (),
-                         tp->executing ());
+                         thread_int_state_string (tp->internal_state ()));
        }
 
       infrun_debug_printf ("resuming [%s] for step-over",
@@ -2258,7 +2257,7 @@ start_step_over (void)
 
       /* If the thread's step over could not be initiated because no buffers
         were available, it was re-added to the global step over chain.  */
-      if (tp->resumed  ())
+      if (tp->internal_state () != THREAD_INT_STOPPED)
        {
          infrun_debug_printf ("[%s] was resumed.",
                               tp->ptid.to_string ().c_str ());
@@ -2658,7 +2657,7 @@ resume_1 (enum gdb_signal sig)
         tp->control.currently_stepping);
 
       tp->inf->process_target ()->threads_executing = true;
-      tp->set_resumed (true);
+      tp->set_internal_state (THREAD_INT_RESUMED_PENDING_STATUS);
 
       /* FIXME: What should we do if we are supposed to resume this
         thread with a signal?  Maybe we should maintain a queue of
@@ -2783,7 +2782,6 @@ resume_1 (enum gdb_signal sig)
 
              resume_ptid = internal_resume_ptid (user_step);
              do_target_resume (resume_ptid, false, GDB_SIGNAL_0);
-             tp->set_resumed (true);
              return;
            }
        }
@@ -2975,7 +2973,6 @@ resume_1 (enum gdb_signal sig)
     }
 
   do_target_resume (resume_ptid, step, sig);
-  tp->set_resumed (true);
 }
 
 /* Resume the inferior.  SIG is the signal to give the inferior
@@ -3039,6 +3036,7 @@ static void
 clear_proceed_status_thread (struct thread_info *tp)
 {
   infrun_debug_printf ("%s", tp->ptid.to_string ().c_str ());
+  gdb_assert (tp->internal_state () != THREAD_INT_RUNNING);
 
   /* If we're starting a new sequence, then the previous finished
      single-step is no longer relevant.  */
@@ -3050,6 +3048,7 @@ clear_proceed_status_thread (struct thread_info *tp)
                               "Discarding.",
                               tp->ptid.to_string ().c_str ());
 
+         tp->set_internal_state (THREAD_INT_STOPPED);
          tp->clear_pending_waitstatus ();
          tp->set_stop_reason (TARGET_STOPPED_BY_NO_REASON);
        }
@@ -3124,7 +3123,8 @@ clear_proceed_status (int step)
       /* In all-stop mode, delete the per-thread status of all threads
         we're about to resume, implicitly and explicitly.  */
       for (thread_info *tp : all_non_exited_threads (resume_target, resume_ptid))
-       clear_proceed_status_thread (tp);
+       if (tp->internal_state () != THREAD_INT_RUNNING)
+         clear_proceed_status_thread (tp);
     }
 
   if (inferior_ptid != null_ptid)
@@ -3484,6 +3484,8 @@ check_multi_target_resumption (process_stratum_target *resume_target)
 static void
 proceed_resume_thread_checked (thread_info *tp)
 {
+  gdb_assert (tp->internal_state () != THREAD_INT_EXITED);
+
   if (!tp->inf->has_execution ())
     {
       infrun_debug_printf ("[%s] target has no execution",
@@ -3491,11 +3493,10 @@ proceed_resume_thread_checked (thread_info *tp)
       return;
     }
 
-  if (tp->resumed ())
+  if (tp->internal_state () != THREAD_INT_STOPPED)
     {
       infrun_debug_printf ("[%s] resumed",
                           tp->ptid.to_string ().c_str ());
-      gdb_assert (tp->executing () || tp->has_pending_waitstatus ());
       return;
     }
 
@@ -3671,7 +3672,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
      inferior function, as in that case we pretend the inferior
      doesn't run at all.  */
   if (!cur_thr->control.in_infcall)
-    set_running (resume_target, resume_ptid, true);
+    set_state (resume_target, resume_ptid, THREAD_RUNNING);
 
   infrun_debug_printf ("addr=%s, signal=%s, resume_ptid=%s",
                       paddress (gdbarch, addr),
@@ -3872,9 +3873,9 @@ infrun_thread_stop_requested (ptid_t ptid)
      for reporting the stop now.  */
   for (thread_info *tp : all_threads (curr_target, ptid))
     {
-      if (tp->state != THREAD_RUNNING)
+      if (tp->state () != THREAD_RUNNING)
        continue;
-      if (tp->executing ())
+      if (tp->internal_state () == THREAD_INT_RUNNING)
        continue;
 
       /* Remove matching threads from the step-over queue, so
@@ -3905,10 +3906,10 @@ infrun_thread_stop_requested (ptid_t ptid)
       if (step_over_info_valid_p ())
        continue;
 
-      /* Otherwise we can process the (new) pending event now.  Set
-        it so this pending event is considered by
+      /* Otherwise we can process the (new) pending event now.  Switch
+        state so this pending event is considered by
         do_target_wait.  */
-      tp->set_resumed (true);
+      tp->set_internal_state (THREAD_INT_RESUMED_PENDING_STATUS);
     }
 }
 
@@ -4014,7 +4015,7 @@ random_pending_event_thread (inferior *inf, ptid_t waiton_ptid)
     }
 
   infrun_debug_printf ("Found %s.", thread->ptid.to_string ().c_str ());
-  gdb_assert (thread->resumed ());
+  gdb_assert (thread->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS);
   gdb_assert (thread->has_pending_waitstatus ());
 
   return thread;
@@ -4127,6 +4128,7 @@ do_target_wait_1 (inferior *inf, ptid_t ptid,
 
       tp->set_stop_reason (TARGET_STOPPED_BY_NO_REASON);
       *status = tp->pending_waitstatus ();
+      tp->set_internal_state (THREAD_INT_STOPPED);
       tp->clear_pending_waitstatus ();
 
       /* Wake up the event loop again, until all pending events are
@@ -4325,7 +4327,7 @@ prepare_for_detach (void)
        {
          if (thr->displaced_step_state.in_progress ())
            {
-             if (thr->executing ())
+             if (thr->internal_state () == THREAD_INT_RUNNING)
                {
                  if (!thr->stop_requested)
                    {
@@ -4333,8 +4335,6 @@ prepare_for_detach (void)
                      thr->stop_requested = true;
                    }
                }
-             else
-               thr->set_resumed (false);
            }
        }
 
@@ -4473,7 +4473,7 @@ clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs)
 
       for (thread_info *thr : all_threads_safe ())
        {
-         if (thr->state == THREAD_EXITED)
+         if (thr->state () == THREAD_EXITED)
            continue;
 
          if (thr == ecs->event_thread)
@@ -4809,7 +4809,7 @@ fetch_inferior_event ()
   if (cmd_done
       && exec_done_display_p
       && (inferior_ptid == null_ptid
-         || inferior_thread ()->state != THREAD_RUNNING))
+         || inferior_thread ()->state () != THREAD_RUNNING))
     gdb_printf (_("completed.\n"));
 }
 
@@ -5372,14 +5372,14 @@ save_waitstatus (struct thread_info *tp, const target_waitstatus &ws)
     }
 }
 
-/* Mark the non-executing threads accordingly.  In all-stop, all
+/* Mark the internally stopped threads accordingly.  In all-stop, all
    threads of all processes are stopped when we get any event
    reported.  In non-stop mode, only the event thread stops.  */
 
 static void
-mark_non_executing_threads (process_stratum_target *target,
-                           ptid_t event_ptid,
-                           const target_waitstatus &ws)
+mark_internally_stopped_threads (process_stratum_target *target,
+                                ptid_t event_ptid,
+                                const target_waitstatus &ws)
 {
   ptid_t mark_ptid;
 
@@ -5399,18 +5399,15 @@ mark_non_executing_threads (process_stratum_target *target,
         target_mourn_inferior, by associating the same
         inferior/thread to another fork.  We haven't mourned yet at
         this point, but we must mark any threads left in the
-        process as not-executing so that finish_thread_state marks
-        them stopped (in the user's perspective) if/when we present
+        process as internally stopped so that finish_thread_state marks
+        them stopped in the user's perspective if/when we present
         the stop to the user.  */
       mark_ptid = ptid_t (event_ptid.pid ());
     }
   else
     mark_ptid = event_ptid;
 
-  set_executing (target, mark_ptid, false);
-
-  /* Likewise the resumed flag.  */
-  set_resumed (target, mark_ptid, false);
+  set_internal_state (target, mark_ptid, THREAD_INT_STOPPED);
 }
 
 /* Handle one event after stopping threads.  If the eventing thread
@@ -5476,11 +5473,11 @@ handle_one (const wait_one_event &event)
 
       if (t != nullptr)
        {
-         /* Set the threads as non-executing to avoid
-            another stop attempt on them.  */
+         /* Set the threads as internally stopped to avoid another
+            stop attempt on them.  */
          switch_to_thread_no_regs (t);
-         mark_non_executing_threads (event.target, event.ptid,
-                                     event.ws);
+         mark_internally_stopped_threads (event.target, event.ptid,
+                                          event.ws);
          save_waitstatus (t, event.ws);
          t->stop_requested = false;
 
@@ -5502,8 +5499,7 @@ handle_one (const wait_one_event &event)
        t = add_thread (event.target, event.ptid);
 
       t->stop_requested = false;
-      t->set_executing (false);
-      t->set_resumed (false);
+      t->set_internal_state (THREAD_INT_STOPPED);
       t->control.may_range_step = 0;
 
       /* This may be the first time we see the inferior report
@@ -5732,7 +5728,7 @@ stop_all_threads (const char *reason, inferior *inf)
              if (!target_is_non_stop_p ())
                continue;
 
-             if (t->executing ())
+             if (t->internal_state () == THREAD_INT_RUNNING)
                {
                  /* If already stopping, don't request a stop again.
                     We just haven't seen the notification yet.  */
@@ -5759,7 +5755,7 @@ stop_all_threads (const char *reason, inferior *inf)
 
                  /* The thread may be not executing, but still be
                     resumed with a pending status to process.  */
-                 t->set_resumed (false);
+                 t->set_internal_state (THREAD_INT_STOPPED);
                }
            }
 
@@ -5875,7 +5871,7 @@ handle_no_resumed (struct execution_control_state *ecs)
 
   for (thread_info *thread : all_non_exited_threads ())
     {
-      if (swap_terminal && thread->executing ())
+      if (swap_terminal && thread->internal_state () == THREAD_INT_RUNNING)
        {
          if (thread->inf != curr_inf)
            {
@@ -5887,7 +5883,7 @@ handle_no_resumed (struct execution_control_state *ecs)
          swap_terminal = false;
        }
 
-      if (!ignore_event && thread->resumed ())
+      if (!ignore_event && thread->internal_state () != THREAD_INT_STOPPED)
        {
          /* Either there were no unwaited-for children left in the
             target at some point, but there are now, or some target
@@ -6159,7 +6155,7 @@ handle_inferior_event (struct execution_control_state *ecs)
        }
     }
 
-  mark_non_executing_threads (ecs->target, ecs->ptid, ecs->ws);
+  mark_internally_stopped_threads (ecs->target, ecs->ptid, ecs->ws);
 
   switch (ecs->ws.kind ())
     {
@@ -6423,7 +6419,7 @@ handle_inferior_event (struct execution_control_state *ecs)
          /* If not resuming the parent, mark it stopped.  */
          if (ecs->ws.kind () != TARGET_WAITKIND_THREAD_CLONED
              && follow_child && !detach_fork && !non_stop && !sched_multi)
-           parent->set_running (false);
+           parent->set_state (THREAD_STOPPED);
 
          /* If resuming the child, mark it running.  */
          if ((ecs->ws.kind () == TARGET_WAITKIND_THREAD_CLONED
@@ -6431,7 +6427,7 @@ handle_inferior_event (struct execution_control_state *ecs)
              || (ecs->ws.kind () != TARGET_WAITKIND_THREAD_CLONED
                  && (follow_child
                      || (!detach_fork && (non_stop || sched_multi)))))
-           child->set_running (true);
+           child->set_state (THREAD_RUNNING);
 
          /* In non-stop mode, also resume the other branch.  */
          if ((ecs->ws.kind () == TARGET_WAITKIND_THREAD_CLONED
@@ -6623,18 +6619,17 @@ restart_threads (struct thread_info *event_thread, inferior *inf)
          continue;
        }
 
-      if (!(tp->state == THREAD_RUNNING || tp->control.in_infcall))
+      if (!(tp->state () == THREAD_RUNNING || tp->control.in_infcall))
        {
          infrun_debug_printf ("restart threads: [%s] not meant to be running",
                               tp->ptid.to_string ().c_str ());
          continue;
        }
 
-      if (tp->resumed ())
+      if (tp->internal_state () != THREAD_INT_STOPPED)
        {
-         infrun_debug_printf ("restart threads: [%s] resumed",
+         infrun_debug_printf ("restart threads: [%s] already resumed",
                              tp->ptid.to_string ().c_str ());
-         gdb_assert (tp->executing () || tp->has_pending_waitstatus ());
          continue;
        }
 
@@ -6642,7 +6637,6 @@ restart_threads (struct thread_info *event_thread, inferior *inf)
        {
          infrun_debug_printf ("restart threads: [%s] needs step-over",
                               tp->ptid.to_string ().c_str ());
-         gdb_assert (!tp->resumed ());
          continue;
        }
 
@@ -6651,7 +6645,7 @@ restart_threads (struct thread_info *event_thread, inferior *inf)
        {
          infrun_debug_printf ("restart threads: [%s] has pending status",
                               tp->ptid.to_string ().c_str ());
-         tp->set_resumed (true);
+         tp->set_internal_state (THREAD_INT_RESUMED_PENDING_STATUS);
          continue;
        }
 
@@ -6690,7 +6684,7 @@ restart_threads (struct thread_info *event_thread, inferior *inf)
 static bool
 resumed_thread_with_pending_status (struct thread_info *tp)
 {
-  return tp->resumed () && tp->has_pending_waitstatus ();
+  return tp->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS;
 }
 
 /* Called when we get an event that may finish an in-line or
@@ -6779,12 +6773,12 @@ finish_step_over (struct execution_control_state *ecs)
 
          /* Record the event thread's event for later.  */
          save_waitstatus (tp, ecs->ws);
-         /* This was cleared early, by handle_inferior_event.  Set it
+         /* The internal state was reset to stopped early, by
+            handle_inferior_event.  Switch to resumed-pending-status
             so this pending event is considered by
             do_target_wait.  */
-         tp->set_resumed (true);
-
-         gdb_assert (!tp->executing ());
+         gdb_assert (tp->internal_state () == THREAD_INT_STOPPED);
+         tp->set_internal_state (THREAD_INT_RESUMED_PENDING_STATUS);
 
          regcache = get_thread_regcache (tp);
          tp->set_stop_pc (regcache_read_pc (regcache));
@@ -8436,7 +8430,7 @@ restart_stepped_thread (process_stratum_target *resume_target,
 
   for (thread_info *tp : all_threads_safe ())
     {
-      if (tp->state == THREAD_EXITED)
+      if (tp->state () == THREAD_EXITED)
        continue;
 
       if (tp->has_pending_waitstatus ())
@@ -8460,7 +8454,7 @@ restart_stepped_thread (process_stratum_target *resume_target,
 
   for (thread_info *tp : all_threads_safe ())
     {
-      if (tp->state == THREAD_EXITED)
+      if (tp->state () == THREAD_EXITED)
        continue;
 
       if (tp->has_pending_waitstatus ())
@@ -8495,26 +8489,27 @@ restart_after_all_stop_detach (process_stratum_target *proc_target)
      current inferior may no longer have a process_stratum target
      pushed, as we just detached.  */
 
-  /* See if we have a THREAD_RUNNING thread that need to be
-     re-resumed.  If we have any thread that is already executing,
-     then we don't need to resume the target -- it is already been
-     resumed.  With the remote target (in all-stop), it's even
-     impossible to issue another resumption if the target is already
-     resumed, until the target reports a stop.  */
+  /* See if we have a thread that is running from the user's
+     perspective that need to be re-resumed.  If we have any thread
+     that is already executing, then we don't need to resume the
+     target -- it is already been resumed.  With the remote target (in
+     all-stop), it's even impossible to issue another resumption if
+     the target is already resumed, until the target reports a
+     stop.  */
   for (thread_info *thr : all_threads (proc_target))
     {
-      if (thr->state != THREAD_RUNNING)
+      if (thr->state () != THREAD_RUNNING)
        continue;
 
       /* If we have any thread that is already executing, then we
         don't need to resume the target -- it is already been
         resumed.  */
-      if (thr->executing ())
+      if (thr->internal_state () == THREAD_INT_RUNNING)
        return;
 
-      /* If we have a pending event to process, skip resuming the
+      /* If we have a pending status to process, skip resuming the
         target and go straight to processing it.  */
-      if (thr->resumed () && thr->has_pending_waitstatus ())
+      if (thr->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS)
        return;
     }
 
@@ -8527,7 +8522,7 @@ restart_after_all_stop_detach (process_stratum_target *proc_target)
      it.  */
   for (thread_info *thr : all_threads (proc_target))
     {
-      if (thr->state != THREAD_RUNNING)
+      if (thr->state () != THREAD_RUNNING)
        continue;
 
       execution_control_state ecs (thr);
@@ -8564,7 +8559,7 @@ keep_going_stepped_thread (struct thread_info *tp)
        stepping thread is still alive.  For that reason, we need to
        synchronously query the target now.  */
 
-  if (tp->state == THREAD_EXITED || !target_thread_alive (tp->ptid))
+  if (tp->state () == THREAD_EXITED || !target_thread_alive (tp->ptid))
     {
       infrun_debug_printf ("not resuming previously stepped thread, it has "
                           "vanished");
@@ -8617,7 +8612,6 @@ keep_going_stepped_thread (struct thread_info *tp)
                                     get_frame_address_space (frame),
                                     tp->stop_pc ());
 
-      tp->set_resumed (true);
       resume_ptid = internal_resume_ptid (tp->control.stepping_command);
       do_target_resume (resume_ptid, false, GDB_SIGNAL_0);
     }
@@ -9026,7 +9020,7 @@ static void
 keep_going_pass_signal (struct execution_control_state *ecs)
 {
   gdb_assert (ecs->event_thread->ptid == inferior_ptid);
-  gdb_assert (!ecs->event_thread->resumed ());
+  gdb_assert (ecs->event_thread->internal_state () == THREAD_INT_STOPPED);
 
   /* Save the pc before execution, to compare with pc after stop.  */
   ecs->event_thread->prev_pc
@@ -9494,7 +9488,7 @@ stop_context::changed () const
     return true;
   if (inf_num != current_inferior ()->num)
     return true;
-  if (thread != nullptr && thread->state != THREAD_STOPPED)
+  if (thread != nullptr && thread->state () != THREAD_STOPPED)
     return true;
   if (get_stop_id () != stop_id)
     return true;
index b9b64aca45a695a5cbdc9d1edbcbf314e937150a..b09e7c1df8a561330934df13d851b02d037768f2 100644 (file)
@@ -66,12 +66,11 @@ infrun_debug_show_threads (const char *title, ThreadRange threads)
 
       infrun_debug_printf ("%s:", title);
       for (thread_info *thread : threads)
-       infrun_debug_printf ("  thread %s, executing = %d, resumed = %d, "
+       infrun_debug_printf ("  thread %s, internal_state = %s, "
                             "state = %s",
                             thread->ptid.to_string ().c_str (),
-                            thread->executing (),
-                            thread->resumed (),
-                            thread_state_string (thread->state));
+                            thread_int_state_string (thread->internal_state ()),
+                            thread_state_string (thread->state ()));
     }
 }
 
index 338ba032a0e75862d449b9c02c3c61cfc5492dbe..377c68ae6b97db03cfb05dad89a0f0a17930e663 100644 (file)
@@ -363,8 +363,7 @@ fork_load_infrun_state (struct fork_info *fp)
 
   inferior_thread ()->set_stop_pc
     (regcache_read_pc (get_thread_regcache (inferior_thread ())));
-  inferior_thread ()->set_executing (false);
-  inferior_thread ()->set_resumed (false);
+  inferior_thread ()->set_internal_state (THREAD_INT_STOPPED);
   nullify_last_target_wait_ptid ();
 
   /* Now restore the file positions of open file descriptors.  */
@@ -726,7 +725,7 @@ delete_checkpoint_command (const char *args, int from_tty)
      ptid.  */
   thread_info *parent = linux_target->find_thread (pptid);
   if ((parent == NULL && find_fork_ptid (pptid).first != nullptr)
-      || (parent != NULL && parent->state == THREAD_STOPPED))
+      || (parent != NULL && parent->state () == THREAD_STOPPED))
     {
       if (inferior_call_waitpid (pptid, ptid.pid ()))
        warning (_("Unable to wait pid %s"),
@@ -866,7 +865,7 @@ print_checkpoints (struct ui_out *uiout, inferior *req_inf, fork_info *req_fi)
          uiout->field_string
            ("target-id", target_pid_to_str (proc_ptid (fi.ptid)).c_str ());
 
-         if (t->state == THREAD_RUNNING && is_current)
+         if (t->state () == THREAD_RUNNING && is_current)
            uiout->text ("(running)");
          else
            {
@@ -1108,7 +1107,7 @@ restart_command (const char *args, int from_tty)
   /* Don't allow switching from a thread/fork that's running.  */
   inferior *curinf = current_inferior ();
   if (curinf->pid != 0
-      && any_thread_of_inferior (curinf)->state == THREAD_RUNNING)
+      && any_thread_of_inferior (curinf)->state () == THREAD_RUNNING)
     error (_("Cannot execute this command while "
             "the selected thread is running."));
 
index 2f98060506bb7afb3e92bc4e4ce533a7db939c91..4de4cc83cfa14e3296864ecd793f303511dad9dc 100644 (file)
@@ -1246,8 +1246,8 @@ linux_nat_target::attach (const char *args, int from_tty)
                       if (lwp->ptid.pid () != lwp->ptid.lwp ())
                         {
                           add_thread (linux_target, lwp->ptid);
-                          set_running (linux_target, lwp->ptid, true);
-                          set_executing (linux_target, lwp->ptid, true);
+                          set_state (linux_target, lwp->ptid, THREAD_RUNNING);
+                          set_internal_state (linux_target, lwp->ptid, THREAD_INT_RUNNING);
                         }
                       return 0;
                     });
@@ -1331,7 +1331,8 @@ get_detach_signal (struct lwp_info *lp)
     {
       thread_info *tp = linux_target->find_thread (lp->ptid);
 
-      if (target_is_non_stop_p () && !tp->executing ())
+      if (target_is_non_stop_p ()
+         && tp->internal_state () != THREAD_INT_RUNNING)
        {
          if (tp->has_pending_waitstatus ())
            {
index f60116afb2cebb81d9021bfb97b7fdf85ac02ced..7f8f9eeaa533bf615c4060cd24cabcc8fb7eac8c 100644 (file)
@@ -1361,7 +1361,7 @@ record_thread (struct thread_db_info *info,
   /* Add the thread to GDB's thread list.  If we already know about a
      thread with this PTID, but it's marked exited, then the kernel
      reused the tid of an old thread.  */
-  if (tp == NULL || tp->state == THREAD_EXITED)
+  if (tp == NULL || tp->state () == THREAD_EXITED)
     tp = add_thread_with_info (info->process_target, ptid,
                               private_thread_info_up (priv));
   else
@@ -1625,7 +1625,7 @@ thread_db_target::update_thread_list ()
        continue;
 
       thread_info *thread = any_live_thread_of_inferior (inf);
-      if (thread == NULL || thread->executing ())
+      if (thread == NULL || thread->internal_state () == THREAD_INT_RUNNING)
        continue;
 
       /* It's best to avoid td_ta_thr_iter if possible.  That walks
index 9cbb85722b3d81d4c1096f1245d988c4f7818405..79c8b9979e22299d0aefc362d16db52f2a82e403 100644 (file)
@@ -608,14 +608,14 @@ mi_cmd_var_update_iter (struct varobj *var, bool only_floating,
   if (thread_id == -1)
     {
       thread_stopped = (inferior_ptid == null_ptid
-                       || inferior_thread ()->state == THREAD_STOPPED);
+                       || inferior_thread ()->state () == THREAD_STOPPED);
     }
   else
     {
       thread_info *tp = find_thread_global_id (thread_id);
 
       thread_stopped = (tp == NULL
-                       || tp->state == THREAD_STOPPED);
+                       || tp->state () == THREAD_STOPPED);
     }
 
   if (thread_stopped
index 1c905347007e5cd93d7bcae5462a05ec6adaaf18..de8173676b16b15eec9adfd0568fff3ecd8d3da5 100644 (file)
@@ -868,7 +868,7 @@ mi_interp::on_user_selected_context_changed (user_selected_what selection)
       gdb_printf (this->event_channel, "thread-selected,id=\"%d\"",
                  tp->global_num);
 
-      if (tp->state != THREAD_RUNNING)
+      if (tp->state () != THREAD_RUNNING)
        {
          if (has_stack_frames ())
            print_stack_frame_to_uiout (mi_uiout, get_selected_frame (NULL),
index cda72ca4f5b3ccfedba4c19715fa928a512f52f3..cfb6fcf077216a0d38c8477eb589af17cb0defac 100644 (file)
@@ -239,7 +239,7 @@ mi_cmd_exec_jump (const char *args, const char *const *argv, int argc)
 static void
 proceed_thread (struct thread_info *thread, int pid)
 {
-  if (thread->state != THREAD_STOPPED)
+  if (thread->state () != THREAD_STOPPED)
     return;
 
   if (pid != 0 && thread->ptid.pid () != pid)
@@ -367,7 +367,7 @@ mi_cmd_exec_interrupt (const char *command, const char *const *argv, int argc)
 
       iterate_over_threads ([&] (struct thread_info *thread)
        {
-         if (thread->state != THREAD_RUNNING)
+         if (thread->state () != THREAD_RUNNING)
            return false;
 
          if (thread->ptid.pid () != inf->pid)
@@ -508,7 +508,7 @@ mi_cmd_target_detach (const char *command, const char *const *argv, int argc)
         target_detach detaches from the parent of inferior_ptid.  */
       tp = iterate_over_threads ([&] (struct thread_info *ti)
        {
-         return ti->ptid.pid () == pid && ti->state != THREAD_EXITED;
+         return ti->ptid.pid () == pid && ti->state () != THREAD_EXITED;
        });
       if (!tp)
        error (_("Thread group is empty"));
@@ -2059,7 +2059,7 @@ mi_cmd_execute (struct mi_parse *parse)
       if (tp == NULL)
        error (_("Invalid thread id: %d"), parse->thread);
 
-      if (tp->state == THREAD_EXITED)
+      if (tp->state () == THREAD_EXITED)
        error (_("Thread id: %d has terminated"), parse->thread);
 
       if (parse->cmd->preserve_user_selected_context ())
index 329589dc34b69f57e34cae2fefa109a93173ef77..039dac4c0fe93a088db6130cab5779a07db17eda 100644 (file)
@@ -114,8 +114,9 @@ process_stratum_target::maybe_add_resumed_with_pending_wait_status
 {
   gdb_assert (!thread->resumed_with_pending_wait_status_node.is_linked ());
 
-  if (thread->resumed () && thread->has_pending_waitstatus ())
+  if (thread->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS)
     {
+      gdb_assert (thread->has_pending_waitstatus ());
       infrun_debug_printf ("adding to resumed threads with event list: %s",
                           thread->ptid.to_string ().c_str ());
       m_resumed_with_pending_wait_status.push_back (*thread);
@@ -128,8 +129,9 @@ void
 process_stratum_target::maybe_remove_resumed_with_pending_wait_status
   (thread_info *thread)
 {
-  if (thread->resumed () && thread->has_pending_waitstatus ())
+  if (thread->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS)
     {
+      gdb_assert (thread->has_pending_waitstatus ());
       infrun_debug_printf ("removing from resumed threads with event list: %s",
                           thread->ptid.to_string ().c_str ());
       gdb_assert (thread->resumed_with_pending_wait_status_node.is_linked ());
index 4f1f8d47e32ec6a2a92853056d7026bbdb4e4ca9..0a392616d485c1cedbde6be458282a1eb4122fd9 100644 (file)
@@ -261,7 +261,7 @@ thpy_is_stopped (PyObject *self, PyObject *args)
 
   THPY_REQUIRE_VALID (thread_obj);
 
-  if (thread_obj->thread->state == THREAD_STOPPED)
+  if (thread_obj->thread->state () == THREAD_STOPPED)
     Py_RETURN_TRUE;
 
   Py_RETURN_FALSE;
@@ -277,7 +277,7 @@ thpy_is_running (PyObject *self, PyObject *args)
 
   THPY_REQUIRE_VALID (thread_obj);
 
-  if (thread_obj->thread->state == THREAD_RUNNING)
+  if (thread_obj->thread->state () == THREAD_RUNNING)
     Py_RETURN_TRUE;
 
   Py_RETURN_FALSE;
@@ -293,7 +293,7 @@ thpy_is_exited (PyObject *self, PyObject *args)
 
   THPY_REQUIRE_VALID (thread_obj);
 
-  if (thread_obj->thread->state == THREAD_EXITED)
+  if (thread_obj->thread->state () == THREAD_EXITED)
     Py_RETURN_TRUE;
 
   Py_RETURN_FALSE;
index 5dd3f1e1ddd7064e4d3da592dd40b190f503d9d5..6dbf26a21908c1cc091fefbef16ba8ddca21ad0d 100644 (file)
@@ -2039,18 +2039,18 @@ get_thread_current_frame_id (struct thread_info *tp)
 
   process_stratum_target *proc_target = tp->inf->process_target ();
 
-  /* Clear the executing flag to allow changes to the current frame.
-     We are not actually running, yet.  We just started a reverse execution
-     command or a record goto command.
-     For the latter, EXECUTING is false and this has no effect.
-     For the former, EXECUTING is true and we're in wait, about to
-     move the thread.  Since we need to recompute the stack, we temporarily
-     set EXECUTING to false.  */
-  bool executing = tp->executing ();
-  set_executing (proc_target, inferior_ptid, false);
+  /* Temporarily set the thread to internally stopped to allow changes
+     to the current frame.  We are not actually running, yet.  We just
+     started a reverse execution command or a record goto command.
+     For the latter, the thread is stopped and this has no effect.
+     For the former, the thread is running and we're in wait, about to
+     move the thread.  Since we need to recompute the stack, we
+     temporarily set the thread to internally stopped.  */
+  thread_int_state prev_int_state = tp->internal_state ();
+  set_internal_state (proc_target, inferior_ptid, THREAD_INT_STOPPED);
   SCOPE_EXIT
     {
-      set_executing (proc_target, inferior_ptid, executing);
+      set_internal_state (proc_target, inferior_ptid, prev_int_state);
     };
   return get_frame_id (get_current_frame ());
 }
index b52fb062d80187d399059211ad5708e6dd453061..cf162f451fc4fe1aa546f8166e5706eed377fe79 100644 (file)
@@ -1270,10 +1270,12 @@ record_full_wait_1 (struct target_ops *ops,
                        {
                          /* Try to insert the software single step breakpoint.
                             If insert success, set step to 0.  */
-                         set_executing (proc_target, inferior_ptid, false);
+                         set_internal_state (proc_target, inferior_ptid,
+                                             THREAD_INT_STOPPED);
                          SCOPE_EXIT
                            {
-                             set_executing (proc_target, inferior_ptid, true);
+                             set_internal_state (proc_target, inferior_ptid,
+                                                 THREAD_INT_RUNNING);
                            };
 
                          reinit_frame_cache ();
index e3d435f90d52796c3f500d7fe4fa91394e99231c..cd6e65f9dc9ef41a572d9f60b66840ab0126ba58 100644 (file)
@@ -429,7 +429,7 @@ get_thread_regcache (process_stratum_target *target, ptid_t ptid)
 struct regcache *
 get_thread_regcache (thread_info *thread)
 {
-  gdb_assert (thread->state != THREAD_EXITED);
+  gdb_assert (thread->state () != THREAD_EXITED);
 
   return get_thread_regcache (thread->inf->process_target (),
                              thread->ptid);
index 1c49cdf0fc0a9750c7cf537434857e86e57ddda7..413425ab8e75869a13c946133414708ec79464dc 100644 (file)
@@ -1220,12 +1220,15 @@ public: /* Remote specific methods.  */
   ptid_t select_thread_for_ambiguous_stop_reply
     (const struct target_waitstatus &status);
 
-  void remote_notice_new_inferior (ptid_t currthread, bool executing);
+  void remote_notice_new_inferior (ptid_t currthread,
+                                  thread_int_state internal_state);
 
   void print_one_stopped_thread (thread_info *thread);
   void process_initial_stop_replies (int from_tty);
 
-  thread_info *remote_add_thread (ptid_t ptid, bool running, bool executing,
+  thread_info *remote_add_thread (ptid_t ptid,
+                                 thread_state state,
+                                 thread_int_state internal_state,
                                  bool silent_p);
 
   void btrace_sync_conf (const btrace_config *conf);
@@ -2924,13 +2927,16 @@ static remote_thread_info *get_remote_thread_info (thread_info *thread);
 static remote_thread_info *get_remote_thread_info (remote_target *target,
                                                   ptid_t ptid);
 
-/* Add thread PTID to GDB's thread list.  Tag it as executing/running
-   according to EXECUTING and RUNNING respectively.  If SILENT_P (or the
-   remote_state::starting_up flag) is true then the new thread is added
-   silently, otherwise the new thread will be announced to the user.  */
+/* Add thread PTID to GDB's thread list.  Tag its user and internal
+   states according to STATE and INTERNAL_STATE respectively.  If
+   SILENT_P (or the remote_state::starting_up flag) is true then the
+   new thread is added silently, otherwise the new thread will be
+   announced to the user.  */
 
 thread_info *
-remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing,
+remote_target::remote_add_thread (ptid_t ptid,
+                                 thread_state state,
+                                 thread_int_state internal_state,
                                  bool silent_p)
 {
   struct remote_state *rs = get_remote_state ();
@@ -2947,10 +2953,10 @@ remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing,
   else
     thread = add_thread (this, ptid);
 
-  if (executing)
+  if (internal_state == THREAD_INT_RUNNING)
     get_remote_thread_info (thread)->set_resumed ();
-  set_executing (this, ptid, executing);
-  set_running (this, ptid, running);
+  set_internal_state (this, ptid, internal_state);
+  set_state (this, ptid, state);
 
   return thread;
 }
@@ -2959,26 +2965,29 @@ remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing,
    It may be the first time we hear about such thread, so take the
    opportunity to add it to GDB's thread list.  In case this is the
    first time we're noticing its corresponding inferior, add it to
-   GDB's inferior list as well.  EXECUTING indicates whether the
-   thread is (internally) executing or stopped.  */
+   GDB's inferior list as well.  INTERNAL_STATE indicates whether the
+   thread is internally running or stopped.  */
 
 void
-remote_target::remote_notice_new_inferior (ptid_t currthread, bool executing)
+remote_target::remote_notice_new_inferior (ptid_t currthread,
+                                          thread_int_state internal_state)
 {
   /* In non-stop mode, we assume new found threads are (externally)
      running until proven otherwise with a stop reply.  In all-stop,
      we can only get here if all threads are stopped.  */
-  bool running = target_is_non_stop_p ();
+  thread_state state = (target_is_non_stop_p ()
+                       ? THREAD_RUNNING
+                       : THREAD_STOPPED);
 
   /* If this is a new thread, add it to GDB's thread list.
      If we leave it up to WFI to do this, bad things will happen.  */
 
   thread_info *tp = this->find_thread (currthread);
-  if (tp != NULL && tp->state == THREAD_EXITED)
+  if (tp != NULL && tp->state () == THREAD_EXITED)
     {
       /* We're seeing an event on a thread id we knew had exited.
         This has to be a new thread reusing the old id.  Add it.  */
-      remote_add_thread (currthread, running, executing, false);
+      remote_add_thread (currthread, state, internal_state, false);
       return;
     }
 
@@ -3000,7 +3009,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, bool executing)
          else
            {
              thread_info *thr
-               = remote_add_thread (currthread, running, executing, false);
+               = remote_add_thread (currthread, state, internal_state, false);
              switch_to_thread (thr);
            }
          return;
@@ -3031,7 +3040,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, bool executing)
 
       /* This is really a new thread.  Add it.  */
       thread_info *new_thr
-       = remote_add_thread (currthread, running, executing, false);
+       = remote_add_thread (currthread, state, internal_state, false);
 
       /* If we found a new inferior, let the common code do whatever
         it needs to with it (e.g., read shared libraries, insert
@@ -3042,7 +3051,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, bool executing)
          struct remote_state *rs = get_remote_state ();
 
          if (!rs->starting_up)
-           notice_new_inferior (new_thr, executing, 0);
+           notice_new_inferior (new_thr, internal_state, 0);
        }
     }
 }
@@ -4363,12 +4372,14 @@ remote_target::update_thread_list ()
          if (item.ptid != null_ptid)
            {
              /* In non-stop mode, we assume new found threads are
-                executing until proven otherwise with a stop reply.
-                In all-stop, we can only get here if all threads are
+                running until proven otherwise with a stop reply.  In
+                all-stop, we can only get here if all threads are
                 stopped.  */
-             bool executing = target_is_non_stop_p ();
+             thread_int_state internal_state = (target_is_non_stop_p ()
+                                                ? THREAD_INT_RUNNING
+                                                : THREAD_INT_STOPPED);
 
-             remote_notice_new_inferior (item.ptid, executing);
+             remote_notice_new_inferior (item.ptid, internal_state);
 
              thread_info *tp = this->find_thread (item.ptid);
              remote_thread_info *info = get_remote_thread_info (tp);
@@ -4982,8 +4993,8 @@ remote_target::process_initial_stop_replies (int from_tty)
          || ws.sig () != GDB_SIGNAL_0)
        evthread->set_pending_waitstatus (ws);
 
-      set_executing (this, event_ptid, false);
-      set_running (this, event_ptid, false);
+      set_internal_state (this, event_ptid, THREAD_INT_STOPPED);
+      set_state (this, event_ptid, THREAD_STOPPED);
       get_remote_thread_info (evthread)->set_not_resumed ();
     }
 
@@ -4996,7 +5007,7 @@ remote_target::process_initial_stop_replies (int from_tty)
       if (non_stop)
        {
          thread_info *thread = any_live_thread_of_inferior (inf);
-         notice_new_inferior (thread, thread->state == THREAD_RUNNING,
+         notice_new_inferior (thread, thread->state () == THREAD_RUNNING,
                               from_tty);
        }
     }
@@ -5038,8 +5049,8 @@ remote_target::process_initial_stop_replies (int from_tty)
        first = thread;
 
       if (!non_stop)
-       thread->set_running (false);
-      else if (thread->state != THREAD_STOPPED)
+       thread->set_state (THREAD_STOPPED);
+      else if (thread->state () != THREAD_STOPPED)
        continue;
 
       if (selected == nullptr && thread->has_pending_waitstatus ())
@@ -6585,7 +6596,7 @@ remote_target::follow_fork (inferior *child_inf, ptid_t child_ptid,
 void
 remote_target::follow_clone (ptid_t child_ptid)
 {
-  remote_add_thread (child_ptid, false, false, false);
+  remote_add_thread (child_ptid, THREAD_STOPPED, THREAD_INT_STOPPED, false);
 }
 
 /* Target follow-exec function for remote targets.  Save EXECD_PATHNAME
@@ -6693,7 +6704,8 @@ extended_remote_target::attach (const char *args, int from_tty)
 
       /* Add the main thread to the thread list.  We add the thread
         silently in this case (the final true parameter).  */
-      thread_info *thr = remote_add_thread (curr_ptid, true, true, true);
+      thread_info *thr = remote_add_thread (curr_ptid, THREAD_RUNNING,
+                                           THREAD_INT_RUNNING, true);
 
       switch_to_thread (thr);
     }
@@ -8571,7 +8583,7 @@ remote_target::process_stop_reply (stop_reply_up stop_reply,
       && status->kind () != TARGET_WAITKIND_SIGNALLED
       && status->kind () != TARGET_WAITKIND_NO_RESUMED)
     {
-      remote_notice_new_inferior (ptid, false);
+      remote_notice_new_inferior (ptid, THREAD_INT_STOPPED);
 
       /* Expedited registers.  */
       if (!stop_reply->regcache.empty ())
@@ -8677,7 +8689,7 @@ static ptid_t
 first_remote_resumed_thread (remote_target *target)
 {
   for (thread_info *tp : all_non_exited_threads (target, minus_one_ptid))
-    if (tp->resumed ())
+    if (tp->internal_state () != THREAD_INT_STOPPED)
       return tp->ptid;
   return null_ptid;
 }
index ae1e5c0745736f19328c460282a74eb332ef40fd..3c7f0d3d35367834cf7aaf514dc81723b981dd5d 100644 (file)
@@ -451,7 +451,7 @@ sol_thread_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
       if (rtnval.tid_p ())
        {
          thread_info *thr = current_inferior ()->find_thread (rtnval);
-         if (thr == NULL || thr->state == THREAD_EXITED)
+         if (thr == NULL || thr->state () == THREAD_EXITED)
            {
              process_stratum_target *proc_target
                = current_inferior ()->process_target ();
@@ -997,7 +997,7 @@ sol_update_thread_list_callback (const td_thrhandle_t *th, void *ignored)
 
   ptid_t ptid = ptid_t (current_inferior ()->pid, 0, ti.ti_tid);
   thread_info *thr = current_inferior ()->find_thread (ptid);
-  if (thr == NULL || thr->state == THREAD_EXITED)
+  if (thr == NULL || thr->state () == THREAD_EXITED)
     {
       process_stratum_target *proc_target
        = current_inferior ()->process_target ();
index 522bed8e939cc6bc098b3607b117017ee48540d2..c55c0878c6bd4db60ec5caea7741fec3bc953b30 100644 (file)
@@ -2653,10 +2653,10 @@ target_resume (ptid_t scope_ptid, int step, enum gdb_signal signal)
   current_inferior ()->top_target ()->resume (scope_ptid, step, signal);
 
   registers_changed_ptid (curr_target, scope_ptid);
-  /* We only set the internal executing state here.  The user/frontend
-     running state is set at a higher level.  This also clears the
-     thread's stop_pc as side effect.  */
-  set_executing (curr_target, scope_ptid, true);
+  /* We only set the internal state here.  The user/frontend state is
+     set at a higher level.  This also clears the thread's stop_pc as
+     side effect.  */
+  set_internal_state (curr_target, scope_ptid, THREAD_INT_RUNNING);
   clear_inline_frame_state (curr_target, scope_ptid);
 
   if (target_can_async_p ())
@@ -3805,9 +3805,10 @@ target_pass_ctrlc (void)
 
       for (thread_info *thr : inf->non_exited_threads ())
        {
-         /* A thread can be THREAD_STOPPED and executing, while
-            running an infcall.  */
-         if (thr->state == THREAD_RUNNING || thr->executing ())
+         /* A thread can be externally THREAD_STOPPED and internally
+            THREAD_INT_RUNNING, while running an infcall.  */
+         if (thr->state () == THREAD_RUNNING
+             || thr->internal_state () == THREAD_INT_RUNNING)
            {
              /* We can get here quite deep in target layers.  Avoid
                 switching thread context or anything that would
index abd7daff1f8b12d67699d29eeb8f7e3cd530da76..4463aaf37a625a434c2728e7b60379545486cd09 100644 (file)
@@ -151,7 +151,7 @@ struct non_exited_thread_filter
 {
   bool operator() (struct thread_info *thr) const
   {
-    return thr->state != THREAD_EXITED;
+    return thr->state () != THREAD_EXITED;
   }
 };
 
index 0228027fb928160fde98e338a4eb8498722dd539..da45c263c92b9e646111df461423691a01ee8dfa 100644 (file)
@@ -223,23 +223,13 @@ set_thread_exited (thread_info *tp, std::optional<ULONGEST> exit_code,
   if (thread_is_in_step_over_chain (tp))
     global_thread_step_over_chain_remove (tp);
 
-  if (tp->state != THREAD_EXITED)
+  if (tp->state () != THREAD_EXITED)
     {
-      process_stratum_target *proc_target = tp->inf->process_target ();
-
-      /* Some targets unpush themselves from the inferior's target stack before
-        clearing the inferior's thread list (which marks all threads as exited,
-        and therefore leads to this function).  In this case, the inferior's
-        process target will be nullptr when we arrive here.
-
-        See also the comment in inferior::unpush_target.  */
-      if (proc_target != nullptr)
-       proc_target->maybe_remove_resumed_with_pending_wait_status (tp);
-
       notify_thread_exited (tp, exit_code, silent);
 
       /* Tag it as exited.  */
-      tp->state = THREAD_EXITED;
+      tp->set_state (THREAD_EXITED);
+      tp->set_internal_state (THREAD_INT_EXITED);
 
       /* Clear breakpoints, etc. associated with this thread.  */
       clear_thread_inferior_resources (tp);
@@ -373,34 +363,50 @@ thread_info::deletable () const
 /* See gdbthread.h.  */
 
 void
-thread_info::set_executing (bool executing)
-{
-  m_executing = executing;
-  if (executing)
-    this->clear_stop_pc ();
-}
-
-/* See gdbthread.h.  */
-
-void
-thread_info::set_resumed (bool resumed)
+thread_info::set_internal_state (thread_int_state state)
 {
-  if (resumed == m_resumed)
+  if (m_internal_state == state)
     return;
 
-  process_stratum_target *proc_target = this->inf->process_target ();
-
-  /* If we transition from resumed to not resumed, we might need to remove
-     the thread from the resumed threads with pending statuses list.  */
-  if (!resumed)
-    proc_target->maybe_remove_resumed_with_pending_wait_status (this);
+  if (state == THREAD_INT_RUNNING)
+    this->clear_stop_pc ();
 
-  m_resumed = resumed;
+  if (state == THREAD_INT_RESUMED_PENDING_STATUS)
+    gdb_assert (this->has_pending_waitstatus ());
+  else if (state == THREAD_INT_RUNNING)
+    gdb_assert (!this->has_pending_waitstatus ());
 
-  /* If we transition from not resumed to resumed, we might need to add
+  /* If we transition from resumed-pending-status to another state, we
+     might need to remove the thread from the resumed threads with
+     pending statuses list.  Conversely, if we transition to
+     resumed-pending-status from another state, we might need to add
      the thread to the resumed threads with pending statuses list.  */
-  if (resumed)
-    proc_target->maybe_add_resumed_with_pending_wait_status (this);
+  if (state == THREAD_INT_RESUMED_PENDING_STATUS
+      || m_internal_state == THREAD_INT_RESUMED_PENDING_STATUS)
+    {
+      process_stratum_target *proc_target = this->inf->process_target ();
+
+      /* We need the proc_target NULL checks below, because some
+        targets unpush themselves from the inferior's target stack
+        before clearing the inferior's thread list (which marks all
+        threads as exited, and therefore leads to this function).  In
+        this case, the inferior's process target will be nullptr when
+        we arrive here.  See also the comment in
+        inferior::unpush_target.  */
+
+      if (state != THREAD_INT_RESUMED_PENDING_STATUS && proc_target != nullptr)
+       proc_target->maybe_remove_resumed_with_pending_wait_status (this);
+
+      /* Note maybe_remove_resumed_with_pending_wait_status internally
+        reads this state.  Thus it must be updated after the call
+        above, and before the call below.  */
+      m_internal_state = state;
+
+      if (state == THREAD_INT_RESUMED_PENDING_STATUS && proc_target != nullptr)
+       proc_target->maybe_add_resumed_with_pending_wait_status (this);
+    }
+  else
+    m_internal_state = state;
 }
 
 /* See gdbthread.h.  */
@@ -409,12 +415,13 @@ void
 thread_info::set_pending_waitstatus (const target_waitstatus &ws)
 {
   gdb_assert (!this->has_pending_waitstatus ());
+  /* Doesn't make sense to set a pending status on an exited or
+     running thread.  */
+  gdb_assert (this->internal_state () == THREAD_INT_STOPPED
+             || this->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS);
 
   m_suspend.waitstatus = ws;
   m_suspend.waitstatus_pending_p = 1;
-
-  process_stratum_target *proc_target = this->inf->process_target ();
-  proc_target->maybe_add_resumed_with_pending_wait_status (this);
 }
 
 /* See gdbthread.h.  */
@@ -424,9 +431,6 @@ thread_info::clear_pending_waitstatus ()
 {
   gdb_assert (this->has_pending_waitstatus ());
 
-  process_stratum_target *proc_target = this->inf->process_target ();
-  proc_target->maybe_remove_resumed_with_pending_wait_status (this);
-
   m_suspend.waitstatus_pending_p = 0;
 }
 
@@ -435,8 +439,8 @@ thread_info::clear_pending_waitstatus ()
 void
 thread_info::set_thread_options (gdb_thread_options thread_options)
 {
-  gdb_assert (this->state != THREAD_EXITED);
-  gdb_assert (!this->executing ());
+  gdb_assert (this->state () != THREAD_EXITED);
+  gdb_assert (this->internal_state () == THREAD_INT_STOPPED);
 
   if (m_thread_options == thread_options)
     return;
@@ -682,30 +686,30 @@ any_thread_of_inferior (inferior *inf)
 thread_info *
 any_live_thread_of_inferior (inferior *inf)
 {
-  struct thread_info *curr_tp = NULL;
-  struct thread_info *tp_executing = NULL;
+  thread_info *curr_tp = NULL;
+  thread_info *tp_running = NULL;
 
   gdb_assert (inf != NULL && inf->pid != 0);
 
-  /* Prefer the current thread if it's not executing.  */
+  /* Prefer the current thread if it's stopped.  */
   if (inferior_ptid != null_ptid && current_inferior () == inf)
     {
-      /* If the current thread is dead, forget it.  If it's not
-        executing, use it.  Otherwise, still choose it (below), but
-        only if no other non-executing thread is found.  */
+      /* If the current thread is dead, forget it.  If it's stopped,
+        use it.  Otherwise, still choose it (below), but only if no
+        other running thread is found.  */
       curr_tp = inferior_thread ();
-      if (curr_tp->state == THREAD_EXITED)
+      if (curr_tp->internal_state () == THREAD_INT_EXITED)
        curr_tp = NULL;
-      else if (!curr_tp->executing ())
+      else if (curr_tp->internal_state () != THREAD_INT_RUNNING)
        return curr_tp;
     }
 
   for (thread_info *tp : inf->non_exited_threads ())
     {
-      if (!tp->executing ())
+      if (tp->internal_state () != THREAD_INT_RUNNING)
        return tp;
 
-      tp_executing = tp;
+      tp_running = tp;
     }
 
   /* If both the current thread and all live threads are executing,
@@ -713,15 +717,15 @@ any_live_thread_of_inferior (inferior *inf)
   if (curr_tp != NULL)
     return curr_tp;
 
-  /* Otherwise, just return an executing thread, if any.  */
-  return tp_executing;
+  /* Otherwise, just return a running thread, if any.  */
+  return tp_running;
 }
 
 /* Return true if TP is an active thread.  */
 static bool
 thread_alive (thread_info *tp)
 {
-  if (tp->state == THREAD_EXITED)
+  if (tp->state () == THREAD_EXITED)
     return false;
 
   /* Ensure we're looking at the right target stack.  */
@@ -773,7 +777,7 @@ void
 delete_exited_threads (void)
 {
   for (thread_info *tp : all_threads_safe ())
-    if (tp->state == THREAD_EXITED)
+    if (tp->state () == THREAD_EXITED)
       delete_thread (tp);
 }
 
@@ -852,43 +856,6 @@ thread_change_ptid (process_stratum_target *targ,
   gdb::observers::thread_ptid_changed.notify (targ, old_ptid, new_ptid);
 }
 
-/* See gdbthread.h.  */
-
-void
-set_resumed (process_stratum_target *targ, ptid_t ptid, bool resumed)
-{
-  for (thread_info *tp : all_non_exited_threads (targ, ptid))
-    tp->set_resumed (resumed);
-}
-
-/* Helper for set_running, that marks one thread either running or
-   stopped.  */
-
-static bool
-set_running_thread (struct thread_info *tp, bool running)
-{
-  bool started = false;
-
-  if (running && tp->state == THREAD_STOPPED)
-    started = true;
-  tp->state = running ? THREAD_RUNNING : THREAD_STOPPED;
-
-  threads_debug_printf ("thread: %s, running? %d%s",
-                       tp->ptid.to_string ().c_str (), running,
-                       (started ? " (started)" : ""));
-
-  if (!running)
-    {
-      /* If the thread is now marked stopped, remove it from
-        the step-over queue, so that we don't try to resume
-        it until the user wants it to.  */
-      if (thread_is_in_step_over_chain (tp))
-       global_thread_step_over_chain_remove (tp);
-    }
-
-  return started;
-}
-
 /* Notify interpreters and observers that the target was resumed.  */
 
 static void
@@ -905,41 +872,73 @@ notify_target_resumed (ptid_t ptid)
 
 /* See gdbthread.h.  */
 
-void
-thread_info::set_running (bool running)
+thread_state
+thread_info::set_state (thread_state state,
+                       bool suppress_notification)
 {
-  if (set_running_thread (this, running))
-    notify_target_resumed (this->ptid);
+  thread_state prev_state = m_state;
+
+  if (prev_state == state)
+    return prev_state;
+
+  threads_debug_printf ("thread: %s, %s -> %s",
+                       this->ptid.to_string ().c_str (),
+                       thread_state_string (m_state),
+                       thread_state_string (state));
+
+  m_state = state;
+
+  switch (m_state)
+    {
+    case THREAD_EXITED:
+      break;
+
+    case THREAD_STOPPED:
+      /* If the thread is now marked stopped, remove it from
+        the step-over queue, so that we don't try to resume
+        it until the user wants it to.  */
+      if (thread_is_in_step_over_chain (this))
+       global_thread_step_over_chain_remove (this);
+      break;
+
+    case THREAD_RUNNING:
+      if (!suppress_notification)
+       notify_target_resumed (this->ptid);
+      break;
+    }
+
+  return prev_state;
 }
 
 void
-set_running (process_stratum_target *targ, ptid_t ptid, bool running)
+set_state (process_stratum_target *targ, ptid_t ptid, thread_state state)
 {
   /* We try not to notify the observer if no thread has actually
-     changed the running state -- merely to reduce the number of
+     changed its public state -- merely to reduce the number of
      messages to the MI frontend.  A frontend is supposed to handle
      multiple *running notifications just fine.  */
-  bool any_started = false;
+  bool any_changed = false;
 
   for (thread_info *tp : all_non_exited_threads (targ, ptid))
-    if (set_running_thread (tp, running))
-      any_started = true;
+    if (tp->set_state (state, true) != state)
+      any_changed = true;
 
-  if (any_started)
+  if (any_changed && state == THREAD_RUNNING)
     notify_target_resumed (ptid);
 }
 
 void
-set_executing (process_stratum_target *targ, ptid_t ptid, bool executing)
+set_internal_state (process_stratum_target *targ, ptid_t ptid,
+                   thread_int_state state)
 {
   for (thread_info *tp : all_non_exited_threads (targ, ptid))
-    tp->set_executing (executing);
+    tp->set_internal_state (state);
 
   /* It only takes one running thread to spawn more threads.  */
-  if (executing)
+  if (state == THREAD_INT_RUNNING)
     targ->threads_executing = true;
   /* Only clear the flag if the caller is telling us everything is
-     stopped.  */
+     stopped or dead.  */
   else if (minus_one_ptid == ptid)
     targ->threads_executing = false;
 }
@@ -964,14 +963,41 @@ set_stop_requested (process_stratum_target *targ, ptid_t ptid, bool stop)
     gdb::observers::thread_stop_requested.notify (ptid);
 }
 
+/* Map INT_STATE to a user state.  */
+
+static thread_state
+state_from_int_state (thread_int_state int_state)
+{
+  switch (int_state)
+    {
+    case THREAD_INT_RUNNING:
+    case THREAD_INT_RESUMED_PENDING_STATUS:
+      return THREAD_RUNNING;
+    case THREAD_INT_STOPPED:
+      return THREAD_STOPPED;
+    case THREAD_INT_EXITED:
+      return THREAD_EXITED;
+    }
+
+  gdb_assert_not_reached ("unknown thread_int_state: %d", int_state);
+}
+
+/* See gdbthread.h.  Note this is a friend of thread_info so that it
+   can access the thread_info::set_state overload that lets us
+   suppress the target_resumed notification.  */
+
 void
 finish_thread_state (process_stratum_target *targ, ptid_t ptid)
 {
   bool any_started = false;
 
   for (thread_info *tp : all_non_exited_threads (targ, ptid))
-    if (set_running_thread (tp, tp->executing ()))
-      any_started = true;
+    {
+      thread_state new_state = state_from_int_state (tp->internal_state ());
+      thread_state prev_state = tp->set_state (new_state, true);
+      if (prev_state != new_state && new_state == THREAD_RUNNING)
+       any_started = true;
+    }
 
   if (any_started)
     notify_target_resumed (ptid);
@@ -989,7 +1015,7 @@ validate_registers_access (void)
   thread_info *tp = inferior_thread ();
 
   /* Don't try to read from a dead thread.  */
-  if (tp->state == THREAD_EXITED)
+  if (tp->state () == THREAD_EXITED)
     error (_("The current thread has terminated"));
 
   /* ... or from a spinning thread.  FIXME: This isn't actually fully
@@ -997,7 +1023,7 @@ validate_registers_access (void)
      at the prompt) when a thread is not executing for some internal
      reason, but is marked running from the user's perspective.  E.g.,
      the thread is waiting for its turn in the step-over queue.  */
-  if (tp->executing ())
+  if (tp->internal_state () == THREAD_INT_RUNNING)
     {
       /* If we are replaying with the record-full subsystem, even though
         the thread is executing, it is always safe to read from it since
@@ -1017,11 +1043,11 @@ can_access_registers_thread (thread_info *thread)
     return false;
 
   /* Don't try to read from a dead thread.  */
-  if (thread->state == THREAD_EXITED)
+  if (thread->state () == THREAD_EXITED)
     return false;
 
   /* ... or from a spinning thread.  FIXME: see validate_registers_access.  */
-  if (thread->executing ())
+  if (thread->internal_state () == THREAD_INT_RUNNING)
     {
       /* See validate_registers_access.  */
       if (!record_full_is_replaying ())
@@ -1105,14 +1131,14 @@ should_print_thread (const char *requested_threads,
       return false;
     }
 
-  if (thr->state == THREAD_EXITED)
+  if (thr->state () == THREAD_EXITED)
     return false;
 
-  bool is_stopped = (thr->state == THREAD_STOPPED);
+  bool is_stopped = (thr->state () == THREAD_STOPPED);
   if (opts.show_stopped_threads && is_stopped)
     return true;
 
-  bool is_running = (thr->state == THREAD_RUNNING);
+  bool is_running = (thr->state () == THREAD_RUNNING);
   if (opts.show_running_threads && is_running)
     return true;
 
@@ -1203,7 +1229,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
       uiout->field_string ("target-id", thread_target_id_str (tp));
     }
 
-  if (tp->state == THREAD_RUNNING)
+  if (tp->state () == THREAD_RUNNING)
     uiout->text ("(running)\n");
   else
     {
@@ -1219,7 +1245,7 @@ do_print_thread (ui_out *uiout, const char *requested_threads,
     {
       const char *state = "stopped";
 
-      if (tp->state == THREAD_RUNNING)
+      if (tp->state () == THREAD_RUNNING)
        state = "running";
       uiout->field_string ("state", state);
     }
@@ -1330,7 +1356,7 @@ print_thread_info_1 (struct ui_out *uiout, const char *requested_threads,
     for (inferior *inf : all_inferiors ())
       for (thread_info *tp : inf->threads ())
        {
-         if (tp == current_thread && tp->state == THREAD_EXITED)
+         if (tp == current_thread && tp->state () == THREAD_EXITED)
            current_exited = true;
 
          print_thread (uiout, requested_threads, opts, global_ids, pid,
@@ -1495,7 +1521,7 @@ scoped_restore_current_thread::restore ()
      changed, so we have to recheck it here.  */
   if (inferior_ptid != null_ptid
       && m_was_stopped
-      && m_thread->state == THREAD_STOPPED
+      && m_thread->state () == THREAD_STOPPED
       && target_has_registers ()
       && target_has_stack ()
       && target_has_memory ())
@@ -1518,7 +1544,7 @@ scoped_restore_current_thread::scoped_restore_current_thread ()
     {
       m_thread = thread_info_ref::new_reference (inferior_thread ());
 
-      m_was_stopped = m_thread->state == THREAD_STOPPED;
+      m_was_stopped = m_thread->state () == THREAD_STOPPED;
       save_selected_frame (&m_selected_frame_id, &m_selected_frame_level);
     }
 }
@@ -1964,7 +1990,7 @@ thread_command (const char *tidstr, int from_tty)
        {
          struct thread_info *tp = inferior_thread ();
 
-         if (tp->state == THREAD_EXITED)
+         if (tp->state () == THREAD_EXITED)
            gdb_printf (_("[Current thread is %s (%s) (exited)]\n"),
                        print_thread_id (tp),
                        target_pid_to_str (inferior_ptid).c_str ());
@@ -2122,7 +2148,7 @@ print_selected_thread_frame (struct ui_out *uiout,
        }
     }
 
-  if (tp->state == THREAD_RUNNING)
+  if (tp->state () == THREAD_RUNNING)
     {
       if (selection & USER_SELECTED_THREAD)
        uiout->text ("(running)\n");
@@ -2167,7 +2193,7 @@ update_threads_executing (void)
 
       for (thread_info *tp : inf->non_exited_threads ())
        {
-         if (tp->executing ())
+         if (tp->internal_state () == THREAD_INT_RUNNING)
            {
              targ->threads_executing = true;
              return;
@@ -2221,6 +2247,29 @@ thread_state_string (enum thread_state state)
   gdb_assert_not_reached ("unknown thread state");
 }
 
+/* See gdbthread.h.  */
+
+const char *
+thread_int_state_string (thread_int_state state)
+{
+  switch (state)
+    {
+    case THREAD_INT_STOPPED:
+      return "INT_STOPPED";
+
+    case THREAD_INT_RUNNING:
+      return "INT_RUNNING";
+
+    case THREAD_INT_RESUMED_PENDING_STATUS:
+      return "INT_RESUMED_PENDING_STATUS";
+
+    case THREAD_INT_EXITED:
+      return "INT_EXITED";
+    }
+
+  gdb_assert_not_reached ("unknown thread internal state");
+}
+
 /* Return a new value for the selected thread's id.  Return a value of
    0 if no thread is selected.  If GLOBAL is true, return the thread's
    global number.  Otherwise return the per-inferior number.  */
index 25a2afe09c87e62b1837f0095ce6adceb6339d8e..469313db22f530dcd0f17e5e68205268a46bb02a 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -586,7 +586,7 @@ execute_command (const char *p, int from_tty)
      we just finished executing did not resume the inferior's execution.
      If it did resume the inferior, we will do that check after
      the inferior stopped.  */
-  if (has_stack_frames () && inferior_thread ()->state != THREAD_RUNNING)
+  if (has_stack_frames () && inferior_thread ()->state () != THREAD_RUNNING)
     check_frame_language_change ();
 
   cleanup_if_error.release ();