summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2020-12-13 01:35:05 +0000
committerPedro Alves <pedro@palves.net>2021-02-03 01:15:00 +0000
commitd758e62c0ecca0c26547cfe40aa1f32d6e8464b7 (patch)
treea6ff84e19b8089548fee67abb16f7acd86940610
parent7e9cf1fe361dda0d6f06daeaa95eb98234f50764 (diff)
downloadbinutils-gdb-d758e62c0ecca0c26547cfe40aa1f32d6e8464b7.tar.gz
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.
-rw-r--r--gdb/ChangeLog5
-rw-r--r--gdb/infrun.c290
2 files changed, 157 insertions, 138 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f11092d840c..920df3ec312 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
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
TARGET_WAITKIND_IGNORE; instead, just ignore the notification.
(remote_target::discard_pending_stop_replies): Don't delete
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 405b907856a..51d60f49629 100644
--- a/gdb/infrun.c
+++ b/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;
}
}
}