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 "lldb/API/SBQueue.h" 12 13 #include "lldb/API/SBProcess.h" 14 #include "lldb/API/SBQueueItem.h" 15 #include "lldb/API/SBThread.h" 16 17 #include "lldb/Target/Process.h" 18 #include "lldb/Target/Queue.h" 19 #include "lldb/Target/QueueItem.h" 20 #include "lldb/Target/Thread.h" 21 #include "lldb/Utility/Log.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() != NULL; } 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 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 74 if (log) 75 log->Printf("SBQueue(%p)::GetQueueID () => 0x%" PRIx64, 76 static_cast<const void *>(this), result); 77 return result; 78 } 79 80 uint32_t GetIndexID() const { 81 uint32_t result = LLDB_INVALID_INDEX32; 82 lldb::QueueSP queue_sp = m_queue_wp.lock(); 83 if (queue_sp) { 84 result = queue_sp->GetIndexID(); 85 } 86 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 87 if (log) 88 log->Printf("SBQueueImpl(%p)::GetIndexID () => %d", 89 static_cast<const void *>(this), result); 90 return result; 91 } 92 93 const char *GetName() const { 94 const char *name = NULL; 95 lldb::QueueSP queue_sp = m_queue_wp.lock(); 96 if (queue_sp.get()) { 97 name = queue_sp->GetName(); 98 } 99 100 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 101 if (log) 102 log->Printf("SBQueueImpl(%p)::GetName () => %s", 103 static_cast<const void *>(this), name ? name : "NULL"); 104 105 return name; 106 } 107 108 void FetchThreads() { 109 if (!m_thread_list_fetched) { 110 lldb::QueueSP queue_sp = m_queue_wp.lock(); 111 if (queue_sp) { 112 Process::StopLocker stop_locker; 113 if (stop_locker.TryLock(&queue_sp->GetProcess()->GetRunLock())) { 114 const std::vector<ThreadSP> thread_list(queue_sp->GetThreads()); 115 m_thread_list_fetched = true; 116 const uint32_t num_threads = thread_list.size(); 117 for (uint32_t idx = 0; idx < num_threads; ++idx) { 118 ThreadSP thread_sp = thread_list[idx]; 119 if (thread_sp && thread_sp->IsValid()) { 120 m_threads.push_back(thread_sp); 121 } 122 } 123 } 124 } 125 } 126 } 127 128 void FetchItems() { 129 if (!m_pending_items_fetched) { 130 QueueSP queue_sp = m_queue_wp.lock(); 131 if (queue_sp) { 132 Process::StopLocker stop_locker; 133 if (stop_locker.TryLock(&queue_sp->GetProcess()->GetRunLock())) { 134 const std::vector<QueueItemSP> queue_items( 135 queue_sp->GetPendingItems()); 136 m_pending_items_fetched = true; 137 const uint32_t num_pending_items = queue_items.size(); 138 for (uint32_t idx = 0; idx < num_pending_items; ++idx) { 139 QueueItemSP item = queue_items[idx]; 140 if (item && item->IsValid()) { 141 m_pending_items.push_back(item); 142 } 143 } 144 } 145 } 146 } 147 } 148 149 uint32_t GetNumThreads() { 150 uint32_t result = 0; 151 152 FetchThreads(); 153 if (m_thread_list_fetched) { 154 result = m_threads.size(); 155 } 156 return result; 157 } 158 159 lldb::SBThread GetThreadAtIndex(uint32_t idx) { 160 FetchThreads(); 161 162 SBThread sb_thread; 163 QueueSP queue_sp = m_queue_wp.lock(); 164 if (queue_sp && idx < m_threads.size()) { 165 ProcessSP process_sp = queue_sp->GetProcess(); 166 if (process_sp) { 167 ThreadSP thread_sp = m_threads[idx].lock(); 168 if (thread_sp) { 169 sb_thread.SetThread(thread_sp); 170 } 171 } 172 } 173 return sb_thread; 174 } 175 176 uint32_t GetNumPendingItems() { 177 uint32_t result = 0; 178 179 QueueSP queue_sp = m_queue_wp.lock(); 180 if (!m_pending_items_fetched && queue_sp) { 181 result = queue_sp->GetNumPendingWorkItems(); 182 } else { 183 result = m_pending_items.size(); 184 } 185 return result; 186 } 187 188 lldb::SBQueueItem GetPendingItemAtIndex(uint32_t idx) { 189 SBQueueItem result; 190 FetchItems(); 191 if (m_pending_items_fetched && idx < m_pending_items.size()) { 192 result.SetQueueItem(m_pending_items[idx]); 193 } 194 return result; 195 } 196 197 uint32_t GetNumRunningItems() { 198 uint32_t result = 0; 199 QueueSP queue_sp = m_queue_wp.lock(); 200 if (queue_sp) 201 result = queue_sp->GetNumRunningWorkItems(); 202 return result; 203 } 204 205 lldb::SBProcess GetProcess() { 206 SBProcess result; 207 QueueSP queue_sp = m_queue_wp.lock(); 208 if (queue_sp) { 209 result.SetSP(queue_sp->GetProcess()); 210 } 211 return result; 212 } 213 214 lldb::QueueKind GetKind() { 215 lldb::QueueKind kind = eQueueKindUnknown; 216 QueueSP queue_sp = m_queue_wp.lock(); 217 if (queue_sp) 218 kind = queue_sp->GetKind(); 219 220 return kind; 221 } 222 223 private: 224 lldb::QueueWP m_queue_wp; 225 std::vector<lldb::ThreadWP> 226 m_threads; // threads currently executing this queue's items 227 bool 228 m_thread_list_fetched; // have we tried to fetch the threads list already? 229 std::vector<lldb::QueueItemSP> m_pending_items; // items currently enqueued 230 bool m_pending_items_fetched; // have we tried to fetch the item list already? 231 }; 232 } 233 234 SBQueue::SBQueue() : m_opaque_sp(new QueueImpl()) {} 235 236 SBQueue::SBQueue(const QueueSP &queue_sp) 237 : m_opaque_sp(new QueueImpl(queue_sp)) {} 238 239 SBQueue::SBQueue(const SBQueue &rhs) { 240 if (&rhs == this) 241 return; 242 243 m_opaque_sp = rhs.m_opaque_sp; 244 } 245 246 const lldb::SBQueue &SBQueue::operator=(const lldb::SBQueue &rhs) { 247 m_opaque_sp = rhs.m_opaque_sp; 248 return *this; 249 } 250 251 SBQueue::~SBQueue() {} 252 253 bool SBQueue::IsValid() const { 254 bool is_valid = m_opaque_sp->IsValid(); 255 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 256 if (log) 257 log->Printf("SBQueue(0x%" PRIx64 ")::IsValid() == %s", 258 m_opaque_sp->GetQueueID(), is_valid ? "true" : "false"); 259 return is_valid; 260 } 261 262 void SBQueue::Clear() { 263 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 264 if (log) 265 log->Printf("SBQueue(0x%" PRIx64 ")::Clear()", m_opaque_sp->GetQueueID()); 266 m_opaque_sp->Clear(); 267 } 268 269 void SBQueue::SetQueue(const QueueSP &queue_sp) { 270 m_opaque_sp->SetQueue(queue_sp); 271 } 272 273 lldb::queue_id_t SBQueue::GetQueueID() const { 274 lldb::queue_id_t qid = m_opaque_sp->GetQueueID(); 275 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 276 if (log) 277 log->Printf("SBQueue(0x%" PRIx64 ")::GetQueueID() == 0x%" PRIx64, 278 m_opaque_sp->GetQueueID(), (uint64_t)qid); 279 return qid; 280 } 281 282 uint32_t SBQueue::GetIndexID() const { 283 uint32_t index_id = m_opaque_sp->GetIndexID(); 284 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 285 if (log) 286 log->Printf("SBQueue(0x%" PRIx64 ")::GetIndexID() == 0x%" PRIx32, 287 m_opaque_sp->GetQueueID(), index_id); 288 return index_id; 289 } 290 291 const char *SBQueue::GetName() const { 292 const char *name = m_opaque_sp->GetName(); 293 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 294 if (log) 295 log->Printf("SBQueue(0x%" PRIx64 ")::GetName() == %s", 296 m_opaque_sp->GetQueueID(), name ? name : ""); 297 return name; 298 } 299 300 uint32_t SBQueue::GetNumThreads() { 301 uint32_t numthreads = m_opaque_sp->GetNumThreads(); 302 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 303 if (log) 304 log->Printf("SBQueue(0x%" PRIx64 ")::GetNumThreads() == %d", 305 m_opaque_sp->GetQueueID(), numthreads); 306 return numthreads; 307 } 308 309 SBThread SBQueue::GetThreadAtIndex(uint32_t idx) { 310 SBThread th = m_opaque_sp->GetThreadAtIndex(idx); 311 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 312 if (log) 313 log->Printf("SBQueue(0x%" PRIx64 ")::GetThreadAtIndex(%d)", 314 m_opaque_sp->GetQueueID(), idx); 315 return th; 316 } 317 318 uint32_t SBQueue::GetNumPendingItems() { 319 uint32_t pending_items = m_opaque_sp->GetNumPendingItems(); 320 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 321 if (log) 322 log->Printf("SBQueue(0x%" PRIx64 ")::GetNumPendingItems() == %d", 323 m_opaque_sp->GetQueueID(), pending_items); 324 return pending_items; 325 } 326 327 SBQueueItem SBQueue::GetPendingItemAtIndex(uint32_t idx) { 328 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 329 if (log) 330 log->Printf("SBQueue(0x%" PRIx64 ")::GetPendingItemAtIndex(%d)", 331 m_opaque_sp->GetQueueID(), idx); 332 return m_opaque_sp->GetPendingItemAtIndex(idx); 333 } 334 335 uint32_t SBQueue::GetNumRunningItems() { 336 uint32_t running_items = m_opaque_sp->GetNumRunningItems(); 337 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 338 if (log) 339 log->Printf("SBQueue(0x%" PRIx64 ")::GetNumRunningItems() == %d", 340 m_opaque_sp->GetQueueID(), running_items); 341 return running_items; 342 } 343 344 SBProcess SBQueue::GetProcess() { return m_opaque_sp->GetProcess(); } 345 346 lldb::QueueKind SBQueue::GetKind() { return m_opaque_sp->GetKind(); } 347