LLDB mainline
TargetGroup.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
10#include "lldb/Core/Debugger.h"
11#include "lldb/Target/Target.h"
13
14#include <algorithm>
15#include <cassert>
16
17using namespace lldb;
18using namespace lldb_private;
19
22
24 llvm::StringRef description)
25 : m_debugger_wp(group_list.m_debugger.shared_from_this()),
26 m_description(description), m_mutex(group_list.m_mutex) {}
27
29 assert(m_entries.empty() &&
30 "target group destroyed while it still contains targets");
31}
32
34 return llvm::Error::success();
35}
36
38 TargetGroupList &group_list, llvm::StringRef description)
39 : Base(group_list, description) {}
40
41llvm::Error
43 Role role) const {
44 switch (role) {
45 case Role::CPU:
46 if (!GetTargets().empty())
47 return llvm::createStringError(
48 "the CPU target must be the first target in the group");
49 break;
50 case Role::Accelerator:
51 if (GetTargets(Role::CPU).size() != 1)
52 return llvm::createStringError(
53 "the group must contain one CPU target before adding accelerators");
54 break;
55 }
56 return llvm::Error::success();
57}
58
60 std::vector<TargetSP> cpu_targets = GetTargets(Role::CPU);
61 assert(cpu_targets.size() <= 1 &&
62 "CPU and accelerator group contains multiple CPU targets");
63 return cpu_targets.empty() ? nullptr : cpu_targets.front();
64}
65
66llvm::Error TargetGroup::AddTarget(const TargetSP &target_sp, Role role) {
67 if (!target_sp)
68 return llvm::createStringError(
69 "cannot add a null target to a target group");
70 if (!target_sp->IsValid())
71 return llvm::createStringError(
72 "cannot add an invalid target to a target group");
73
74 DebuggerSP debugger_sp = m_debugger_wp.lock();
75 if (!debugger_sp)
76 return llvm::createStringError("target group's debugger no longer exists");
77 if (&target_sp->GetDebugger() != debugger_sp.get())
78 return llvm::createStringError("target belongs to a different debugger");
79
80 std::lock_guard<std::recursive_mutex> guard(*m_mutex);
81 for (const Entry &entry : m_entries) {
82 TargetSP member_sp = entry.target_wp.lock();
83 assert(member_sp && "target did not remove itself from its target group");
84 if (!member_sp)
85 continue;
86 if (member_sp != target_sp)
87 continue;
88 if (entry.role == role)
89 return llvm::Error::success();
90 return llvm::createStringError(
91 "target is already in the group with a different role");
92 }
93
94 if (llvm::Error error = ValidateTargetAddition(target_sp, role))
95 return error;
96
97 m_entries.push_back({target_sp, role});
98 target_sp->AddTargetGroup(shared_from_this());
99 return llvm::Error::success();
100}
101
102bool TargetGroup::RemoveTarget(const TargetSP &target_sp) {
103 if (!target_sp)
104 return false;
105
106 std::lock_guard<std::recursive_mutex> guard(*m_mutex);
107 bool removed = false;
108 auto it = std::remove_if(
109 m_entries.begin(), m_entries.end(), [&](const Entry &entry) {
110 TargetSP member_sp = entry.target_wp.lock();
111 assert(member_sp && "target did not remove itself from its "
112 "target group");
113 if (member_sp == target_sp) {
114 removed = true;
115 return true;
116 }
117 return false;
118 });
119 m_entries.erase(it, m_entries.end());
120 if (removed)
121 target_sp->RemoveTargetGroup(this);
122 return removed;
123}
124
125std::optional<TargetGroup::Role>
126TargetGroup::GetRole(const TargetSP &target_sp) const {
127 if (!target_sp)
128 return std::nullopt;
129
130 std::lock_guard<std::recursive_mutex> guard(*m_mutex);
131 for (const Entry &entry : m_entries) {
132 TargetSP member_sp = entry.target_wp.lock();
133 assert(member_sp && "target did not remove itself from its target group");
134 if (member_sp == target_sp)
135 return entry.role;
136 }
137 return std::nullopt;
138}
139
140std::vector<TargetSP> TargetGroup::GetTargets() const {
141 std::vector<TargetSP> targets;
142 std::lock_guard<std::recursive_mutex> guard(*m_mutex);
143 for (const Entry &entry : m_entries) {
144 TargetSP target_sp = entry.target_wp.lock();
145 assert(target_sp && "target did not remove itself from its target group");
146 if (target_sp)
147 targets.push_back(std::move(target_sp));
148 }
149 return targets;
150}
151
152std::vector<TargetSP> TargetGroup::GetTargets(Role role) const {
153 std::vector<TargetSP> targets;
154 std::lock_guard<std::recursive_mutex> guard(*m_mutex);
155 for (const Entry &entry : m_entries) {
156 if (entry.role != role)
157 continue;
158 TargetSP target_sp = entry.target_wp.lock();
159 assert(target_sp && "target did not remove itself from its target group");
160 if (target_sp)
161 targets.push_back(std::move(target_sp));
162 }
163 return targets;
164}
static llvm::raw_ostream & error(Stream &strm)
lldb::TargetSP GetCPUTarget() const
Return the CPU target, or nullptr if the group has no CPU target.
llvm::Error ValidateTargetAddition(const lldb::TargetSP &target_sp, Role role) const override
TargetGroupCPUAndAccelerators(TargetGroupList &group_list, llvm::StringRef description)
llvm::RTTIExtends< TargetGroupCPUAndAccelerators, TargetGroup > Base
Definition TargetGroup.h:98
std::shared_ptr< std::recursive_mutex > m_mutex
Definition TargetGroup.h:89
friend class TargetGroupList
Definition TargetGroup.h:80
bool RemoveTarget(const lldb::TargetSP &target_sp)
Remove target_sp from the group.
std::vector< Entry > m_entries
Targets are weakly held so membership does not extend their lifetime.
Definition TargetGroup.h:91
Role
Describes the part a target plays in this group.
Definition TargetGroup.h:37
llvm::Error AddTarget(const lldb::TargetSP &target_sp, Role role)
Add target_sp to the group with role.
std::optional< Role > GetRole(const lldb::TargetSP &target_sp) const
Return the role assigned to target_sp, if it is a member.
TargetGroup(const TargetGroup &)=delete
Target groups have identity and maintain backlinks in their member targets, so they cannot be copied ...
std::vector< lldb::TargetSP > GetTargets() const
Return every target in the group.
virtual llvm::Error ValidateTargetAddition(const lldb::TargetSP &target_sp, Role role) const
Validate a new membership while the membership lock is held.
lldb::DebuggerWP m_debugger_wp
Definition TargetGroup.h:87
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::Debugger > DebuggerSP
std::shared_ptr< lldb_private::Target > TargetSP