mirror of
https://github.com/wolfpld/tracy.git
synced 2026-08-22 02:58:24 +00:00
support for toggling EnableFlags after the singleton kernel session has started
This commit is contained in:
@@ -191,33 +191,21 @@ bool SysTraceStart( int64_t& samplingPeriod )
|
||||
if ( !etw::CheckAdminPrivilege() )
|
||||
return false;
|
||||
|
||||
ULONGLONG EnableFlags = 0;
|
||||
#ifndef TRACY_NO_CONTEXT_SWITCH
|
||||
EnableFlags |= EVENT_TRACE_FLAG_CSWITCH;
|
||||
EnableFlags |= EVENT_TRACE_FLAG_DISPATCHER;
|
||||
EnableFlags |= EVENT_TRACE_FLAG_THREAD;
|
||||
#endif
|
||||
#ifndef TRACY_NO_SAMPLING
|
||||
DWORD access = etw::ElevatePrivilege( SE_SYSTEM_PROFILE_NAME );
|
||||
if( access != ERROR_SUCCESS )
|
||||
return access;
|
||||
EnableFlags |= etw::IsOS64Bit() ? EVENT_TRACE_FLAG_PROFILE : 0;
|
||||
#endif
|
||||
|
||||
session_kernel = etw::StartSingletonKernelLoggerSession( EnableFlags );
|
||||
session_kernel = etw::StartSingletonKernelLoggerSession();
|
||||
if ( session_kernel.handle == 0 )
|
||||
return false;
|
||||
|
||||
#ifndef TRACY_NO_CONTEXT_SWITCH
|
||||
if ( etw::EnableStackWalk( session_kernel, etw::ThreadGuid, etw::CSwitch::Opcode ) != ERROR_SUCCESS )
|
||||
if ( etw::EnableProcessAndThreadMonitoring( session_kernel ) != ERROR_SUCCESS )
|
||||
return etw::StopSession( session_kernel ), false;
|
||||
if ( etw::EnableContextSwitchMonitoring( session_kernel ) != ERROR_SUCCESS )
|
||||
return etw::StopSession( session_kernel ), false;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef TRACY_NO_SAMPLING
|
||||
if ( etw::EnableStackWalk( session_kernel, etw::PerfInfoGuid, etw::SampledProfile::Opcode ) != ERROR_SUCCESS )
|
||||
return etw::StopSession( session_kernel ), false;
|
||||
int microseconds = GetSamplingInterval() / 10;
|
||||
if ( etw::SetCPUProfilingInterval( microseconds ) != ERROR_SUCCESS )
|
||||
if ( etw::EnableCPUProfiling( session_kernel, microseconds ) != ERROR_SUCCESS )
|
||||
return etw::StopSession( session_kernel ), false;
|
||||
samplingPeriod = GetSamplingPeriod();
|
||||
#endif
|
||||
|
||||
@@ -317,7 +317,7 @@ static ULONG EnableStackWalk( Session& session, GUID EventGuid, UCHAR Opcode )
|
||||
static ULONG SetCPUProfilingInterval(int microseconds)
|
||||
{
|
||||
if( !IsOS64Bit() )
|
||||
return 0 /* ERROR_SUCCESS */; // TODO: return error instead?
|
||||
return 0 /* ERROR_SUCCESS */; // TODO: fabricate SetLastError(ERROR_NOT_SUPPORTED) instead?
|
||||
TRACE_PROFILE_INTERVAL interval = {};
|
||||
interval.Source = 0; // 0: ProfileTime (from enum KPROFILE_SOURCE in wdm.h)
|
||||
interval.Interval = ( microseconds * 1000 ) / 100; // in 100's of nanoseconds
|
||||
@@ -326,7 +326,7 @@ static ULONG SetCPUProfilingInterval(int microseconds)
|
||||
return ETWError( status );
|
||||
}
|
||||
|
||||
static Session StartSingletonKernelLoggerSession( ULONGLONG EnableFlags )
|
||||
static Session StartSingletonKernelLoggerSession( ULONGLONG EnableFlags = 0 )
|
||||
{
|
||||
Session session = {};
|
||||
|
||||
@@ -421,29 +421,70 @@ static Session StartUserSession( const CHAR* name )
|
||||
return session;
|
||||
}
|
||||
|
||||
bool IsSingletonKernelLoggerSession( Session& session )
|
||||
{
|
||||
bool check = true;
|
||||
check &= ( session.handle == 0xFFFF );
|
||||
check &= ( strncmp( session.name, KERNEL_LOGGER_NAMEA, sizeof( session.name ) ) == 0 );
|
||||
return check;
|
||||
}
|
||||
|
||||
static ULONG UpdateSessionEnableFlags( Session& session, ULONGLONG EnableFlags )
|
||||
{
|
||||
// Use a copy of the session properties, because ControlTrace(UPDATE) will modify
|
||||
// LogFileNameOffset and "pad" the rest with zeros, overwriting the session.handle!
|
||||
Session temp = session;
|
||||
temp.properties.EnableFlags = EnableFlags;
|
||||
ULONG status = ControlTraceA( temp.handle, temp.name, &temp.properties, EVENT_TRACE_CONTROL_UPDATE );
|
||||
if (status != ERROR_SUCCESS)
|
||||
return ETWError(status);
|
||||
session.properties.EnableFlags = EnableFlags;
|
||||
return status;
|
||||
}
|
||||
|
||||
static ULONG EnableProcessAndThreadMonitoring( Session& session )
|
||||
{
|
||||
if ( IsSingletonKernelLoggerSession(session) )
|
||||
{
|
||||
ULONGLONG EnableFlags = session.properties.EnableFlags;
|
||||
EnableFlags |= EVENT_TRACE_FLAG_THREAD;
|
||||
ULONG status = UpdateSessionEnableFlags( session, EnableFlags );
|
||||
return status;
|
||||
}
|
||||
|
||||
ULONGLONG MatchAnyKeyword = SYSTEM_PROCESS_KW_THREAD; // ThreadStart and ThreadDCStart events
|
||||
ULONG status = EnableProvider( session, SystemProcessProviderGuid,
|
||||
EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, MatchAnyKeyword );
|
||||
if( status != ERROR_SUCCESS )
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
|
||||
static ULONG EnableCPUProfiling( Session& session, int microseconds = 125 /* 8KHz = 125us */ )
|
||||
{
|
||||
if ( !IsOS64Bit() )
|
||||
return 0 /* ERROR_SUCCESS */; // TODO: fabricate SetLastError(ERROR_NOT_SUPPORTED) instead?
|
||||
|
||||
// CPU Profiling requires special privileges on top of admin privileges
|
||||
DWORD access = ElevatePrivilege( SE_SYSTEM_PROFILE_NAME );
|
||||
if( access != ERROR_SUCCESS )
|
||||
return access;
|
||||
|
||||
CheckProviderSessions( SystemProfileProviderGuid, 0 );
|
||||
ULONG status = EnableProvider( session, SystemProfileProviderGuid );
|
||||
if( status != ERROR_SUCCESS )
|
||||
return status;
|
||||
if ( IsSingletonKernelLoggerSession( session ) )
|
||||
{
|
||||
ULONGLONG EnableFlags = session.properties.EnableFlags;
|
||||
EnableFlags |= EVENT_TRACE_FLAG_PROFILE;
|
||||
ULONG status = UpdateSessionEnableFlags( session, EnableFlags );
|
||||
if ( status != ERROR_SUCCESS )
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckProviderSessions( SystemProfileProviderGuid, 0 );
|
||||
ULONG status = EnableProvider( session, SystemProfileProviderGuid );
|
||||
if( status != ERROR_SUCCESS )
|
||||
return status;
|
||||
}
|
||||
|
||||
status = SetCPUProfilingInterval(microseconds);
|
||||
ULONG status = SetCPUProfilingInterval(microseconds);
|
||||
if( status != ERROR_SUCCESS )
|
||||
return status;
|
||||
|
||||
@@ -453,15 +494,28 @@ static ULONG EnableCPUProfiling( Session& session, int microseconds = 125 /* 8KH
|
||||
|
||||
static ULONG EnableContextSwitchMonitoring( Session& session )
|
||||
{
|
||||
ULONGLONG MatchAnyKeyword = 0;
|
||||
MatchAnyKeyword |= SYSTEM_SCHEDULER_KW_CONTEXT_SWITCH; // CSwitch events
|
||||
MatchAnyKeyword |= SYSTEM_SCHEDULER_KW_DISPATCHER; // ReadyThread events
|
||||
CheckProviderSessions( SystemSchedulerProviderGuid, MatchAnyKeyword );
|
||||
ULONG status = EnableProvider( session, SystemSchedulerProviderGuid,
|
||||
EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, MatchAnyKeyword );
|
||||
if( status != ERROR_SUCCESS )
|
||||
return status;
|
||||
status = EnableStackWalk( session, ThreadGuid, CSwitch::Opcode );
|
||||
if ( IsSingletonKernelLoggerSession( session ) )
|
||||
{
|
||||
ULONGLONG EnableFlags = session.properties.EnableFlags;
|
||||
EnableFlags |= EVENT_TRACE_FLAG_CSWITCH;
|
||||
EnableFlags |= EVENT_TRACE_FLAG_DISPATCHER;
|
||||
ULONG status = UpdateSessionEnableFlags( session, EnableFlags );
|
||||
if ( status != ERROR_SUCCESS )
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONGLONG MatchAnyKeyword = 0;
|
||||
MatchAnyKeyword |= SYSTEM_SCHEDULER_KW_CONTEXT_SWITCH; // CSwitch events
|
||||
MatchAnyKeyword |= SYSTEM_SCHEDULER_KW_DISPATCHER; // ReadyThread events
|
||||
CheckProviderSessions( SystemSchedulerProviderGuid, MatchAnyKeyword );
|
||||
ULONG status = EnableProvider( session, SystemSchedulerProviderGuid,
|
||||
EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, MatchAnyKeyword );
|
||||
if( status != ERROR_SUCCESS )
|
||||
return status;
|
||||
}
|
||||
|
||||
ULONG status = EnableStackWalk( session, ThreadGuid, CSwitch::Opcode );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user