319 lines · cpp
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-exception6//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 23using namespace lldb;24using namespace lldb_private;25 26namespace lldb_private {27 28class QueueImpl {29public:30 QueueImpl() = default;31 32 QueueImpl(const lldb::QueueSP &queue_sp) { m_queue_wp = queue_sp; }33 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 46 bool IsValid() { return m_queue_wp.lock() != nullptr; }47 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 56 void SetQueue(const lldb::QueueSP &queue_sp) {57 Clear();58 m_queue_wp = queue_sp;59 }60 61 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 70 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 79 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 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 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 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 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 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 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 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 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 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 201private:202 lldb::QueueWP m_queue_wp;203 std::vector<lldb::ThreadWP>204 m_threads; // threads currently executing this queue's items205 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 enqueued208 bool m_pending_items_fetched =209 false; // have we tried to fetch the item list already?210};211}212 213SBQueue::SBQueue() : m_opaque_sp(new QueueImpl()) { LLDB_INSTRUMENT_VA(this); }214 215SBQueue::SBQueue(const QueueSP &queue_sp)216 : m_opaque_sp(new QueueImpl(queue_sp)) {217 LLDB_INSTRUMENT_VA(this, queue_sp);218}219 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 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 236SBQueue::~SBQueue() = default;237 238bool SBQueue::IsValid() const {239 LLDB_INSTRUMENT_VA(this);240 return this->operator bool();241}242SBQueue::operator bool() const {243 LLDB_INSTRUMENT_VA(this);244 245 return m_opaque_sp->IsValid();246}247 248void SBQueue::Clear() {249 LLDB_INSTRUMENT_VA(this);250 251 m_opaque_sp->Clear();252}253 254void SBQueue::SetQueue(const QueueSP &queue_sp) {255 m_opaque_sp->SetQueue(queue_sp);256}257 258lldb::queue_id_t SBQueue::GetQueueID() const {259 LLDB_INSTRUMENT_VA(this);260 261 return m_opaque_sp->GetQueueID();262}263 264uint32_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 271const char *SBQueue::GetName() const {272 LLDB_INSTRUMENT_VA(this);273 274 return m_opaque_sp->GetName();275}276 277uint32_t SBQueue::GetNumThreads() {278 LLDB_INSTRUMENT_VA(this);279 280 return m_opaque_sp->GetNumThreads();281}282 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 290uint32_t SBQueue::GetNumPendingItems() {291 LLDB_INSTRUMENT_VA(this);292 293 return m_opaque_sp->GetNumPendingItems();294}295 296SBQueueItem SBQueue::GetPendingItemAtIndex(uint32_t idx) {297 LLDB_INSTRUMENT_VA(this, idx);298 299 return m_opaque_sp->GetPendingItemAtIndex(idx);300}301 302uint32_t SBQueue::GetNumRunningItems() {303 LLDB_INSTRUMENT_VA(this);304 305 return m_opaque_sp->GetNumRunningItems();306}307 308SBProcess SBQueue::GetProcess() {309 LLDB_INSTRUMENT_VA(this);310 311 return m_opaque_sp->GetProcess();312}313 314lldb::QueueKind SBQueue::GetKind() {315 LLDB_INSTRUMENT_VA(this);316 317 return m_opaque_sp->GetKind();318}319