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