Skip to content

Commit 04c3256

Browse files
author
Marcos Slomp
committed
adressing review comments
1 parent d363ddd commit 04c3256

File tree

2 files changed

+135
-112
lines changed

2 files changed

+135
-112
lines changed

public/client/TracySysTrace.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record )
157157
}
158158
break;
159159
case etw::DxgKrnlGuid.Data1:
160-
assert( hdr.EventDescriptor.Id == etw::VSyncInfo::EventId );
160+
assert( hdr.EventDescriptor.Id == etw::VSyncDPC::EventId );
161161
{
162-
const auto vs = (const etw::VSyncInfo*)record->UserData;
162+
const auto vs = (const etw::VSyncDPC*)record->UserData;
163163
TracyLfqPrepare( QueueType::FrameVsync );
164164
MemWrite( &item->frameVsync.time, hdr.TimeStamp.QuadPart );
165165
MemWrite( &item->frameVsync.id, vs->vidPnTargetId );

public/client/windows/TracyETW.cpp

Lines changed: 133 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,109 @@ struct Session
2525
CONTROLTRACE_ID handle = 0;
2626
};
2727

28+
// ---- ETW Events ----------
29+
30+
struct CSwitch
31+
{
32+
// V2 fields:
33+
static constexpr UCHAR Opcode = 36;
34+
uint32_t newThreadId;
35+
uint32_t oldThreadId;
36+
int8_t newThreadPriority;
37+
int8_t oldThreadPriority;
38+
uint8_t previousCState;
39+
int8_t spareByte;
40+
int8_t oldThreadWaitReason;
41+
int8_t oldThreadWaitMode;
42+
int8_t oldThreadState;
43+
int8_t oldThreadWaitIdealProcessor;
44+
uint32_t newThreadWaitTime;
45+
uint32_t reserved;
46+
};
47+
static_assert( sizeof( CSwitch ) == 24, "unexpected CSwitch struct size/alignment" );
48+
49+
struct ReadyThread
50+
{
51+
// V2 fields:
52+
static constexpr UCHAR Opcode = 50;
53+
uint32_t threadId;
54+
int8_t adjustReason;
55+
int8_t adjustIncrement;
56+
int8_t flag;
57+
int8_t reserverd;
58+
};
59+
static_assert( sizeof( ReadyThread ) == 8, "unexpected ReadyThread struct size/alignment" );
60+
61+
struct ThreadInfo
62+
{
63+
// V0 (Thread_V0_TypeGroup1) fields:
64+
uint32_t processId;
65+
uint32_t threadId;
66+
// NOTE: we only care about PID and TID for now, and these two are "invariant"
67+
// across all revisions (versions) of this event. As such, let's omit the other
68+
// fields since they vary based on the event version; their sizes also vary by
69+
// target architecture (32bit or 64bit), and this is not even mentioned in the
70+
// MSDN documentation, and worse, have not been updated in the official schemas
71+
// either (which ETW Explorer uses), but can be introspected via the TDH API.
72+
};
73+
static_assert( sizeof( ThreadInfo ) == 8, "unexpected ThreadInfo struct size/alignment" );
74+
75+
struct ThreadStart : public ThreadInfo
76+
{
77+
static constexpr UCHAR Opcode = 1;
78+
};
79+
static_assert( sizeof( ThreadStart ) == 8, "unexpected ThreadStart struct size/alignment") ;
80+
81+
// DC: Data Collection (associated with the "rundown" phase)
82+
struct ThreadDCStart : public ThreadInfo
83+
{
84+
static constexpr UCHAR Opcode = 3;
85+
};
86+
static_assert( sizeof( ThreadDCStart ) == 8, "unexpected ThreadDCStart struct size/alignment" );
87+
88+
struct SampledProfile
89+
{
90+
static constexpr UCHAR Opcode = 46;
91+
// NOTE: we don't handle SampledProfile events directly; instead, we handle
92+
// the StackWalk event associated with each SampledProfile event. Just like
93+
// ThreadInfo, the data layout varies based on the target architecture, and
94+
// the MSDN documentation and schemas are outdated.
95+
//uint64_t instructionPointer; // 32/64 bits
96+
//uint32_t threadId;
97+
//uint32_t count; // Not used.
98+
};
99+
static_assert( sizeof( SampledProfile ) == 1, "unexpected SampledProfile struct size/alignment" );
100+
101+
struct StackWalkEvent
102+
{
103+
// V2 fields:
104+
static constexpr UCHAR Opcode = 32;
105+
uint64_t eventTimeStamp;
106+
uint32_t stackProcess;
107+
uint32_t stackThread;
108+
uint64_t stack[192]; // arbitrary upperbound limit; schema stops at [32]
109+
};
110+
static_assert( offsetof( StackWalkEvent, stackProcess ) == 8, "unexpected StackWalkEvent struct size/alignment" );
111+
static_assert( offsetof( StackWalkEvent, stackThread ) == 12, "unexpected StackWalkEvent struct size/alignment" );
112+
static_assert( offsetof( StackWalkEvent, stack ) == 16, "unexpected StackWalkEvent struct size/alignment" );
113+
114+
struct VSyncDPC
115+
{
116+
static constexpr USHORT EventId = 17; // 0x11
117+
void* dxgAdapter;
118+
uint32_t vidPnTargetId;
119+
uint64_t scannedPhysicalAddress;
120+
uint32_t vidPnSourceId;
121+
uint32_t frameNumber;
122+
int64_t frameQpcTime;
123+
void* hFlipDevice;
124+
uint32_t flipType;
125+
uint64_t flipFenceId;
126+
};
127+
static_assert( sizeof( VSyncDPC ) == 64, "unexpected VSyncInfo struct size/alignment" );
128+
129+
// --------------------------
130+
28131
static void ETWErrorAction( ULONG error_code, const char* message, int length )
29132
{
30133
#ifdef TRACY_HAS_CALLSTACK
@@ -73,6 +176,18 @@ static DWORD ElevatePrivilege( LPCTSTR PrivilegeName )
73176
return ETWError( status );
74177
}
75178

179+
static bool IsOS64Bit()
180+
{
181+
#if defined _WIN64
182+
constexpr bool isOs64Bit = true;
183+
#else
184+
BOOL _iswow64;
185+
IsWow64Process(GetCurrentProcess(), &_iswow64);
186+
const bool isOs64Bit = _iswow64;
187+
#endif
188+
return isOs64Bit;
189+
}
190+
76191
static ULONG StartSession( Session& session )
77192
{
78193
ULONG status = StartTraceA( &session.handle, session.name, &session.properties );
@@ -116,14 +231,7 @@ static ULONG EnableProvider(
116231

117232
static ULONG EnableStackWalk( Session& session, GUID EventGuid, UCHAR Opcode )
118233
{
119-
#if defined _WIN64
120-
constexpr bool isOs64Bit = true;
121-
#else
122-
BOOL _iswow64;
123-
IsWow64Process( GetCurrentProcess(), &_iswow64 );
124-
const bool isOs64Bit = _iswow64;
125-
#endif
126-
if( !isOs64Bit )
234+
if( !IsOS64Bit() )
127235
return 0 /* ERROR_SUCCESS */; // TODO: return error instead?
128236
CLASSIC_EVENT_ID stackId[1] = {};
129237
stackId[0].EventGuid = EventGuid;
@@ -136,11 +244,9 @@ static Session StartPrivateKernelSession( const CHAR* name )
136244
{
137245
Session session = {};
138246

139-
size_t maxlen = sizeof( session.name );
140-
for( size_t i = 0; i < maxlen && name[i] != 0; ++i )
141-
{
142-
session.name[i] = name[i];
143-
}
247+
size_t maxlen = sizeof( session.name ) - 1;
248+
strncpy(session.name, name, maxlen);
249+
session.name[maxlen] = '\0';
144250

145251
auto& props = session.properties;
146252
props.LoggerNameOffset = offsetof( Session, name );
@@ -156,7 +262,7 @@ static Session StartPrivateKernelSession( const CHAR* name )
156262
props.LogFileMode |= EVENT_TRACE_REAL_TIME_MODE;
157263

158264
// TODO: should we really be tweaking the buffering parameters?
159-
props.BufferSize = 1024;
265+
props.BufferSize = 1024; // in KB
160266
props.MinimumBuffers = std::thread::hardware_concurrency() * 4;
161267
props.MaximumBuffers = std::thread::hardware_concurrency() * 6;
162268

@@ -187,15 +293,18 @@ static ULONG EnableCPUProfiling( Session& session, int microseconds = 125 /* 8KH
187293
if( status != ERROR_SUCCESS )
188294
return status;
189295

190-
TRACE_PROFILE_INTERVAL interval = {};
191-
interval.Source = 0; // 0: ProfileTime
192-
interval.Interval = ( microseconds * 1000 ) / 100; // in 100's of nanoseconds
193-
CONTROLTRACE_ID TraceId = 0; // must be zero for TraceSampledProfileIntervalInfo
194-
status = TraceSetInformation( TraceId, TraceSampledProfileIntervalInfo, &interval, sizeof( interval ) );
195-
if( status != ERROR_SUCCESS )
196-
return ETWError( status );
296+
if ( IsOS64Bit() )
297+
{
298+
TRACE_PROFILE_INTERVAL interval = {};
299+
interval.Source = 0; // 0: ProfileTime (from enum KPROFILE_SOURCE in wdm.h)
300+
interval.Interval = ( microseconds * 1000 ) / 100; // in 100's of nanoseconds
301+
CONTROLTRACE_ID TraceId = 0; // must be zero for TraceSampledProfileIntervalInfo
302+
status = TraceSetInformation( TraceId, TraceSampledProfileIntervalInfo, &interval, sizeof( interval ) );
303+
if( status != ERROR_SUCCESS )
304+
return ETWError( status );
305+
}
197306

198-
status = EnableStackWalk( session, PerfInfoGuid, 46 ); // PerfInfoGuid Opcode 46: SampledProfile event
307+
status = EnableStackWalk( session, PerfInfoGuid, SampledProfile::Opcode );
199308
return status;
200309
}
201310

@@ -208,7 +317,7 @@ static ULONG EnableContextSwitchMonitoring( Session& session )
208317
EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, MatchAnyKeyword );
209318
if( status != ERROR_SUCCESS )
210319
return status;
211-
status = EnableStackWalk( session, ThreadGuid, 36 ); // ThreadGuid Opcode 36: CSwitch event
320+
status = EnableStackWalk( session, ThreadGuid, CSwitch::Opcode );
212321
return status;
213322
}
214323

@@ -232,7 +341,7 @@ static ULONG EnableVSyncMonitoring( Session& session )
232341
EVENT_FILTER_EVENT_ID fe = {};
233342
fe.FilterIn = TRUE;
234343
fe.Count = 1;
235-
fe.Events[0] = 0x0011; // 0x11 = 17 : VSyncDPC_Info
344+
fe.Events[0] = VSyncDPC::EventId;
236345
EVENT_FILTER_DESCRIPTOR desc = {};
237346
desc.Ptr = (ULONGLONG)&fe;
238347
desc.Size = sizeof( fe );
@@ -294,91 +403,5 @@ static ULONG EventConsumerLoop( PROCESSTRACE_HANDLE hEventConsumer )
294403
return status;
295404
}
296405

297-
struct CSwitch
298-
{
299-
// V2 fields:
300-
static constexpr UCHAR Opcode = 36;
301-
uint32_t newThreadId;
302-
uint32_t oldThreadId;
303-
int8_t newThreadPriority;
304-
int8_t oldThreadPriority;
305-
uint8_t previousCState;
306-
int8_t spareByte;
307-
int8_t oldThreadWaitReason;
308-
int8_t oldThreadWaitMode;
309-
int8_t oldThreadState;
310-
int8_t oldThreadWaitIdealProcessor;
311-
uint32_t newThreadWaitTime;
312-
uint32_t reserved;
313-
};
314-
static_assert(sizeof(CSwitch) == 24, "unexpected CSwitch struct size/alignment");
315-
316-
struct ReadyThread
317-
{
318-
// V2 fields:
319-
static constexpr UCHAR Opcode = 50;
320-
uint32_t threadId;
321-
int8_t adjustReason;
322-
int8_t adjustIncrement;
323-
int8_t flag;
324-
int8_t reserverd;
325-
};
326-
static_assert(sizeof(ReadyThread) == 8, "unexpected ReadyThread struct size/alignment");
327-
328-
struct ThreadInfo
329-
{
330-
// V0 (Thread_V0_TypeGroup1) fields:
331-
uint32_t processId;
332-
uint32_t threadId;
333-
// NOTE: we only care about PID and TID for now, and these two are "invariant"
334-
// across all revisions (versions) of this event. As such, let's omit the other
335-
// fields since they vary based on the event version; their sizes also vary by
336-
// target architecture (32bit or 64bit), and this is not even mentioned in the
337-
// MSDN documentation, and worse, have not been updated in the official schemas
338-
// either (which ETW Explorer uses), but can be introspected via the TDH API.
339-
};
340-
static_assert(sizeof(ThreadInfo) == 8, "unexpected ThreadInfo struct size/alignment");
341-
342-
struct ThreadStart : public ThreadInfo
343-
{
344-
static constexpr UCHAR Opcode = 1;
345-
};
346-
static_assert(sizeof(ThreadStart) == 8, "unexpected ThreadStart struct size/alignment");
347-
348-
// DC: Data Collection (associated with the "rundown" phase)
349-
struct ThreadDCStart : public ThreadInfo
350-
{
351-
static constexpr UCHAR Opcode = 3;
352-
};
353-
static_assert(sizeof(ThreadDCStart) == 8, "unexpected ThreadDCStart struct size/alignment");
354-
355-
struct StackWalkEvent
356-
{
357-
// V2 fields:
358-
static constexpr UCHAR Opcode = 32;
359-
uint64_t eventTimeStamp;
360-
uint32_t stackProcess;
361-
uint32_t stackThread;
362-
uint64_t stack[192]; // arbitrary upperbound limit; schema stops at [32]
363-
};
364-
static_assert(offsetof(StackWalkEvent, stackProcess) == 8, "unexpected StackWalkEvent struct size/alignment");
365-
static_assert(offsetof(StackWalkEvent, stackThread) == 12, "unexpected StackWalkEvent struct size/alignment");
366-
static_assert(offsetof(StackWalkEvent, stack) == 16, "unexpected StackWalkEvent struct size/alignment");
367-
368-
struct VSyncInfo
369-
{
370-
static constexpr USHORT EventId = 17; // 0x11
371-
void* dxgAdapter;
372-
uint32_t vidPnTargetId;
373-
uint64_t scannedPhysicalAddress;
374-
uint32_t vidPnSourceId;
375-
uint32_t frameNumber;
376-
int64_t frameQpcTime;
377-
void* hFlipDevice;
378-
uint32_t flipType;
379-
uint64_t flipFenceId;
380-
};
381-
static_assert(sizeof(VSyncInfo) == 64, "unexpected VSyncInfo struct size/alignment");
382-
383406
}
384407
}

0 commit comments

Comments
 (0)