mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-07 13:39:43 +08:00
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:
parent
7e9cf1fe36
commit
d758e62c0e
@ -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
|
||||
|
290
gdb/infrun.c
290
gdb/infrun.c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user