diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index d43a96a0aee..c6bc016ce81 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,10 @@ +2016-10-27 Yao Qi + + * inferiors.c (find_inferior_in_random): New function. + * inferiors.h (find_inferior_in_random): Declare. + * linux-low.c (linux_wait_for_event_filtered): Call + find_inferior_in_random instead of find_inferior. + 2016-10-27 Yao Qi * linux-low.c (linux_wait_1): If single-step breakpoints are diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c index 7888f3c1852..574a7ba7d57 100644 --- a/gdb/gdbserver/inferiors.c +++ b/gdb/gdbserver/inferiors.c @@ -248,6 +248,51 @@ find_inferior (struct inferior_list *list, return NULL; } +/* Find the random inferior_list_entry E in LIST for which FUNC (E, ARG) + returns non-zero. If no entry is found then return NULL. */ + +struct inferior_list_entry * +find_inferior_in_random (struct inferior_list *list, + int (*func) (struct inferior_list_entry *, void *), + void *arg) +{ + struct inferior_list_entry *inf = list->head; + int count = 0; + int random_selector; + + /* First count how many interesting entries we have. */ + while (inf != NULL) + { + struct inferior_list_entry *next; + + next = inf->next; + if ((*func) (inf, arg)) + count++; + inf = next; + } + + if (count == 0) + return NULL; + + /* Now randomly pick an entry out of those. */ + random_selector = (int) + ((count * (double) rand ()) / (RAND_MAX + 1.0)); + + inf = list->head; + while (inf != NULL) + { + struct inferior_list_entry *next; + + next = inf->next; + if ((*func) (inf, arg) && (random_selector-- == 0)) + return inf; + inf = next; + } + + gdb_assert_not_reached ("failed to find an inferior in random."); + return NULL; +} + struct inferior_list_entry * find_inferior_id (struct inferior_list *list, ptid_t id) { diff --git a/gdb/gdbserver/inferiors.h b/gdb/gdbserver/inferiors.h index 65ab1c6fc60..6ea7a999d59 100644 --- a/gdb/gdbserver/inferiors.h +++ b/gdb/gdbserver/inferiors.h @@ -154,6 +154,11 @@ struct inferior_list_entry *find_inferior void *arg); struct inferior_list_entry *find_inferior_id (struct inferior_list *list, ptid_t id); +struct inferior_list_entry * + find_inferior_in_random (struct inferior_list *, + int (*func) (struct inferior_list_entry *, + void *), + void *arg); void *inferior_target_data (struct thread_info *); void set_inferior_target_data (struct thread_info *, void *); diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index a463774971b..5dcf376ecf6 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -2700,7 +2700,8 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid, if (ptid_equal (filter_ptid, minus_one_ptid) || ptid_is_pid (filter_ptid)) { event_thread = (struct thread_info *) - find_inferior (&all_threads, status_pending_p_callback, &filter_ptid); + find_inferior_in_random (&all_threads, status_pending_p_callback, + &filter_ptid); if (event_thread != NULL) event_child = get_thread_lwp (event_thread); if (debug_threads && event_thread) @@ -2811,7 +2812,8 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid, /* ... and find an LWP with a status to report to the core, if any. */ event_thread = (struct thread_info *) - find_inferior (&all_threads, status_pending_p_callback, &filter_ptid); + find_inferior_in_random (&all_threads, status_pending_p_callback, + &filter_ptid); if (event_thread != NULL) { event_child = get_thread_lwp (event_thread);