10000 Merge pull request #10894 from felipepiovezan/felipe/cache_tls · swiftlang/llvm-project@45781f1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 45781f1

Browse files
Merge pull request #10894 from felipepiovezan/felipe/cache_tls
[lldb] Cache Task pointer location and Task names
2 parents b79c639 + 1d2a6be commit 45781f1

File tree

7 files changed

+163
-50
lines changed

7 files changed

+163
-50
lines changed

lldb/include/lldb/Target/Target.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ class TargetProperties : public Properties {
201201

202202
bool GetSwiftUseTasksPlugin() const;
203203

204+
bool GetSwiftCacheTaskPointerLocation() const;
205+
204206
Args GetSwiftPluginServerForPath() const;
205207

206208
bool GetSwiftAutoImportFrameworks() const;

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,8 +2325,9 @@ class CommandObjectLanguageSwiftTaskInfo final : public CommandObjectParsed {
23252325
return;
23262326
}
23272327

2328-
auto task_addr_or_err =
2329-
GetTaskAddrFromThreadLocalStorage(m_exe_ctx.GetThreadRef());
2328+
TaskInspector task_inspector;
2329+
auto task_addr_or_err = task_inspector.GetTaskAddrFromThreadLocalStorage(
2330+
m_exe_ctx.GetThreadRef());
23302331
if (auto error = task_addr_or_err.takeError()) {
23312332
result.AppendError(toString(std::move(error)));
23322333
return;
@@ -2939,17 +2940,30 @@ std::optional<lldb::addr_t> SwiftLanguageRuntime::TrySkipVirtualParentProlog(
29392940
return pc_value + prologue_size;
29402941
}
29412942

2942-
llvm::Expected<lldb::addr_t> GetTaskAddrFromThreadLocalStorage(Thread &thread) {
2943+
/// Attempts to read the memory location at `task_addr_location`, producing
2944+
/// the Task pointer if possible.
2945+
static llvm::Expected<lldb::addr_t>
2946+
ReadTaskAddr(lldb::addr_t task_addr_location, Process &process) {
2947+
Status status;
2948+
addr_t task_addr = process.ReadPointerFromMemory(task_addr_location, status);
2949+
if (status.Fail())
2950+
return llvm::joinErrors(
2951+
llvm::createStringError("could not get current task from thread"),
2952+
status.takeError());
2953+
return task_addr;
2954+
}
2955+
2956+
/// Compute the location where the Task pointer for `real_thread` is stored by
2957+
/// the runtime.
2958+
static llvm::Expected<lldb::addr_t>
2959+
ComputeTaskAddrLocationFromThreadLocalStorage(Thread &real_thread) {
29432960
#if !SWIFT_THREADING_USE_RESERVED_TLS_KEYS
29442961
return llvm::createStringError(
29452962
"getting the current task from a thread is not supported");
29462963
#else
29472964
// Compute the thread local storage address for this thread.
29482965
addr_t tsd_addr = LLDB_INVALID_ADDRESS;
29492966

2950-
// Look through backing threads when inspecting TLS.
2951-
Thread &real_thread =
2952-
thread.GetBackingThread() ? *thread.GetBackingThread() : thread;
29532967
if (auto info_sp = real_thread.GetExtendedInfo())
29542968
if (auto *info_dict = info_sp->GetAsDictionary())
29552969
info_dict->GetValueForKeyAsInteger("tsd_address", tsd_addr);
@@ -2958,18 +2972,56 @@ llvm::Expected<lldb::addr_t> GetTaskAddrFromThreadLocalStorage(Thread &thread) {
29582972
return llvm::createStringError("could not read current task from thread");
29592973

29602974
// Offset of the Task pointer in a Thread's local storage.
2961-
Process &process = *thread.GetProcess();
2975+
Process &process = *real_thread.GetProcess();
29622976
size_t ptr_size = process.GetAddressByteSize();
29632977
uint64_t task_ptr_offset_in_tls =
29642978
swift::tls_get_key(swift::tls_key::concurrency_task) * ptr_size;
2965-
addr_t task_addr_location = tsd_addr + task_ptr_offset_in_tls;
2966-
Status status;
2967-
addr_t task_addr = process.ReadPointerFromMemory(task_addr_location, status);
2968-
if (status.Fail())
2969-
return llvm::createStringError("could not get current task from thread: %s",
2970-
status.AsCString());
2971-
return task_addr;
2979+
return tsd_addr + task_ptr_offset_in_tls;
2980+
#endif
2981+
}
2982+
2983+
llvm::Expected<lldb::addr_t>
2984+
TaskInspector::GetTaskAddrFromThreadLocalStorage(Thread &thread) {
2985+
// Look through backing threads when inspecting TLS.
2986+
Thread &real_thread =
2987+
thread.GetBackingThread() ? *thread.GetBackingThread() : thread;
2988+
2989+
if (auto it = m_tid_to_task_addr_location.find(real_thread.GetID());
2990+
it != m_tid_to_task_addr_location.end()) {
2991+
#ifndef NDEBUG
2992+
// In assert builds, check that caching did not produce incorrect results.
2993+
llvm::Expected<lldb::addr_t> task_addr_location =
2994+
ComputeTaskAddrLocationFromThreadLocalStorage(real_thread);
2995+
assert(task_addr_location);
2996+
assert(it->second == *task_addr_location);
29722997
#endif
2998+
llvm::Expected<lldb::addr_t> task_addr =
2999+
ReadTaskAddr(it->second, *thread.GetProcess());
3000+
if (task_addr)
3001+
return task_addr;
3002+
// If the cached task addr location became invalid, invalidate the cache.
3003+
m_tid_to_task_addr_location.erase(it);
3004+
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), task_addr.takeError(),
3005+
"TaskInspector: evicted task location address due to "
3006+
"invalid memory read: {0}");
3007+
}
3008+
3009+
llvm::Expected<lldb::addr_t> task_addr_location =
3010+
ComputeTaskAddrLocationFromThreadLocalStorage(real_thread);
3011+
if (!task_addr_location)
3012+
return task_addr_location;
3013+
3014+
llvm::Expected<lldb::addr_t> task_addr =
3015+
ReadTaskAddr(*task_addr_location, *thread.GetProcess());
3016+
3017+
// If the read from this TLS address is successful, cache the TLS address.
3018+
// Caching without a valid read is dangerous: earlier in the thread
3019+
// lifetime, the result of GetExtendedInfo can be invalid.
3020+
if (task_addr &&
3021+
real_thread.GetProcess()->GetTarget().GetSwiftCacheTaskPointerLocation())
3022+
m_tid_to_task_addr_location.try_emplace(real_thread.GetID(),
3023+
*task_addr_location);
3024+
return task_addr;
29733025
}
29743026

29753027
namespace {

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -902,9 +902,17 @@ struct AsyncUnwindRegisterNumbers {
902902
std::optional<AsyncUnwindRegisterNumbers>
903903
GetAsyncUnwindRegisterNumbers(llvm::Triple::ArchType triple);
904904

905-
/// Inspects thread local storage to find the address of the currently executing
906-
/// task.
907-
llvm::Expected<lldb::addr_t> GetTaskAddrFromThreadLocalStorage(Thread &thread);
905+
/// A helper class to find and cache the location of Task pointer inside TLS.
906+
class TaskInspector {
907+
public:
908+
/// Inspects thread local storage to find the address of the currently
909+
/// executing task, if any.
910+
llvm::Expected<lldb::addr_t>
911+
GetTaskAddrFromThreadLocalStorage(Thread &thread);
912+
913+
private:
914+
llvm::DenseMap<uint64_t, lldb::addr_t> m_tid_to_task_addr_location;
915+
};
908916

909917
llvm::Expected<std::optional<std::string>> GetTaskName(lldb::addr_t task,
910918
Process &process);

lldb/source/Plugins/OperatingSystem/SwiftTasks/OperatingSystemSwiftTasks.cpp

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,55 @@ void OperatingSystemSwiftTasks::Terminate() {
3838
PluginManager::UnregisterPlugin(CreateInstance);
3939
}
4040

41+
/// A wrapper around ThreadMemory providing lazy name evaluation, as this is
42+
/// expensive to compute for Swift Tasks.
43+
class SwiftTaskThreadMemory : public ThreadMemory {
44+
public:
45+
SwiftTaskThreadMemory(lldb_private::Process &process, lldb::tid_t tid,
46+
lldb::addr_t register_data_addr)
47+
: ThreadMemory(process, tid, register_data_addr) {}
48+
49+
/// Updates the backing thread of this Task, as well as the location where the
50+
/// task pointer is stored.
51+
void UpdateBackingThread(const ThreadSP &new_backing_thread,
52+
lldb::addr_t task_addr) {
53+
SetBackingThread(new_backing_thread);
54+
m_task_addr = task_addr;
55+
}
56+
57+
const char *GetName() override {
58+
if (m_task_name.empty())
59+
m_task_name = FindTaskName();
60+
return m_task_name.c_str();
61+
}
62+
63+
private:
64+
std::string GetDefaultTaskName() const {
65+
return llvm::formatv("Task {0}", GetID());
66+
}
67+
68+
/// If possible, read a user-provided task name from memory, otherwise use a
69+
/// default name. This never returns an empty string.
70+
std::string FindTaskName() const {
71+
llvm::Expected<std::optional<std::string>> task_name =
72+
GetTaskName(m_task_addr, *GetProcess());
73+
if (auto err = task_name.takeError()) {
74+
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), std::move(err),
75+
"OperatingSystemSwiftTasks: failed while looking for name "
76+
"of task {1:x}: {0}",
77+
m_task_addr);
78+
return GetDefaultTaskName();
79+
}
80+
81+
if (!task_name->has_value())
82+
return GetDefaultTaskName();
83+
return llvm::formatv("{0} (Task {1})", *task_name, GetID());
84+
}
85+
86+
std::string m_task_name = "";
87+
lldb::addr_t m_task_addr = LLDB_INVALID_ADDRESS;
88+
};
89+
4190
OperatingSystem *OperatingSystemSwiftTasks::CreateInstance(Process *process,
4291
bool force) {
4392
if (!process || !process->GetTarget().GetSwiftUseTasksPlugin())
@@ -78,9 +127,9 @@ OperatingSystemSwiftTasks::OperatingSystemSwiftTasks(
78127
lldb_private::Process &process)
79128
: OperatingSystem(&process) {}
80129

81-
ThreadSP OperatingSystemSwiftTasks::FindOrCreateSwiftThread(
82-
ThreadList &old_thread_list, uint64_t task_id,
83-
std::optional<std::string> task_name) {
130+
ThreadSP
131+
OperatingSystemSwiftTasks::FindOrCreateSwiftThread(ThreadList &old_thread_list,
132+
uint64_t task_id) {
84133
// Mask higher bits to avoid conflicts with core thread IDs.
85134
uint64_t masked_task_id = 0x0000000f00000000 | task_id;
86135

@@ -89,19 +138,14 @@ ThreadSP OperatingSystemSwiftTasks::FindOrCreateSwiftThread(
89138
IsOperatingSystemPluginThread(old_thread))
90139
return old_thread;
91140

92-
std::string name;
93-
if (task_name)
94-
name = llvm::formatv("{0} (Task {1})", *task_name, task_id);
95-
else
96-
name = llvm::formatv("Task {0}", task_id);
97-
98-
return std::make_shared<ThreadMemoryProvidingName>(*m_process, masked_task_id,
99-
/*register_data_addr*/ 0,
100-
name);
141+
return std::make_shared<SwiftTaskThreadMemory>(*m_process, masked_task_id,
142+
/*register_data_addr*/ 0);
101143
}
102144

103-
static std::optional<addr_t> FindTaskAddress(Thread &thread) {
104-
llvm::Expected<addr_t> task_addr = GetTaskAddrFromThreadLocalStorage(thread);
145+
static std::optional<addr_t> FindTaskAddress(TaskInspector &task_inspector,
146+
Thread &thread) {
147+
llvm::Expected<addr_t> task_addr =
148+
task_inspector.GetTaskAddrFromThreadLocalStorage(thread);
105149
if (!task_addr) {
106150
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), task_addr.takeError(),
107151
"OperatingSystemSwiftTasks: failed to find task address in "
@@ -130,27 +174,15 @@ static std::optional<uint64_t> FindTaskId(addr_t task_addr, Process &process) {
130174
return task_id;
131175
}
132176

133-
static std::optional<std::string> FindTaskName(addr_t task_addr,
134-
Process &process) {
135-
auto task_name_or_err = GetTaskName(task_addr, process);
136-
if (auto err = task_name_or_err.takeError()) {
137-
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), std::move(err),
138-
"OperatingSystemSwiftTasks: failed while looking for name "
139-
"of task {1:x}: {0}",
140-
task_addr);
141-
return {};
142-
}
143-
return *task_name_or_err;
144-
}
145-
146177
bool OperatingSystemSwiftTasks::UpdateThreadList(ThreadList &old_thread_list,
147178
ThreadList &core_thread_list,
148179
ThreadList &new_thread_list) {
149180
Log *log = GetLog(LLDBLog::OS);
150181
LLDB_LOG(log, "OperatingSystemSwiftTasks: Updating thread list");
151182

152183
for (const ThreadSP &real_thread : core_thread_list.Threads()) {
153-
std::optional<addr_t> task_addr = FindTaskAddress(*real_thread);
184+
std::optional<addr_t> task_addr =
185+
FindTaskAddress(m_task_inspector, *real_thread);
154186

155187
// If this is not a thread running a Task, add it to the list as is.
156188
if (!task_addr) {
@@ -170,9 +202,9 @@ bool OperatingSystemSwiftTasks::UpdateThreadList(ThreadList &old_thread_list,
170202
continue;
171203
}
172204

173-
ThreadSP swift_thread = FindOrCreateSwiftThread(
174-
old_thread_list, *task_id, FindTaskName(*task_addr, *m_process));
175-
swift_thread->SetBackingThread(real_thread);
205+
ThreadSP swift_thread = FindOrCreateSwiftThread(old_thread_list, *task_id);
206+
static_cast<SwiftTaskThreadMemory &>(*swift_thread)
207+
.UpdateBackingThread(real_thread, *task_addr);
176208
new_thread_list.AddThread(swift_thread);
177209
LLDB_LOGF(log,
178210
"OperatingSystemSwiftTasks: mapping thread IDs: %" PRIx64

lldb/source/Plugins/OperatingSystem/SwiftTasks/OperatingSystemSwiftTasks.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#if LLDB_ENABLE_SWIFT
1313

14+
#include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h"
1415
#include "lldb/Target/OperatingSystem.h"
1516

1617
namespace lldb_private {
@@ -49,8 +50,11 @@ class OperatingSystemSwiftTasks : public OperatingSystem {
4950
/// If a thread for task_id had been created in the last stop, return it.
5051
/// Otherwise, create a new MemoryThread for it.
5152
lldb::ThreadSP FindOrCreateSwiftThread(ThreadList &old_thread_list,
52-
uint64_t task_id,
53-
std::optional<std::string> task_name);
53+
uint64_t task_id);
54+
55+
/// A cache for task addr locations, which are expensive to compute but
56+
/// immutable.
57+
TaskInspector m_task_inspector;
5458
};
5559
} // namespace lldb_private
5660

lldb/source/Target/Target.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4529,6 +4529,18 @@ bool TargetProperties::GetSwiftUseTasksPlugin() const {
45294529
return true;
45304530
}
45314531

4532+
bool TargetProperties::GetSwiftCacheTaskPointerLocation() const {
4533+
const Property *exp_property =
4534+
m_collection_sp->GetPropertyAtIndex(ePropertyExperimental);
4535+
OptionValueProperties *exp_values =
4536+
exp_property->GetValue()->GetAsProperties();
4537+
if (exp_values)
4538+
return exp_values
4539+
->GetPropertyAtIndexAs<bool>(ePropertySwiftCacheTaskPointerLocation)
4540+
.value_or(true);
4541+
return true;
4542+
}
4543+
45324544
Args TargetProperties::GetSwiftPluginServerForPath() const {
45334545
const uint32_t idx = ePropertySwiftPluginServerForPath;
45344546

lldb/source/Target/TargetProperties.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ let Definition = "target_experimental" in {
3434
def SwiftUseTasksPlugin: Property<"swift-tasks-plugin-enabled", "Boolean">,
3535
DefaultTrue,
3636
Desc<"Enables the swift plugin converting tasks into threads">;
37+
def SwiftCacheTaskPointerLocation: Property<"swift-cache-task-pointer-location", "Boolean">,
38+
DefaultTrue,
39+
Desc<"Enables caching of task pointers inside the swift tasks plugin">;
3740
}
3841

3942
let Definition = "target" in {

0 commit comments

Comments
 (0)
0