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