19f2f44ceSEd Maste //===-- ThreadSpec.cpp ------------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "lldb/Target/ThreadSpec.h"
11a580b014SDimitry Andric #include "lldb/Target/Thread.h"
12a580b014SDimitry Andric #include "lldb/Utility/StructuredData.h"
13ac7ddfbfSEd Maste 
14ac7ddfbfSEd Maste using namespace lldb;
15ac7ddfbfSEd Maste using namespace lldb_private;
16ac7ddfbfSEd Maste 
17435933ddSDimitry Andric const char *ThreadSpec::g_option_names[static_cast<uint32_t>(
18435933ddSDimitry Andric     ThreadSpec::OptionNames::LastOptionName)]{"Index", "ID", "Name",
19435933ddSDimitry Andric                                               "QueueName"};
20ac7ddfbfSEd Maste 
ThreadSpec()21435933ddSDimitry Andric ThreadSpec::ThreadSpec()
22435933ddSDimitry Andric     : m_index(UINT32_MAX), m_tid(LLDB_INVALID_THREAD_ID), m_name(),
23435933ddSDimitry Andric       m_queue_name() {}
24ac7ddfbfSEd Maste 
ThreadSpec(const ThreadSpec & rhs)25435933ddSDimitry Andric ThreadSpec::ThreadSpec(const ThreadSpec &rhs)
26435933ddSDimitry Andric     : m_index(rhs.m_index), m_tid(rhs.m_tid), m_name(rhs.m_name),
27435933ddSDimitry Andric       m_queue_name(rhs.m_queue_name) {}
28435933ddSDimitry Andric 
operator =(const ThreadSpec & rhs)29435933ddSDimitry Andric const ThreadSpec &ThreadSpec::operator=(const ThreadSpec &rhs) {
30ac7ddfbfSEd Maste   m_index = rhs.m_index;
31ac7ddfbfSEd Maste   m_tid = rhs.m_tid;
32ac7ddfbfSEd Maste   m_name = rhs.m_name;
33ac7ddfbfSEd Maste   m_queue_name = rhs.m_queue_name;
34ac7ddfbfSEd Maste   return *this;
35ac7ddfbfSEd Maste }
36ac7ddfbfSEd Maste 
CreateFromStructuredData(const StructuredData::Dictionary & spec_dict,Status & error)37435933ddSDimitry Andric std::unique_ptr<ThreadSpec> ThreadSpec::CreateFromStructuredData(
385517e702SDimitry Andric     const StructuredData::Dictionary &spec_dict, Status &error) {
39435933ddSDimitry Andric   uint32_t index = UINT32_MAX;
40435933ddSDimitry Andric   lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
415517e702SDimitry Andric   llvm::StringRef name;
425517e702SDimitry Andric   llvm::StringRef queue_name;
43435933ddSDimitry Andric 
44435933ddSDimitry Andric   std::unique_ptr<ThreadSpec> thread_spec_up(new ThreadSpec());
45435933ddSDimitry Andric   bool success = spec_dict.GetValueForKeyAsInteger(
46435933ddSDimitry Andric       GetKey(OptionNames::ThreadIndex), index);
47435933ddSDimitry Andric   if (success)
48435933ddSDimitry Andric     thread_spec_up->SetIndex(index);
49435933ddSDimitry Andric 
50435933ddSDimitry Andric   success =
51435933ddSDimitry Andric       spec_dict.GetValueForKeyAsInteger(GetKey(OptionNames::ThreadID), tid);
52435933ddSDimitry Andric   if (success)
53435933ddSDimitry Andric     thread_spec_up->SetTID(tid);
54435933ddSDimitry Andric 
55435933ddSDimitry Andric   success =
56435933ddSDimitry Andric       spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName), name);
57435933ddSDimitry Andric   if (success)
585517e702SDimitry Andric     thread_spec_up->SetName(name);
59435933ddSDimitry Andric 
60435933ddSDimitry Andric   success = spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName),
61435933ddSDimitry Andric                                              queue_name);
62435933ddSDimitry Andric   if (success)
635517e702SDimitry Andric     thread_spec_up->SetQueueName(queue_name);
64435933ddSDimitry Andric 
65435933ddSDimitry Andric   return thread_spec_up;
66435933ddSDimitry Andric }
67435933ddSDimitry Andric 
SerializeToStructuredData()68435933ddSDimitry Andric StructuredData::ObjectSP ThreadSpec::SerializeToStructuredData() {
69435933ddSDimitry Andric   StructuredData::DictionarySP data_dict_sp(new StructuredData::Dictionary());
70435933ddSDimitry Andric 
71435933ddSDimitry Andric   if (m_index != UINT32_MAX)
72435933ddSDimitry Andric     data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadIndex), m_index);
73435933ddSDimitry Andric   if (m_tid != LLDB_INVALID_THREAD_ID)
74435933ddSDimitry Andric     data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadID), m_tid);
75435933ddSDimitry Andric   if (!m_name.empty())
76435933ddSDimitry Andric     data_dict_sp->AddStringItem(GetKey(OptionNames::ThreadName), m_name);
77435933ddSDimitry Andric   if (!m_queue_name.empty())
78435933ddSDimitry Andric     data_dict_sp->AddStringItem(GetKey(OptionNames::QueueName), m_queue_name);
79435933ddSDimitry Andric 
80435933ddSDimitry Andric   return data_dict_sp;
81435933ddSDimitry Andric }
82435933ddSDimitry Andric 
GetName() const83435933ddSDimitry Andric const char *ThreadSpec::GetName() const {
849f2f44ceSEd Maste   return m_name.empty() ? nullptr : m_name.c_str();
85ac7ddfbfSEd Maste }
86ac7ddfbfSEd Maste 
GetQueueName() const87435933ddSDimitry Andric const char *ThreadSpec::GetQueueName() const {
889f2f44ceSEd Maste   return m_queue_name.empty() ? nullptr : m_queue_name.c_str();
89ac7ddfbfSEd Maste }
90ac7ddfbfSEd Maste 
TIDMatches(Thread & thread) const91435933ddSDimitry Andric bool ThreadSpec::TIDMatches(Thread &thread) const {
92ac7ddfbfSEd Maste   if (m_tid == LLDB_INVALID_THREAD_ID)
93ac7ddfbfSEd Maste     return true;
94ac7ddfbfSEd Maste 
95ac7ddfbfSEd Maste   lldb::tid_t thread_id = thread.GetID();
96ac7ddfbfSEd Maste   return TIDMatches(thread_id);
97ac7ddfbfSEd Maste }
989f2f44ceSEd Maste 
IndexMatches(Thread & thread) const99435933ddSDimitry Andric bool ThreadSpec::IndexMatches(Thread &thread) const {
100ac7ddfbfSEd Maste   if (m_index == UINT32_MAX)
101ac7ddfbfSEd Maste     return true;
102ac7ddfbfSEd Maste   uint32_t index = thread.GetIndexID();
103ac7ddfbfSEd Maste   return IndexMatches(index);
104ac7ddfbfSEd Maste }
1059f2f44ceSEd Maste 
NameMatches(Thread & thread) const106435933ddSDimitry Andric bool ThreadSpec::NameMatches(Thread &thread) const {
107ac7ddfbfSEd Maste   if (m_name.empty())
108ac7ddfbfSEd Maste     return true;
109ac7ddfbfSEd Maste 
110ac7ddfbfSEd Maste   const char *name = thread.GetName();
111ac7ddfbfSEd Maste   return NameMatches(name);
112ac7ddfbfSEd Maste }
1139f2f44ceSEd Maste 
QueueNameMatches(Thread & thread) const114435933ddSDimitry Andric bool ThreadSpec::QueueNameMatches(Thread &thread) const {
115ac7ddfbfSEd Maste   if (m_queue_name.empty())
116ac7ddfbfSEd Maste     return true;
117ac7ddfbfSEd Maste 
118ac7ddfbfSEd Maste   const char *queue_name = thread.GetQueueName();
119ac7ddfbfSEd Maste   return QueueNameMatches(queue_name);
120ac7ddfbfSEd Maste }
121ac7ddfbfSEd Maste 
ThreadPassesBasicTests(Thread & thread) const122435933ddSDimitry Andric bool ThreadSpec::ThreadPassesBasicTests(Thread &thread) const {
123ac7ddfbfSEd Maste   if (!HasSpecification())
124ac7ddfbfSEd Maste     return true;
125ac7ddfbfSEd Maste 
126ac7ddfbfSEd Maste   if (!TIDMatches(thread))
127ac7ddfbfSEd Maste     return false;
128ac7ddfbfSEd Maste 
129ac7ddfbfSEd Maste   if (!IndexMatches(thread))
130ac7ddfbfSEd Maste     return false;
131ac7ddfbfSEd Maste 
132ac7ddfbfSEd Maste   if (!NameMatches(thread))
133ac7ddfbfSEd Maste     return false;
134ac7ddfbfSEd Maste 
135ac7ddfbfSEd Maste   if (!QueueNameMatches(thread))
136ac7ddfbfSEd Maste     return false;
137ac7ddfbfSEd Maste 
138ac7ddfbfSEd Maste   return true;
139ac7ddfbfSEd Maste }
140ac7ddfbfSEd Maste 
HasSpecification() const141435933ddSDimitry Andric bool ThreadSpec::HasSpecification() const {
142435933ddSDimitry Andric   return (m_index != UINT32_MAX || m_tid != LLDB_INVALID_THREAD_ID ||
143435933ddSDimitry Andric           !m_name.empty() || !m_queue_name.empty());
144ac7ddfbfSEd Maste }
1459f2f44ceSEd Maste 
GetDescription(Stream * s,lldb::DescriptionLevel level) const146435933ddSDimitry Andric void ThreadSpec::GetDescription(Stream *s, lldb::DescriptionLevel level) const {
147435933ddSDimitry Andric   if (!HasSpecification()) {
148435933ddSDimitry Andric     if (level == eDescriptionLevelBrief) {
149ac7ddfbfSEd Maste       s->PutCString("thread spec: no ");
150ac7ddfbfSEd Maste     }
151435933ddSDimitry Andric   } else {
152435933ddSDimitry Andric     if (level == eDescriptionLevelBrief) {
153ac7ddfbfSEd Maste       s->PutCString("thread spec: yes ");
154435933ddSDimitry Andric     } else {
155ac7ddfbfSEd Maste       if (GetTID() != LLDB_INVALID_THREAD_ID)
156ac7ddfbfSEd Maste         s->Printf("tid: 0x%" PRIx64 " ", GetTID());
157ac7ddfbfSEd Maste 
158ac7ddfbfSEd Maste       if (GetIndex() != UINT32_MAX)
159ac7ddfbfSEd Maste         s->Printf("index: %d ", GetIndex());
160ac7ddfbfSEd Maste 
161ac7ddfbfSEd Maste       const char *name = GetName();
162ac7ddfbfSEd Maste       if (name)
163ac7ddfbfSEd Maste         s->Printf("thread name: \"%s\" ", name);
164ac7ddfbfSEd Maste 
165ac7ddfbfSEd Maste       const char *queue_name = GetQueueName();
166ac7ddfbfSEd Maste       if (queue_name)
167ac7ddfbfSEd Maste         s->Printf("queue name: \"%s\" ", queue_name);
168ac7ddfbfSEd Maste     }
169ac7ddfbfSEd Maste   }
170ac7ddfbfSEd Maste }
171