15ffd83dbSDimitry Andric //===-- SBQueue.cpp -------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 9fe6060f1SDimitry Andric #include <cinttypes> 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/API/SBQueue.h" 1204eeddc0SDimitry Andric #include "lldb/Utility/Instrumentation.h" 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "lldb/API/SBProcess.h" 150b57cec5SDimitry Andric #include "lldb/API/SBQueueItem.h" 160b57cec5SDimitry Andric #include "lldb/API/SBThread.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "lldb/Target/Process.h" 190b57cec5SDimitry Andric #include "lldb/Target/Queue.h" 200b57cec5SDimitry Andric #include "lldb/Target/QueueItem.h" 210b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric using namespace lldb; 240b57cec5SDimitry Andric using namespace lldb_private; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric namespace lldb_private { 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric class QueueImpl { 290b57cec5SDimitry Andric public: 3081ad6265SDimitry Andric QueueImpl() = default; 310b57cec5SDimitry Andric QueueImpl(const lldb::QueueSP & queue_sp)3281ad6265SDimitry Andric QueueImpl(const lldb::QueueSP &queue_sp) { m_queue_wp = queue_sp; } 330b57cec5SDimitry Andric QueueImpl(const QueueImpl & rhs)340b57cec5SDimitry Andric QueueImpl(const QueueImpl &rhs) { 350b57cec5SDimitry Andric if (&rhs == this) 360b57cec5SDimitry Andric return; 370b57cec5SDimitry Andric m_queue_wp = rhs.m_queue_wp; 380b57cec5SDimitry Andric m_threads = rhs.m_threads; 390b57cec5SDimitry Andric m_thread_list_fetched = rhs.m_thread_list_fetched; 400b57cec5SDimitry Andric m_pending_items = rhs.m_pending_items; 410b57cec5SDimitry Andric m_pending_items_fetched = rhs.m_pending_items_fetched; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 445ffd83dbSDimitry Andric ~QueueImpl() = default; 450b57cec5SDimitry Andric IsValid()460b57cec5SDimitry Andric bool IsValid() { return m_queue_wp.lock() != nullptr; } 470b57cec5SDimitry Andric Clear()480b57cec5SDimitry Andric void Clear() { 490b57cec5SDimitry Andric m_queue_wp.reset(); 500b57cec5SDimitry Andric m_thread_list_fetched = false; 510b57cec5SDimitry Andric m_threads.clear(); 520b57cec5SDimitry Andric m_pending_items_fetched = false; 530b57cec5SDimitry Andric m_pending_items.clear(); 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric SetQueue(const lldb::QueueSP & queue_sp)560b57cec5SDimitry Andric void SetQueue(const lldb::QueueSP &queue_sp) { 570b57cec5SDimitry Andric Clear(); 580b57cec5SDimitry Andric m_queue_wp = queue_sp; 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric GetQueueID() const610b57cec5SDimitry Andric lldb::queue_id_t GetQueueID() const { 620b57cec5SDimitry Andric lldb::queue_id_t result = LLDB_INVALID_QUEUE_ID; 630b57cec5SDimitry Andric lldb::QueueSP queue_sp = m_queue_wp.lock(); 640b57cec5SDimitry Andric if (queue_sp) { 650b57cec5SDimitry Andric result = queue_sp->GetID(); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric return result; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric GetIndexID() const700b57cec5SDimitry Andric uint32_t GetIndexID() const { 710b57cec5SDimitry Andric uint32_t result = LLDB_INVALID_INDEX32; 720b57cec5SDimitry Andric lldb::QueueSP queue_sp = m_queue_wp.lock(); 730b57cec5SDimitry Andric if (queue_sp) { 740b57cec5SDimitry Andric result = queue_sp->GetIndexID(); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric return result; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric GetName() const790b57cec5SDimitry Andric const char *GetName() const { 800b57cec5SDimitry Andric lldb::QueueSP queue_sp = m_queue_wp.lock(); 8106c3fb27SDimitry Andric if (!queue_sp) 8206c3fb27SDimitry Andric return nullptr; 8306c3fb27SDimitry Andric return ConstString(queue_sp->GetName()).GetCString(); 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric FetchThreads()860b57cec5SDimitry Andric void FetchThreads() { 870b57cec5SDimitry Andric if (!m_thread_list_fetched) { 880b57cec5SDimitry Andric lldb::QueueSP queue_sp = m_queue_wp.lock(); 890b57cec5SDimitry Andric if (queue_sp) { 900b57cec5SDimitry Andric Process::StopLocker stop_locker; 910b57cec5SDimitry Andric if (stop_locker.TryLock(&queue_sp->GetProcess()->GetRunLock())) { 920b57cec5SDimitry Andric const std::vector<ThreadSP> thread_list(queue_sp->GetThreads()); 930b57cec5SDimitry Andric m_thread_list_fetched = true; 940b57cec5SDimitry Andric const uint32_t num_threads = thread_list.size(); 950b57cec5SDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) { 960b57cec5SDimitry Andric ThreadSP thread_sp = thread_list[idx]; 970b57cec5SDimitry Andric if (thread_sp && thread_sp->IsValid()) { 980b57cec5SDimitry Andric m_threads.push_back(thread_sp); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric FetchItems()1060b57cec5SDimitry Andric void FetchItems() { 1070b57cec5SDimitry Andric if (!m_pending_items_fetched) { 1080b57cec5SDimitry Andric QueueSP queue_sp = m_queue_wp.lock(); 1090b57cec5SDimitry Andric if (queue_sp) { 1100b57cec5SDimitry Andric Process::StopLocker stop_locker; 1110b57cec5SDimitry Andric if (stop_locker.TryLock(&queue_sp->GetProcess()->GetRunLock())) { 1120b57cec5SDimitry Andric const std::vector<QueueItemSP> queue_items( 1130b57cec5SDimitry Andric queue_sp->GetPendingItems()); 1140b57cec5SDimitry Andric m_pending_items_fetched = true; 1150b57cec5SDimitry Andric const uint32_t num_pending_items = queue_items.size(); 1160b57cec5SDimitry Andric for (uint32_t idx = 0; idx < num_pending_items; ++idx) { 1170b57cec5SDimitry Andric QueueItemSP item = queue_items[idx]; 1180b57cec5SDimitry Andric if (item && item->IsValid()) { 1190b57cec5SDimitry Andric m_pending_items.push_back(item); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric GetNumThreads()1270b57cec5SDimitry Andric uint32_t GetNumThreads() { 1280b57cec5SDimitry Andric uint32_t result = 0; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric FetchThreads(); 1310b57cec5SDimitry Andric if (m_thread_list_fetched) { 1320b57cec5SDimitry Andric result = m_threads.size(); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric return result; 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric GetThreadAtIndex(uint32_t idx)1370b57cec5SDimitry Andric lldb::SBThread GetThreadAtIndex(uint32_t idx) { 1380b57cec5SDimitry Andric FetchThreads(); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric SBThread sb_thread; 1410b57cec5SDimitry Andric QueueSP queue_sp = m_queue_wp.lock(); 1420b57cec5SDimitry Andric if (queue_sp && idx < m_threads.size()) { 1430b57cec5SDimitry Andric ProcessSP process_sp = queue_sp->GetProcess(); 1440b57cec5SDimitry Andric if (process_sp) { 1450b57cec5SDimitry Andric ThreadSP thread_sp = m_threads[idx].lock(); 1460b57cec5SDimitry Andric if (thread_sp) { 1470b57cec5SDimitry Andric sb_thread.SetThread(thread_sp); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric return sb_thread; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric GetNumPendingItems()1540b57cec5SDimitry Andric uint32_t GetNumPendingItems() { 1550b57cec5SDimitry Andric uint32_t result = 0; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric QueueSP queue_sp = m_queue_wp.lock(); 1580b57cec5SDimitry Andric if (!m_pending_items_fetched && queue_sp) { 1590b57cec5SDimitry Andric result = queue_sp->GetNumPendingWorkItems(); 1600b57cec5SDimitry Andric } else { 1610b57cec5SDimitry Andric result = m_pending_items.size(); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric return result; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric GetPendingItemAtIndex(uint32_t idx)1660b57cec5SDimitry Andric lldb::SBQueueItem GetPendingItemAtIndex(uint32_t idx) { 1670b57cec5SDimitry Andric SBQueueItem result; 1680b57cec5SDimitry Andric FetchItems(); 1690b57cec5SDimitry Andric if (m_pending_items_fetched && idx < m_pending_items.size()) { 1700b57cec5SDimitry Andric result.SetQueueItem(m_pending_items[idx]); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric return result; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric GetNumRunningItems()1750b57cec5SDimitry Andric uint32_t GetNumRunningItems() { 1760b57cec5SDimitry Andric uint32_t result = 0; 1770b57cec5SDimitry Andric QueueSP queue_sp = m_queue_wp.lock(); 1780b57cec5SDimitry Andric if (queue_sp) 1790b57cec5SDimitry Andric result = queue_sp->GetNumRunningWorkItems(); 1800b57cec5SDimitry Andric return result; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric GetProcess()1830b57cec5SDimitry Andric lldb::SBProcess GetProcess() { 1840b57cec5SDimitry Andric SBProcess result; 1850b57cec5SDimitry Andric QueueSP queue_sp = m_queue_wp.lock(); 1860b57cec5SDimitry Andric if (queue_sp) { 1870b57cec5SDimitry Andric result.SetSP(queue_sp->GetProcess()); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric return result; 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric GetKind()1920b57cec5SDimitry Andric lldb::QueueKind GetKind() { 1930b57cec5SDimitry Andric lldb::QueueKind kind = eQueueKindUnknown; 1940b57cec5SDimitry Andric QueueSP queue_sp = m_queue_wp.lock(); 1950b57cec5SDimitry Andric if (queue_sp) 1960b57cec5SDimitry Andric kind = queue_sp->GetKind(); 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric return kind; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric private: 2020b57cec5SDimitry Andric lldb::QueueWP m_queue_wp; 2030b57cec5SDimitry Andric std::vector<lldb::ThreadWP> 2040b57cec5SDimitry Andric m_threads; // threads currently executing this queue's items 205fe6060f1SDimitry Andric bool m_thread_list_fetched = 206fe6060f1SDimitry Andric false; // have we tried to fetch the threads list already? 2070b57cec5SDimitry Andric std::vector<lldb::QueueItemSP> m_pending_items; // items currently enqueued 208fe6060f1SDimitry Andric bool m_pending_items_fetched = 209fe6060f1SDimitry Andric false; // have we tried to fetch the item list already? 2100b57cec5SDimitry Andric }; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric SBQueue()21304eeddc0SDimitry AndricSBQueue::SBQueue() : m_opaque_sp(new QueueImpl()) { LLDB_INSTRUMENT_VA(this); } 2140b57cec5SDimitry Andric SBQueue(const QueueSP & queue_sp)2150b57cec5SDimitry AndricSBQueue::SBQueue(const QueueSP &queue_sp) 2160b57cec5SDimitry Andric : m_opaque_sp(new QueueImpl(queue_sp)) { 21704eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, queue_sp); 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric SBQueue(const SBQueue & rhs)2200b57cec5SDimitry AndricSBQueue::SBQueue(const SBQueue &rhs) { 22104eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric if (&rhs == this) 2240b57cec5SDimitry Andric return; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric m_opaque_sp = rhs.m_opaque_sp; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric operator =(const lldb::SBQueue & rhs)2290b57cec5SDimitry Andricconst lldb::SBQueue &SBQueue::operator=(const lldb::SBQueue &rhs) { 23004eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs); 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric m_opaque_sp = rhs.m_opaque_sp; 23304eeddc0SDimitry Andric return *this; 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2365ffd83dbSDimitry Andric SBQueue::~SBQueue() = default; 2370b57cec5SDimitry Andric IsValid() const2380b57cec5SDimitry Andricbool SBQueue::IsValid() const { 23904eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 2400b57cec5SDimitry Andric return this->operator bool(); 2410b57cec5SDimitry Andric } operator bool() const2420b57cec5SDimitry AndricSBQueue::operator bool() const { 24304eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric return m_opaque_sp->IsValid(); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric Clear()2480b57cec5SDimitry Andricvoid SBQueue::Clear() { 24904eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric m_opaque_sp->Clear(); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric SetQueue(const QueueSP & queue_sp)2540b57cec5SDimitry Andricvoid SBQueue::SetQueue(const QueueSP &queue_sp) { 2550b57cec5SDimitry Andric m_opaque_sp->SetQueue(queue_sp); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric GetQueueID() const2580b57cec5SDimitry Andriclldb::queue_id_t SBQueue::GetQueueID() const { 25904eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric return m_opaque_sp->GetQueueID(); 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric GetIndexID() const2640b57cec5SDimitry Andricuint32_t SBQueue::GetIndexID() const { 26504eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric uint32_t index_id = m_opaque_sp->GetIndexID(); 2680b57cec5SDimitry Andric return index_id; 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric GetName() const2710b57cec5SDimitry Andricconst char *SBQueue::GetName() const { 27204eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric return m_opaque_sp->GetName(); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric GetNumThreads()2770b57cec5SDimitry Andricuint32_t SBQueue::GetNumThreads() { 27804eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric return m_opaque_sp->GetNumThreads(); 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric GetThreadAtIndex(uint32_t idx)2830b57cec5SDimitry AndricSBThread SBQueue::GetThreadAtIndex(uint32_t idx) { 28404eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, idx); 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric SBThread th = m_opaque_sp->GetThreadAtIndex(idx); 28704eeddc0SDimitry Andric return th; 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric GetNumPendingItems()2900b57cec5SDimitry Andricuint32_t SBQueue::GetNumPendingItems() { 29104eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric return m_opaque_sp->GetNumPendingItems(); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric GetPendingItemAtIndex(uint32_t idx)2960b57cec5SDimitry AndricSBQueueItem SBQueue::GetPendingItemAtIndex(uint32_t idx) { 29704eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this, idx); 2980b57cec5SDimitry Andric 29904eeddc0SDimitry Andric return m_opaque_sp->GetPendingItemAtIndex(idx); 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric GetNumRunningItems()3020b57cec5SDimitry Andricuint32_t SBQueue::GetNumRunningItems() { 30304eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric return m_opaque_sp->GetNumRunningItems(); 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric GetProcess()3080b57cec5SDimitry AndricSBProcess SBQueue::GetProcess() { 30904eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 3100b57cec5SDimitry Andric 31104eeddc0SDimitry Andric return m_opaque_sp->GetProcess(); 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric GetKind()3140b57cec5SDimitry Andriclldb::QueueKind SBQueue::GetKind() { 31504eeddc0SDimitry Andric LLDB_INSTRUMENT_VA(this); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric return m_opaque_sp->GetKind(); 3180b57cec5SDimitry Andric } 319