1*0b57cec5SDimitry Andric //===-- ThreadSpec.cpp ----------------------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "lldb/Target/ThreadSpec.h"
10*0b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
11*0b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric using namespace lldb;
14*0b57cec5SDimitry Andric using namespace lldb_private;
15*0b57cec5SDimitry Andric 
16*0b57cec5SDimitry Andric const char *ThreadSpec::g_option_names[static_cast<uint32_t>(
17*0b57cec5SDimitry Andric     ThreadSpec::OptionNames::LastOptionName)]{"Index", "ID", "Name",
18*0b57cec5SDimitry Andric                                               "QueueName"};
19*0b57cec5SDimitry Andric 
ThreadSpec()20*0b57cec5SDimitry Andric ThreadSpec::ThreadSpec() : m_name(), m_queue_name() {}
21*0b57cec5SDimitry Andric 
CreateFromStructuredData(const StructuredData::Dictionary & spec_dict,Status & error)22*0b57cec5SDimitry Andric std::unique_ptr<ThreadSpec> ThreadSpec::CreateFromStructuredData(
23*0b57cec5SDimitry Andric     const StructuredData::Dictionary &spec_dict, Status &error) {
24*0b57cec5SDimitry Andric   uint32_t index = UINT32_MAX;
25*0b57cec5SDimitry Andric   lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
26*0b57cec5SDimitry Andric   llvm::StringRef name;
27*0b57cec5SDimitry Andric   llvm::StringRef queue_name;
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric   std::unique_ptr<ThreadSpec> thread_spec_up(new ThreadSpec());
30*0b57cec5SDimitry Andric   bool success = spec_dict.GetValueForKeyAsInteger(
31*0b57cec5SDimitry Andric       GetKey(OptionNames::ThreadIndex), index);
32*0b57cec5SDimitry Andric   if (success)
33*0b57cec5SDimitry Andric     thread_spec_up->SetIndex(index);
34*0b57cec5SDimitry Andric 
35*0b57cec5SDimitry Andric   success =
36*0b57cec5SDimitry Andric       spec_dict.GetValueForKeyAsInteger(GetKey(OptionNames::ThreadID), tid);
37*0b57cec5SDimitry Andric   if (success)
38*0b57cec5SDimitry Andric     thread_spec_up->SetTID(tid);
39*0b57cec5SDimitry Andric 
40*0b57cec5SDimitry Andric   success =
41*0b57cec5SDimitry Andric       spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName), name);
42*0b57cec5SDimitry Andric   if (success)
43*0b57cec5SDimitry Andric     thread_spec_up->SetName(name);
44*0b57cec5SDimitry Andric 
45*0b57cec5SDimitry Andric   success = spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName),
46*0b57cec5SDimitry Andric                                              queue_name);
47*0b57cec5SDimitry Andric   if (success)
48*0b57cec5SDimitry Andric     thread_spec_up->SetQueueName(queue_name);
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric   return thread_spec_up;
51*0b57cec5SDimitry Andric }
52*0b57cec5SDimitry Andric 
SerializeToStructuredData()53*0b57cec5SDimitry Andric StructuredData::ObjectSP ThreadSpec::SerializeToStructuredData() {
54*0b57cec5SDimitry Andric   StructuredData::DictionarySP data_dict_sp(new StructuredData::Dictionary());
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric   if (m_index != UINT32_MAX)
57*0b57cec5SDimitry Andric     data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadIndex), m_index);
58*0b57cec5SDimitry Andric   if (m_tid != LLDB_INVALID_THREAD_ID)
59*0b57cec5SDimitry Andric     data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadID), m_tid);
60*0b57cec5SDimitry Andric   if (!m_name.empty())
61*0b57cec5SDimitry Andric     data_dict_sp->AddStringItem(GetKey(OptionNames::ThreadName), m_name);
62*0b57cec5SDimitry Andric   if (!m_queue_name.empty())
63*0b57cec5SDimitry Andric     data_dict_sp->AddStringItem(GetKey(OptionNames::QueueName), m_queue_name);
64*0b57cec5SDimitry Andric 
65*0b57cec5SDimitry Andric   return data_dict_sp;
66*0b57cec5SDimitry Andric }
67*0b57cec5SDimitry Andric 
GetName() const68*0b57cec5SDimitry Andric const char *ThreadSpec::GetName() const {
69*0b57cec5SDimitry Andric   return m_name.empty() ? nullptr : m_name.c_str();
70*0b57cec5SDimitry Andric }
71*0b57cec5SDimitry Andric 
GetQueueName() const72*0b57cec5SDimitry Andric const char *ThreadSpec::GetQueueName() const {
73*0b57cec5SDimitry Andric   return m_queue_name.empty() ? nullptr : m_queue_name.c_str();
74*0b57cec5SDimitry Andric }
75*0b57cec5SDimitry Andric 
TIDMatches(Thread & thread) const76*0b57cec5SDimitry Andric bool ThreadSpec::TIDMatches(Thread &thread) const {
77*0b57cec5SDimitry Andric   if (m_tid == LLDB_INVALID_THREAD_ID)
78*0b57cec5SDimitry Andric     return true;
79*0b57cec5SDimitry Andric 
80*0b57cec5SDimitry Andric   lldb::tid_t thread_id = thread.GetID();
81*0b57cec5SDimitry Andric   return TIDMatches(thread_id);
82*0b57cec5SDimitry Andric }
83*0b57cec5SDimitry Andric 
IndexMatches(Thread & thread) const84*0b57cec5SDimitry Andric bool ThreadSpec::IndexMatches(Thread &thread) const {
85*0b57cec5SDimitry Andric   if (m_index == UINT32_MAX)
86*0b57cec5SDimitry Andric     return true;
87*0b57cec5SDimitry Andric   uint32_t index = thread.GetIndexID();
88*0b57cec5SDimitry Andric   return IndexMatches(index);
89*0b57cec5SDimitry Andric }
90*0b57cec5SDimitry Andric 
NameMatches(Thread & thread) const91*0b57cec5SDimitry Andric bool ThreadSpec::NameMatches(Thread &thread) const {
92*0b57cec5SDimitry Andric   if (m_name.empty())
93*0b57cec5SDimitry Andric     return true;
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric   const char *name = thread.GetName();
96*0b57cec5SDimitry Andric   return NameMatches(name);
97*0b57cec5SDimitry Andric }
98*0b57cec5SDimitry Andric 
QueueNameMatches(Thread & thread) const99*0b57cec5SDimitry Andric bool ThreadSpec::QueueNameMatches(Thread &thread) const {
100*0b57cec5SDimitry Andric   if (m_queue_name.empty())
101*0b57cec5SDimitry Andric     return true;
102*0b57cec5SDimitry Andric 
103*0b57cec5SDimitry Andric   const char *queue_name = thread.GetQueueName();
104*0b57cec5SDimitry Andric   return QueueNameMatches(queue_name);
105*0b57cec5SDimitry Andric }
106*0b57cec5SDimitry Andric 
ThreadPassesBasicTests(Thread & thread) const107*0b57cec5SDimitry Andric bool ThreadSpec::ThreadPassesBasicTests(Thread &thread) const {
108*0b57cec5SDimitry Andric   if (!HasSpecification())
109*0b57cec5SDimitry Andric     return true;
110*0b57cec5SDimitry Andric 
111*0b57cec5SDimitry Andric   if (!TIDMatches(thread))
112*0b57cec5SDimitry Andric     return false;
113*0b57cec5SDimitry Andric 
114*0b57cec5SDimitry Andric   if (!IndexMatches(thread))
115*0b57cec5SDimitry Andric     return false;
116*0b57cec5SDimitry Andric 
117*0b57cec5SDimitry Andric   if (!NameMatches(thread))
118*0b57cec5SDimitry Andric     return false;
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric   if (!QueueNameMatches(thread))
121*0b57cec5SDimitry Andric     return false;
122*0b57cec5SDimitry Andric 
123*0b57cec5SDimitry Andric   return true;
124*0b57cec5SDimitry Andric }
125*0b57cec5SDimitry Andric 
HasSpecification() const126*0b57cec5SDimitry Andric bool ThreadSpec::HasSpecification() const {
127*0b57cec5SDimitry Andric   return (m_index != UINT32_MAX || m_tid != LLDB_INVALID_THREAD_ID ||
128*0b57cec5SDimitry Andric           !m_name.empty() || !m_queue_name.empty());
129*0b57cec5SDimitry Andric }
130*0b57cec5SDimitry Andric 
GetDescription(Stream * s,lldb::DescriptionLevel level) const131*0b57cec5SDimitry Andric void ThreadSpec::GetDescription(Stream *s, lldb::DescriptionLevel level) const {
132*0b57cec5SDimitry Andric   if (!HasSpecification()) {
133*0b57cec5SDimitry Andric     if (level == eDescriptionLevelBrief) {
134*0b57cec5SDimitry Andric       s->PutCString("thread spec: no ");
135*0b57cec5SDimitry Andric     }
136*0b57cec5SDimitry Andric   } else {
137*0b57cec5SDimitry Andric     if (level == eDescriptionLevelBrief) {
138*0b57cec5SDimitry Andric       s->PutCString("thread spec: yes ");
139*0b57cec5SDimitry Andric     } else {
140*0b57cec5SDimitry Andric       if (GetTID() != LLDB_INVALID_THREAD_ID)
141*0b57cec5SDimitry Andric         s->Printf("tid: 0x%" PRIx64 " ", GetTID());
142*0b57cec5SDimitry Andric 
143*0b57cec5SDimitry Andric       if (GetIndex() != UINT32_MAX)
144*0b57cec5SDimitry Andric         s->Printf("index: %d ", GetIndex());
145*0b57cec5SDimitry Andric 
146*0b57cec5SDimitry Andric       const char *name = GetName();
147*0b57cec5SDimitry Andric       if (name)
148*0b57cec5SDimitry Andric         s->Printf("thread name: \"%s\" ", name);
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric       const char *queue_name = GetQueueName();
151*0b57cec5SDimitry Andric       if (queue_name)
152*0b57cec5SDimitry Andric         s->Printf("queue name: \"%s\" ", queue_name);
153*0b57cec5SDimitry Andric     }
154*0b57cec5SDimitry Andric   }
155*0b57cec5SDimitry Andric }
156*0b57cec5SDimitry Andric