1cfca06d7SDimitry Andric //===-- ThreadSpec.cpp ----------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/Target/ThreadSpec.h"
101b306c26SDimitry Andric #include "lldb/Target/Thread.h"
111b306c26SDimitry Andric #include "lldb/Utility/StructuredData.h"
12f034231aSEd Maste
13f034231aSEd Maste using namespace lldb;
14f034231aSEd Maste using namespace lldb_private;
15f034231aSEd Maste
1614f1b3e8SDimitry Andric const char *ThreadSpec::g_option_names[static_cast<uint32_t>(
1714f1b3e8SDimitry Andric ThreadSpec::OptionNames::LastOptionName)]{"Index", "ID", "Name",
1814f1b3e8SDimitry Andric "QueueName"};
19f034231aSEd Maste
ThreadSpec()20344a3780SDimitry Andric ThreadSpec::ThreadSpec() : m_name(), m_queue_name() {}
21f034231aSEd Maste
CreateFromStructuredData(const StructuredData::Dictionary & spec_dict,Status & error)2214f1b3e8SDimitry Andric std::unique_ptr<ThreadSpec> ThreadSpec::CreateFromStructuredData(
23b76161e4SDimitry Andric const StructuredData::Dictionary &spec_dict, Status &error) {
2414f1b3e8SDimitry Andric uint32_t index = UINT32_MAX;
2514f1b3e8SDimitry Andric lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
26b76161e4SDimitry Andric llvm::StringRef name;
27b76161e4SDimitry Andric llvm::StringRef queue_name;
2814f1b3e8SDimitry Andric
2914f1b3e8SDimitry Andric std::unique_ptr<ThreadSpec> thread_spec_up(new ThreadSpec());
3014f1b3e8SDimitry Andric bool success = spec_dict.GetValueForKeyAsInteger(
3114f1b3e8SDimitry Andric GetKey(OptionNames::ThreadIndex), index);
3214f1b3e8SDimitry Andric if (success)
3314f1b3e8SDimitry Andric thread_spec_up->SetIndex(index);
3414f1b3e8SDimitry Andric
3514f1b3e8SDimitry Andric success =
3614f1b3e8SDimitry Andric spec_dict.GetValueForKeyAsInteger(GetKey(OptionNames::ThreadID), tid);
3714f1b3e8SDimitry Andric if (success)
3814f1b3e8SDimitry Andric thread_spec_up->SetTID(tid);
3914f1b3e8SDimitry Andric
4014f1b3e8SDimitry Andric success =
4114f1b3e8SDimitry Andric spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName), name);
4214f1b3e8SDimitry Andric if (success)
43b76161e4SDimitry Andric thread_spec_up->SetName(name);
4414f1b3e8SDimitry Andric
4514f1b3e8SDimitry Andric success = spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName),
4614f1b3e8SDimitry Andric queue_name);
4714f1b3e8SDimitry Andric if (success)
48b76161e4SDimitry Andric thread_spec_up->SetQueueName(queue_name);
4914f1b3e8SDimitry Andric
5014f1b3e8SDimitry Andric return thread_spec_up;
5114f1b3e8SDimitry Andric }
5214f1b3e8SDimitry Andric
SerializeToStructuredData()5314f1b3e8SDimitry Andric StructuredData::ObjectSP ThreadSpec::SerializeToStructuredData() {
5414f1b3e8SDimitry Andric StructuredData::DictionarySP data_dict_sp(new StructuredData::Dictionary());
5514f1b3e8SDimitry Andric
5614f1b3e8SDimitry Andric if (m_index != UINT32_MAX)
5714f1b3e8SDimitry Andric data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadIndex), m_index);
5814f1b3e8SDimitry Andric if (m_tid != LLDB_INVALID_THREAD_ID)
5914f1b3e8SDimitry Andric data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadID), m_tid);
6014f1b3e8SDimitry Andric if (!m_name.empty())
6114f1b3e8SDimitry Andric data_dict_sp->AddStringItem(GetKey(OptionNames::ThreadName), m_name);
6214f1b3e8SDimitry Andric if (!m_queue_name.empty())
6314f1b3e8SDimitry Andric data_dict_sp->AddStringItem(GetKey(OptionNames::QueueName), m_queue_name);
6414f1b3e8SDimitry Andric
6514f1b3e8SDimitry Andric return data_dict_sp;
6614f1b3e8SDimitry Andric }
6714f1b3e8SDimitry Andric
GetName() const6814f1b3e8SDimitry Andric const char *ThreadSpec::GetName() const {
69e81d9d49SDimitry Andric return m_name.empty() ? nullptr : m_name.c_str();
70f034231aSEd Maste }
71f034231aSEd Maste
GetQueueName() const7214f1b3e8SDimitry Andric const char *ThreadSpec::GetQueueName() const {
73e81d9d49SDimitry Andric return m_queue_name.empty() ? nullptr : m_queue_name.c_str();
74f034231aSEd Maste }
75f034231aSEd Maste
TIDMatches(Thread & thread) const7614f1b3e8SDimitry Andric bool ThreadSpec::TIDMatches(Thread &thread) const {
77f034231aSEd Maste if (m_tid == LLDB_INVALID_THREAD_ID)
78f034231aSEd Maste return true;
79f034231aSEd Maste
80f034231aSEd Maste lldb::tid_t thread_id = thread.GetID();
81f034231aSEd Maste return TIDMatches(thread_id);
82f034231aSEd Maste }
83e81d9d49SDimitry Andric
IndexMatches(Thread & thread) const8414f1b3e8SDimitry Andric bool ThreadSpec::IndexMatches(Thread &thread) const {
85f034231aSEd Maste if (m_index == UINT32_MAX)
86f034231aSEd Maste return true;
87f034231aSEd Maste uint32_t index = thread.GetIndexID();
88f034231aSEd Maste return IndexMatches(index);
89f034231aSEd Maste }
90e81d9d49SDimitry Andric
NameMatches(Thread & thread) const9114f1b3e8SDimitry Andric bool ThreadSpec::NameMatches(Thread &thread) const {
92f034231aSEd Maste if (m_name.empty())
93f034231aSEd Maste return true;
94f034231aSEd Maste
95f034231aSEd Maste const char *name = thread.GetName();
96f034231aSEd Maste return NameMatches(name);
97f034231aSEd Maste }
98e81d9d49SDimitry Andric
QueueNameMatches(Thread & thread) const9914f1b3e8SDimitry Andric bool ThreadSpec::QueueNameMatches(Thread &thread) const {
100f034231aSEd Maste if (m_queue_name.empty())
101f034231aSEd Maste return true;
102f034231aSEd Maste
103f034231aSEd Maste const char *queue_name = thread.GetQueueName();
104f034231aSEd Maste return QueueNameMatches(queue_name);
105f034231aSEd Maste }
106f034231aSEd Maste
ThreadPassesBasicTests(Thread & thread) const10714f1b3e8SDimitry Andric bool ThreadSpec::ThreadPassesBasicTests(Thread &thread) const {
108f034231aSEd Maste if (!HasSpecification())
109f034231aSEd Maste return true;
110f034231aSEd Maste
111f034231aSEd Maste if (!TIDMatches(thread))
112f034231aSEd Maste return false;
113f034231aSEd Maste
114f034231aSEd Maste if (!IndexMatches(thread))
115f034231aSEd Maste return false;
116f034231aSEd Maste
117f034231aSEd Maste if (!NameMatches(thread))
118f034231aSEd Maste return false;
119f034231aSEd Maste
120f034231aSEd Maste if (!QueueNameMatches(thread))
121f034231aSEd Maste return false;
122f034231aSEd Maste
123f034231aSEd Maste return true;
124f034231aSEd Maste }
125f034231aSEd Maste
HasSpecification() const12614f1b3e8SDimitry Andric bool ThreadSpec::HasSpecification() const {
12714f1b3e8SDimitry Andric return (m_index != UINT32_MAX || m_tid != LLDB_INVALID_THREAD_ID ||
12814f1b3e8SDimitry Andric !m_name.empty() || !m_queue_name.empty());
129f034231aSEd Maste }
130e81d9d49SDimitry Andric
GetDescription(Stream * s,lldb::DescriptionLevel level) const13114f1b3e8SDimitry Andric void ThreadSpec::GetDescription(Stream *s, lldb::DescriptionLevel level) const {
13214f1b3e8SDimitry Andric if (!HasSpecification()) {
13314f1b3e8SDimitry Andric if (level == eDescriptionLevelBrief) {
134f034231aSEd Maste s->PutCString("thread spec: no ");
135f034231aSEd Maste }
13614f1b3e8SDimitry Andric } else {
13714f1b3e8SDimitry Andric if (level == eDescriptionLevelBrief) {
138f034231aSEd Maste s->PutCString("thread spec: yes ");
13914f1b3e8SDimitry Andric } else {
140f034231aSEd Maste if (GetTID() != LLDB_INVALID_THREAD_ID)
141f034231aSEd Maste s->Printf("tid: 0x%" PRIx64 " ", GetTID());
142f034231aSEd Maste
143f034231aSEd Maste if (GetIndex() != UINT32_MAX)
144f034231aSEd Maste s->Printf("index: %d ", GetIndex());
145f034231aSEd Maste
146f034231aSEd Maste const char *name = GetName();
147f034231aSEd Maste if (name)
148f034231aSEd Maste s->Printf("thread name: \"%s\" ", name);
149f034231aSEd Maste
150f034231aSEd Maste const char *queue_name = GetQueueName();
151f034231aSEd Maste if (queue_name)
152f034231aSEd Maste s->Printf("queue name: \"%s\" ", queue_name);
153f034231aSEd Maste }
154f034231aSEd Maste }
155f034231aSEd Maste }
156