10b57cec5SDimitry Andric //===-- ThreadSpec.cpp ----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Target/ThreadSpec.h"
100b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
110b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric using namespace lldb;
140b57cec5SDimitry Andric using namespace lldb_private;
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric const char *ThreadSpec::g_option_names[static_cast<uint32_t>(
170b57cec5SDimitry Andric     ThreadSpec::OptionNames::LastOptionName)]{"Index", "ID", "Name",
180b57cec5SDimitry Andric                                               "QueueName"};
190b57cec5SDimitry Andric 
ThreadSpec()200b57cec5SDimitry Andric ThreadSpec::ThreadSpec() : m_name(), m_queue_name() {}
210b57cec5SDimitry Andric 
CreateFromStructuredData(const StructuredData::Dictionary & spec_dict,Status & error)220b57cec5SDimitry Andric std::unique_ptr<ThreadSpec> ThreadSpec::CreateFromStructuredData(
230b57cec5SDimitry Andric     const StructuredData::Dictionary &spec_dict, Status &error) {
240b57cec5SDimitry Andric   uint32_t index = UINT32_MAX;
250b57cec5SDimitry Andric   lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
260b57cec5SDimitry Andric   llvm::StringRef name;
270b57cec5SDimitry Andric   llvm::StringRef queue_name;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric   std::unique_ptr<ThreadSpec> thread_spec_up(new ThreadSpec());
300b57cec5SDimitry Andric   bool success = spec_dict.GetValueForKeyAsInteger(
310b57cec5SDimitry Andric       GetKey(OptionNames::ThreadIndex), index);
320b57cec5SDimitry Andric   if (success)
330b57cec5SDimitry Andric     thread_spec_up->SetIndex(index);
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   success =
360b57cec5SDimitry Andric       spec_dict.GetValueForKeyAsInteger(GetKey(OptionNames::ThreadID), tid);
370b57cec5SDimitry Andric   if (success)
380b57cec5SDimitry Andric     thread_spec_up->SetTID(tid);
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   success =
410b57cec5SDimitry Andric       spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName), name);
420b57cec5SDimitry Andric   if (success)
430b57cec5SDimitry Andric     thread_spec_up->SetName(name);
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   success = spec_dict.GetValueForKeyAsString(GetKey(OptionNames::ThreadName),
460b57cec5SDimitry Andric                                              queue_name);
470b57cec5SDimitry Andric   if (success)
480b57cec5SDimitry Andric     thread_spec_up->SetQueueName(queue_name);
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   return thread_spec_up;
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
SerializeToStructuredData()530b57cec5SDimitry Andric StructuredData::ObjectSP ThreadSpec::SerializeToStructuredData() {
540b57cec5SDimitry Andric   StructuredData::DictionarySP data_dict_sp(new StructuredData::Dictionary());
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   if (m_index != UINT32_MAX)
570b57cec5SDimitry Andric     data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadIndex), m_index);
580b57cec5SDimitry Andric   if (m_tid != LLDB_INVALID_THREAD_ID)
590b57cec5SDimitry Andric     data_dict_sp->AddIntegerItem(GetKey(OptionNames::ThreadID), m_tid);
600b57cec5SDimitry Andric   if (!m_name.empty())
610b57cec5SDimitry Andric     data_dict_sp->AddStringItem(GetKey(OptionNames::ThreadName), m_name);
620b57cec5SDimitry Andric   if (!m_queue_name.empty())
630b57cec5SDimitry Andric     data_dict_sp->AddStringItem(GetKey(OptionNames::QueueName), m_queue_name);
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   return data_dict_sp;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
GetName() const680b57cec5SDimitry Andric const char *ThreadSpec::GetName() const {
690b57cec5SDimitry Andric   return m_name.empty() ? nullptr : m_name.c_str();
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
GetQueueName() const720b57cec5SDimitry Andric const char *ThreadSpec::GetQueueName() const {
730b57cec5SDimitry Andric   return m_queue_name.empty() ? nullptr : m_queue_name.c_str();
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
TIDMatches(Thread & thread) const760b57cec5SDimitry Andric bool ThreadSpec::TIDMatches(Thread &thread) const {
770b57cec5SDimitry Andric   if (m_tid == LLDB_INVALID_THREAD_ID)
780b57cec5SDimitry Andric     return true;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   lldb::tid_t thread_id = thread.GetID();
810b57cec5SDimitry Andric   return TIDMatches(thread_id);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
IndexMatches(Thread & thread) const840b57cec5SDimitry Andric bool ThreadSpec::IndexMatches(Thread &thread) const {
850b57cec5SDimitry Andric   if (m_index == UINT32_MAX)
860b57cec5SDimitry Andric     return true;
870b57cec5SDimitry Andric   uint32_t index = thread.GetIndexID();
880b57cec5SDimitry Andric   return IndexMatches(index);
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
NameMatches(Thread & thread) const910b57cec5SDimitry Andric bool ThreadSpec::NameMatches(Thread &thread) const {
920b57cec5SDimitry Andric   if (m_name.empty())
930b57cec5SDimitry Andric     return true;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   const char *name = thread.GetName();
960b57cec5SDimitry Andric   return NameMatches(name);
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
QueueNameMatches(Thread & thread) const990b57cec5SDimitry Andric bool ThreadSpec::QueueNameMatches(Thread &thread) const {
1000b57cec5SDimitry Andric   if (m_queue_name.empty())
1010b57cec5SDimitry Andric     return true;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   const char *queue_name = thread.GetQueueName();
1040b57cec5SDimitry Andric   return QueueNameMatches(queue_name);
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
ThreadPassesBasicTests(Thread & thread) const1070b57cec5SDimitry Andric bool ThreadSpec::ThreadPassesBasicTests(Thread &thread) const {
1080b57cec5SDimitry Andric   if (!HasSpecification())
1090b57cec5SDimitry Andric     return true;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   if (!TIDMatches(thread))
1120b57cec5SDimitry Andric     return false;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   if (!IndexMatches(thread))
1150b57cec5SDimitry Andric     return false;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   if (!NameMatches(thread))
1180b57cec5SDimitry Andric     return false;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   if (!QueueNameMatches(thread))
1210b57cec5SDimitry Andric     return false;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   return true;
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
HasSpecification() const1260b57cec5SDimitry Andric bool ThreadSpec::HasSpecification() const {
1270b57cec5SDimitry Andric   return (m_index != UINT32_MAX || m_tid != LLDB_INVALID_THREAD_ID ||
1280b57cec5SDimitry Andric           !m_name.empty() || !m_queue_name.empty());
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
GetDescription(Stream * s,lldb::DescriptionLevel level) const1310b57cec5SDimitry Andric void ThreadSpec::GetDescription(Stream *s, lldb::DescriptionLevel level) const {
1320b57cec5SDimitry Andric   if (!HasSpecification()) {
1330b57cec5SDimitry Andric     if (level == eDescriptionLevelBrief) {
1340b57cec5SDimitry Andric       s->PutCString("thread spec: no ");
1350b57cec5SDimitry Andric     }
1360b57cec5SDimitry Andric   } else {
1370b57cec5SDimitry Andric     if (level == eDescriptionLevelBrief) {
1380b57cec5SDimitry Andric       s->PutCString("thread spec: yes ");
1390b57cec5SDimitry Andric     } else {
1400b57cec5SDimitry Andric       if (GetTID() != LLDB_INVALID_THREAD_ID)
1410b57cec5SDimitry Andric         s->Printf("tid: 0x%" PRIx64 " ", GetTID());
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric       if (GetIndex() != UINT32_MAX)
1440b57cec5SDimitry Andric         s->Printf("index: %d ", GetIndex());
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric       const char *name = GetName();
1470b57cec5SDimitry Andric       if (name)
1480b57cec5SDimitry Andric         s->Printf("thread name: \"%s\" ", name);
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric       const char *queue_name = GetQueueName();
1510b57cec5SDimitry Andric       if (queue_name)
1520b57cec5SDimitry Andric         s->Printf("queue name: \"%s\" ", queue_name);
1530b57cec5SDimitry Andric     }
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric