static void
ada_tasks_new_objfile_observer (struct objfile *objfile)
{
- struct inferior *inf;
-
/* Invalidate the relevant data in our program-space data. */
if (objfile == NULL)
If all objfiles are being cleared (OBJFILE is NULL), then
clear the caches for all inferiors. */
- for (inf = inferior_list; inf != NULL; inf = inf->next)
+ for (inferior *inf : all_inferiors ())
if (objfile == NULL || inf->pspace == objfile->pspace)
ada_tasks_invalidate_inferior_data (inf);
}
typedef int difference_type;
/* Create an iterator pointing at HEAD. */
- all_inferiors_iterator (process_stratum_target *proc_target, inferior *head)
- : m_proc_target (proc_target)
+ all_inferiors_iterator (process_stratum_target *proc_target,
+ const intrusive_list<inferior> &list)
+ : m_proc_target (proc_target), m_inf_iter (list.begin ())
{
+ intrusive_list<inferior>::iterator end;
+
/* Advance M_INF to the first inferior's position. */
- for (m_inf = head; m_inf != NULL; m_inf = m_inf->next)
+ for (; m_inf_iter != end; ++m_inf_iter)
if (m_inf_matches ())
return;
}
/* Create a one-past-end iterator. */
all_inferiors_iterator ()
- : m_proc_target (nullptr), m_inf (nullptr)
+ : m_proc_target (nullptr)
{}
all_inferiors_iterator &operator++ ()
}
inferior *operator* () const
- { return m_inf; }
+ { return &*m_inf_iter; }
bool operator!= (const all_inferiors_iterator &other) const
- { return m_inf != other.m_inf; }
+ { return m_inf_iter != other.m_inf_iter; }
private:
/* Advance to next inferior, skipping filtered inferiors. */
void advance ()
{
+ intrusive_list<inferior>::iterator end;
+
/* The loop below is written in the natural way as-if we'd always
start at the beginning of the inferior list. This
fast-forwards the algorithm to the actual current position. */
goto start;
- while (m_inf != NULL)
+ while (m_inf_iter != end)
{
if (m_inf_matches ())
return;
start:
- m_inf = m_inf->next;
+ ++m_inf_iter;
}
}
bool m_inf_matches ()
{
return (m_proc_target == nullptr
- || m_proc_target == m_inf->process_target ());
+ || m_proc_target == m_inf_iter->process_target ());
}
process_stratum_target *m_proc_target;
- inferior *m_inf;
+ intrusive_list<inferior>::iterator m_inf_iter;
};
/* A range adapter that makes it possible to iterate over all
DEFINE_REGISTRY (inferior, REGISTRY_ACCESS_FIELD)
-struct inferior *inferior_list = NULL;
+intrusive_list<inferior> inferior_list;
static int highest_inferior_num;
/* See inferior.h. */
{
inferior *inf = new inferior (pid);
- if (inferior_list == NULL)
- inferior_list = inf;
- else
- {
- inferior *last;
-
- for (last = inferior_list; last->next != NULL; last = last->next)
- ;
- last->next = inf;
- }
+ inferior_list.push_back (*inf);
gdb::observers::inferior_added.notify (inf);
}
void
-delete_inferior (struct inferior *todel)
+delete_inferior (struct inferior *inf)
{
- struct inferior *inf, *infprev;
-
- infprev = NULL;
-
- for (inf = inferior_list; inf; infprev = inf, inf = inf->next)
- if (inf == todel)
- break;
-
- if (!inf)
- return;
-
inf->clear_thread_list (true);
- if (infprev)
- infprev->next = inf->next;
- else
- inferior_list = inf->next;
+ auto it = inferior_list.iterator_to (*inf);
+ inferior_list.erase (it);
gdb::observers::inferior_removed.notify (inf);
exit of its threads. */
static void
-exit_inferior_1 (struct inferior *inftoex, int silent)
+exit_inferior_1 (struct inferior *inf, int silent)
{
- struct inferior *inf;
-
- for (inf = inferior_list; inf; inf = inf->next)
- if (inf == inftoex)
- break;
-
- if (!inf)
- return;
-
inf->clear_thread_list (silent);
gdb::observers::inferior_exit.notify (inf);
void
prune_inferiors (void)
{
- inferior *ss;
-
- ss = inferior_list;
- while (ss)
+ for (inferior *inf : all_inferiors_safe ())
{
- if (!ss->deletable ()
- || !ss->removable
- || ss->pid != 0)
- {
- ss = ss->next;
- continue;
- }
+ if (!inf->deletable ()
+ || !inf->removable
+ || inf->pid != 0)
+ continue;
- inferior *ss_next = ss->next;
- delete_inferior (ss);
- ss = ss_next;
+ delete_inferior (inf);
}
}
#include "gdbsupport/refcounted-object.h"
#include "gdbsupport/forward-scope-exit.h"
#include "gdbsupport/gdb_unique_ptr.h"
+#include "gdbsupport/intrusive_list.h"
#include "gdbsupport/common-inferior.h"
#include "gdbthread.h"
listed exactly once in the inferior list, so placing an inferior in
the inferior list is an implicit, not counted strong reference. */
-class inferior : public refcounted_object
+class inferior : public refcounted_object,
+ public intrusive_list_node<inferior>
{
public:
explicit inferior (int pid);
bool has_execution ()
{ return target_has_execution (this); }
- /* Pointer to next inferior in singly-linked list of inferiors. */
- struct inferior *next = NULL;
-
/* This inferior's thread list, sorted by creation order. */
intrusive_list<thread_info> thread_list;
/* Traverse all inferiors. */
-extern struct inferior *inferior_list;
+extern intrusive_list<inferior> inferior_list;
/* Pull in the internals of the inferiors ranges and iterators. Must
be done after struct inferior is defined. */
reported the stop to the user, polling for events. */
scoped_restore_current_thread restore_thread;
- int inf_num = selected->num;
- for (inferior *inf = selected; inf != NULL; inf = inf->next)
- if (inferior_matches (inf))
- if (do_wait (inf))
+ intrusive_list_iterator<inferior> start
+ = inferior_list.iterator_to (*selected);
+
+ for (intrusive_list_iterator<inferior> it = start;
+ it != inferior_list.end ();
+ ++it)
+ {
+ inferior *inf = &*it;
+
+ if (inferior_matches (inf) && do_wait (inf))
return true;
+ }
- for (inferior *inf = inferior_list;
- inf != NULL && inf->num < inf_num;
- inf = inf->next)
- if (inferior_matches (inf))
- if (do_wait (inf))
+ for (intrusive_list_iterator<inferior> it = inferior_list.begin ();
+ it != start;
+ ++it)
+ {
+ inferior *inf = &*it;
+
+ if (inferior_matches (inf) && do_wait (inf))
return true;
+ }
ecs->ws.kind = TARGET_WAITKIND_IGNORE;
return false;
scoped_mock_context<test_target_ops> target1 (arch);
scoped_mock_context<test_target_ops> target2 (arch);
- target2.mock_inferior.next = &target1.mock_inferior;
ptid_t old_ptid (111, 222);
ptid_t new_ptid (111, 333);
scoped_mock_context<test_target_ops> target1 (arch);
scoped_mock_context<test_target_ops> target2 (arch);
- target2.mock_inferior.next = &target1.mock_inferior;
ptid_t old_ptid (111, 222);
ptid_t new_ptid (111, 333);
update_address_spaces (void)
{
int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch ());
- struct inferior *inf;
init_address_spaces ();
pspace->aspace = new_address_space ();
}
- for (inf = inferior_list; inf; inf = inf->next)
+ for (inferior *inf : all_inferiors ())
if (gdbarch_has_global_solist (target_gdbarch ()))
inf->aspace = maybe_new_address_space ();
else
/* Prepare two targets with one thread each, with the same ptid. */
scoped_mock_context<test_target_ops> target1 (arch);
scoped_mock_context<test_target_ops> target2 (arch);
- target2.mock_inferior.next = &target1.mock_inferior;
ptid_t old_ptid (111, 222);
ptid_t new_ptid (111, 333);
scoped_restore_current_pspace_and_thread restore_pspace_thread;
- /* Add the mock inferior to the inferior list so that look ups by
- target+ptid can find it. */
- scoped_restore_tmpl<inferior *> restore_inferior_list
- {&inferior_list, &mock_inferior};
-
explicit scoped_mock_context (gdbarch *gdbarch)
{
+ /* Add the mock inferior to the inferior list so that look ups by
+ target+ptid can find it. */
+ inferior_list.push_back (mock_inferior);
+
mock_inferior.thread_list.push_back (mock_thread);
mock_inferior.gdbarch = gdbarch;
mock_inferior.aspace = mock_pspace.aspace;
~scoped_mock_context ()
{
+ inferior_list.erase (inferior_list.iterator_to (mock_inferior));
pop_all_targets_at_and_above (process_stratum);
}
};
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)
+
+ for (inferior &inf : inferior_list)
{
- auto thr_iter = m_inf->thread_list.begin ();
- if (thr_iter != m_inf->thread_list.end ())
+ auto thr_iter = inf.thread_list.begin ();
+ if (thr_iter != inf.thread_list.end ())
{
+ m_inf = &inf;
m_thr = &*thr_iter;
return;
}
}
+ m_inf = nullptr;
m_thr = nullptr;
}
void
all_threads_iterator::advance ()
{
+ intrusive_list<inferior>::iterator inf_iter (m_inf);
intrusive_list<thread_info>::iterator thr_iter (m_thr);
/* The loop below is written in the natural way as-if we'd always
the algorithm to the actual current position. */
goto start;
- for (; m_inf != NULL; m_inf = m_inf->next)
+ for (; inf_iter != inferior_list.end (); ++inf_iter)
{
+ m_inf = &*inf_iter;
thr_iter = m_inf->thread_list.begin ();
while (thr_iter != m_inf->thread_list.end ())
{
gdb_assert ((filter_target == nullptr && filter_ptid == minus_one_ptid)
|| filter_target->stratum () == process_stratum);
- for (m_inf = inferior_list; m_inf != NULL; m_inf = m_inf->next)
- if (m_inf_matches ())
- for (auto thr_iter = m_inf->thread_list.begin ();
- thr_iter != m_inf->thread_list.end ();
- ++thr_iter)
- if (thr_iter->ptid.matches (m_filter_ptid))
+ for (inferior &inf : inferior_list)
+ {
+ m_inf = &inf;
+ if (m_inf_matches ())
+ for (auto thr_iter = m_inf->thread_list.begin ();
+ thr_iter != m_inf->thread_list.end ();
+ ++thr_iter)
{
- m_thr = &*thr_iter;
- return;
+ if (thr_iter->ptid.matches (m_filter_ptid))
+ {
+ m_thr = &*thr_iter;
+ return;
+ }
}
+ }
m_thr = nullptr;
}
void
all_matching_threads_iterator::advance ()
{
+ intrusive_list<inferior>::iterator inf_iter (m_inf);
intrusive_list<thread_info>::iterator thr_iter (m_thr);
/* The loop below is written in the natural way as-if we'd always
the algorithm to the actual current position. */
goto start;
- for (; m_inf != NULL; m_inf = m_inf->next)
- if (m_inf_matches ())
- {
- thr_iter = m_inf->thread_list.begin ();
- while (thr_iter != m_inf->thread_list.end ())
- {
- if (thr_iter->ptid.matches (m_filter_ptid))
- {
- m_thr = &*thr_iter;
- return;
- }
- start:
- ++thr_iter;
- }
- }
+ for (; inf_iter != inferior_list.end (); ++inf_iter)
+ {
+ m_inf = &*inf_iter;
+ if (m_inf_matches ())
+ {
+ thr_iter = m_inf->thread_list.begin ();
+ while (thr_iter != m_inf->thread_list.end ())
+ {
+ if (thr_iter->ptid.matches (m_filter_ptid))
+ {
+ m_thr = &*thr_iter;
+ return;
+ }
+ start:
+ ++thr_iter;
+ }
+ }
+ }
m_thr = nullptr;
}
int
show_inferior_qualified_tids (void)
{
- return (inferior_list->next != NULL || inferior_list->num != 1);
+ auto inf = inferior_list.begin ();
+ if (inf->num != 1)
+ return true;
+ ++inf;
+ return inf != inferior_list.end ();
}
/* See gdbthread.h. */