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() 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