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