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