Skip to content

Commit

Permalink
Change inferior thread list to be a thread map
Browse files Browse the repository at this point in the history
Remove the inferior::thread_list linked list, replace with
inferior::thread_map, an std::map indexed by ptid.  This should make it
faster to look up a thread from its ptid.
  • Loading branch information
simark committed Dec 18, 2019
1 parent 27e4fac commit 25c6772
Show file tree
Hide file tree
Showing 10 changed files with 352 additions and 145 deletions.
4 changes: 1 addition & 3 deletions gdb/gdbarch-selftests.c
Expand Up @@ -86,9 +86,7 @@ register_to_value_test (struct gdbarch *gdbarch)
mock_inferior.gdbarch = gdbarch;
mock_inferior.aspace = &mock_aspace;
thread_info mock_thread (&mock_inferior, mock_ptid);

scoped_restore restore_thread_list
= make_scoped_restore (&mock_inferior.thread_list, &mock_thread);
mock_inferior.thread_map[mock_ptid] = &mock_thread;

/* Add the mock inferior to the inferior list so that look ups by
target+ptid can find it. */
Expand Down
10 changes: 8 additions & 2 deletions gdb/gdbthread.h
Expand Up @@ -251,7 +251,6 @@ class thread_info : public refcounted_object
/* Mark this thread as running and notify observers. */
void set_running (bool running);

struct thread_info *next = NULL;
ptid_t ptid; /* "Actual process id";
In fact, this may be overloaded with
kernel thread id, etc. */
Expand Down Expand Up @@ -429,14 +428,21 @@ extern struct thread_info *add_thread_silent (ptid_t ptid);
extern struct thread_info *add_thread_with_info (ptid_t ptid,
struct private_thread_info *);

/* Delete an existing thread list entry. */
/* Delete an existing thread, removing the entry from its inferior's thread
map. */
extern void delete_thread (struct thread_info *thread);

/* Like the above, but don't remove the entry from the inferior thread map. */
extern void delete_thread_noremove(struct thread_info *thread);

/* Delete an existing thread list entry, and be quiet about it. Used
after the process this thread having belonged to having already
exited, for example. */
extern void delete_thread_silent (struct thread_info *thread);

/* Like the above, but don't remove the entry from the inferior thread map. */
extern void delete_thread_silent_noremove (thread_info *thread);

/* Delete a step_resume_breakpoint from the thread database. */
extern void delete_step_resume_breakpoint (struct thread_info *);

Expand Down
12 changes: 7 additions & 5 deletions gdb/inferior.c
Expand Up @@ -148,8 +148,8 @@ delete_inferior (struct inferior *todel)
if (!inf)
return;

for (thread_info *tp : inf->threads_safe ())
delete_thread_silent (tp);
for (thread_info *tp : inf->threads ())
delete_thread_silent_noremove (tp);

if (infprev)
infprev->next = inf->next;
Expand Down Expand Up @@ -180,14 +180,16 @@ exit_inferior_1 (struct inferior *inftoex, int silent)
if (!inf)
return;

for (thread_info *tp : inf->threads_safe ())
for (thread_info *tp : inf->threads ())
{
if (silent)
delete_thread_silent (tp);
delete_thread_silent_noremove (tp);
else
delete_thread (tp);
delete_thread_noremove (tp);
}

inf->thread_map.clear ();

gdb::observers::inferior_exit.notify (inf);

inf->pid = 0;
Expand Down
22 changes: 6 additions & 16 deletions gdb/inferior.h
Expand Up @@ -55,6 +55,7 @@ struct thread_info;

#include "gdbsupport/common-inferior.h"
#include "gdbthread.h"
#include "thread-map.h"

struct infcall_suspend_state;
struct infcall_control_state;
Expand Down Expand Up @@ -343,36 +344,25 @@ class inferior : public refcounted_object
struct inferior *next = NULL;

/* This inferior's thread list. */
thread_info *thread_list = nullptr;
ptid_thread_map thread_map;

/* Returns a range adapter covering the inferior's threads,
including exited threads. Used like this:
for (thread_info *thr : inf->threads ())
{ .... }
*/
inf_threads_range threads ()
{ return inf_threads_range (this->thread_list); }
all_thread_map_range threads ()
{ return all_thread_map_range (this->thread_map); }

/* Returns a range adapter covering the inferior's non-exited
threads. Used like this:
for (thread_info *thr : inf->non_exited_threads ())
{ .... }
*/
inf_non_exited_threads_range non_exited_threads ()
{ return inf_non_exited_threads_range (this->thread_list); }

/* Like inferior::threads(), but returns a range adapter that can be
used with range-for, safely. I.e., it is safe to delete the
currently-iterated thread, like this:
for (thread_info *t : inf->threads_safe ())
if (some_condition ())
delete f;
*/
inline safe_inf_threads_range threads_safe ()
{ return safe_inf_threads_range (this->thread_list); }
non_exited_thread_map_range non_exited_threads ()
{ return non_exited_thread_map_range (this->thread_map); }

/* Convenient handle (GDB inferior id). Unique across all
inferiors. */
Expand Down
2 changes: 1 addition & 1 deletion gdb/regcache.c
Expand Up @@ -1535,7 +1535,7 @@ cooked_read_test (struct gdbarch *gdbarch)
mock_inferior.gdbarch = gdbarch;
mock_inferior.aspace = &mock_aspace;
thread_info mock_thread (&mock_inferior, mock_ptid);
mock_inferior.thread_list = &mock_thread;
mock_inferior.thread_map[mock_ptid] = &mock_thread;

/* Add the mock inferior to the inferior list so that look ups by
target+ptid can find it. */
Expand Down
2 changes: 1 addition & 1 deletion gdb/remote.c
Expand Up @@ -4698,7 +4698,7 @@ remote_target::start_remote (int from_tty, int extended_p)
"warning: couldn't determine remote "
"current thread; picking first in list.\n");

inferior_ptid = inferior_list->thread_list->ptid;
inferior_ptid = inferior_list->thread_map.begin ()->second->ptid;
}
}

Expand Down
55 changes: 41 additions & 14 deletions gdb/thread-iter.c
Expand Up @@ -27,8 +27,13 @@ all_threads_iterator::all_threads_iterator (begin_t)
{
/* Advance M_INF/M_THR to the first thread's position. */
for (m_inf = inferior_list; m_inf != NULL; m_inf = m_inf->next)
if ((m_thr = m_inf->thread_list) != NULL)
return;
{
if (!m_inf->thread_map.empty())
{
this->m_thr_iter = m_inf->thread_map.cbegin ();
return;
}
}
}

/* See thread-iter.h. */
Expand All @@ -43,16 +48,24 @@ all_threads_iterator::advance ()

for (; m_inf != NULL; m_inf = m_inf->next)
{
m_thr = m_inf->thread_list;
while (m_thr != NULL)
m_thr_iter = m_inf->thread_map.cbegin ();
while (m_thr_iter != m_inf->thread_map.cend ())
{
return;
start:
m_thr = m_thr->next;
++m_thr_iter;
}
}
}

thread_info *all_threads_iterator::operator* () const
{
gdb_assert (m_inf != NULL);
gdb_assert (m_thr_iter != m_inf->thread_map.cend ());

return m_thr_iter->second;
}

/* See thread-iter.h. */

bool
Expand All @@ -68,12 +81,19 @@ all_matching_threads_iterator::all_matching_threads_iterator
(ptid_t filter_ptid)
: m_filter_ptid (filter_ptid)
{
m_thr = nullptr;
for (m_inf = inferior_list; m_inf != NULL; m_inf = m_inf->next)
if (m_inf_matches ())
for (m_thr = m_inf->thread_list; m_thr != NULL; m_thr = m_thr->next)
if (m_thr->ptid.matches (m_filter_ptid))
return;
{
if (!m_inf->thread_map.empty () && m_inf_matches ())
{
for (m_thr_iter = m_inf->thread_map.cbegin ();
m_thr_iter != m_inf->thread_map.cend ();
m_thr_iter++)
{
if (m_thr_iter->second->ptid.matches (m_filter_ptid))
return;
}
}
}
}

/* See thread-iter.h. */
Expand All @@ -89,13 +109,20 @@ all_matching_threads_iterator::advance ()
for (; m_inf != NULL; m_inf = m_inf->next)
if (m_inf_matches ())
{
m_thr = m_inf->thread_list;
while (m_thr != NULL)
m_thr_iter = m_inf->thread_map.cbegin ();
while (m_thr_iter != m_inf->thread_map.cend ())
{
if (m_thr->ptid.matches (m_filter_ptid))
if (m_thr_iter->second->ptid.matches (m_filter_ptid))
return;
start:
m_thr = m_thr->next;
++m_thr_iter;
}
}
}

thread_info *all_matching_threads_iterator::operator* () const
{
gdb_assert (m_inf != nullptr);

return m_thr_iter->second;
}
50 changes: 39 additions & 11 deletions gdb/thread-iter.h
Expand Up @@ -22,6 +22,7 @@
#include "gdbsupport/filtered-iterator.h"
#include "gdbsupport/next-iterator.h"
#include "gdbsupport/safe-iterator.h"
#include "thread-map.h"

/* A forward iterator that iterates over a given inferior's
threads. */
Expand Down Expand Up @@ -50,10 +51,10 @@ class all_threads_iterator

/* Create a one-past-end iterator. */
all_threads_iterator ()
: m_thr (nullptr)
: m_inf (nullptr)
{}

thread_info *operator* () const { return m_thr; }
thread_info *operator* () const;

all_threads_iterator &operator++ ()
{
Expand All @@ -62,20 +63,34 @@ class all_threads_iterator
}

bool operator== (const all_threads_iterator &other) const
{ return m_thr == other.m_thr; }
{
if (m_inf != other.m_inf)
return false;

/* Inferiors of both iterators are equal. */
if (m_inf == NULL) {
/* They are both ended iterators. */
return true;
} else {
/* Do they both point to the same thread? */
return m_thr_iter == other.m_thr_iter;
}
}

bool operator!= (const all_threads_iterator &other) const
{ return m_thr != other.m_thr; }
{
return !(*this == other);
}

private:
/* Advance to the next thread. */
void advance ();

private:
/* The current inferior and thread. M_THR is NULL if we reached the
/* The current inferior and thread. M_INF is NULL if we reached the
end of the threads list of the last inferior. */
inferior *m_inf;
thread_info *m_thr;
ptid_thread_map::const_iterator m_thr_iter;
};

/* Iterate over all threads that match a given PTID. */
Expand All @@ -97,11 +112,10 @@ class all_matching_threads_iterator
/* Create a one-past-end iterator. */
all_matching_threads_iterator ()
: m_inf (nullptr),
m_thr (nullptr),
m_filter_ptid (minus_one_ptid)
{}

thread_info *operator* () const { return m_thr; }
thread_info *operator* () const;

all_matching_threads_iterator &operator++ ()
{
Expand All @@ -110,10 +124,24 @@ class all_matching_threads_iterator
}

bool operator== (const all_matching_threads_iterator &other) const
{ return m_thr == other.m_thr; }
{
if (m_inf != other.m_inf)
return false;

/* Inferiors of both iterators are equal. */
if (m_inf == NULL) {
/* They are both ended iterators. */
return true;
} else {
/* Do they both point to the same thread? */
return m_thr_iter == other.m_thr_iter;
}
}

bool operator!= (const all_matching_threads_iterator &other) const
{ return m_thr != other.m_thr; }
{
return !(* this == other);
}

private:
/* Advance to next thread, skipping filtered threads. */
Expand All @@ -128,7 +156,7 @@ class all_matching_threads_iterator
inferior *m_inf;

/* The current thread. */
thread_info *m_thr;
ptid_thread_map::const_iterator m_thr_iter;

/* The filter. */
ptid_t m_filter_ptid;
Expand Down

0 comments on commit 25c6772

Please sign in to comment.