1 //===-- SBQueue.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 
10 #include "lldb/lldb-python.h"
11 
12 #include <inttypes.h>
13 
14 #include "lldb/API/SBQueue.h"
15 
16 #include "lldb/API/SBProcess.h"
17 #include "lldb/API/SBThread.h"
18 #include "lldb/API/SBQueueItem.h"
19 
20 #include "lldb/Core/Log.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/Queue.h"
23 #include "lldb/Target/QueueItem.h"
24 #include "lldb/Target/Thread.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 namespace lldb_private
30 {
31 
32     class QueueImpl
33     {
34     public:
35         QueueImpl () :
36             m_queue_wp(),
37             m_threads(),
38             m_thread_list_fetched(false),
39             m_pending_items(),
40             m_pending_items_fetched(false)
41         {
42         }
43 
44         QueueImpl (const lldb::QueueSP &queue_sp) :
45             m_queue_wp(),
46             m_threads(),
47             m_thread_list_fetched(false),
48             m_pending_items(),
49             m_pending_items_fetched(false)
50         {
51             m_queue_wp = queue_sp;
52         }
53 
54         QueueImpl (const QueueImpl &rhs)
55         {
56             if (&rhs == this)
57                 return;
58             m_queue_wp = rhs.m_queue_wp;
59             m_threads = rhs.m_threads;
60             m_thread_list_fetched = rhs.m_thread_list_fetched;
61             m_pending_items = rhs.m_pending_items;
62             m_pending_items_fetched = rhs.m_pending_items_fetched;
63         }
64 
65         ~QueueImpl ()
66         {
67         }
68 
69         bool
70         IsValid ()
71         {
72             return m_queue_wp.lock() != NULL;
73         }
74 
75         void
76         Clear ()
77         {
78             m_queue_wp.reset();
79             m_thread_list_fetched = false;
80             m_threads.clear();
81             m_pending_items_fetched = false;
82             m_pending_items.clear();
83         }
84 
85         void
86         SetQueue (const lldb::QueueSP &queue_sp)
87         {
88             Clear();
89             m_queue_wp = queue_sp;
90         }
91 
92         lldb::queue_id_t
93         GetQueueID () const
94         {
95             lldb::queue_id_t result = LLDB_INVALID_QUEUE_ID;
96             lldb::QueueSP queue_sp = m_queue_wp.lock();
97             if (queue_sp)
98             {
99                 result = queue_sp->GetID();
100             }
101             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
102             if (log)
103                 log->Printf ("SBQueue(%p)::GetQueueID () => 0x%" PRIx64,
104                              static_cast<const void*>(this), result);
105             return result;
106         }
107 
108         uint32_t
109         GetIndexID () const
110         {
111             uint32_t result = LLDB_INVALID_INDEX32;
112             lldb::QueueSP queue_sp = m_queue_wp.lock();
113             if (queue_sp)
114             {
115                 result = queue_sp->GetIndexID();
116             }
117             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
118             if (log)
119                 log->Printf ("SBQueueImpl(%p)::GetIndexID () => %d",
120                              static_cast<const void*>(this), result);
121             return result;
122         }
123 
124         const char *
125         GetName () const
126         {
127             const char *name = NULL;
128             lldb::QueueSP queue_sp = m_queue_wp.lock ();
129             if (queue_sp.get())
130             {
131                 name = queue_sp->GetName();
132             }
133 
134             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
135             if (log)
136                 log->Printf ("SBQueueImpl(%p)::GetName () => %s",
137                              static_cast<const void*>(this),
138                              name ? name : "NULL");
139 
140             return name;
141         }
142 
143         void
144         FetchThreads ()
145         {
146             if (m_thread_list_fetched == false)
147             {
148                 lldb::QueueSP queue_sp = m_queue_wp.lock();
149                 if (queue_sp)
150                 {
151                     Process::StopLocker stop_locker;
152                     if (stop_locker.TryLock (&queue_sp->GetProcess()->GetRunLock()))
153                     {
154                         const std::vector<ThreadSP> thread_list(queue_sp->GetThreads());
155                         m_thread_list_fetched = true;
156                         const uint32_t num_threads = thread_list.size();
157                         for (uint32_t idx = 0; idx < num_threads; ++idx)
158                         {
159                             ThreadSP thread_sp = thread_list[idx];
160                             if (thread_sp && thread_sp->IsValid())
161                             {
162                                 m_threads.push_back (thread_sp);
163                             }
164                         }
165                     }
166                 }
167             }
168         }
169 
170         void
171         FetchItems ()
172         {
173             if (m_pending_items_fetched == false)
174             {
175                 QueueSP queue_sp = m_queue_wp.lock();
176                 if (queue_sp)
177                 {
178                     Process::StopLocker stop_locker;
179                     if (stop_locker.TryLock (&queue_sp->GetProcess()->GetRunLock()))
180                     {
181                         const std::vector<QueueItemSP> queue_items(queue_sp->GetPendingItems());
182                         m_pending_items_fetched = true;
183                         const uint32_t num_pending_items = queue_items.size();
184                         for (uint32_t idx = 0; idx < num_pending_items; ++idx)
185                         {
186                             QueueItemSP item = queue_items[idx];
187                             if (item && item->IsValid())
188                             {
189                                 m_pending_items.push_back (item);
190                             }
191                         }
192                     }
193                 }
194             }
195         }
196 
197         uint32_t
198         GetNumThreads ()
199         {
200             uint32_t result = 0;
201 
202             FetchThreads();
203             if (m_thread_list_fetched)
204             {
205                 result = m_threads.size();
206             }
207             return result;
208         }
209 
210         lldb::SBThread
211         GetThreadAtIndex (uint32_t idx)
212         {
213             FetchThreads();
214 
215             SBThread sb_thread;
216             QueueSP queue_sp = m_queue_wp.lock();
217             if (queue_sp && idx < m_threads.size())
218             {
219                 ProcessSP process_sp = queue_sp->GetProcess();
220                 if (process_sp)
221                 {
222                     ThreadSP thread_sp = m_threads[idx].lock();
223                     if (thread_sp)
224                     {
225                         sb_thread.SetThread (thread_sp);
226                     }
227                 }
228             }
229             return sb_thread;
230         }
231 
232         uint32_t
233         GetNumPendingItems ()
234         {
235             uint32_t result = 0;
236 
237             QueueSP queue_sp = m_queue_wp.lock();
238             if (m_pending_items_fetched == false && queue_sp)
239             {
240                 result = queue_sp->GetNumPendingWorkItems();
241             }
242             else
243             {
244                 result = m_pending_items.size();
245             }
246             return result;
247         }
248 
249         lldb::SBQueueItem
250         GetPendingItemAtIndex (uint32_t idx)
251         {
252             SBQueueItem result;
253             FetchItems();
254             if (m_pending_items_fetched && idx < m_pending_items.size())
255             {
256                 result.SetQueueItem (m_pending_items[idx]);
257             }
258             return result;
259         }
260 
261         uint32_t
262         GetNumRunningItems ()
263         {
264             uint32_t result = 0;
265             QueueSP queue_sp = m_queue_wp.lock();
266             if (queue_sp)
267                 result = queue_sp->GetNumRunningWorkItems();
268             return result;
269         }
270 
271         lldb::SBProcess
272         GetProcess ()
273         {
274             SBProcess result;
275             QueueSP queue_sp = m_queue_wp.lock();
276             if (queue_sp)
277             {
278                 result.SetSP (queue_sp->GetProcess());
279             }
280             return result;
281         }
282 
283         lldb::QueueKind
284         GetKind ()
285         {
286             lldb::QueueKind kind = eQueueKindUnknown;
287             QueueSP queue_sp = m_queue_wp.lock();
288             if (queue_sp)
289                 kind = queue_sp->GetKind();
290 
291             return kind;
292         }
293 
294     private:
295         lldb::QueueWP                   m_queue_wp;
296         std::vector<lldb::ThreadWP>     m_threads;              // threads currently executing this queue's items
297         bool                            m_thread_list_fetched;  // have we tried to fetch the threads list already?
298         std::vector<lldb::QueueItemSP>  m_pending_items;       // items currently enqueued
299         bool                            m_pending_items_fetched;  // have we tried to fetch the item list already?
300     };
301 
302 }
303 
304 SBQueue::SBQueue () :
305     m_opaque_sp (new QueueImpl())
306 {
307 }
308 
309 SBQueue::SBQueue (const QueueSP& queue_sp) :
310     m_opaque_sp (new QueueImpl (queue_sp))
311 {
312 }
313 
314 SBQueue::SBQueue (const SBQueue &rhs)
315 {
316     if (&rhs == this)
317         return;
318 
319     m_opaque_sp = rhs.m_opaque_sp;
320 }
321 
322 const lldb::SBQueue &
323 SBQueue::operator = (const lldb::SBQueue &rhs)
324 {
325     m_opaque_sp = rhs.m_opaque_sp;
326     return *this;
327 }
328 
329 SBQueue::~SBQueue()
330 {
331 }
332 
333 bool
334 SBQueue::IsValid() const
335 {
336     bool is_valid = m_opaque_sp->IsValid ();
337     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
338     if (log)
339         log->Printf("SBQueue(0x%" PRIx64 ")::IsValid() == %s", m_opaque_sp->GetQueueID(),
340                     is_valid ? "true" : "false");
341     return is_valid;
342 }
343 
344 
345 void
346 SBQueue::Clear ()
347 {
348     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
349     if (log)
350         log->Printf("SBQueue(0x%" PRIx64 ")::Clear()", m_opaque_sp->GetQueueID());
351     m_opaque_sp->Clear();
352 }
353 
354 
355 void
356 SBQueue::SetQueue (const QueueSP& queue_sp)
357 {
358     m_opaque_sp->SetQueue (queue_sp);
359 }
360 
361 lldb::queue_id_t
362 SBQueue::GetQueueID () const
363 {
364     lldb::queue_id_t qid = m_opaque_sp->GetQueueID ();
365     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
366     if (log)
367         log->Printf("SBQueue(0x%" PRIx64 ")::GetQueueID() == 0x%" PRIx64, m_opaque_sp->GetQueueID(), (uint64_t) qid);
368     return qid;
369 }
370 
371 uint32_t
372 SBQueue::GetIndexID () const
373 {
374     uint32_t index_id = m_opaque_sp->GetIndexID ();
375     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
376     if (log)
377         log->Printf("SBQueue(0x%" PRIx64 ")::GetIndexID() == 0x%" PRIx32, m_opaque_sp->GetQueueID(), index_id);
378     return index_id;
379 }
380 
381 const char *
382 SBQueue::GetName () const
383 {
384     const char *name = m_opaque_sp->GetName ();
385     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
386     if (log)
387         log->Printf("SBQueue(0x%" PRIx64 ")::GetName() == %s", m_opaque_sp->GetQueueID(),
388                      name ? name : "");
389     return name;
390 }
391 
392 uint32_t
393 SBQueue::GetNumThreads ()
394 {
395     uint32_t numthreads = m_opaque_sp->GetNumThreads ();
396     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
397     if (log)
398         log->Printf("SBQueue(0x%" PRIx64 ")::GetNumThreads() == %d", m_opaque_sp->GetQueueID(), numthreads);
399     return numthreads;
400 }
401 
402 SBThread
403 SBQueue::GetThreadAtIndex (uint32_t idx)
404 {
405     SBThread th = m_opaque_sp->GetThreadAtIndex (idx);
406     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
407     if (log)
408         log->Printf("SBQueue(0x%" PRIx64 ")::GetThreadAtIndex(%d)", m_opaque_sp->GetQueueID(), idx);
409     return th;
410 }
411 
412 
413 uint32_t
414 SBQueue::GetNumPendingItems ()
415 {
416     uint32_t pending_items = m_opaque_sp->GetNumPendingItems ();
417     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
418     if (log)
419         log->Printf("SBQueue(0x%" PRIx64 ")::GetNumPendingItems() == %d", m_opaque_sp->GetQueueID(), pending_items);
420     return pending_items;
421 }
422 
423 SBQueueItem
424 SBQueue::GetPendingItemAtIndex (uint32_t idx)
425 {
426     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
427     if (log)
428         log->Printf("SBQueue(0x%" PRIx64 ")::GetPendingItemAtIndex(%d)", m_opaque_sp->GetQueueID(),  idx);
429     return m_opaque_sp->GetPendingItemAtIndex (idx);
430 }
431 
432 uint32_t
433 SBQueue::GetNumRunningItems ()
434 {
435     uint32_t running_items = m_opaque_sp->GetNumRunningItems ();
436     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
437     if (log)
438         log->Printf("SBQueue(0x%" PRIx64 ")::GetNumRunningItems() == %d", m_opaque_sp->GetQueueID(), running_items);
439     return running_items;
440 }
441 
442 SBProcess
443 SBQueue::GetProcess ()
444 {
445     return m_opaque_sp->GetProcess();
446 }
447 
448 lldb::QueueKind
449 SBQueue::GetKind ()
450 {
451     return m_opaque_sp->GetKind();
452 }
453