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 ThreadSpec::ThreadSpec(const ThreadSpec &rhs) 25 : m_index(rhs.m_index), m_tid(rhs.m_tid), m_name(rhs.m_name), 26 m_queue_name(rhs.m_queue_name) {} 27 28 const ThreadSpec &ThreadSpec::operator=(const ThreadSpec &rhs) { 29 m_index = rhs.m_index; 30 m_tid = rhs.m_tid; 31 m_name = rhs.m_name; 32 m_queue_name = rhs.m_queue_name; 33 return *this; 34 } 35 36 std::unique_ptr<ThreadSpec> ThreadSpec::CreateFromStructuredData( 37 const StructuredData::Dictionary &spec_dict, Status &error) { 38 uint32_t index = UINT32_MAX; 39 lldb::tid_t tid = LLDB_INVALID_THREAD_ID; 40 llvm::StringRef name; 41 llvm::StringRef queue_name; 42 43 std::unique_ptr<ThreadSpec> thread_spec_up(new ThreadSpec()); 44 bool success = spec_dict.GetValueForKeyAsInteger( 45 GetKey(OptionNames::ThreadIndex), index); 46 if (success) 47 thread_spec_up->SetIndex(index); 48 49 success = 50 spec_dict.GetValueForKeyAsInteger(GetKey(OptionNames::ThreadID), tid); 51 if (success) 52 thread_spec_up->SetTID(tid); 53 54 success = 55 spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName), name); 56 if (success) 57 thread_spec_up->SetName(name); 58 59 success = spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName), 60 queue_name); 61 if (success) 62 thread_spec_up->SetQueueName(queue_name); 63 64 return thread_spec_up; 65 } 66 67 StructuredData::ObjectSP ThreadSpec::SerializeToStructuredData() { 68 StructuredData::DictionarySP data_dict_sp(new StructuredData::Dictionary()); 69 70 if (m_index != UINT32_MAX) 71 data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadIndex), m_index); 72 if (m_tid != LLDB_INVALID_THREAD_ID) 73 data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadID), m_tid); 74 if (!m_name.empty()) 75 data_dict_sp->AddStringItem(GetKey(OptionNames::ThreadName), m_name); 76 if (!m_queue_name.empty()) 77 data_dict_sp->AddStringItem(GetKey(OptionNames::QueueName), m_queue_name); 78 79 return data_dict_sp; 80 } 81 82 const char *ThreadSpec::GetName() const { 83 return m_name.empty() ? nullptr : m_name.c_str(); 84 } 85 86 const char *ThreadSpec::GetQueueName() const { 87 return m_queue_name.empty() ? nullptr : m_queue_name.c_str(); 88 } 89 90 bool ThreadSpec::TIDMatches(Thread &thread) const { 91 if (m_tid == LLDB_INVALID_THREAD_ID) 92 return true; 93 94 lldb::tid_t thread_id = thread.GetID(); 95 return TIDMatches(thread_id); 96 } 97 98 bool ThreadSpec::IndexMatches(Thread &thread) const { 99 if (m_index == UINT32_MAX) 100 return true; 101 uint32_t index = thread.GetIndexID(); 102 return IndexMatches(index); 103 } 104 105 bool ThreadSpec::NameMatches(Thread &thread) const { 106 if (m_name.empty()) 107 return true; 108 109 const char *name = thread.GetName(); 110 return NameMatches(name); 111 } 112 113 bool ThreadSpec::QueueNameMatches(Thread &thread) const { 114 if (m_queue_name.empty()) 115 return true; 116 117 const char *queue_name = thread.GetQueueName(); 118 return QueueNameMatches(queue_name); 119 } 120 121 bool ThreadSpec::ThreadPassesBasicTests(Thread &thread) const { 122 if (!HasSpecification()) 123 return true; 124 125 if (!TIDMatches(thread)) 126 return false; 127 128 if (!IndexMatches(thread)) 129 return false; 130 131 if (!NameMatches(thread)) 132 return false; 133 134 if (!QueueNameMatches(thread)) 135 return false; 136 137 return true; 138 } 139 140 bool ThreadSpec::HasSpecification() const { 141 return (m_index != UINT32_MAX || m_tid != LLDB_INVALID_THREAD_ID || 142 !m_name.empty() || !m_queue_name.empty()); 143 } 144 145 void ThreadSpec::GetDescription(Stream *s, lldb::DescriptionLevel level) const { 146 if (!HasSpecification()) { 147 if (level == eDescriptionLevelBrief) { 148 s->PutCString("thread spec: no "); 149 } 150 } else { 151 if (level == eDescriptionLevelBrief) { 152 s->PutCString("thread spec: yes "); 153 } else { 154 if (GetTID() != LLDB_INVALID_THREAD_ID) 155 s->Printf("tid: 0x%" PRIx64 " ", GetTID()); 156 157 if (GetIndex() != UINT32_MAX) 158 s->Printf("index: %d ", GetIndex()); 159 160 const char *name = GetName(); 161 if (name) 162 s->Printf("thread name: \"%s\" ", name); 163 164 const char *queue_name = GetQueueName(); 165 if (queue_name) 166 s->Printf("queue name: \"%s\" ", queue_name); 167 } 168 } 169 } 170