Skip to content
Open
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
6 changes: 6 additions & 0 deletions docs/design/datacontracts/StressLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ internal record struct StressLogData(
int TotalChunks,
ulong TickFrequency,
ulong StartTimestamp,
ulong StartTime,
TargetPointer Logs);

internal record struct ThreadStressLogData(
TargetPointer Address,
TargetPointer NextPointer,
ulong ThreadId,
bool WriteHasWrapped,
Expand Down Expand Up @@ -52,6 +54,7 @@ Data descriptors used:
| StressLog | TotalChunks | Total number of chunks across all thread-specific logs |
| StressLog | TickFrequency | Number of ticks per second for stresslog timestamps |
| StressLog | StartTimestamp | Timestamp when the stress log was started |
| StressLog | StartTime | Wall-clock time when the stress log was started (FILETIME, 100ns units since Jan 1 1601) |
| StressLog | ModuleOffset | Offset of the module in the stress log |
| StressLog | Modules | Offset of the stress log's module table (if StressLogHasModuleTable is `1`) |
| StressLog | Logs | Pointer to the thread-specific logs |
Expand Down Expand Up @@ -104,6 +107,7 @@ StressLogData GetStressLogData()
stressLog.TotalChunks,
stressLog.TickFrequency,
stressLog.StartTimestamp,
stressLog.StartTime,
stressLog.Logs);
}

Expand All @@ -118,6 +122,7 @@ StressLogData GetStressLogData(TargetPointer stressLogPointer)
stressLog.TotalChunks,
stressLog.TickFrequency,
stressLog.StartTimestamp,
stressLog.StartTime,
stressLog.Logs);
}

Expand Down Expand Up @@ -151,6 +156,7 @@ IEnumerable<ThreadStressLogData> GetThreadStressLogs(TargetPointer logs)
}

yield return new ThreadStressLogData(
currentPointer,
threadStressLog.Next,
threadStressLog.ThreadId,
threadStressLog.WriteHasWrapped,
Expand Down
83 changes: 83 additions & 0 deletions src/coreclr/inc/sospriv.idl
Original file line number Diff line number Diff line change
Expand Up @@ -572,3 +572,86 @@ interface ISOSDacInterface16 : IUnknown
{
HRESULT GetGCDynamicAdaptationMode(int* pDynamicAdaptationMode);
}

cpp_quote("#ifndef _SOS_StressLogData")
cpp_quote("#define _SOS_StressLogData")

typedef struct _SOSStressLogData
{
unsigned int LoggedFacilities;
unsigned int Level;
unsigned int MaxSizePerThread;
unsigned int MaxSizeTotal;
int TotalChunks;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does SOS need fields like 'TotalChunks' or 'Logs'? Those seem like internal implementation details of the data structure and not info we'd need to include in the interface.

@max-charlamb max-charlamb Jun 17, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed everything that isn't used by the SOS implementation: dotnet/diagnostics#5873

Logs is not used, but TotalChunks is used to print data in the !dumplog header.

UINT64 TickFrequency;
UINT64 StartTimestamp;
UINT64 StartTime;
} SOSStressLogData;

cpp_quote("#endif //_SOS_StressLogData")

cpp_quote("#ifndef _SOS_ThreadStressLogData")
cpp_quote("#define _SOS_ThreadStressLogData")

typedef struct _SOSThreadStressLogData
{
CLRDATA_ADDRESS ThreadLogAddress;
UINT64 ThreadId;
} SOSThreadStressLogData;

cpp_quote("#endif //_SOS_ThreadStressLogData")

cpp_quote("#ifndef _SOS_StressMsgData")
cpp_quote("#define _SOS_StressMsgData")

typedef struct _SOSStressMsgData
{
unsigned int Facility;
CLRDATA_ADDRESS FormatString;
UINT64 Timestamp;
unsigned int ArgumentCount;
} SOSStressMsgData;

cpp_quote("#endif //_SOS_StressMsgData")

[
object,
local,
uuid(94a2bd3d-ab3d-43bf-81d8-3ae96b8e33cd)
]
interface ISOSStressLogThreadEnum : ISOSEnum
{
HRESULT Next([in] unsigned int count,
[out, size_is(count), length_is(*pFetched)] SOSThreadStressLogData values[],
[out] unsigned int *pFetched);
}

[
object,
local,
uuid(437cb033-afe7-4c0f-a4a7-82c891bc049e)
]
interface ISOSStressLogMsgEnum : ISOSEnum
{
HRESULT Next([in] unsigned int count,
[out, size_is(count), length_is(*pFetched)] SOSStressMsgData values[],
[out] unsigned int *pFetched);

HRESULT GetArguments([in] unsigned int messageIndex,
[in] unsigned int argCount,
[out, size_is(argCount), length_is(*pFetched)] CLRDATA_ADDRESS args[],
[out] unsigned int *pFetched);
}

[
object,
local,
uuid(2f4bb585-ed50-479e-bbe0-10a95a5da3bb)
]
interface ISOSDacInterface17 : IUnknown
{
HRESULT GetStressLogData([out] SOSStressLogData *data);
HRESULT GetStressLogThreadEnumerator([out] ISOSStressLogThreadEnum **ppEnum);
HRESULT GetStressLogMessageEnumerator([in] CLRDATA_ADDRESS threadStressLogAddress,
[out] ISOSStressLogMsgEnum **ppEnum);
}
Comment thread
max-charlamb marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ CDAC_TYPE_FIELD(StressLog, T_INT32, TotalChunks, offsetof(StressLog, totalChunk)
CDAC_TYPE_FIELD(StressLog, T_POINTER, Logs, offsetof(StressLog, logs))
CDAC_TYPE_FIELD(StressLog, T_UINT64, TickFrequency, offsetof(StressLog, tickFrequency))
CDAC_TYPE_FIELD(StressLog, T_UINT64, StartTimestamp, offsetof(StressLog, startTimeStamp))
CDAC_TYPE_FIELD(StressLog, T_UINT64, StartTime, offsetof(StressLog, startTime))
CDAC_TYPE_END(StressLog)

CDAC_TYPE_BEGIN(ThreadStressLog)
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -564,10 +564,11 @@ CDAC_TYPE_FIELD(StressLog, T_UINT32, LoggedFacilities, cdac_offsets<StressLog>::
CDAC_TYPE_FIELD(StressLog, T_UINT32, Level, cdac_offsets<StressLog>::levelToLog)
CDAC_TYPE_FIELD(StressLog, T_UINT32, MaxSizePerThread, cdac_offsets<StressLog>::MaxSizePerThread)
CDAC_TYPE_FIELD(StressLog, T_UINT32, MaxSizeTotal, cdac_offsets<StressLog>::MaxSizeTotal)
CDAC_TYPE_FIELD(StressLog, T_UINT32, TotalChunks, cdac_offsets<StressLog>::totalChunk)
CDAC_TYPE_FIELD(StressLog, T_INT32, TotalChunks, cdac_offsets<StressLog>::totalChunk)
CDAC_TYPE_FIELD(StressLog, T_POINTER, Logs, cdac_offsets<StressLog>::logs)
CDAC_TYPE_FIELD(StressLog, T_UINT64, TickFrequency, cdac_offsets<StressLog>::tickFrequency)
CDAC_TYPE_FIELD(StressLog, T_UINT64, StartTimestamp, cdac_offsets<StressLog>::startTimeStamp)
CDAC_TYPE_FIELD(StressLog, T_UINT64, StartTime, cdac_offsets<StressLog>::startTime)
CDAC_TYPE_FIELD(StressLog, T_NUINT, ModuleOffset, cdac_offsets<StressLog>::moduleOffset)
CDAC_TYPE_FIELD(StressLog, T_ARRAY(TYPE(StressLogModuleDesc)), Modules, cdac_offsets<StressLog>::modules)
CDAC_TYPE_END(StressLog)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ public abstract class ContractRegistry
/// Gets an instance of the Debugger contract for the target.
/// </summary>
public virtual IDebugger Debugger => GetContract<IDebugger>();
/// <summary>
/// Gets an instance of the StressLog contract for the target.
/// </summary>
public virtual IStressLog StressLog => GetContract<IStressLog>();
Comment thread
max-charlamb marked this conversation as resolved.

/// <summary>
/// Gets an instance of the RuntimeMutableTypeSystem contract for the target.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ public record struct StressLogData(
int TotalChunks,
ulong TickFrequency,
ulong StartTimestamp,
ulong StartTime,
TargetPointer Logs);

public record struct ThreadStressLogData(
TargetPointer Address,
TargetPointer NextPointer,
ulong ThreadId,
bool WriteHasWrapped,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public StressLogData GetStressLogData(TargetPointer stressLogPointer)
stressLog.TotalChunks,
stressLog.TickFrequency,
stressLog.StartTimestamp,
stressLog.StartTime,
stressLog.Logs);
}

Expand Down Expand Up @@ -79,6 +80,7 @@ public IEnumerable<ThreadStressLogData> GetThreadStressLogs(TargetPointer Logs)
}

yield return new ThreadStressLogData(
currentPointer,
threadStressLog.Next,
threadStressLog.ThreadId,
threadStressLog.WriteHasWrapped,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal sealed partial class StressLog : IData<StressLog>
[Field] public int TotalChunks { get; }
[Field] public ulong TickFrequency { get; }
[Field] public ulong StartTimestamp { get; }
[Field] public ulong StartTime { get; }
[Field] public TargetNUInt ModuleOffset { get; }
[Field] public TargetPointer? Modules { get; }
[Field] public TargetPointer Logs { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1191,3 +1191,78 @@ public unsafe partial interface ISOSDacInterface16
[PreserveSig]
int GetGCDynamicAdaptationMode(int* pDynamicAdaptationMode);
}

// StressLog data structures for ISOSDacInterface17

public struct SOSStressLogData
{
public uint LoggedFacilities;
public uint Level;
public uint MaxSizePerThread;
public uint MaxSizeTotal;
public int TotalChunks;
public ulong TickFrequency;
public ulong StartTimestamp;
public ulong StartTime;
}

public struct SOSThreadStressLogData
{
public ClrDataAddress ThreadLogAddress;
public ulong ThreadId;
}

public struct SOSStressMsgData
{
public uint Facility;
public ClrDataAddress FormatString;
public ulong Timestamp;
public uint ArgumentCount;
}

[GeneratedComInterface]
[Guid("94a2bd3d-ab3d-43bf-81d8-3ae96b8e33cd")]
public unsafe partial interface ISOSStressLogThreadEnum : ISOSEnum
{
[PreserveSig]
int Next(uint count,
[In, Out, MarshalUsing(CountElementName = nameof(count))]
SOSThreadStressLogData[] values,
uint* pFetched);
}

[GeneratedComInterface]
[Guid("437cb033-afe7-4c0f-a4a7-82c891bc049e")]
public unsafe partial interface ISOSStressLogMsgEnum : ISOSEnum
{
[PreserveSig]
int Next(uint count,
[In, Out, MarshalUsing(CountElementName = nameof(count))]
SOSStressMsgData[] values,
uint* pFetched);

[PreserveSig]
int GetArguments(uint messageIndex,
uint argCount,
[In, Out, MarshalUsing(CountElementName = nameof(argCount))]
ClrDataAddress[] args,
uint* pFetched);
}

[GeneratedComInterface]
[Guid("2f4bb585-ed50-479e-bbe0-10a95a5da3bb")]
public unsafe partial interface ISOSDacInterface17
{
[PreserveSig]
Comment thread
max-charlamb marked this conversation as resolved.
int GetStressLogData(SOSStressLogData* data);

[PreserveSig]
int GetStressLogThreadEnumerator(
DacComNullableByRef<ISOSStressLogThreadEnum> ppEnum);

[PreserveSig]
int GetStressLogMessageEnumerator(
ClrDataAddress threadStressLogAddress,
DacComNullableByRef<ISOSStressLogMsgEnum> ppEnum);

}
Comment thread
max-charlamb marked this conversation as resolved.
Comment thread
max-charlamb marked this conversation as resolved.
Loading