diff --git a/gdb/infrun.c b/gdb/infrun.c index bec8e83e193..93cb55e70c7 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -3492,39 +3492,21 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid, static struct thread_info * random_pending_event_thread (inferior *inf, ptid_t waiton_ptid) { - int num_events = 0; + process_stratum_target *proc_target = inf->process_target (); + thread_info *thread + = proc_target->random_resumed_with_pending_wait_status (inf, waiton_ptid); - auto has_event = [&] (thread_info *tp) + if (thread == nullptr) { - return (tp->ptid.matches (waiton_ptid) - && tp->resumed () - && tp->has_pending_waitstatus ()); - }; + infrun_debug_printf ("None found."); + return nullptr; + } - /* First see how many events we have. Count only resumed threads - that have an event pending. */ - for (thread_info *tp : inf->non_exited_threads ()) - if (has_event (tp)) - num_events++; + infrun_debug_printf ("Found %s.", target_pid_to_str (thread->ptid).c_str ()); + gdb_assert (thread->resumed ()); + gdb_assert (thread->has_pending_waitstatus ()); - if (num_events == 0) - return NULL; - - /* Now randomly pick a thread out of those that have had events. */ - int random_selector = (int) ((num_events * (double) rand ()) - / (RAND_MAX + 1.0)); - - if (num_events > 1) - infrun_debug_printf ("Found %d events, selecting #%d", - num_events, random_selector); - - /* Select the Nth thread that has had an event. */ - for (thread_info *tp : inf->non_exited_threads ()) - if (has_event (tp)) - if (random_selector-- == 0) - return tp; - - gdb_assert_not_reached ("event thread not found"); + return thread; } /* Wrapper for target_wait that first checks whether threads have diff --git a/gdb/process-stratum-target.c b/gdb/process-stratum-target.c index 2cb6dfc251a..7aeda79e04c 100644 --- a/gdb/process-stratum-target.c +++ b/gdb/process-stratum-target.c @@ -20,6 +20,7 @@ #include "defs.h" #include "process-stratum-target.h" #include "inferior.h" +#include process_stratum_target::~process_stratum_target () { @@ -140,6 +141,48 @@ process_stratum_target::maybe_remove_resumed_with_pending_wait_status /* See process-stratum-target.h. */ +thread_info * +process_stratum_target::random_resumed_with_pending_wait_status + (inferior *inf, ptid_t filter_ptid) +{ + auto matches = [inf, filter_ptid] (const thread_info &thread) + { + return thread.inf == inf && thread.ptid.matches (filter_ptid); + }; + + /* First see how many matching events we have. */ + const auto &l = m_resumed_with_pending_wait_status; + unsigned int count = std::count_if (l.begin (), l.end (), matches); + + if (count == 0) + return nullptr; + + /* Now randomly pick a thread out of those that match the criteria. */ + int random_selector + = (int) ((count * (double) rand ()) / (RAND_MAX + 1.0)); + + if (count > 1) + infrun_debug_printf ("Found %u events, selecting #%d", + count, random_selector); + + /* Select the Nth thread that matches. */ + auto it = std::find_if (l.begin (), l.end (), + [&random_selector, &matches] + (const thread_info &thread) + { + if (!matches (thread)) + return false; + + return random_selector-- == 0; + }); + + gdb_assert (it != l.end ()); + + return &*it; +} + +/* See process-stratum-target.h. */ + std::set all_non_exited_process_targets () { diff --git a/gdb/process-stratum-target.h b/gdb/process-stratum-target.h index 6bd8bc37b5e..ed6907c2bd1 100644 --- a/gdb/process-stratum-target.h +++ b/gdb/process-stratum-target.h @@ -93,6 +93,11 @@ public: bool has_resumed_with_pending_wait_status () const { return !m_resumed_with_pending_wait_status.empty (); } + /* Return a random resumed thread with pending wait status belonging to INF + and matching FILTER_PTID. */ + thread_info *random_resumed_with_pending_wait_status + (inferior *inf, ptid_t filter_ptid); + /* The connection number. Visible in "info connections". */ int connection_number = 0;