diff options
author | Pedro Alves <pedro@palves.net> | 2020-12-13 01:35:05 +0000 |
---|---|---|
committer | Pedro Alves <pedro@palves.net> | 2021-02-03 01:15:00 +0000 |
commit | d758e62c0ecca0c26547cfe40aa1f32d6e8464b7 (patch) | |
tree | a6ff84e19b8089548fee67abb16f7acd86940610 /gdb | |
parent | 7e9cf1fe361dda0d6f06daeaa95eb98234f50764 (diff) | |
download | gdb-d758e62c0ecca0c26547cfe40aa1f32d6e8464b7.zip gdb-d758e62c0ecca0c26547cfe40aa1f32d6e8464b7.tar.gz gdb-d758e62c0ecca0c26547cfe40aa1f32d6e8464b7.tar.bz2 |
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.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/infrun.c | 290 |
2 files changed, 157 insertions, 138 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f11092d..920df3e 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 405b907..51d60f4 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; } } } |