xref: /openbsd-src/gnu/llvm/lldb/source/API/SBQueue.cpp (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 //===-- SBQueue.cpp -------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <cinttypes>
10 
11 #include "SBReproducerPrivate.h"
12 #include "lldb/API/SBQueue.h"
13 
14 #include "lldb/API/SBProcess.h"
15 #include "lldb/API/SBQueueItem.h"
16 #include "lldb/API/SBThread.h"
17 
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/Queue.h"
20 #include "lldb/Target/QueueItem.h"
21 #include "lldb/Target/Thread.h"
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 namespace lldb_private {
27 
28 class QueueImpl {
29 public:
30   QueueImpl() : m_queue_wp(), m_threads(), m_pending_items() {}
31 
32   QueueImpl(const lldb::QueueSP &queue_sp)
33       : m_queue_wp(), m_threads(), m_thread_list_fetched(false),
34         m_pending_items(), m_pending_items_fetched(false) {
35     m_queue_wp = queue_sp;
36   }
37 
38   QueueImpl(const QueueImpl &rhs) {
39     if (&rhs == this)
40       return;
41     m_queue_wp = rhs.m_queue_wp;
42     m_threads = rhs.m_threads;
43     m_thread_list_fetched = rhs.m_thread_list_fetched;
44     m_pending_items = rhs.m_pending_items;
45     m_pending_items_fetched = rhs.m_pending_items_fetched;
46   }
47 
48   ~QueueImpl() = default;
49 
50   bool IsValid() { return m_queue_wp.lock() != nullptr; }
51 
52   void Clear() {
53     m_queue_wp.reset();
54     m_thread_list_fetched = false;
55     m_threads.clear();
56     m_pending_items_fetched = false;
57     m_pending_items.clear();
58   }
59 
60   void SetQueue(const lldb::QueueSP &queue_sp) {
61     Clear();
62     m_queue_wp = queue_sp;
63   }
64 
65   lldb::queue_id_t GetQueueID() const {
66     lldb::queue_id_t result = LLDB_INVALID_QUEUE_ID;
67     lldb::QueueSP queue_sp = m_queue_wp.lock();
68     if (queue_sp) {
69       result = queue_sp->GetID();
70     }
71     return result;
72   }
73 
74   uint32_t GetIndexID() const {
75     uint32_t result = LLDB_INVALID_INDEX32;
76     lldb::QueueSP queue_sp = m_queue_wp.lock();
77     if (queue_sp) {
78       result = queue_sp->GetIndexID();
79     }
80     return result;
81   }
82 
83   const char *GetName() const {
84     const char *name = nullptr;
85     lldb::QueueSP queue_sp = m_queue_wp.lock();
86     if (queue_sp.get()) {
87       name = queue_sp->GetName();
88     }
89     return name;
90   }
91 
92   void FetchThreads() {
93     if (!m_thread_list_fetched) {
94       lldb::QueueSP queue_sp = m_queue_wp.lock();
95       if (queue_sp) {
96         Process::StopLocker stop_locker;
97         if (stop_locker.TryLock(&queue_sp->GetProcess()->GetRunLock())) {
98           const std::vector<ThreadSP> thread_list(queue_sp->GetThreads());
99           m_thread_list_fetched = true;
100           const uint32_t num_threads = thread_list.size();
101           for (uint32_t idx = 0; idx < num_threads; ++idx) {
102             ThreadSP thread_sp = thread_list[idx];
103             if (thread_sp && thread_sp->IsValid()) {
104               m_threads.push_back(thread_sp);
105             }
106           }
107         }
108       }
109     }
110   }
111 
112   void FetchItems() {
113     if (!m_pending_items_fetched) {
114       QueueSP queue_sp = m_queue_wp.lock();
115       if (queue_sp) {
116         Process::StopLocker stop_locker;
117         if (stop_locker.TryLock(&queue_sp->GetProcess()->GetRunLock())) {
118           const std::vector<QueueItemSP> queue_items(
119               queue_sp->GetPendingItems());
120           m_pending_items_fetched = true;
121           const uint32_t num_pending_items = queue_items.size();
122           for (uint32_t idx = 0; idx < num_pending_items; ++idx) {
123             QueueItemSP item = queue_items[idx];
124             if (item && item->IsValid()) {
125               m_pending_items.push_back(item);
126             }
127           }
128         }
129       }
130     }
131   }
132 
133   uint32_t GetNumThreads() {
134     uint32_t result = 0;
135 
136     FetchThreads();
137     if (m_thread_list_fetched) {
138       result = m_threads.size();
139     }
140     return result;
141   }
142 
143   lldb::SBThread GetThreadAtIndex(uint32_t idx) {
144     FetchThreads();
145 
146     SBThread sb_thread;
147     QueueSP queue_sp = m_queue_wp.lock();
148     if (queue_sp && idx < m_threads.size()) {
149       ProcessSP process_sp = queue_sp->GetProcess();
150       if (process_sp) {
151         ThreadSP thread_sp = m_threads[idx].lock();
152         if (thread_sp) {
153           sb_thread.SetThread(thread_sp);
154         }
155       }
156     }
157     return sb_thread;
158   }
159 
160   uint32_t GetNumPendingItems() {
161     uint32_t result = 0;
162 
163     QueueSP queue_sp = m_queue_wp.lock();
164     if (!m_pending_items_fetched && queue_sp) {
165       result = queue_sp->GetNumPendingWorkItems();
166     } else {
167       result = m_pending_items.size();
168     }
169     return result;
170   }
171 
172   lldb::SBQueueItem GetPendingItemAtIndex(uint32_t idx) {
173     SBQueueItem result;
174     FetchItems();
175     if (m_pending_items_fetched && idx < m_pending_items.size()) {
176       result.SetQueueItem(m_pending_items[idx]);
177     }
178     return result;
179   }
180 
181   uint32_t GetNumRunningItems() {
182     uint32_t result = 0;
183     QueueSP queue_sp = m_queue_wp.lock();
184     if (queue_sp)
185       result = queue_sp->GetNumRunningWorkItems();
186     return result;
187   }
188 
189   lldb::SBProcess GetProcess() {
190     SBProcess result;
191     QueueSP queue_sp = m_queue_wp.lock();
192     if (queue_sp) {
193       result.SetSP(queue_sp->GetProcess());
194     }
195     return result;
196   }
197 
198   lldb::QueueKind GetKind() {
199     lldb::QueueKind kind = eQueueKindUnknown;
200     QueueSP queue_sp = m_queue_wp.lock();
201     if (queue_sp)
202       kind = queue_sp->GetKind();
203 
204     return kind;
205   }
206 
207 private:
208   lldb::QueueWP m_queue_wp;
209   std::vector<lldb::ThreadWP>
210       m_threads; // threads currently executing this queue's items
211   bool m_thread_list_fetched =
212       false; // have we tried to fetch the threads list already?
213   std::vector<lldb::QueueItemSP> m_pending_items; // items currently enqueued
214   bool m_pending_items_fetched =
215       false; // have we tried to fetch the item list already?
216 };
217 }
218 
219 SBQueue::SBQueue() : m_opaque_sp(new QueueImpl()) {
220   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBQueue);
221 }
222 
223 SBQueue::SBQueue(const QueueSP &queue_sp)
224     : m_opaque_sp(new QueueImpl(queue_sp)) {
225   LLDB_RECORD_CONSTRUCTOR(SBQueue, (const lldb::QueueSP &), queue_sp);
226 }
227 
228 SBQueue::SBQueue(const SBQueue &rhs) {
229   LLDB_RECORD_CONSTRUCTOR(SBQueue, (const lldb::SBQueue &), rhs);
230 
231   if (&rhs == this)
232     return;
233 
234   m_opaque_sp = rhs.m_opaque_sp;
235 }
236 
237 const lldb::SBQueue &SBQueue::operator=(const lldb::SBQueue &rhs) {
238   LLDB_RECORD_METHOD(const lldb::SBQueue &,
239                      SBQueue, operator=,(const lldb::SBQueue &), rhs);
240 
241   m_opaque_sp = rhs.m_opaque_sp;
242   return LLDB_RECORD_RESULT(*this);
243 }
244 
245 SBQueue::~SBQueue() = default;
246 
247 bool SBQueue::IsValid() const {
248   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBQueue, IsValid);
249   return this->operator bool();
250 }
251 SBQueue::operator bool() const {
252   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBQueue, operator bool);
253 
254   return m_opaque_sp->IsValid();
255 }
256 
257 void SBQueue::Clear() {
258   LLDB_RECORD_METHOD_NO_ARGS(void, SBQueue, Clear);
259 
260   m_opaque_sp->Clear();
261 }
262 
263 void SBQueue::SetQueue(const QueueSP &queue_sp) {
264   m_opaque_sp->SetQueue(queue_sp);
265 }
266 
267 lldb::queue_id_t SBQueue::GetQueueID() const {
268   LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::queue_id_t, SBQueue, GetQueueID);
269 
270   return m_opaque_sp->GetQueueID();
271 }
272 
273 uint32_t SBQueue::GetIndexID() const {
274   LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBQueue, GetIndexID);
275 
276   uint32_t index_id = m_opaque_sp->GetIndexID();
277   return index_id;
278 }
279 
280 const char *SBQueue::GetName() const {
281   LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBQueue, GetName);
282 
283   return m_opaque_sp->GetName();
284 }
285 
286 uint32_t SBQueue::GetNumThreads() {
287   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBQueue, GetNumThreads);
288 
289   return m_opaque_sp->GetNumThreads();
290 }
291 
292 SBThread SBQueue::GetThreadAtIndex(uint32_t idx) {
293   LLDB_RECORD_METHOD(lldb::SBThread, SBQueue, GetThreadAtIndex, (uint32_t),
294                      idx);
295 
296   SBThread th = m_opaque_sp->GetThreadAtIndex(idx);
297   return LLDB_RECORD_RESULT(th);
298 }
299 
300 uint32_t SBQueue::GetNumPendingItems() {
301   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBQueue, GetNumPendingItems);
302 
303   return m_opaque_sp->GetNumPendingItems();
304 }
305 
306 SBQueueItem SBQueue::GetPendingItemAtIndex(uint32_t idx) {
307   LLDB_RECORD_METHOD(lldb::SBQueueItem, SBQueue, GetPendingItemAtIndex,
308                      (uint32_t), idx);
309 
310   return LLDB_RECORD_RESULT(m_opaque_sp->GetPendingItemAtIndex(idx));
311 }
312 
313 uint32_t SBQueue::GetNumRunningItems() {
314   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBQueue, GetNumRunningItems);
315 
316   return m_opaque_sp->GetNumRunningItems();
317 }
318 
319 SBProcess SBQueue::GetProcess() {
320   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBProcess, SBQueue, GetProcess);
321 
322   return LLDB_RECORD_RESULT(m_opaque_sp->GetProcess());
323 }
324 
325 lldb::QueueKind SBQueue::GetKind() {
326   LLDB_RECORD_METHOD_NO_ARGS(lldb::QueueKind, SBQueue, GetKind);
327 
328   return m_opaque_sp->GetKind();
329 }
330 
331 namespace lldb_private {
332 namespace repro {
333 
334 template <>
335 void RegisterMethods<SBQueue>(Registry &R) {
336   LLDB_REGISTER_CONSTRUCTOR(SBQueue, ());
337   LLDB_REGISTER_CONSTRUCTOR(SBQueue, (const lldb::QueueSP &));
338   LLDB_REGISTER_CONSTRUCTOR(SBQueue, (const lldb::SBQueue &));
339   LLDB_REGISTER_METHOD(const lldb::SBQueue &,
340                        SBQueue, operator=,(const lldb::SBQueue &));
341   LLDB_REGISTER_METHOD_CONST(bool, SBQueue, IsValid, ());
342   LLDB_REGISTER_METHOD_CONST(bool, SBQueue, operator bool, ());
343   LLDB_REGISTER_METHOD(void, SBQueue, Clear, ());
344   LLDB_REGISTER_METHOD_CONST(lldb::queue_id_t, SBQueue, GetQueueID, ());
345   LLDB_REGISTER_METHOD_CONST(uint32_t, SBQueue, GetIndexID, ());
346   LLDB_REGISTER_METHOD_CONST(const char *, SBQueue, GetName, ());
347   LLDB_REGISTER_METHOD(uint32_t, SBQueue, GetNumThreads, ());
348   LLDB_REGISTER_METHOD(lldb::SBThread, SBQueue, GetThreadAtIndex, (uint32_t));
349   LLDB_REGISTER_METHOD(uint32_t, SBQueue, GetNumPendingItems, ());
350   LLDB_REGISTER_METHOD(lldb::SBQueueItem, SBQueue, GetPendingItemAtIndex,
351                        (uint32_t));
352   LLDB_REGISTER_METHOD(uint32_t, SBQueue, GetNumRunningItems, ());
353   LLDB_REGISTER_METHOD(lldb::SBProcess, SBQueue, GetProcess, ());
354   LLDB_REGISTER_METHOD(lldb::QueueKind, SBQueue, GetKind, ());
355 }
356 
357 }
358 }
359