relocating ETW events (structs), and adding checks and comments

This commit is contained in:
Marcos Slomp
2025-12-05 12:03:57 -08:00
parent 16724b39c5
commit 7b5de9e2b9
2 changed files with 101 additions and 74 deletions

View File

@@ -66,66 +66,6 @@ namespace tracy
static DWORD s_pid;
struct CSwitch
{
uint32_t newThreadId;
uint32_t oldThreadId;
int8_t newThreadPriority;
int8_t oldThreadPriority;
uint8_t previousCState;
int8_t spareByte;
int8_t oldThreadWaitReason;
int8_t oldThreadWaitMode;
int8_t oldThreadState;
int8_t oldThreadWaitIdealProcessor;
uint32_t newThreadWaitTime;
uint32_t reserved;
};
struct ReadyThread
{
uint32_t threadId;
int8_t adjustReason;
int8_t adjustIncrement;
int8_t flag;
int8_t reserverd;
};
struct ThreadTrace
{
uint32_t processId;
uint32_t threadId;
uint32_t stackBase;
uint32_t stackLimit;
uint32_t userStackBase;
uint32_t userStackLimit;
uint32_t startAddr;
uint32_t win32StartAddr;
uint32_t tebBase;
uint32_t subProcessTag;
};
struct StackWalkEvent
{
uint64_t eventTimeStamp;
uint32_t stackProcess;
uint32_t stackThread;
uint64_t stack[192];
};
struct VSyncInfo
{
void* dxgAdapter;
uint32_t vidPnTargetId;
uint64_t scannedPhysicalAddress;
uint32_t vidPnSourceId;
uint32_t frameNumber;
int64_t frameQpcTime;
void* hFlipDevice;
uint32_t flipType;
uint64_t flipFenceId;
};
extern "C" typedef NTSTATUS (WINAPI *t_NtQueryInformationThread)( HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG );
extern "C" typedef BOOL (WINAPI *t_EnumProcessModules)( HANDLE, HMODULE*, DWORD, LPDWORD );
extern "C" typedef BOOL (WINAPI *t_GetModuleInformation)( HANDLE, HMODULE, LPMODULEINFO, DWORD );
@@ -154,9 +94,9 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record )
switch( hdr.ProviderId.Data1 )
{
case etw::ThreadGuid.Data1:
if( hdr.EventDescriptor.Opcode == 36 )
if( hdr.EventDescriptor.Opcode == etw::CSwitch::Opcode )
{
const auto cswitch = (const CSwitch*)record->UserData;
const auto cswitch = (const etw::CSwitch*)record->UserData;
TracyLfqPrepare( QueueType::ContextSwitch );
MemWrite( &item->contextSwitch.time, hdr.TimeStamp.QuadPart );
@@ -170,9 +110,9 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record )
MemWrite( &item->contextSwitch.previousCState, cswitch->previousCState );
TracyLfqCommit;
}
else if( hdr.EventDescriptor.Opcode == 50 )
else if( hdr.EventDescriptor.Opcode == etw::ReadyThread::Opcode )
{
const auto rt = (const ReadyThread*)record->UserData;
const auto rt = (const etw::ReadyThread*)record->UserData;
TracyLfqPrepare( QueueType::ThreadWakeup );
MemWrite( &item->threadWakeup.time, hdr.TimeStamp.QuadPart );
@@ -182,13 +122,13 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record )
MemWrite( &item->threadWakeup.adjustIncrement, rt->adjustIncrement );
TracyLfqCommit;
}
else if( hdr.EventDescriptor.Opcode == 1 || hdr.EventDescriptor.Opcode == 3 )
else if( hdr.EventDescriptor.Opcode == etw::ThreadStart::Opcode || hdr.EventDescriptor.Opcode == etw::ThreadDCStart::Opcode )
{
const auto tt = (const ThreadTrace*)record->UserData;
const auto ti = (const etw::ThreadInfo*)record->UserData;
uint64_t tid = tt->threadId;
uint64_t tid = ti->threadId;
if( tid == 0 ) return;
uint64_t pid = tt->processId;
uint64_t pid = ti->processId;
TracyLfqPrepare( QueueType::TidToPid );
MemWrite( &item->tidToPid.tid, tid );
MemWrite( &item->tidToPid.pid, pid );
@@ -196,9 +136,9 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record )
}
break;
case etw::StackWalkGuid.Data1:
if( hdr.EventDescriptor.Opcode == 32 )
if( hdr.EventDescriptor.Opcode == etw::StackWalkEvent::Opcode )
{
const auto sw = (const StackWalkEvent*)record->UserData;
const auto sw = (const etw::StackWalkEvent*)record->UserData;
if( sw->stackProcess == s_pid )
{
const uint64_t sz = ( record->UserDataLength - 16 ) / 8;
@@ -217,9 +157,9 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record )
}
break;
case etw::DxgKrnlGuid.Data1:
assert( hdr.EventDescriptor.Id == 0x0011 );
assert( hdr.EventDescriptor.Id == etw::VSyncInfo::EventId );
{
const auto vs = (const VSyncInfo*)record->UserData;
const auto vs = (const etw::VSyncInfo*)record->UserData;
TracyLfqPrepare( QueueType::FrameVsync );
MemWrite( &item->frameVsync.time, hdr.TimeStamp.QuadPart );
MemWrite( &item->frameVsync.id, vs->vidPnTargetId );

View File

@@ -1,6 +1,7 @@
#include <windows.h>
#include <guiddef.h>
#include <evntcons.h>
#include <evntrace.h>
#include <windows.h>
#include <stdio.h>
#include <thread>
@@ -43,7 +44,7 @@ static ULONG ETWError( ULONG result )
return result;
ZoneScopedC( tracy::Color::Red4 );
char message[128] = {};
size_t written = snprintf( message, sizeof( message ), "ETW Error %u (0x%x): ", result, result );
int written = snprintf( message, sizeof( message ), "ETW Error %u (0x%x): ", result, result );
written += FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
@@ -282,5 +283,91 @@ static ULONG EventConsumerLoop( PROCESSTRACE_HANDLE hEventConsumer )
return status;
}
struct CSwitch
{
// V2 fields:
static constexpr UCHAR Opcode = 36;
uint32_t newThreadId;
uint32_t oldThreadId;
int8_t newThreadPriority;
int8_t oldThreadPriority;
uint8_t previousCState;
int8_t spareByte;
int8_t oldThreadWaitReason;
int8_t oldThreadWaitMode;
int8_t oldThreadState;
int8_t oldThreadWaitIdealProcessor;
uint32_t newThreadWaitTime;
uint32_t reserved;
};
static_assert(sizeof(CSwitch) == 24, "unexpected CSwitch struct size/alignment");
struct ReadyThread
{
// V2 fields:
static constexpr UCHAR Opcode = 50;
uint32_t threadId;
int8_t adjustReason;
int8_t adjustIncrement;
int8_t flag;
int8_t reserverd;
};
static_assert(sizeof(ReadyThread) == 8, "unexpected ReadyThread struct size/alignment");
struct ThreadInfo
{
// V0 (Thread_V0_TypeGroup1) fields:
uint32_t processId;
uint32_t threadId;
// NOTE: we only care about PID and TID for now, and these two are "invariant"
// across all revisions (versions) of this event. As such, let's omit the other
// fields since they vary based on the event version; their sizes also vary by
// target architecture (32bit or 64bit), and this is not even mentioned in the
// MSDN documentation, and worse, have not been updated in the official schemas
// either (which ETW Explorer uses), but can be introspected via the TDH API.
};
static_assert(sizeof(ThreadInfo) == 8, "unexpected ThreadInfo struct size/alignment");
struct ThreadStart : public ThreadInfo
{
static constexpr UCHAR Opcode = 1;
};
static_assert(sizeof(ThreadStart) == 8, "unexpected ThreadStart struct size/alignment");
// DC: Data Collection (associated with the "rundown" phase)
struct ThreadDCStart : public ThreadInfo
{
static constexpr UCHAR Opcode = 3;
};
static_assert(sizeof(ThreadDCStart) == 8, "unexpected ThreadDCStart struct size/alignment");
struct StackWalkEvent
{
// V2 fields:
static constexpr UCHAR Opcode = 32;
uint64_t eventTimeStamp;
uint32_t stackProcess;
uint32_t stackThread;
uint64_t stack[192]; // arbitrary upperbound limit; schema stops at [32]
};
static_assert(offsetof(StackWalkEvent, stackProcess) == 8, "unexpected StackWalkEvent struct size/alignment");
static_assert(offsetof(StackWalkEvent, stackThread) == 12, "unexpected StackWalkEvent struct size/alignment");
static_assert(offsetof(StackWalkEvent, stack) == 16, "unexpected StackWalkEvent struct size/alignment");
struct VSyncInfo
{
static constexpr USHORT EventId = 17; // 0x11
void* dxgAdapter;
uint32_t vidPnTargetId;
uint64_t scannedPhysicalAddress;
uint32_t vidPnSourceId;
uint32_t frameNumber;
int64_t frameQpcTime;
void* hFlipDevice;
uint32_t flipType;
uint64_t flipFenceId;
};
static_assert(sizeof(VSyncInfo) == 64, "unexpected VSyncInfo struct size/alignment");
}
}