Skip to content

Commit

Permalink
Make sure profilers work well together
Browse files Browse the repository at this point in the history
  • Loading branch information
gleocadie committed Oct 31, 2024
1 parent 3bdd036 commit da9696d
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc.

#include "StackWalkMutex.h"

#include <sys/syscall.h>
#include <time.h>


StackWalkMutex::StackWalkMutex() :
_isLockTaken{0}, _ownerTid{0}
{
}

void StackWalkMutex::lock()
{
pid_t tid = syscall(SYS_gettid);

// Attempt to acquire the lock using atomic operation
while (__sync_lock_test_and_set(&_isLockTaken, 1) != 0) {
struct timespec ts = {0, 1000000}; // Sleep for 1 millisecond
nanosleep(&ts, NULL);
// or sched_yield();
}
_ownerTid = tid;
}

bool StackWalkMutex::try_lock()
{
auto acquired = __sync_lock_test_and_set(&_isLockTaken, 1) == 0;
if (acquired)
{
_ownerTid = syscall(SYS_gettid);
}
return acquired;
}

void StackWalkMutex::unlock()
{
_ownerTid = 0;
__sync_lock_release(&_isLockTaken);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc.

#pragma once

#include <signal.h>
#include <sys/types.h>
#include <unistd.h>


/// This is temporary, to make sure that the profiler(s) works correctly together.
//
// This mutex is a simple/naive non-recursive mutex
class StackWalkMutex
{
public:
StackWalkMutex();
~StackWalkMutex() = default;

StackWalkMutex(StackWalkMutex const&) = delete;
StackWalkMutex& operator=(StackWalkMutex const&) = delete;

StackWalkMutex(StackWalkMutex&&) = delete;
StackWalkMutex& operator=(StackWalkMutex&&) = delete;

// make it usable with std::unique_lock
// so naming will be different from the rest of the code
void lock();
void unlock();
bool try_lock();

private:
volatile sig_atomic_t _isLockTaken;
// mainly for debug reason
pid_t _ownerTid;
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ TimerCreateCpuProfiler::TimerCreateCpuProfiler(
_pManagedThreadsList{pManagedThreadsList},
_pProvider{pProvider},
_callstackProvider{std::move(callstackProvider)},
_samplingInterval{pConfiguration->GetCpuProfilingInterval()},
_processId{OpSysTools::GetProcId()}
_samplingInterval{pConfiguration->GetCpuProfilingInterval()}
{
Log::Info("Cpu profiling interval: ", _samplingInterval.count(), "ms");
Log::Info("timer_create Cpu profiler is enabled");
Expand Down Expand Up @@ -132,9 +131,11 @@ struct ErrnoSaveAndRestore
struct StackWalkLock
{
public:
StackWalkLock(std::shared_ptr<ManagedThreadInfo>& threadInfo) :
_threadInfo{threadInfo}
StackWalkLock(std::shared_ptr<ManagedThreadInfo> threadInfo) :
_threadInfo{std::move(threadInfo)}
{
// Do not call lock while being in the signal handler otherwise
// we might end in a deadlock situation (lock inversion...)
_lockTaken = _threadInfo->TryAcquireLock();
}
~StackWalkLock()
Expand All @@ -151,7 +152,7 @@ struct StackWalkLock
}

private:
std::shared_ptr<ManagedThreadInfo>& _threadInfo;
std::shared_ptr<ManagedThreadInfo> _threadInfo;
bool _lockTaken;
};

Expand All @@ -177,12 +178,6 @@ bool TimerCreateCpuProfiler::CanCollect(std::shared_ptr<ManagedThreadInfo>& thre
return false;
}

// don't stack walk if the signal is coming from another process
if (info->si_pid != _processId)
{
return false;
}

return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,4 @@ class TimerCreateCpuProfiler : public ServiceBase
CallstackProvider _callstackProvider;
std::chrono::milliseconds _samplingInterval;
std::shared_mutex _registerLock;
pid_t _processId;
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,20 @@

#include <atomic>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <mutex>
#include <utility>

// To be removed (with the StackWalkMutex class) once the pipeline is improved
#ifdef LINUX // temporary on linux
#include "StackWalkMutex.h"

using mutex = StackWalkMutex;
#else // Windows only

using mutex = std::mutex;
#endif

static constexpr int32_t MinFieldAlignRequirement = 8;
static constexpr int32_t FieldAlignRequirement = (MinFieldAlignRequirement >= alignof(std::uint64_t)) ? MinFieldAlignRequirement : alignof(std::uint64_t);

Expand Down Expand Up @@ -151,7 +161,7 @@ struct ManagedThreadInfo : public IThreadInfo
#endif
uint64_t _blockingThreadId;
shared::WSTRING _blockingThreadName;
std::mutex _objLock;
mutex _objLock;
};

std::string ManagedThreadInfo::GetProfileThreadId()
Expand Down

0 comments on commit da9696d

Please sign in to comment.