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