Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ if(BUILD_UNIVERSAL_DDPROF)
endif()
endif()

if(USE_LOADER)
target_compile_definitions(dd_profiling-embedded PRIVATE "DDPROF_USE_LOADER")
endif()

# Fix for link error in sanitizeddebug build mode with gcc:
# ~~~
# /usr/bin/ld: ./libdd_profiling.so: undefined reference to `__dynamic_cast'
Expand Down
2 changes: 1 addition & 1 deletion cmake/dd_profiling.version
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
global: ddprof_start_profiling; ddprof_stop_profiling;
global: ddprof_start_profiling; ddprof_stop_profiling; ddprof_lib_state;
local: *;
};
2 changes: 0 additions & 2 deletions include/lib/allocation_tracker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ class AllocationTracker {

static void delete_tl_state(void *tl_state);

static void make_key();

void track_allocation(uintptr_t addr, size_t size,
TrackerThreadLocalState &tl_state, bool is_large_alloc);
void track_deallocation(uintptr_t addr, TrackerThreadLocalState &tl_state,
Expand Down
29 changes: 10 additions & 19 deletions src/lib/allocation_tracker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ pthread_key_t AllocationTracker::_tl_state_key;
AllocationTracker *AllocationTracker::_instance;

namespace {

#ifdef DDPROF_USE_LOADER
extern "C"
__attribute((tls_model("initial-exec"))) __thread void *ddprof_lib_state;
#else
__attribute((tls_model("initial-exec"))) __thread void *ddprof_lib_state;
#endif

DDPROF_NOINLINE auto sleep_and_retry_reserve(MPSCRingBufferWriter &writer,
size_t size, bool &timeout) {
constexpr std::chrono::nanoseconds k_sleep_duration =
Expand All @@ -53,13 +61,7 @@ DDPROF_NOINLINE auto sleep_and_retry_reserve(MPSCRingBufferWriter &writer,
} // namespace

TrackerThreadLocalState *AllocationTracker::get_tl_state() {
// In shared libraries, TLS access requires a call to tls_get_addr,
// tls_get_addr can call into malloc, which can create a recursive loop
// instead we call pthread APIs to control the creation of TLS objects
pthread_once(&_key_once, make_key);
auto *tl_state = static_cast<TrackerThreadLocalState *>(
pthread_getspecific(_tl_state_key));
return tl_state;
return static_cast<TrackerThreadLocalState *>(ddprof_lib_state);
}

TrackerThreadLocalState *AllocationTracker::init_tl_state() {
Expand All @@ -69,13 +71,7 @@ TrackerThreadLocalState *AllocationTracker::init_tl_state() {
auto tl_state = std::make_unique<TrackerThreadLocalState>();
tl_state->tid = ddprof::gettid();
tl_state->stack_bounds = retrieve_stack_bounds();

if (int const res = pthread_setspecific(_tl_state_key, tl_state.get());
res != 0) {
// should return 0
LG_DBG("Unable to store tl_state. Error %d: %s\n", res, strerror(res));
tl_state.reset();
}
ddprof_lib_state = tl_state.get();

return tl_state.release();
}
Expand All @@ -91,11 +87,6 @@ void AllocationTracker::delete_tl_state(void *tl_state) {
delete static_cast<TrackerThreadLocalState *>(tl_state);
}

void AllocationTracker::make_key() {
// delete is called on all key objects
pthread_key_create(&_tl_state_key, delete_tl_state);
}

DDRes AllocationTracker::allocation_tracking_init(
uint64_t allocation_profiling_rate, uint32_t flags,
uint32_t stack_sample_size, const RingBufferInfo &ring_buffer,
Expand Down
3 changes: 3 additions & 0 deletions src/lib/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include <time.h>
#include <unistd.h>

__attribute__((__visibility__("default")))
__attribute__((tls_model("initial-exec"))) __thread void *ddprof_lib_state;

/* Role of loader is to ensure that all dependencies (libdl/lim/libpthread) of
* libdd_profiling-embedded.so are satisfied before dlopen'ing it.
* On musl, all libc features are in libc.so and hence are available once libc
Expand Down