Skip to content

Commit 774f6b9

Browse files
committed
Try something else with UnwindTracersProvider
1 parent 18fe7a4 commit 774f6b9

6 files changed

Lines changed: 146 additions & 1 deletion

File tree

profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ if (ISARM64)
9595
else()
9696
list(REMOVE_ITEM LINUX_PROFILER_SRC "${CMAKE_CURRENT_SOURCE_DIR}/HybridUnwinder.cpp")
9797
list(REMOVE_ITEM LINUX_PROFILER_SRC "${CMAKE_CURRENT_SOURCE_DIR}/UnwinderTracer.cpp")
98+
list(REMOVE_ITEM LINUX_PROFILER_SRC "${CMAKE_CURRENT_SOURCE_DIR}/UnwindTracersProvider.cpp")
9899
endif()
99100

100101
FILE(GLOB COMMON_PROFILER_SRC LIST_DIRECTORIES false "../Datadog.Profiler.Native/*.cpp")

profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/TimerCreateCpuProfiler.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@
1111
#include "OpSysTools.h"
1212
#include "ProfilerSignalManager.h"
1313
#include "IConfiguration.h"
14+
#ifdef ARM64
15+
#include "UnwindTracersProvider.h"
16+
#endif
1417

1518
#include <sys/syscall.h> /* Definition of SYS_* constants */
1619
#include <sys/types.h>
1720
#include <ucontext.h>
1821
#include <unistd.h>
1922

2023
std::atomic<TimerCreateCpuProfiler*> TimerCreateCpuProfiler::Instance = nullptr;
24+
thread_local UnwinderTracer* TimerCreateCpuProfiler::Tracer = nullptr;
2125

2226
TimerCreateCpuProfiler::TimerCreateCpuProfiler(
2327
IConfiguration* pConfiguration,
@@ -261,8 +265,14 @@ bool TimerCreateCpuProfiler::Collect(void* ctx)
261265
std::tie(stackBase, stackEnd) = threadInfo->GetStackBounds();
262266
}
263267

268+
#ifdef ARM64
269+
auto tracer = UnwindTracersProvider::GetInstance().GetTracer();
270+
Tracer = tracer.get();
271+
#else
272+
Tracer = nullptr;
273+
#endif
264274
auto buffer = rawCpuSample->Stack.AsSpan();
265-
auto count = _pUnwinder->Unwind(ctx, buffer.data(), buffer.size(), stackBase, stackEnd);
275+
auto count = _pUnwinder->Unwind(ctx, buffer.data(), buffer.size(), stackBase, stackEnd, Tracer);
266276
rawCpuSample->Stack.SetCount(count);
267277

268278
if (count == 0)

profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/TimerCreateCpuProfiler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class IManagedThreadList;
2323
class ProfilerSignalManager;
2424
class CpuSampleProvider;
2525
class IUnwinder;
26+
class UnwinderTracer;
2627

2728
class TimerCreateCpuProfiler : public ServiceBase
2829
{
@@ -63,4 +64,5 @@ class TimerCreateCpuProfiler : public ServiceBase
6364
std::shared_ptr<DiscardMetrics> _discardMetrics;
6465
std::atomic<std::uint64_t> _nbThreadsInSignalHandler;
6566
std::unique_ptr<IUnwinder> _pUnwinder;
67+
static thread_local UnwinderTracer* Tracer;
6668
};
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#include "UnwindTracersProvider.h"
2+
3+
#define NB_TRACER 50
4+
5+
UnwindTracersProvider::UnwindTracersProvider(std::size_t nbTracers)
6+
: _headTracer(nullptr)
7+
{
8+
for (std::size_t i = 0; i < nbTracers; ++i)
9+
{
10+
auto* node = new TracerNode();
11+
node->tracer = new UnwinderTracer();
12+
node->next.store(_headTracer.load(std::memory_order_relaxed), std::memory_order_relaxed);
13+
_headTracer.store(node, std::memory_order_relaxed);
14+
}
15+
}
16+
17+
UnwindTracersProvider::~UnwindTracersProvider()
18+
{
19+
auto* current = _headTracer.load(std::memory_order_relaxed);
20+
while (current != nullptr)
21+
{
22+
auto* next = current->next.load(std::memory_order_relaxed);
23+
delete current->tracer;
24+
delete current;
25+
current = next;
26+
}
27+
}
28+
29+
UnwindTracersProvider& UnwindTracersProvider::GetInstance()
30+
{
31+
static UnwindTracersProvider instance(NB_TRACER);
32+
return instance;
33+
}
34+
35+
UnwindTracersProvider::ScopedTracer UnwindTracersProvider::GetTracer()
36+
{
37+
return ScopedTracer(*this);
38+
}
39+
40+
UnwindTracersProvider::ScopedTracer::ScopedTracer(UnwindTracersProvider& provider)
41+
: _provider(provider), _node(_provider.AcquireTracer())
42+
{
43+
}
44+
45+
UnwindTracersProvider::ScopedTracer::~ScopedTracer()
46+
{
47+
if (_node != nullptr)
48+
{
49+
_provider.ReleaseTracer(_node);
50+
}
51+
}
52+
53+
UnwinderTracer* UnwindTracersProvider::ScopedTracer::get()
54+
{
55+
return _node->tracer;
56+
}
57+
58+
UnwindTracersProvider::TracerNode* UnwindTracersProvider::AcquireTracer()
59+
{
60+
TracerNode* head = _headTracer.load(std::memory_order_acquire);
61+
while (head != nullptr)
62+
{
63+
if (_headTracer.compare_exchange_weak(head, head->next.load(std::memory_order_relaxed),
64+
std::memory_order_acq_rel, std::memory_order_relaxed))
65+
{
66+
head->next.store(nullptr, std::memory_order_relaxed);
67+
return head;
68+
}
69+
}
70+
return nullptr;
71+
}
72+
73+
void UnwindTracersProvider::ReleaseTracer(TracerNode* node)
74+
{
75+
TracerNode* head = _headTracer.load(std::memory_order_relaxed);
76+
node->tracer->Reset();
77+
do
78+
{
79+
node->next.store(head, std::memory_order_relaxed);
80+
} while (!_headTracer.compare_exchange_weak(head, node,
81+
std::memory_order_release, std::memory_order_relaxed));
82+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#pragma once
2+
3+
#include <atomic>
4+
#include <cstddef>
5+
6+
#include "UnwinderTracer.h"
7+
8+
class UnwindTracersProvider
9+
{
10+
public:
11+
~UnwindTracersProvider();
12+
13+
UnwindTracersProvider(UnwindTracersProvider&& other) noexcept = delete;
14+
UnwindTracersProvider(const UnwindTracersProvider& other) = delete;
15+
UnwindTracersProvider& operator=(UnwindTracersProvider&& other) noexcept = delete;
16+
UnwindTracersProvider& operator=(const UnwindTracersProvider& other) = delete;
17+
18+
static UnwindTracersProvider& GetInstance();
19+
20+
struct TracerNode
21+
{
22+
UnwinderTracer* tracer;
23+
std::atomic<TracerNode*> next;
24+
};
25+
26+
struct ScopedTracer
27+
{
28+
ScopedTracer(UnwindTracersProvider& provider);
29+
~ScopedTracer();
30+
31+
UnwinderTracer* get();
32+
33+
private:
34+
UnwindTracersProvider& _provider;
35+
TracerNode* _node;
36+
};
37+
38+
ScopedTracer GetTracer();
39+
40+
private:
41+
UnwindTracersProvider(std::size_t nbTracers);
42+
TracerNode* AcquireTracer();
43+
void ReleaseTracer(TracerNode* node);
44+
45+
friend class ScopedTracer;
46+
std::atomic<TracerNode*> _headTracer;
47+
};

profiler/src/ProfilerEngine/Datadog.Profiler.Native/CorProfilerCallback.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#ifdef LINUX
5959
#ifdef ARM64
6060
#include "HybridUnwinder.h"
61+
#include "UnwindTracersProvider.h"
6162
#else
6263
#include "Backtrace2Unwinder.h"
6364
#endif
@@ -626,6 +627,8 @@ void CorProfilerCallback::InitializeServices()
626627
if (_pConfiguration->IsCpuProfilingEnabled() && _pConfiguration->GetCpuProfilerType() == CpuProfilerType::TimerCreate)
627628
{
628629
#ifdef ARM64
630+
// Initialize the UnwindTracersProvider
631+
UnwindTracersProvider::GetInstance();
629632
_pUnwinder = std::make_unique<HybridUnwinder>(_managedCodeCache.get());
630633
#else
631634
_pUnwinder = std::make_unique<Backtrace2Unwinder>();

0 commit comments

Comments
 (0)