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