blob: c0d5c6ab5c6ededc9ab9d4bd00d0370b4beb7ccc [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- ThreadList.cpp ------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include <stdlib.h>
10
11#include <algorithm>
12
13#include "lldb/Target/ThreadList.h"
14#include "lldb/Target/Thread.h"
15#include "lldb/Target/ThreadPlan.h"
16#include "lldb/Target/Process.h"
17
18using namespace lldb;
19using namespace lldb_private;
20
21ThreadList::ThreadList (Process *process) :
22 m_process (process),
23 m_stop_id (0),
24 m_threads(),
25 m_threads_mutex (Mutex::eMutexTypeRecursive),
26 m_current_tid (LLDB_INVALID_THREAD_ID)
27{
28}
29
30ThreadList::ThreadList (const ThreadList &rhs) :
31 m_process (),
32 m_stop_id (),
33 m_threads (),
34 m_threads_mutex (Mutex::eMutexTypeRecursive),
35 m_current_tid ()
36{
37 // Use the assignment operator since it uses the mutex
38 *this = rhs;
39}
40
41const ThreadList&
42ThreadList::operator = (const ThreadList& rhs)
43{
44 if (this != &rhs)
45 {
46 // Lock both mutexes to make sure neither side changes anyone on us
47 // while the assignement occurs
Greg Claytonbef15832010-07-14 00:18:15 +000048 Mutex::Locker locker_lhs(m_threads_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +000049 Mutex::Locker locker_rhs(rhs.m_threads_mutex);
50 m_process = rhs.m_process;
51 m_stop_id = rhs.m_stop_id;
52 m_threads = rhs.m_threads;
53 m_current_tid = rhs.m_current_tid;
54 }
55 return *this;
56}
57
58
59ThreadList::~ThreadList()
60{
61}
62
63
64uint32_t
65ThreadList::GetStopID () const
66{
67 return m_stop_id;
68}
69
70void
71ThreadList::SetStopID (uint32_t stop_id)
72{
73 m_stop_id = stop_id;
74}
75
76
77void
78ThreadList::AddThread (ThreadSP &thread_sp)
79{
80 Mutex::Locker locker(m_threads_mutex);
81 m_threads.push_back(thread_sp);
82}
83
84uint32_t
85ThreadList::GetSize (bool can_update)
86{
87 Mutex::Locker locker(m_threads_mutex);
88 if (can_update)
89 m_process->UpdateThreadListIfNeeded();
90 return m_threads.size();
91}
92
93ThreadSP
94ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update)
95{
96 Mutex::Locker locker(m_threads_mutex);
97 if (can_update)
98 m_process->UpdateThreadListIfNeeded();
99
100 ThreadSP thread_sp;
101 if (idx < m_threads.size())
102 thread_sp = m_threads[idx];
103 return thread_sp;
104}
105
106ThreadSP
107ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update)
108{
109 Mutex::Locker locker(m_threads_mutex);
110
111 if (can_update)
112 m_process->UpdateThreadListIfNeeded();
113
114 ThreadSP thread_sp;
115 uint32_t idx = 0;
116 const uint32_t num_threads = m_threads.size();
117 for (idx = 0; idx < num_threads; ++idx)
118 {
119 if (m_threads[idx]->GetID() == tid)
120 {
121 thread_sp = m_threads[idx];
122 break;
123 }
124 }
125 return thread_sp;
126}
127
128ThreadSP
129ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr)
130{
131 ThreadSP thread_sp;
132 if (thread_ptr)
133 {
134 Mutex::Locker locker(m_threads_mutex);
135
136 uint32_t idx = 0;
137 const uint32_t num_threads = m_threads.size();
138 for (idx = 0; idx < num_threads; ++idx)
139 {
140 if (m_threads[idx].get() == thread_ptr)
141 {
142 thread_sp = m_threads[idx];
143 break;
144 }
145 }
146 }
147 return thread_sp;
148}
149
150
151
152ThreadSP
153ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update)
154{
155 Mutex::Locker locker(m_threads_mutex);
156
157 if (can_update)
158 m_process->UpdateThreadListIfNeeded();
159
160 ThreadSP thread_sp;
161 const uint32_t num_threads = m_threads.size();
162 for (uint32_t idx = 0; idx < num_threads; ++idx)
163 {
164 if (m_threads[idx]->GetIndexID() == index_id)
165 {
166 thread_sp = m_threads[idx];
167 break;
168 }
169 }
170 return thread_sp;
171}
172
173bool
174ThreadList::ShouldStop (Event *event_ptr)
175{
176 Mutex::Locker locker(m_threads_mutex);
177
178 // Running events should never stop, obviously...
179
180
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000181 bool should_stop = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000182 m_process->UpdateThreadListIfNeeded();
183
184 collection::iterator pos, end = m_threads.end();
185
186 // Run through the threads and ask whether we should stop. Don't ask
187 // suspended threads, however, it makes more sense for them to preserve their
188 // state across the times the process runs but they don't get a chance to.
189 for (pos = m_threads.begin(); pos != end; ++pos)
190 {
191 ThreadSP thread_sp(*pos);
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000192 if ((thread_sp->GetResumeState () != eStateSuspended) && (thread_sp->ThreadStoppedForAReason()))
Chris Lattner24943d22010-06-08 16:52:24 +0000193 {
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000194 should_stop |= thread_sp->ShouldStop(event_ptr);
Chris Lattner24943d22010-06-08 16:52:24 +0000195 }
196 }
Jim Ingham5a47e8b2010-06-19 04:45:32 +0000197
Chris Lattner24943d22010-06-08 16:52:24 +0000198 if (should_stop)
199 {
200 for (pos = m_threads.begin(); pos != end; ++pos)
201 {
202 ThreadSP thread_sp(*pos);
203 thread_sp->WillStop ();
204 }
205 }
206
207 return should_stop;
208}
209
210Vote
211ThreadList::ShouldReportStop (Event *event_ptr)
212{
213 Vote result = eVoteNoOpinion;
214 m_process->UpdateThreadListIfNeeded();
215 collection::iterator pos, end = m_threads.end();
216
217 // Run through the threads and ask whether we should report this event.
218 // For stopping, a YES vote wins over everything. A NO vote wins over NO opinion.
219 for (pos = m_threads.begin(); pos != end; ++pos)
220 {
221 ThreadSP thread_sp(*pos);
222 if (thread_sp->ThreadStoppedForAReason() && (thread_sp->GetResumeState () != eStateSuspended))
223 {
224 switch (thread_sp->ShouldReportStop (event_ptr))
225 {
226 case eVoteNoOpinion:
227 continue;
228 case eVoteYes:
229 result = eVoteYes;
230 break;
231 case eVoteNo:
232 if (result == eVoteNoOpinion)
233 result = eVoteNo;
234 break;
235 }
236 }
237 }
238 return result;
239}
240
241Vote
242ThreadList::ShouldReportRun (Event *event_ptr)
243{
244 Vote result = eVoteNoOpinion;
245 m_process->UpdateThreadListIfNeeded();
246 collection::iterator pos, end = m_threads.end();
247
248 // Run through the threads and ask whether we should report this event.
249 // The rule is NO vote wins over everything, a YES vote wins over no opinion.
250
251 for (pos = m_threads.begin(); pos != end; ++pos)
252 {
253 ThreadSP thread_sp(*pos);
254 if (thread_sp->GetResumeState () != eStateSuspended)
255
256 switch (thread_sp->ShouldReportRun (event_ptr))
257 {
258 case eVoteNoOpinion:
259 continue;
260 case eVoteYes:
261 if (result == eVoteNoOpinion)
262 result = eVoteYes;
263 break;
264 case eVoteNo:
265 result = eVoteNo;
266 break;
267 }
268 }
269 return result;
270}
271
272void
273ThreadList::Clear()
274{
275 m_stop_id = 0;
276 m_threads.clear();
277 m_current_tid = LLDB_INVALID_THREAD_ID;
278}
279
280void
281ThreadList::RefreshStateAfterStop ()
282{
283 Mutex::Locker locker(m_threads_mutex);
284
285 m_process->UpdateThreadListIfNeeded();
286
287 collection::iterator pos, end = m_threads.end();
288 for (pos = m_threads.begin(); pos != end; ++pos)
289 (*pos)->RefreshStateAfterStop ();
290}
291
292void
293ThreadList::DiscardThreadPlans ()
294{
295 // You don't need to update the thread list here, because only threads
296 // that you currently know about have any thread plans.
297 Mutex::Locker locker(m_threads_mutex);
298
299 collection::iterator pos, end = m_threads.end();
300 for (pos = m_threads.begin(); pos != end; ++pos)
301 (*pos)->DiscardThreadPlans (true);
302
303}
304
305bool
306ThreadList::WillResume ()
307{
308 // Run through the threads and perform their momentary actions.
309 // But we only do this for threads that are running, user suspended
310 // threads stay where they are.
311 bool success = true;
312
313 Mutex::Locker locker(m_threads_mutex);
314 m_process->UpdateThreadListIfNeeded();
315
316 collection::iterator pos, end = m_threads.end();
Chris Lattner24943d22010-06-08 16:52:24 +0000317
Jim Inghama99afce2010-07-14 02:27:20 +0000318 // See if any thread wants to run stopping others. If it does, then we won't
319 // setup the other threads for resume, since they aren't going to get a chance
320 // to run. This is necessary because the SetupForResume might add "StopOthers"
321 // plans which would then get to be part of the who-gets-to-run negotiation, but
322 // they're coming in after the fact, and the threads that are already set up should
323 // take priority.
Chris Lattner24943d22010-06-08 16:52:24 +0000324
Jim Inghama99afce2010-07-14 02:27:20 +0000325 bool wants_solo_run = false;
326
327 for (pos = m_threads.begin(); pos != end; ++pos)
328 {
329 if ((*pos)->GetResumeState() != eStateSuspended &&
330 (*pos)->GetCurrentPlan()->StopOthers())
331 {
332 wants_solo_run = true;
333 break;
334 }
335 }
336
337
338 // Give all the threads that are likely to run a last chance to set up their state before we
339 // negotiate who is actually going to get a chance to run...
340 // Don't set to resume suspended threads, and if any thread wanted to stop others, only
341 // call setup on the threads that request StopOthers...
342
343 for (pos = m_threads.begin(); pos != end; ++pos)
344 {
345 if ((*pos)->GetResumeState() != eStateSuspended
346 && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers()))
347 {
348 (*pos)->SetupForResume ();
349 }
350 }
351
Chris Lattner24943d22010-06-08 16:52:24 +0000352 // Now go through the threads and see if any thread wants to run just itself.
353 // if so then pick one and run it.
Jim Inghama99afce2010-07-14 02:27:20 +0000354
Chris Lattner24943d22010-06-08 16:52:24 +0000355 ThreadList run_me_only_list (m_process);
356
357 run_me_only_list.SetStopID(m_process->GetStopID());
358
359 ThreadSP immediate_thread_sp;
360 bool run_only_current_thread = false;
361
362 for (pos = m_threads.begin(); pos != end; ++pos)
363 {
364 ThreadSP thread_sp(*pos);
365 if (thread_sp->GetCurrentPlan()->IsImmediate())
366 {
367 // We first do all the immediate plans, so if we find one, set
368 // immediate_thread_sp and break out, and we'll pick it up first thing
369 // when we're negotiating which threads get to run.
370 immediate_thread_sp = thread_sp;
371 break;
372 }
373 else if (thread_sp->GetResumeState() != eStateSuspended &&
374 thread_sp->GetCurrentPlan()->StopOthers())
375 {
376 // You can't say "stop others" and also want yourself to be suspended.
377 assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
378
379 if (thread_sp == GetCurrentThread())
380 {
381 run_only_current_thread = true;
382 run_me_only_list.Clear();
383 run_me_only_list.AddThread (thread_sp);
384 break;
385 }
386
387 run_me_only_list.AddThread (thread_sp);
388 }
389
390 }
391
392 if (immediate_thread_sp)
393 {
394 for (pos = m_threads.begin(); pos != end; ++pos)
395 {
396 ThreadSP thread_sp(*pos);
397 if (thread_sp.get() == immediate_thread_sp.get())
398 thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState());
399 else
400 thread_sp->WillResume (eStateSuspended);
401 }
402 }
403 else if (run_me_only_list.GetSize (false) == 0)
404 {
405 // Everybody runs as they wish:
406 for (pos = m_threads.begin(); pos != end; ++pos)
407 {
408 ThreadSP thread_sp(*pos);
409 thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState());
410 }
411 }
412 else
413 {
414 ThreadSP thread_to_run;
415
416 if (run_only_current_thread)
417 {
418 thread_to_run = GetCurrentThread();
419 }
420 else if (run_me_only_list.GetSize (false) == 1)
421 {
422 thread_to_run = run_me_only_list.GetThreadAtIndex (0);
423 }
424 else
425 {
426 int random_thread = (int)
427 ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0));
428 thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread);
429 }
430
431 for (pos = m_threads.begin(); pos != end; ++pos)
432 {
433 ThreadSP thread_sp(*pos);
434 if (thread_sp == thread_to_run)
435 thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState());
436 else
437 thread_sp->WillResume (eStateSuspended);
438 }
439 }
440
441 return success;
442}
443
444void
445ThreadList::DidResume ()
446{
447 collection::iterator pos, end = m_threads.end();
448 for (pos = m_threads.begin(); pos != end; ++pos)
449 {
450 // Don't clear out threads that aren't going to get a chance to run, rather
451 // leave their state for the next time around.
452 ThreadSP thread_sp(*pos);
453 if (thread_sp->GetResumeState() != eStateSuspended)
454 thread_sp->DidResume ();
455 }
456}
457
458ThreadSP
459ThreadList::GetCurrentThread ()
460{
461 Mutex::Locker locker(m_threads_mutex);
462 return FindThreadByID(m_current_tid);
463}
464
465bool
466ThreadList::SetCurrentThreadByID (lldb::tid_t tid)
467{
468 Mutex::Locker locker(m_threads_mutex);
469 if (FindThreadByID(tid).get())
470 m_current_tid = tid;
471 else
472 m_current_tid = LLDB_INVALID_THREAD_ID;
473
474 return m_current_tid != LLDB_INVALID_THREAD_ID;
475}
476
477bool
478ThreadList::SetCurrentThreadByIndexID (uint32_t index_id)
479{
480 Mutex::Locker locker(m_threads_mutex);
481 ThreadSP thread_sp (FindThreadByIndexID(index_id));
482 if (thread_sp.get())
483 m_current_tid = thread_sp->GetID();
484 else
485 m_current_tid = LLDB_INVALID_THREAD_ID;
486
487 return m_current_tid != LLDB_INVALID_THREAD_ID;
488}
489