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