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
10 changes: 10 additions & 0 deletions CcpTelemetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ bool CcpTelemetryMemoryTrackingIsEnabled()
return s_config.trackMemoryAllocations;
}

bool CcpTelemetryLockTrackingIsEnabled()
{
return s_config.trackLocks;
}

void CcpRegisterMutex( class CcpMutex& m, const char* owner, const char* name )
{
// Store the name for future Telemetry sessions, even if we're already connected.
Expand Down Expand Up @@ -450,6 +455,11 @@ bool CcpTelemetryMemoryTrackingIsEnabled()
return false;
}

bool CcpTelemetryLockTrackingIsEnabled()
{
return false;
}

void CcpRegisterThread( CcpThreadId_t threadId, const char* name )
{
}
Expand Down
92 changes: 75 additions & 17 deletions include/CcpMutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
#ifndef CCPMUTEX_H
#define CCPMUTEX_H

#include "CcpTelemetry.h"
#include <string>

#include "CcpAtomic.h"
#include "CcpTelemetry.h"

#ifdef _WIN32

Expand All @@ -19,10 +21,9 @@ class CcpMutex
m_name = name;

#if CCP_TELEMETRY_ENABLED
if ( CcpTelemetryIsConnected() )
{
TracyCLockAnnounce( m_tracyLockContext );
}
// Lazily announce on first Acquire/Release; this also handles the case where
// the mutex is created before telemetry is connected.
EnsureTracyLockState();
#endif

CcpRegisterMutex( *this, owner, name );
Expand All @@ -32,24 +33,29 @@ class CcpMutex
{
::DeleteCriticalSection( &m_mutex );
#if CCP_TELEMETRY_ENABLED
if ( m_tracyLockContext ) {
// Only terminate if Lock tracking is turned on, we still have a live context AND telemetry is still connected.
// If telemetry has been disconnected meanwhile, the context is already stale.
if ( CcpTelemetryLockTrackingIsEnabled() && m_tracyLockContext && CcpTelemetryIsConnected() )
{
TracyCLockTerminate( m_tracyLockContext );
}
m_tracyLockContext = nullptr;
#endif
}

void Acquire()
{
#if CCP_TELEMETRY_ENABLED
EnsureTracyLockState();
bool notifyTracy{false};
if ( CcpTelemetryIsConnected() && m_tracyLockContext )
if ( m_tracyLockContext )
{
notifyTracy = TracyCLockBeforeLock( m_tracyLockContext );
}
#endif
EnterCriticalSection( &m_mutex);
#if CCP_TELEMETRY_ENABLED
if ( notifyTracy )
if ( notifyTracy && m_tracyLockContext )
{
TracyCLockAfterLock( m_tracyLockContext );
}
Expand All @@ -60,7 +66,8 @@ class CcpMutex
{
LeaveCriticalSection( &m_mutex );
#if CCP_TELEMETRY_ENABLED
if ( CcpTelemetryIsConnected() && m_tracyLockContext )
EnsureTracyLockState();
if ( m_tracyLockContext )
{
TracyCLockAfterUnlock( m_tracyLockContext );
}
Expand All @@ -82,6 +89,33 @@ class CcpMutex

private:
#if CCP_TELEMETRY_ENABLED
// Synchronizes m_tracyLockContext with the current telemetry connection state.
// - If Lock tracking is disabled, behave as if telemetry were disconnected.
// - If telemetry is connected, and we don't yet have a context, announce one.
// - If telemetry is disconnected, but we still have a (now stale) context, drop it
// so that a future reconnect will produce a fresh, valid context.
// After this returns, all other Tracy calls in Acquire/Release can rely on a
// single, fast null-check of m_tracyLockContext.
void EnsureTracyLockState()
{
const bool connected = CcpTelemetryLockTrackingIsEnabled() && CcpTelemetryIsConnected();
if ( m_tracyLockContext )
{
if ( !connected )
{
// Telemetry disconnected (or lock tracking disabled); drop the stale
// context quickly so that the next connect produces a fresh announce/name.
m_tracyLockContext = nullptr;
}
}
else if ( connected )
{
const std::string tracyLockName = std::string( m_owner ? m_owner : "<owner>" ) + "-" + ( m_name ? m_name : "<name>" );
TracyCLockAnnounce( m_tracyLockContext );
TracyCLockCustomName( m_tracyLockContext, tracyLockName.c_str(), tracyLockName.size() );
}
}

TracyCLockCtx m_tracyLockContext{nullptr};
#endif
CRITICAL_SECTION m_mutex;
Expand Down Expand Up @@ -112,10 +146,9 @@ class CcpMutex
m_name = name;

#if CCP_TELEMETRY_ENABLED
if ( CcpTelemetryIsConnected() )
{
TracyCLockAnnounce( m_tracyLockContext );
}
// Lazily announce on first Acquire/Release; this also handles the case where
// the mutex is created before telemetry is connected.
EnsureTracyLockState();
#endif

CcpRegisterMutex( *this, owner, name );
Expand All @@ -125,24 +158,29 @@ class CcpMutex
{
pthread_mutex_destroy( &m_mutex );
#if CCP_TELEMETRY_ENABLED
if ( m_tracyLockContext ) {
// Only terminate if Lock tracking is turned on, we still have a live context AND telemetry is still connected.
// If telemetry has been disconnected meanwhile, the context is already stale.
if ( CcpTelemetryLockTrackingIsEnabled() && m_tracyLockContext && CcpTelemetryIsConnected() )
{
TracyCLockTerminate( m_tracyLockContext );
}
m_tracyLockContext = nullptr;
#endif
}

void Acquire()
{
#if CCP_TELEMETRY_ENABLED
EnsureTracyLockState();
bool notifyTracy{false};
if ( CcpTelemetryIsConnected() && m_tracyLockContext )
if ( m_tracyLockContext )
{
notifyTracy = TracyCLockBeforeLock( m_tracyLockContext );
}
#endif
pthread_mutex_lock( &m_mutex);
#if CCP_TELEMETRY_ENABLED
if ( notifyTracy )
if ( notifyTracy && m_tracyLockContext )
{
TracyCLockAfterLock( m_tracyLockContext );
}
Expand All @@ -153,7 +191,8 @@ class CcpMutex
{
pthread_mutex_unlock( &m_mutex );
#if CCP_TELEMETRY_ENABLED
if ( CcpTelemetryIsConnected() && m_tracyLockContext )
EnsureTracyLockState();
if ( m_tracyLockContext )
{
TracyCLockAfterUnlock( m_tracyLockContext );
}
Expand All @@ -175,6 +214,25 @@ class CcpMutex

private:
#if CCP_TELEMETRY_ENABLED
// See the Windows variant above for documentation.
void EnsureTracyLockState()
{
const bool connected = CcpTelemetryLockTrackingIsEnabled() && CcpTelemetryIsConnected();
if ( m_tracyLockContext )
{
if ( !connected )
{
m_tracyLockContext = nullptr;
}
}
else if ( connected )
{
const std::string tracyLockName = std::string( m_owner ? m_owner : "<owner>" ) + "-" + ( m_name ? m_name : "<name>" );
TracyCLockAnnounce( m_tracyLockContext );
TracyCLockCustomName( m_tracyLockContext, tracyLockName.c_str(), tracyLockName.size() );
}
}

TracyCLockCtx m_tracyLockContext{nullptr};
#endif
pthread_mutex_t m_mutex;
Expand Down
2 changes: 2 additions & 0 deletions include/CcpTelemetry.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct CcpTelemetryConfig
std::string applicationName;
std::chrono::milliseconds captureDuration{};
bool trackMemoryAllocations{false};
bool trackLocks{false};
};

[[deprecated( "Use `CcpStartTelemetry( const CcpTelemetryConfig& config ) instead" )]] CARBON_CORE_API bool CcpStartTelemetry( const char* server, int connectionType, uint32_t maxThreadCount );
Expand All @@ -69,6 +70,7 @@ CARBON_CORE_API bool CcpTelemetryIsConnected();
CARBON_CORE_API bool CcpTelemetryIsStarted();
CARBON_CORE_API bool CcpTelemetryIsStopped();
CARBON_CORE_API bool CcpTelemetryMemoryTrackingIsEnabled();
CARBON_CORE_API bool CcpTelemetryLockTrackingIsEnabled();

CARBON_CORE_API void CcpTelemetrySetActiveFiber( const std::string& name );
CARBON_CORE_API const std::string& CcpTelemetryGetActiveFiber();
Expand Down
Loading