Factor out after-stop event handling code from stop_all_threads

This moves the code handling an event out of wait_one to a separate
function, to be used in another context in a following patch.

gdb/ChangeLog:

	* infrun.c (handle_one): New function, factored out from ...
	(stop_all_threads): ... here.
This commit is contained in:
Pedro Alves 2020-12-13 01:35:05 +00:00
parent 7e9cf1fe36
commit d758e62c0e
2 changed files with 157 additions and 138 deletions

View File

@ -1,3 +1,8 @@
2021-02-03 Pedro Alves <pedro@palves.net>
* infrun.c (handle_one): New function, factored out from ...
(stop_all_threads): ... here.
2021-02-03 Pedro Alves <pedro@palves.net>
* remote.c (remote_notif_stop_ack): Don't error out on

View File

@ -4560,6 +4560,156 @@ mark_non_executing_threads (process_stratum_target *target,
set_resumed (target, mark_ptid, false);
}
/* Handle one event after stopping threads. If the eventing thread
reports back any interesting event, we leave it pending. If the
eventing thread was in the middle of a displaced step, we
cancel/finish it. Returns true if there are no resumed threads
left in the target (thus there's no point in waiting further),
false otherwise. */
static bool
handle_one (const wait_one_event &event)
{
infrun_debug_printf
("%s %s", target_waitstatus_to_string (&event.ws).c_str (),
target_pid_to_str (event.ptid).c_str ());
if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED)
{
/* All resumed threads exited. */
return true;
}
else if (event.ws.kind == TARGET_WAITKIND_THREAD_EXITED
|| event.ws.kind == TARGET_WAITKIND_EXITED
|| event.ws.kind == TARGET_WAITKIND_SIGNALLED)
{
/* One thread/process exited/signalled. */
thread_info *t = nullptr;
/* The target may have reported just a pid. If so, try
the first non-exited thread. */
if (event.ptid.is_pid ())
{
int pid = event.ptid.pid ();
inferior *inf = find_inferior_pid (event.target, pid);
for (thread_info *tp : inf->non_exited_threads ())
{
t = tp;
break;
}
/* If there is no available thread, the event would
have to be appended to a per-inferior event list,
which does not exist (and if it did, we'd have
to adjust run control command to be able to
resume such an inferior). We assert here instead
of going into an infinite loop. */
gdb_assert (t != nullptr);
infrun_debug_printf
("using %s", target_pid_to_str (t->ptid).c_str ());
}
else
{
t = find_thread_ptid (event.target, event.ptid);
/* Check if this is the first time we see this thread.
Don't bother adding if it individually exited. */
if (t == nullptr
&& event.ws.kind != TARGET_WAITKIND_THREAD_EXITED)
t = add_thread (event.target, event.ptid);
}
if (t != nullptr)
{
/* Set the threads as non-executing to avoid
another stop attempt on them. */
switch_to_thread_no_regs (t);
mark_non_executing_threads (event.target, event.ptid,
event.ws);
save_waitstatus (t, &event.ws);
t->stop_requested = false;
}
}
else
{
thread_info *t = find_thread_ptid (event.target, event.ptid);
if (t == NULL)
t = add_thread (event.target, event.ptid);
t->stop_requested = 0;
t->executing = 0;
t->resumed = false;
t->control.may_range_step = 0;
/* This may be the first time we see the inferior report
a stop. */
inferior *inf = find_inferior_ptid (event.target, event.ptid);
if (inf->needs_setup)
{
switch_to_thread_no_regs (t);
setup_inferior (0);
}
if (event.ws.kind == TARGET_WAITKIND_STOPPED
&& event.ws.value.sig == GDB_SIGNAL_0)
{
/* We caught the event that we intended to catch, so
there's no event pending. */
t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
t->suspend.waitstatus_pending_p = 0;
if (displaced_step_finish (t, GDB_SIGNAL_0)
== DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
{
/* Add it back to the step-over queue. */
infrun_debug_printf
("displaced-step of %s canceled",
target_pid_to_str (t->ptid).c_str ());
t->control.trap_expected = 0;
global_thread_step_over_chain_enqueue (t);
}
}
else
{
enum gdb_signal sig;
struct regcache *regcache;
infrun_debug_printf
("target_wait %s, saving status for %d.%ld.%ld",
target_waitstatus_to_string (&event.ws).c_str (),
t->ptid.pid (), t->ptid.lwp (), t->ptid.tid ());
/* Record for later. */
save_waitstatus (t, &event.ws);
sig = (event.ws.kind == TARGET_WAITKIND_STOPPED
? event.ws.value.sig : GDB_SIGNAL_0);
if (displaced_step_finish (t, sig)
== DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
{
/* Add it back to the step-over queue. */
t->control.trap_expected = 0;
global_thread_step_over_chain_enqueue (t);
}
regcache = get_thread_regcache (t);
t->suspend.stop_pc = regcache_read_pc (regcache);
infrun_debug_printf ("saved stop_pc=%s for %s "
"(currently_stepping=%d)",
paddress (target_gdbarch (),
t->suspend.stop_pc),
target_pid_to_str (t->ptid).c_str (),
currently_stepping (t));
}
}
return false;
}
/* See infrun.h. */
void
@ -4673,144 +4823,8 @@ stop_all_threads (void)
for (int i = 0; i < waits_needed; i++)
{
wait_one_event event = wait_one ();
infrun_debug_printf
("%s %s", target_waitstatus_to_string (&event.ws).c_str (),
target_pid_to_str (event.ptid).c_str ());
if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED)
{
/* All resumed threads exited. */
break;
}
else if (event.ws.kind == TARGET_WAITKIND_THREAD_EXITED
|| event.ws.kind == TARGET_WAITKIND_EXITED
|| event.ws.kind == TARGET_WAITKIND_SIGNALLED)
{
/* One thread/process exited/signalled. */
thread_info *t = nullptr;
/* The target may have reported just a pid. If so, try
the first non-exited thread. */
if (event.ptid.is_pid ())
{
int pid = event.ptid.pid ();
inferior *inf = find_inferior_pid (event.target, pid);
for (thread_info *tp : inf->non_exited_threads ())
{
t = tp;
break;
}
/* If there is no available thread, the event would
have to be appended to a per-inferior event list,
which does not exist (and if it did, we'd have
to adjust run control command to be able to
resume such an inferior). We assert here instead
of going into an infinite loop. */
gdb_assert (t != nullptr);
infrun_debug_printf
("using %s", target_pid_to_str (t->ptid).c_str ());
}
else
{
t = find_thread_ptid (event.target, event.ptid);
/* Check if this is the first time we see this thread.
Don't bother adding if it individually exited. */
if (t == nullptr
&& event.ws.kind != TARGET_WAITKIND_THREAD_EXITED)
t = add_thread (event.target, event.ptid);
}
if (t != nullptr)
{
/* Set the threads as non-executing to avoid
another stop attempt on them. */
switch_to_thread_no_regs (t);
mark_non_executing_threads (event.target, event.ptid,
event.ws);
save_waitstatus (t, &event.ws);
t->stop_requested = false;
}
}
else
{
thread_info *t = find_thread_ptid (event.target, event.ptid);
if (t == NULL)
t = add_thread (event.target, event.ptid);
t->stop_requested = 0;
t->executing = 0;
t->resumed = false;
t->control.may_range_step = 0;
/* This may be the first time we see the inferior report
a stop. */
inferior *inf = find_inferior_ptid (event.target, event.ptid);
if (inf->needs_setup)
{
switch_to_thread_no_regs (t);
setup_inferior (0);
}
if (event.ws.kind == TARGET_WAITKIND_STOPPED
&& event.ws.value.sig == GDB_SIGNAL_0)
{
/* We caught the event that we intended to catch, so
there's no event pending. */
t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
t->suspend.waitstatus_pending_p = 0;
if (displaced_step_finish (t, GDB_SIGNAL_0)
== DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
{
/* Add it back to the step-over queue. */
infrun_debug_printf
("displaced-step of %s canceled: adding back to "
"the step-over queue",
target_pid_to_str (t->ptid).c_str ());
t->control.trap_expected = 0;
global_thread_step_over_chain_enqueue (t);
}
}
else
{
enum gdb_signal sig;
struct regcache *regcache;
infrun_debug_printf
("target_wait %s, saving status for %d.%ld.%ld",
target_waitstatus_to_string (&event.ws).c_str (),
t->ptid.pid (), t->ptid.lwp (), t->ptid.tid ());
/* Record for later. */
save_waitstatus (t, &event.ws);
sig = (event.ws.kind == TARGET_WAITKIND_STOPPED
? event.ws.value.sig : GDB_SIGNAL_0);
if (displaced_step_finish (t, sig)
== DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
{
/* Add it back to the step-over queue. */
t->control.trap_expected = 0;
global_thread_step_over_chain_enqueue (t);
}
regcache = get_thread_regcache (t);
t->suspend.stop_pc = regcache_read_pc (regcache);
infrun_debug_printf ("saved stop_pc=%s for %s "
"(currently_stepping=%d)",
paddress (target_gdbarch (),
t->suspend.stop_pc),
target_pid_to_str (t->ptid).c_str (),
currently_stepping (t));
}
}
if (handle_one (event))
break;
}
}
}