blob: bd112f64fcc2982946da0e9ba62706ab202e1e19 [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();
317
318 // Give all the threads a last chance to set up their state before we
319 // negotiate who is actually going to get a chance to run...
320
321 for (pos = m_threads.begin(); pos != end; ++pos)
322 (*pos)->SetupForResume ();
323
324 // Now go through the threads and see if any thread wants to run just itself.
325 // if so then pick one and run it.
326 ThreadList run_me_only_list (m_process);
327
328 run_me_only_list.SetStopID(m_process->GetStopID());
329
330 ThreadSP immediate_thread_sp;
331 bool run_only_current_thread = false;
332
333 for (pos = m_threads.begin(); pos != end; ++pos)
334 {
335 ThreadSP thread_sp(*pos);
336 if (thread_sp->GetCurrentPlan()->IsImmediate())
337 {
338 // We first do all the immediate plans, so if we find one, set
339 // immediate_thread_sp and break out, and we'll pick it up first thing
340 // when we're negotiating which threads get to run.
341 immediate_thread_sp = thread_sp;
342 break;
343 }
344 else if (thread_sp->GetResumeState() != eStateSuspended &&
345 thread_sp->GetCurrentPlan()->StopOthers())
346 {
347 // You can't say "stop others" and also want yourself to be suspended.
348 assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
349
350 if (thread_sp == GetCurrentThread())
351 {
352 run_only_current_thread = true;
353 run_me_only_list.Clear();
354 run_me_only_list.AddThread (thread_sp);
355 break;
356 }
357
358 run_me_only_list.AddThread (thread_sp);
359 }
360
361 }
362
363 if (immediate_thread_sp)
364 {
365 for (pos = m_threads.begin(); pos != end; ++pos)
366 {
367 ThreadSP thread_sp(*pos);
368 if (thread_sp.get() == immediate_thread_sp.get())
369 thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState());
370 else
371 thread_sp->WillResume (eStateSuspended);
372 }
373 }
374 else if (run_me_only_list.GetSize (false) == 0)
375 {
376 // Everybody runs as they wish:
377 for (pos = m_threads.begin(); pos != end; ++pos)
378 {
379 ThreadSP thread_sp(*pos);
380 thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState());
381 }
382 }
383 else
384 {
385 ThreadSP thread_to_run;
386
387 if (run_only_current_thread)
388 {
389 thread_to_run = GetCurrentThread();
390 }
391 else if (run_me_only_list.GetSize (false) == 1)
392 {
393 thread_to_run = run_me_only_list.GetThreadAtIndex (0);
394 }
395 else
396 {
397 int random_thread = (int)
398 ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0));
399 thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread);
400 }
401
402 for (pos = m_threads.begin(); pos != end; ++pos)
403 {
404 ThreadSP thread_sp(*pos);
405 if (thread_sp == thread_to_run)
406 thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState());
407 else
408 thread_sp->WillResume (eStateSuspended);
409 }
410 }
411
412 return success;
413}
414
415void
416ThreadList::DidResume ()
417{
418 collection::iterator pos, end = m_threads.end();
419 for (pos = m_threads.begin(); pos != end; ++pos)
420 {
421 // Don't clear out threads that aren't going to get a chance to run, rather
422 // leave their state for the next time around.
423 ThreadSP thread_sp(*pos);
424 if (thread_sp->GetResumeState() != eStateSuspended)
425 thread_sp->DidResume ();
426 }
427}
428
429ThreadSP
430ThreadList::GetCurrentThread ()
431{
432 Mutex::Locker locker(m_threads_mutex);
433 return FindThreadByID(m_current_tid);
434}
435
436bool
437ThreadList::SetCurrentThreadByID (lldb::tid_t tid)
438{
439 Mutex::Locker locker(m_threads_mutex);
440 if (FindThreadByID(tid).get())
441 m_current_tid = tid;
442 else
443 m_current_tid = LLDB_INVALID_THREAD_ID;
444
445 return m_current_tid != LLDB_INVALID_THREAD_ID;
446}
447
448bool
449ThreadList::SetCurrentThreadByIndexID (uint32_t index_id)
450{
451 Mutex::Locker locker(m_threads_mutex);
452 ThreadSP thread_sp (FindThreadByIndexID(index_id));
453 if (thread_sp.get())
454 m_current_tid = thread_sp->GetID();
455 else
456 m_current_tid = LLDB_INVALID_THREAD_ID;
457
458 return m_current_tid != LLDB_INVALID_THREAD_ID;
459}
460