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 Andric SBQueue::SBQueue() : m_opaque_sp(new QueueImpl()) { LLDB_INSTRUMENT_VA(this); }
2140b57cec5SDimitry Andric 
SBQueue(const QueueSP & queue_sp)2150b57cec5SDimitry Andric SBQueue::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 Andric SBQueue::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 Andric const 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 Andric bool SBQueue::IsValid() const {
23904eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
2400b57cec5SDimitry Andric   return this->operator bool();
2410b57cec5SDimitry Andric }
operator bool() const2420b57cec5SDimitry Andric SBQueue::operator bool() const {
24304eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   return m_opaque_sp->IsValid();
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric 
Clear()2480b57cec5SDimitry Andric void 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 Andric void SBQueue::SetQueue(const QueueSP &queue_sp) {
2550b57cec5SDimitry Andric   m_opaque_sp->SetQueue(queue_sp);
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
GetQueueID() const2580b57cec5SDimitry Andric lldb::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 Andric uint32_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 Andric const 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 Andric uint32_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 Andric SBThread 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 Andric uint32_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 Andric SBQueueItem 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 Andric uint32_t SBQueue::GetNumRunningItems() {
30304eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   return m_opaque_sp->GetNumRunningItems();
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric 
GetProcess()3080b57cec5SDimitry Andric SBProcess SBQueue::GetProcess() {
30904eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
3100b57cec5SDimitry Andric 
31104eeddc0SDimitry Andric   return m_opaque_sp->GetProcess();
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
GetKind()3140b57cec5SDimitry Andric lldb::QueueKind SBQueue::GetKind() {
31504eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   return m_opaque_sp->GetKind();
3180b57cec5SDimitry Andric }
319