/* 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
/* 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);
}
/* 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;
}
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 ());
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;
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
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;
}
/* 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;
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
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;
}
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;
}
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;
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;
#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
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. */
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;
};
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
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;
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'. */
/* 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.
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.
/* 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 */
/* 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)
{
/* 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 ();
}
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",
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);
}
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);
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);
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 ())
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."));
}
static void
ensure_not_running (void)
{
- if (inferior_thread ()->state == THREAD_RUNNING)
+ if (inferior_thread ()->state () == THREAD_RUNNING)
error_is_running ();
}
/* 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);
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;
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;
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)
{
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 ();
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 ())
/* 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 ();
/* 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 */
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;
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)
{
}
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",
/* 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 ());
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
resume_ptid = internal_resume_ptid (user_step);
do_target_resume (resume_ptid, false, GDB_SIGNAL_0);
- tp->set_resumed (true);
return;
}
}
}
do_target_resume (resume_ptid, step, sig);
- tp->set_resumed (true);
}
/* Resume the inferior. SIG is the signal to give the inferior
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. */
"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);
}
/* 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)
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",
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;
}
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),
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
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);
}
}
}
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;
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
{
if (thr->displaced_step_state.in_progress ())
{
- if (thr->executing ())
+ if (thr->internal_state () == THREAD_INT_RUNNING)
{
if (!thr->stop_requested)
{
thr->stop_requested = true;
}
}
- else
- thr->set_resumed (false);
}
}
for (thread_info *thr : all_threads_safe ())
{
- if (thr->state == THREAD_EXITED)
+ if (thr->state () == THREAD_EXITED)
continue;
if (thr == ecs->event_thread)
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"));
}
}
}
-/* 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;
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
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;
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
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. */
/* 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);
}
}
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)
{
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
}
}
- mark_non_executing_threads (ecs->target, ecs->ptid, ecs->ws);
+ mark_internally_stopped_threads (ecs->target, ecs->ptid, ecs->ws);
switch (ecs->ws.kind ())
{
/* 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
|| (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
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;
}
{
infrun_debug_printf ("restart threads: [%s] needs step-over",
tp->ptid.to_string ().c_str ());
- gdb_assert (!tp->resumed ());
continue;
}
{
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;
}
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
/* 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));
for (thread_info *tp : all_threads_safe ())
{
- if (tp->state == THREAD_EXITED)
+ if (tp->state () == THREAD_EXITED)
continue;
if (tp->has_pending_waitstatus ())
for (thread_info *tp : all_threads_safe ())
{
- if (tp->state == THREAD_EXITED)
+ if (tp->state () == THREAD_EXITED)
continue;
if (tp->has_pending_waitstatus ())
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;
}
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);
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");
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);
}
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
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;
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 ()));
}
}
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. */
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"),
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
{
/* 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."));
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;
});
{
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 ())
{
/* 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
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
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
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),
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)
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)
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"));
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 ())
{
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);
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 ());
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;
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;
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;
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 ());
}
{
/* 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 ();
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);
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);
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 ();
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;
}
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;
}
else
{
thread_info *thr
- = remote_add_thread (currthread, running, executing, false);
+ = remote_add_thread (currthread, state, internal_state, false);
switch_to_thread (thr);
}
return;
/* 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
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);
}
}
}
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);
|| 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 ();
}
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);
}
}
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 ())
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
/* 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);
}
&& 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 ())
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;
}
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 ();
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 ();
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 ())
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
{
bool operator() (struct thread_info *thr) const
{
- return thr->state != THREAD_EXITED;
+ return thr->state () != THREAD_EXITED;
}
};
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);
/* 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. */
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. */
{
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;
}
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;
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,
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. */
delete_exited_threads (void)
{
for (thread_info *tp : all_threads_safe ())
- if (tp->state == THREAD_EXITED)
+ if (tp->state () == THREAD_EXITED)
delete_thread (tp);
}
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
/* 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;
}
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);
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
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
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 ())
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;
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
{
{
const char *state = "stopped";
- if (tp->state == THREAD_RUNNING)
+ if (tp->state () == THREAD_RUNNING)
state = "running";
uiout->field_string ("state", state);
}
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,
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 ())
{
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);
}
}
{
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 ());
}
}
- if (tp->state == THREAD_RUNNING)
+ if (tp->state () == THREAD_RUNNING)
{
if (selection & USER_SELECTED_THREAD)
uiout->text ("(running)\n");
for (thread_info *tp : inf->non_exited_threads ())
{
- if (tp->executing ())
+ if (tp->internal_state () == THREAD_INT_RUNNING)
{
targ->threads_executing = true;
return;
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. */
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 ();