thread-iter.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* Thread iterators and ranges for GDB, the GNU debugger.
  2. Copyright (C) 2018-2022 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #include "defs.h"
  15. #include "gdbthread.h"
  16. #include "inferior.h"
  17. /* See thread-iter.h. */
  18. all_threads_iterator::all_threads_iterator (begin_t)
  19. {
  20. /* Advance M_INF/M_THR to the first thread's position. */
  21. for (inferior &inf : inferior_list)
  22. {
  23. auto thr_iter = inf.thread_list.begin ();
  24. if (thr_iter != inf.thread_list.end ())
  25. {
  26. m_inf = &inf;
  27. m_thr = &*thr_iter;
  28. return;
  29. }
  30. }
  31. m_inf = nullptr;
  32. m_thr = nullptr;
  33. }
  34. /* See thread-iter.h. */
  35. void
  36. all_threads_iterator::advance ()
  37. {
  38. intrusive_list<inferior>::iterator inf_iter (m_inf);
  39. intrusive_list<thread_info>::iterator thr_iter (m_thr);
  40. /* The loop below is written in the natural way as-if we'd always
  41. start at the beginning of the inferior list. This fast forwards
  42. the algorithm to the actual current position. */
  43. goto start;
  44. for (; inf_iter != inferior_list.end (); ++inf_iter)
  45. {
  46. m_inf = &*inf_iter;
  47. thr_iter = m_inf->thread_list.begin ();
  48. while (thr_iter != m_inf->thread_list.end ())
  49. {
  50. m_thr = &*thr_iter;
  51. return;
  52. start:
  53. ++thr_iter;
  54. }
  55. }
  56. m_thr = nullptr;
  57. }
  58. /* See thread-iter.h. */
  59. bool
  60. all_matching_threads_iterator::m_inf_matches ()
  61. {
  62. return (m_filter_target == nullptr
  63. || m_filter_target == m_inf->process_target ());
  64. }
  65. /* See thread-iter.h. */
  66. all_matching_threads_iterator::all_matching_threads_iterator
  67. (process_stratum_target *filter_target, ptid_t filter_ptid)
  68. : m_filter_target (filter_target)
  69. {
  70. if (filter_ptid == minus_one_ptid)
  71. {
  72. /* Iterate on all threads of all inferiors, possibly filtering on
  73. FILTER_TARGET. */
  74. m_mode = mode::ALL_THREADS;
  75. /* Seek the first thread of the first matching inferior. */
  76. for (inferior &inf : inferior_list)
  77. {
  78. m_inf = &inf;
  79. if (!m_inf_matches ()
  80. || inf.thread_list.empty ())
  81. continue;
  82. m_thr = &inf.thread_list.front ();
  83. return;
  84. }
  85. }
  86. else
  87. {
  88. gdb_assert (filter_target != nullptr);
  89. if (filter_ptid.is_pid ())
  90. {
  91. /* Iterate on all threads of the given inferior. */
  92. m_mode = mode::ALL_THREADS_OF_INFERIOR;
  93. m_inf = find_inferior_pid (filter_target, filter_ptid.pid ());
  94. if (m_inf != nullptr)
  95. m_thr = &m_inf->thread_list.front ();
  96. }
  97. else
  98. {
  99. /* Iterate on a single thread. */
  100. m_mode = mode::SINGLE_THREAD;
  101. m_thr = find_thread_ptid (filter_target, filter_ptid);
  102. }
  103. }
  104. }
  105. /* See thread-iter.h. */
  106. void
  107. all_matching_threads_iterator::advance ()
  108. {
  109. switch (m_mode)
  110. {
  111. case mode::ALL_THREADS:
  112. {
  113. intrusive_list<inferior>::iterator inf_iter (m_inf);
  114. intrusive_list<thread_info>::iterator thr_iter
  115. = m_inf->thread_list.iterator_to (*m_thr);
  116. /* The loop below is written in the natural way as-if we'd always
  117. start at the beginning of the inferior list. This fast forwards
  118. the algorithm to the actual current position. */
  119. goto start;
  120. for (; inf_iter != inferior_list.end (); ++inf_iter)
  121. {
  122. m_inf = &*inf_iter;
  123. if (!m_inf_matches ())
  124. continue;
  125. thr_iter = m_inf->thread_list.begin ();
  126. while (thr_iter != m_inf->thread_list.end ())
  127. {
  128. m_thr = &*thr_iter;
  129. return;
  130. start:
  131. ++thr_iter;
  132. }
  133. }
  134. }
  135. m_thr = nullptr;
  136. break;
  137. case mode::ALL_THREADS_OF_INFERIOR:
  138. {
  139. intrusive_list<thread_info>::iterator thr_iter
  140. = m_inf->thread_list.iterator_to (*m_thr);
  141. ++thr_iter;
  142. if (thr_iter != m_inf->thread_list.end ())
  143. m_thr = &*thr_iter;
  144. else
  145. m_thr = nullptr;
  146. break;
  147. }
  148. case mode::SINGLE_THREAD:
  149. m_thr = nullptr;
  150. break;
  151. default:
  152. gdb_assert_not_reached ("invalid mode value");
  153. }
  154. }