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