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