Re: [PATCH v2 05/47] thread_info::executing+resumed -> thread_info::internal_state

Pedro Alves
2026-04-06T18:02:01Z

[-- Attachment #1: Type: text/plain, Size: 1058 bytes --]

On 2025-05-19 14:22, Pedro Alves wrote:
> While working on Windows non-stop support, I ran into a
> very-hard-to-track-down bug.
>

...

> 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().

I've rebased this on current master and I've now merged it, after retesting on native and gdbserver linux.
The rebase only required mechanical changes around thread_info pointer to thread_info references.

> 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.

I've ended up splitting this part into a separate preparatory patch, to help with
archaeology and bisecting if this ever creates a problem.

I've attached the two patches as they were merged.

Pedro Alves

[-- Attachment #2: 0001-init_wait_for_inferior-doesn-t-imply-proceed.patch --]
[-- Type: text/x-patch, Size: 4713 bytes --]

From fdb1f0881318c83d9db836c9558c33407aca173e Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Wed, 19 Feb 2025 14:37:39 +0000
Subject: [PATCH 1/2] init_wait_for_inferior doesn't imply proceed

The next patch 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. This patch fixes.

However, that alone changes MI output when attaching (as caught by
e.g. gdb.rocm/mi-attach.exp). We'd go from:

-target-attach 2468587
=thread-group-started,id="i1",pid="2468587"
=thread-created,id="1",group-id="i1"
^done

to:

-target-attach 2443288
=thread-group-started,id="i1",pid="2443288"
=thread-created,id="1",group-id="i1"
=thread-created,id="2",group-id="i1"
~"[New LWP 2443317 (id 2)]\n"
^running
*running,thread-id="2"
(gdb)

That change would happen because init_wait_for_inferior calls
clear_proceed_status, which calls notify_about_to_proceed, where we
end up in mi_interp::on_about_to_proceed(), setting the mi_proceeded
flag. If that happens before linux_nat_target::attach is called, then
the set_running calls inside linux_nat_target::attach result in
emiting ^running in MI instead of ^done due to the back-compatibility
hack in mi_on_resume_1.

Now, init_wait_inferior really does not imply we're about to call
proceed. So restore the MI output by adding a new parameter to
clear_proceed_status that lets init_wait_inferior tell
clear_proceed_status to skip notifying the about_to_proceed observers.

I audited all init_wait_inferior calls, and this made sense in all of
them. The places do call proceed after init_wait_inferior, already
explicitly clear_proceed_status after init_wait_inferior. E.g.,
run_command_1.

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

Change-Id: I4f5097d68f4694d44e1ae23fea3e9bce45fb078c
commit-id:123f9020
---
gdb/infcmd.c | 8 ++++----
gdb/infrun.c | 7 ++++---
gdb/infrun.h | 5 +++--
3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 98b45f884b1..2be2f4376c0 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2862,6 +2862,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 ();

@@ -2904,10 +2908,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 ())
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 2e53d2a6c30..a6b5db3edd5 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3123,7 +3123,7 @@ notify_about_to_proceed ()
}

void
-clear_proceed_status (int step)
+clear_proceed_status (int step, bool about_to_proceed)
{
/* With scheduler-locking replay, stop replaying other threads in the
same process if we're not replaying the selected thread.
@@ -3162,7 +3162,8 @@ clear_proceed_status (int step)
inferior->control.stop_soon = NO_STOP_QUIETLY;
}

- notify_about_to_proceed ();
+ if (about_to_proceed)
+ notify_about_to_proceed ();
}

/* Returns true if TP is still stopped at a breakpoint that needs
@@ -3851,7 +3852,7 @@ init_wait_for_inferior (void)

breakpoint_init_inferior (current_inferior (), inf_starting);

- clear_proceed_status (0);
+ clear_proceed_status (0, false);

nullify_last_target_wait_ptid ();

diff --git a/gdb/infrun.h b/gdb/infrun.h
index 7e2b652e4f1..9eaa5387ef0 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -129,8 +129,9 @@ extern void start_remote (int from_tty);
/* Clear out all variables saying what to do when inferior is
continued or stepped. First do this, then set the ones you want,
then call `proceed'. STEP indicates whether we're preparing for a
- step/stepi command. */
-extern void clear_proceed_status (int step);
+ step/stepi command. Set ABOUT_TO_PROCEED to false if we're not
+ calling `proceeed` yet. */
+extern void clear_proceed_status (int step, bool about_to_proceed = true);

extern void proceed (CORE_ADDR, enum gdb_signal);

base-commit: 73434094ad8a861fe555045804e943d186ff6879
--
2.53.0

[-- Attachment #3: 0002-thread_info-executing-resumed-thread_info-internal_s.patch --]
[-- Type: text/x-patch, Size: 92355 bytes --]

From 2954dd2b734526165b920eb575bcd0fc07e0aa24 Mon Sep 17 00:00:00 2001
From: Pedro Alves <pedro@palves.net>
Date: Wed, 19 Feb 2025 14:37:39 +0000
Subject: [PATCH 2/2] thread_info::executing+resumed ->
thread_info::internal_state

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().

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
commit-id:42ba97d4
---
gdb/aarch64-tdep.c | 2 +-
gdb/amd-dbgapi-target.c | 8 +-
gdb/breakpoint.c | 10 +-
gdb/bsd-uthread.c | 4 +-
gdb/fork-child.c | 4 +-
gdb/frame.c | 4 +-
gdb/gcore.c | 4 +-
gdb/gdbthread.h | 146 +++++++++--------
gdb/i386-tdep.c | 4 +-
gdb/inf-ptrace.c | 2 +-
gdb/infcall.c | 8 +-
gdb/infcmd.c | 31 ++--
gdb/inferior.h | 4 +-
gdb/inflow.c | 2 +-
gdb/infrun.c | 154 +++++++++---------
gdb/infrun.h | 7 +-
gdb/linux-fork.c | 9 +-
gdb/linux-nat.c | 8 +-
gdb/linux-thread-db.c | 4 +-
gdb/mi/mi-cmd-var.c | 4 +-
gdb/mi/mi-interp.c | 2 +-
gdb/mi/mi-main.c | 8 +-
gdb/process-stratum-target.c | 6 +-
gdb/python/py-infthread.c | 6 +-
gdb/record-btrace.c | 26 +--
gdb/record-full.c | 6 +-
gdb/regcache.c | 2 +-
gdb/remote.c | 76 +++++----
gdb/sol-thread.c | 4 +-
gdb/target.c | 15 +-
gdb/thread-iter.h | 2 +-
gdb/thread.c | 299 ++++++++++++++++++++---------------
gdb/top.c | 2 +-
33 files changed, 476 insertions(+), 397 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index ce00f518299..4befaa2720d 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -4355,7 +4355,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
diff --git a/gdb/amd-dbgapi-target.c b/gdb/amd-dbgapi-target.c
index 655dddd36ed..811e22182c6 100644
--- a/gdb/amd-dbgapi-target.c
+++ b/gdb/amd-dbgapi-target.c
@@ -1160,7 +1160,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);
}
@@ -1388,8 +1388,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;
}

@@ -2112,7 +2112,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 ());

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index d7be1b44229..31811e3a553 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -620,9 +620,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;
@@ -2050,7 +2050,8 @@ 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
@@ -4991,7 +4992,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;
}
diff --git a/gdb/bsd-uthread.c b/gdb/bsd-uthread.c
index e4c5c9ee3e3..0aa8ebda558 100644
--- a/gdb/bsd-uthread.c
+++ b/gdb/bsd-uthread.c
@@ -413,7 +413,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;
@@ -464,7 +464,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
diff --git a/gdb/fork-child.c b/gdb/fork-child.c
index bd75a9593aa..a9d0bffb8e1 100644
--- a/gdb/fork-child.c
+++ b/gdb/fork-child.c
@@ -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;
}
diff --git a/gdb/frame.c b/gdb/frame.c
index cefaa87fec3..7a83f5e61c0 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -1940,11 +1940,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;
}

diff --git a/gdb/gcore.c b/gdb/gcore.c
index 48e431ed8f9..ac3b44eb812 100644
--- a/gdb/gcore.c
+++ b/gdb/gcore.c
@@ -894,7 +894,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;

@@ -903,7 +903,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;
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 7644924b614..d64bf6e5a01 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -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 @@ class thread_info : public intrusive_list_node<thread_info>,

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 @@ class thread_info : public intrusive_list_node<thread_info>,
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 @@ class thread_info : public intrusive_list_node<thread_info>,
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'. */
@@ -818,17 +841,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.
@@ -838,25 +859,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.

@@ -1066,5 +1081,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 */
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 93357b41b10..fa935b5fcdb 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -4765,8 +4765,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);

uint8_t opcode;
if (record_read_memory (gdbarch, ir->addr, &opcode, 1))
diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c
index 98cc1094e24..5363717208e 100644
--- a/gdb/inf-ptrace.c
+++ b/gdb/inf-ptrace.c
@@ -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 ();
}
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 941b0a95c5b..f16a1f376b3 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -807,7 +807,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",
@@ -946,7 +946,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);
}

@@ -1589,7 +1589,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);

@@ -1600,7 +1600,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);
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 2be2f4376c0..b51d2e64f80 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -692,12 +692,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 ())
@@ -713,7 +713,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."));
}

@@ -742,7 +742,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 ();
}

@@ -1100,7 +1100,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);

@@ -2078,12 +2079,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;
@@ -2105,13 +2106,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;
@@ -2707,7 +2708,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)
{
@@ -2990,7 +2991,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 ();

diff --git a/gdb/inferior.h b/gdb/inferior.h
index fbf9765fb0e..9c031035a23 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -200,8 +200,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 */
diff --git a/gdb/inflow.c b/gdb/inflow.c
index ff118b558ca..c40ad2cf529 100644
--- a/gdb/inflow.c
+++ b/gdb/inflow.c
@@ -552,7 +552,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;
diff --git a/gdb/infrun.c b/gdb/infrun.c
index a6b5db3edd5..2c9a27325af 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1007,14 +1007,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)
{
@@ -2247,15 +2247,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",
@@ -2279,7 +2278,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 ());
@@ -2679,7 +2678,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
@@ -2805,7 +2804,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;
}
}
@@ -2997,7 +2995,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
@@ -3061,6 +3058,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. */
@@ -3072,6 +3070,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);
}
@@ -3144,7 +3143,8 @@ clear_proceed_status (int step, bool about_to_proceed)
/* 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)
@@ -3504,6 +3504,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",
@@ -3511,11 +3513,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;
}

@@ -3691,7 +3692,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),
@@ -3892,9 +3893,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
@@ -3925,10 +3926,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);
}
}

@@ -4034,7 +4035,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;
@@ -4147,6 +4148,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
@@ -4345,7 +4347,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)
{
@@ -4353,8 +4355,6 @@ prepare_for_detach (void)
thr.stop_requested = true;
}
}
- else
- thr.set_resumed (false);
}
}

@@ -4488,7 +4488,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)
@@ -4824,7 +4824,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"));
}

@@ -5387,14 +5387,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;

@@ -5414,18 +5414,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
@@ -5491,11 +5488,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;

@@ -5517,8 +5514,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
@@ -5749,7 +5745,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. */
@@ -5776,7 +5772,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);
}
}

@@ -5892,7 +5888,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)
{
@@ -5904,7 +5900,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
@@ -6176,7 +6172,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 ())
{
@@ -6440,7 +6436,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
@@ -6448,7 +6444,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
@@ -6640,18 +6636,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;
}

@@ -6659,7 +6654,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;
}

@@ -6668,7 +6662,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;
}

@@ -6707,7 +6701,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
@@ -6796,12 +6790,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));
@@ -8464,7 +8458,7 @@ restart_stepped_thread (process_stratum_target *resume_target,

for (thread_info &tp : all_threads_safe ())
{
- if (tp.state != THREAD_RUNNING)
+ if (tp.state () == THREAD_EXITED)
continue;

if (tp.has_pending_waitstatus ())
@@ -8488,7 +8482,7 @@ restart_stepped_thread (process_stratum_target *resume_target,

for (thread_info &tp : all_threads_safe ())
{
- if (tp.state != THREAD_RUNNING)
+ if (tp.state () == THREAD_EXITED)
continue;

if (tp.has_pending_waitstatus ())
@@ -8523,26 +8517,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;
}

@@ -8555,7 +8550,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);
@@ -8592,7 +8587,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");
@@ -8645,7 +8640,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);
}
@@ -9054,7 +9048,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
@@ -9525,7 +9519,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;
@@ -9619,7 +9613,7 @@ normal_stop ()
to a spurious stop event. The thread exiting will have already
been reported (when the thread list was parsed), so making this a
spurious stop will cause GDB to drop back to the prompt. */
- if (inferior_thread ()->state != THREAD_EXITED)
+ if (inferior_thread ()->state () != THREAD_EXITED)
notify_signal_received (inferior_thread ()->stop_signal ());
else
{
diff --git a/gdb/infrun.h b/gdb/infrun.h
index 9eaa5387ef0..f15662d5bc9 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -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 ()));
}
}

diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c
index 960995d94f1..92afa4dde6d 100644
--- a/gdb/linux-fork.c
+++ b/gdb/linux-fork.c
@@ -356,8 +356,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. */
@@ -719,7 +718,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"),
@@ -859,7 +858,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
{
@@ -1101,7 +1100,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."));

diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 1d0a4609a3a..9a49d53ea2a 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -1242,8 +1242,9 @@ 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;
});
@@ -1327,7 +1328,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 ())
{
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 0753d2e7915..55b9953ae4f 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -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
diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c
index f1f1637b74b..1f7e0fdfe3d 100644
--- a/gdb/mi/mi-cmd-var.c
+++ b/gdb/mi/mi-cmd-var.c
@@ -607,14 +607,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
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index a7b96c6a64c..8b3048c5a46 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -858,7 +858,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),
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index c03cbfe5117..bf08fe822b3 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -238,7 +238,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)
@@ -366,7 +366,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)
@@ -507,7 +507,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"));
@@ -2060,7 +2060,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 ())
diff --git a/gdb/process-stratum-target.c b/gdb/process-stratum-target.c
index d5c136d0b81..6a205b31eee 100644
--- a/gdb/process-stratum-target.c
+++ b/gdb/process-stratum-target.c
@@ -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 ());
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index cd9e2304ba8..4adfaa71ae2 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -259,7 +259,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;
@@ -275,7 +275,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;
@@ -291,7 +291,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;
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index bded22af8e6..d12d8616140 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -413,7 +413,7 @@ record_btrace_target::stop_recording ()

/* Check that before so stop recording is atomic. */
for (thread_info &tp : current_inferior ()->non_exited_threads ())
- if (tp.state == THREAD_RUNNING)
+ if (tp.state () == THREAD_RUNNING)
error (_("You cannot stop recording while threads are running."));

bool is_replaying = record_is_replaying (inferior_ptid);
@@ -1995,18 +1995,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 ());
}
@@ -2097,7 +2097,7 @@ record_btrace_stop_replaying (struct thread_info *tp)
if (btinfo->replay == nullptr)
return;

- switch (tp->state)
+ switch (tp->state ())
{
case THREAD_STOPPED:
/* Forget why we stopped; it was at a different location. */
@@ -2777,7 +2777,7 @@ record_btrace_set_replay (struct thread_info *tp,
{
struct btrace_thread_info *btinfo;

- if (tp->state == THREAD_RUNNING)
+ if (tp->state () == THREAD_RUNNING)
error (_("You cannot do that while the thread is running."));

btinfo = &tp->btrace;
diff --git a/gdb/record-full.c b/gdb/record-full.c
index e0af376f3eb..5258c3c5f84 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -1272,10 +1272,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 ();
diff --git a/gdb/regcache.c b/gdb/regcache.c
index ccd24d588d3..e94a94c48eb 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -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);
diff --git a/gdb/remote.c b/gdb/remote.c
index 3ec56a6d61b..c2555d528fa 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1329,12 +1329,15 @@ class remote_target : public process_stratum_target
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);
@@ -3151,13 +3154,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 ();
@@ -3174,10 +3180,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;
}
@@ -3186,26 +3192,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;
}

@@ -3227,7 +3236,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;
@@ -3264,7 +3273,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
@@ -3275,7 +3284,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);
}
}
}
@@ -4616,12 +4625,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);
@@ -5237,8 +5248,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 ();
}

@@ -5251,7 +5262,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);
}
}
@@ -5311,8 +5322,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 ())
@@ -7011,7 +7022,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
@@ -7120,7 +7131,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);
}
@@ -8998,7 +9010,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 ())
@@ -9104,7 +9116,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;
}
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index ec480186b59..c765a4205a0 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -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 ();
@@ -998,7 +998,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 ();
diff --git a/gdb/target.c b/gdb/target.c
index 359618e800f..b38a0536525 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2662,10 +2662,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 ())
@@ -3802,9 +3802,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
diff --git a/gdb/thread-iter.h b/gdb/thread-iter.h
index caaf7220e27..3c15ada1cbb 100644
--- a/gdb/thread-iter.h
+++ b/gdb/thread-iter.h
@@ -148,7 +148,7 @@ struct non_exited_thread_filter
{
bool operator() (struct thread_info &thr) const
{
- return thr.state != THREAD_EXITED;
+ return thr.state () != THREAD_EXITED;
}
};

diff --git a/gdb/thread.c b/gdb/thread.c
index 96e3bb7b50f..a6ae2a75139 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -228,23 +228,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);
@@ -379,34 +369,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. */
@@ -415,12 +421,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. */
@@ -430,9 +437,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;
}

@@ -441,8 +445,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;
@@ -688,30 +692,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,
@@ -719,15 +723,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. */
@@ -779,7 +783,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);
}

@@ -858,43 +862,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
@@ -911,41 +878,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;
}
@@ -970,14 +969,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);
@@ -995,7 +1021,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
@@ -1003,7 +1029,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
@@ -1023,11 +1049,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 ())
@@ -1111,14 +1137,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;

@@ -1209,7 +1235,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
{
@@ -1225,7 +1251,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);
}
@@ -1336,7 +1362,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,
@@ -1501,7 +1527,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 ())
@@ -1524,7 +1550,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);
}
}
@@ -1970,7 +1996,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 ());
@@ -2115,7 +2141,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");
@@ -2160,7 +2186,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;
@@ -2214,6 +2240,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. */
diff --git a/gdb/top.c b/gdb/top.c
index 510e65c1d09..7526c07a87b 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -654,7 +654,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 ();
--
2.53.0