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