summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs28
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs127
-rw-r--r--src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs4
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs4
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs50
-rw-r--r--src/scripts/genEventPipe.py2
-rw-r--r--src/vm/ecalllist.h2
-rw-r--r--src/vm/eventpipe.cpp23
-rw-r--r--src/vm/eventpipe.h8
-rw-r--r--src/vm/eventpipeconfiguration.cpp8
-rw-r--r--src/vm/eventpipeconfiguration.h2
-rw-r--r--src/vm/eventpipeevent.cpp36
-rw-r--r--src/vm/eventpipeevent.h17
-rw-r--r--src/vm/eventpipeprovider.cpp10
-rw-r--r--src/vm/eventpipeprovider.h6
-rw-r--r--src/vm/sampleprofiler.cpp2
16 files changed, 286 insertions, 43 deletions
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs
index c8671db283..5292551314 100644
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs
@@ -54,6 +54,7 @@ namespace System.Diagnostics.Tracing
// subclasses of EventProvider use when creating efficient (but unsafe) version of
// EventWrite. We do make it a nested type because we really don't expect anyone to use
// it except subclasses (and then only rarely).
+ [StructLayout(LayoutKind.Sequential)]
public struct EventData
{
internal unsafe ulong Ptr;
@@ -78,7 +79,7 @@ namespace System.Diagnostics.Tracing
private static bool m_setInformationMissing;
- private IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions.
+ internal IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions.
UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
private long m_regHandle; // Trace Registration Handle
private byte m_level; // Tracing Level
@@ -936,7 +937,7 @@ namespace System.Diagnostics.Tracing
// </SecurityKernel>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
- internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
+ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
{
int status = 0;
@@ -1064,7 +1065,7 @@ namespace System.Diagnostics.Tracing
userDataPtr[refObjPosition[7]].Ptr = (ulong)v7;
}
- status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
}
}
else
@@ -1090,7 +1091,7 @@ namespace System.Diagnostics.Tracing
}
}
- status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
for (int i = 0; i < refObjIndex; ++i)
{
@@ -1132,7 +1133,7 @@ namespace System.Diagnostics.Tracing
// <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
// </SecurityKernel>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
- internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
+ internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
{
if (childActivityID != null)
{
@@ -1143,7 +1144,7 @@ namespace System.Diagnostics.Tracing
(EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
}
- int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data);
+ int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data);
if (status != 0)
{
@@ -1166,6 +1167,7 @@ namespace System.Diagnostics.Tracing
status = m_eventProvider.EventWriteTransferWrapper(
m_regHandle,
ref eventDescriptor,
+ IntPtr.Zero,
activityID,
relatedActivityID,
dataCount,
@@ -1241,6 +1243,7 @@ namespace System.Diagnostics.Tracing
unsafe int IEventProvider.EventWriteTransferWrapper(
long registrationHandle,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
@@ -1262,6 +1265,12 @@ namespace System.Diagnostics.Tracing
ControlCode,
ref ActivityId);
}
+
+ // Define an EventPipeEvent handle.
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ {
+ throw new System.NotSupportedException();
+ }
}
#elif !FEATURE_PERFTRACING
@@ -1285,6 +1294,7 @@ namespace System.Diagnostics.Tracing
unsafe int IEventProvider.EventWriteTransferWrapper(
long registrationHandle,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
@@ -1297,6 +1307,12 @@ namespace System.Diagnostics.Tracing
{
return 0;
}
+
+ // Define an EventPipeEvent handle.
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ {
+ throw new System.NotSupportedException();
+ }
}
#endif
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
index 513366ff88..a0f0e1e06d 100644
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs
@@ -686,6 +686,106 @@ namespace System.Diagnostics.Tracing
Initialize(eventSourceGuid, eventSourceName, traits);
}
+#if FEATURE_PERFTRACING
+ // Generate the serialized blobs that describe events for all strongly typed events (that is events that define strongly
+ // typed event methods. Dynamically defined events (that use Write) hare defined on the fly and are handled elsewhere.
+ private unsafe void DefineEventPipeEvents()
+ {
+ Debug.Assert(m_eventData != null);
+ Debug.Assert(m_provider != null);
+ int cnt = m_eventData.Length;
+ for (int i = 0; i < cnt; i++)
+ {
+ uint eventID = (uint)m_eventData[i].Descriptor.EventId;
+ if (eventID == 0)
+ continue;
+
+ string eventName = m_eventData[i].Name;
+ Int64 keywords = m_eventData[i].Descriptor.Keywords;
+ uint eventVersion = m_eventData[i].Descriptor.Version;
+ uint level = m_eventData[i].Descriptor.Level;
+
+ // evnetID : 4 bytes
+ // eventName : (eventName.Length + 1) * 2 bytes
+ // keywords : 8 bytes
+ // eventVersion : 4 bytes
+ // level : 4 bytes
+ // parameterCount : 4 bytes
+ uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;
+
+ // Increase the metadataLength for the types of all parameters.
+ metadataLength += (uint)m_eventData[i].Parameters.Length * 4;
+
+ // Increase the metadataLength for the names of all parameters.
+ foreach (var parameter in m_eventData[i].Parameters)
+ {
+ string parameterName = parameter.Name;
+ metadataLength = metadataLength + ((uint)parameterName.Length + 1) * 2;
+ }
+
+ byte[] metadata = new byte[metadataLength];
+
+ // Write metadata: evnetID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
+ fixed (byte *pMetadata = metadata)
+ {
+ uint offset = 0;
+ WriteToBuffer(pMetadata, metadataLength, ref offset, eventID);
+ fixed(char *pEventName = eventName)
+ {
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pEventName, ((uint)eventName.Length + 1) * 2);
+ }
+ WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, eventVersion);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, level);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)m_eventData[i].Parameters.Length);
+ foreach (var parameter in m_eventData[i].Parameters)
+ {
+ // Write parameter type.
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)Type.GetTypeCode(parameter.ParameterType));
+
+ // Write parameter name.
+ string parameterName = parameter.Name;
+ fixed (char *pParameterName = parameterName)
+ {
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pParameterName, ((uint)parameterName.Length + 1) * 2);
+ }
+ }
+ Debug.Assert(metadataLength == offset);
+ IntPtr eventHandle = m_provider.m_eventProvider.DefineEventHandle(eventID, eventName, keywords, eventVersion, level, pMetadata, metadataLength);
+ m_eventData[i].EventHandle = eventHandle;
+ }
+ }
+ }
+
+ // Copy src to buffer and modify the offset.
+ // Note: We know the buffer size ahead of time to make sure no buffer overflow.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, byte *src, uint srcLength)
+ {
+ Debug.Assert(bufferLength >= (offset + srcLength));
+ for (int i = 0; i < srcLength; i++)
+ {
+ *(byte *)(buffer + offset + i) = *(byte *)(src + i);
+ }
+ offset += srcLength;
+ }
+
+ // Copy uint value to buffer.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, uint value)
+ {
+ Debug.Assert(bufferLength >= (offset + 4));
+ *(uint *)(buffer + offset) = value;
+ offset += 4;
+ }
+
+ // Copy long value to buffer.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, long value)
+ {
+ Debug.Assert(bufferLength >= (offset + 8));
+ *(long *)(buffer + offset) = value;
+ offset += 8;
+ }
+#endif
+
internal virtual void GetMetadata(out Guid eventSourceGuid, out string eventSourceName, out EventMetadata[] eventData, out byte[] manifestBytes)
{
//
@@ -1179,7 +1279,7 @@ namespace System.Diagnostics.Tracing
// by default the Descriptor.Keyword will have the perEventSourceSessionId bit
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
// synthesize a new one
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
@@ -1199,7 +1299,7 @@ namespace System.Diagnostics.Tracing
m_eventData[eventId].Descriptor.Task,
unchecked((long)etwSessions.ToEventKeywords() | origKwd));
- if (!m_provider.WriteEvent(ref desc, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
}
}
@@ -1229,7 +1329,7 @@ namespace System.Diagnostics.Tracing
#else
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
@@ -1489,7 +1589,6 @@ namespace System.Diagnostics.Tracing
}
#endif // PLATFORM_WINDOWS
#endif // FEATURE_MANAGED_ETW
-
Debug.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted.
// We are logically completely initialized at this point.
m_completelyInited = true;
@@ -1941,7 +2040,7 @@ namespace System.Diagnostics.Tracing
// by default the Descriptor.Keyword will have the perEventSourceSessionId bit
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
// synthesize a new one
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
@@ -1958,7 +2057,7 @@ namespace System.Diagnostics.Tracing
m_eventData[eventId].Descriptor.Task,
unchecked((long)etwSessions.ToEventKeywords() | origKwd));
- if (!m_provider.WriteEvent(ref desc, pActivityId, childActivityID, args))
+ if (!m_provider.WriteEvent(ref desc, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
}
}
@@ -1988,7 +2087,7 @@ namespace System.Diagnostics.Tracing
#else
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
}
else
@@ -2232,7 +2331,7 @@ namespace System.Diagnostics.Tracing
data.Ptr = (ulong)msgStringPtr;
data.Size = (uint)(2 * (msgString.Length + 1));
data.Reserved = 0;
- m_provider.WriteEvent(ref descr, null, null, 1, (IntPtr)((void*)&data));
+ m_provider.WriteEvent(ref descr, m_eventData[0].EventHandle, null, null, 1, (IntPtr)((void*)&data));
}
}
}
@@ -2517,6 +2616,7 @@ namespace System.Diagnostics.Tracing
partial struct EventMetadata
{
public EventDescriptor Descriptor;
+ public IntPtr EventHandle; // EventPipeEvent handle.
public EventTags Tags;
public bool EnabledForAnyListener; // true if any dispatcher has this event turned on
public bool EnabledForETW; // is this event on for the OS ETW data dispatcher?
@@ -3065,6 +3165,10 @@ namespace System.Diagnostics.Tracing
dispatcher.m_EventEnabled = new bool[m_eventData.Length];
dispatcher = dispatcher.m_Next;
}
+#if FEATURE_PERFTRACING
+ // Initialize the EventPipe event handles.
+ DefineEventPipeEvents();
+#endif
}
if (s_currentPid == 0)
{
@@ -3119,7 +3223,7 @@ namespace System.Diagnostics.Tracing
dataDescrs[1].Size = (uint)Math.Min(dataLeft, chunkSize);
if (m_provider != null)
{
- if (!m_provider.WriteEvent(ref manifestDescr, null, null, 2, (IntPtr)dataDescrs))
+ if (!m_provider.WriteEvent(ref manifestDescr, IntPtr.Zero, null, null, 2, (IntPtr)dataDescrs))
{
// Turns out that if users set the BufferSize to something less than 64K then WriteEvent
// can fail. If we get this failure on the first chunk try again with something smaller
@@ -3597,7 +3701,11 @@ namespace System.Diagnostics.Tracing
throw new ArgumentException(msg, exception);
}
+#if FEATURE_PERFTRACING
+ return null;
+#else
return bNeedsManifest ? res : null;
+#endif
}
private static bool RemoveFirstArgIfRelatedActivityId(ref ParameterInfo[] args)
@@ -3686,6 +3794,7 @@ namespace System.Diagnostics.Tracing
eventData[eventAttribute.EventId].Message = eventAttribute.Message;
eventData[eventAttribute.EventId].ActivityOptions = eventAttribute.ActivityOptions;
eventData[eventAttribute.EventId].HasRelatedActivityID = hasRelatedActivityID;
+ eventData[eventAttribute.EventId].EventHandle = IntPtr.Zero;
}
// Helper used by code:CreateManifestAndDescriptors that trims the m_eventData array to the correct
diff --git a/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs b/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs
index 0b51e52ec4..71a2fe4d44 100644
--- a/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs
+++ b/src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs
@@ -27,6 +27,7 @@ namespace System.Diagnostics.Tracing
unsafe int EventWriteTransferWrapper(
long registrationHandle,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
@@ -34,5 +35,8 @@ namespace System.Diagnostics.Tracing
// Get or set the per-thread activity ID.
int EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId);
+
+ // Define an EventPipeEvent handle.
+ unsafe IntPtr DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength);
}
}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs
index d962023540..0d66c94e8d 100644
--- a/src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs
@@ -162,7 +162,7 @@ namespace System.Diagnostics.Tracing
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
- internal static extern IntPtr AddEvent(IntPtr provHandle, Int64 keywords, uint eventID, uint eventVersion, uint level, bool needStack);
+ internal static extern unsafe IntPtr DefineEvent(IntPtr provHandle, uint eventID, Int64 keywords, uint eventVersion, uint level, void *pMetadata, uint metadataLength);
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
@@ -170,6 +170,6 @@ namespace System.Diagnostics.Tracing
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
- internal static extern unsafe void WriteEvent(IntPtr eventHandle, void* data, uint length);
+ internal static extern unsafe void WriteEvent(IntPtr eventHandle, uint eventID, void* pData, uint length);
}
}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs
index 42eb42ae2d..cd9bd3c713 100644
--- a/src/mscorlib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs
@@ -6,6 +6,8 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using Microsoft.Win32;
+using System.Diagnostics;
+using System.Collections.Generic;
namespace System.Diagnostics.Tracing
{
@@ -49,11 +51,40 @@ namespace System.Diagnostics.Tracing
unsafe int IEventProvider.EventWriteTransferWrapper(
long registrationHandle,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
EventProvider.EventData* userData)
{
+ uint eventID = (uint)eventDescriptor.EventId;
+ if(eventID != 0 && eventHandle != IntPtr.Zero)
+ {
+ if (userDataCount == 0)
+ {
+ EventPipeInternal.WriteEvent(eventHandle, eventID, null, 0);
+ return 0;
+ }
+
+ uint length = 0;
+ for (int i = 0; i < userDataCount; i++)
+ {
+ length += userData[i].Size;
+ }
+
+ byte[] data = new byte[length];
+ fixed (byte *pData = data)
+ {
+ uint offset = 0;
+ for (int i = 0; i < userDataCount; i++)
+ {
+ byte * singleUserDataPtr = (byte *)(userData[i].Ptr);
+ uint singleUserDataSize = userData[i].Size;
+ WriteToBuffer(pData, length, ref offset, singleUserDataPtr, singleUserDataSize);
+ }
+ EventPipeInternal.WriteEvent(eventHandle, eventID, pData, length);
+ }
+ }
return 0;
}
@@ -62,5 +93,24 @@ namespace System.Diagnostics.Tracing
{
return 0;
}
+
+ // Define an EventPipeEvent handle.
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ {
+ IntPtr eventHandlePtr = EventPipeInternal.DefineEvent(m_provHandle, eventID, keywords, eventVersion, level, pMetadata, metadataLength);
+ return eventHandlePtr;
+ }
+
+ // Copy src to buffer and modify the offset.
+ // Note: We know the buffer size ahead of time to make sure no buffer overflow.
+ private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, byte *src, uint srcLength)
+ {
+ Debug.Assert(bufferLength >= (offset + srcLength));
+ for (int i = 0; i < srcLength; i++)
+ {
+ *(byte *)(buffer + offset + i) = *(byte *)(src + i);
+ }
+ offset += srcLength;
+ }
}
}
diff --git a/src/scripts/genEventPipe.py b/src/scripts/genEventPipe.py
index 02634adf8c..7fd1a459b3 100644
--- a/src/scripts/genEventPipe.py
+++ b/src/scripts/genEventPipe.py
@@ -138,7 +138,7 @@ def generateClrEventPipeWriteEventsImpl(
taskName = eventNode.getAttribute('task')
initEvent = """ EventPipeEvent%s = EventPipeProvider%s->AddEvent(%s,%s,%s,%s);
-""" % (eventName, providerPrettyName, eventKeywordsMask, eventValue, eventVersion, eventLevel)
+""" % (eventName, providerPrettyName, eventValue, eventKeywordsMask, eventVersion, eventLevel)
WriteEventImpl.append(initEvent)
WriteEventImpl.append("}")
diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h
index c51b4a8eae..39056a9198 100644
--- a/src/vm/ecalllist.h
+++ b/src/vm/ecalllist.h
@@ -1276,7 +1276,7 @@ FCFuncStart(gEventPipeInternalFuncs)
QCFuncElement("Enable", EventPipeInternal::Enable)
QCFuncElement("Disable", EventPipeInternal::Disable)
QCFuncElement("CreateProvider", EventPipeInternal::CreateProvider)
- QCFuncElement("AddEvent", EventPipeInternal::AddEvent)
+ QCFuncElement("DefineEvent", EventPipeInternal::DefineEvent)
QCFuncElement("DeleteProvider", EventPipeInternal::DeleteProvider)
QCFuncElement("WriteEvent", EventPipeInternal::WriteEvent)
FCFuncEnd()
diff --git a/src/vm/eventpipe.cpp b/src/vm/eventpipe.cpp
index 5805641bc5..58f93ef179 100644
--- a/src/vm/eventpipe.cpp
+++ b/src/vm/eventpipe.cpp
@@ -484,22 +484,30 @@ INT_PTR QCALLTYPE EventPipeInternal::CreateProvider(
return reinterpret_cast<INT_PTR>(pProvider);
}
-INT_PTR QCALLTYPE EventPipeInternal::AddEvent(
+INT_PTR QCALLTYPE EventPipeInternal::DefineEvent(
INT_PTR provHandle,
- __int64 keywords,
unsigned int eventID,
+ __int64 keywords,
unsigned int eventVersion,
unsigned int level,
- bool needStack)
+ void *pMetadata,
+ unsigned int metadataLength)
{
QCALL_CONTRACT;
+
+ EventPipeEvent *pEvent = NULL;
+
BEGIN_QCALL;
- // TODO
+ _ASSERTE(provHandle != NULL);
+ _ASSERTE(pMetadata != NULL);
+ EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider *>(provHandle);
+ pEvent = pProvider->AddEvent(eventID, keywords, eventVersion, (EventPipeEventLevel)level, (BYTE *)pMetadata, metadataLength);
+ _ASSERTE(pEvent != NULL);
END_QCALL;
- return 0;
+ return reinterpret_cast<INT_PTR>(pEvent);
}
void QCALLTYPE EventPipeInternal::DeleteProvider(
@@ -519,13 +527,16 @@ void QCALLTYPE EventPipeInternal::DeleteProvider(
void QCALLTYPE EventPipeInternal::WriteEvent(
INT_PTR eventHandle,
+ unsigned int eventID,
void *pData,
unsigned int length)
{
QCALL_CONTRACT;
BEGIN_QCALL;
- // TODO
+ _ASSERTE(eventHandle != NULL);
+ EventPipeEvent *pEvent = reinterpret_cast<EventPipeEvent *>(eventHandle);
+ EventPipe::WriteEvent(*pEvent, (BYTE *)pData, length);
END_QCALL;
}
diff --git a/src/vm/eventpipe.h b/src/vm/eventpipe.h
index 180a7686cd..0aced258c0 100644
--- a/src/vm/eventpipe.h
+++ b/src/vm/eventpipe.h
@@ -282,19 +282,21 @@ public:
GUID providerID,
EventPipeCallback pCallbackFunc);
- static INT_PTR QCALLTYPE AddEvent(
+ static INT_PTR QCALLTYPE DefineEvent(
INT_PTR provHandle,
- __int64 keywords,
unsigned int eventID,
+ __int64 keywords,
unsigned int eventVersion,
unsigned int level,
- bool needStack);
+ void *pMetadata,
+ unsigned int metadataLength);
static void QCALLTYPE DeleteProvider(
INT_PTR provHandle);
static void QCALLTYPE WriteEvent(
INT_PTR eventHandle,
+ unsigned int eventID,
void *pData,
unsigned int length);
};
diff --git a/src/vm/eventpipeconfiguration.cpp b/src/vm/eventpipeconfiguration.cpp
index 7ce06badff..a227d9d68a 100644
--- a/src/vm/eventpipeconfiguration.cpp
+++ b/src/vm/eventpipeconfiguration.cpp
@@ -63,8 +63,8 @@ void EventPipeConfiguration::Initialize()
// Create the metadata event.
m_pMetadataEvent = m_pConfigProvider->AddEvent(
- 0, /* keywords */
0, /* eventID */
+ 0, /* keywords */
0, /* eventVersion */
EventPipeEventLevel::LogAlways,
false); /* needStack */
@@ -315,7 +315,7 @@ void EventPipeConfiguration::EnableRundown()
Enable(1 /* circularBufferSizeInMB */, rundownProviders, numRundownProviders);
}
-EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance, BYTE *pPayloadData, unsigned int payloadLength)
+EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance)
{
CONTRACTL
{
@@ -336,6 +336,8 @@ EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPip
const GUID &providerID = sourceEvent.GetProvider()->GetProviderID();
unsigned int eventID = sourceEvent.GetEventID();
unsigned int eventVersion = sourceEvent.GetEventVersion();
+ BYTE *pPayloadData = sourceEvent.GetMetadata();
+ unsigned int payloadLength = sourceEvent.GetMetadataLength();
unsigned int instancePayloadSize = sizeof(providerID) + sizeof(eventID) + sizeof(eventVersion) + sizeof(payloadLength) + payloadLength;
// Allocate the payload.
@@ -398,7 +400,7 @@ EventPipeEnabledProviderList::EventPipeEnabledProviderList(
if((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PerformanceTracing) & 1) == 1)
{
m_pCatchAllProvider = new EventPipeEnabledProvider();
- m_pCatchAllProvider->Set(NULL, 0xFFFFFFFF, EventPipeEventLevel::Verbose);
+ m_pCatchAllProvider->Set(NULL, 0xFFFFFFFFFFFFFFFF, EventPipeEventLevel::Verbose);
return;
}
diff --git a/src/vm/eventpipeconfiguration.h b/src/vm/eventpipeconfiguration.h
index c579bee845..44c4205c55 100644
--- a/src/vm/eventpipeconfiguration.h
+++ b/src/vm/eventpipeconfiguration.h
@@ -69,7 +69,7 @@ public:
void EnableRundown();
// Get the event used to write metadata to the event stream.
- EventPipeEventInstance* BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance, BYTE *pPayloadData = NULL, unsigned int payloadLength = 0);
+ EventPipeEventInstance* BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance);
private:
diff --git a/src/vm/eventpipeevent.cpp b/src/vm/eventpipeevent.cpp
index 3b9f36bc4b..abf942b253 100644
--- a/src/vm/eventpipeevent.cpp
+++ b/src/vm/eventpipeevent.cpp
@@ -8,7 +8,7 @@
#ifdef FEATURE_PERFTRACING
-EventPipeEvent::EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack)
+EventPipeEvent::EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata, unsigned int metadataLength)
{
CONTRACTL
{
@@ -25,6 +25,26 @@ EventPipeEvent::EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsi
m_level = level;
m_needStack = needStack;
m_enabled = false;
+ if (pMetadata != NULL)
+ {
+ m_pMetadata = new BYTE[metadataLength];
+ memcpy(m_pMetadata, pMetadata, metadataLength);
+ m_metadataLength = metadataLength;
+ }
+ else
+ {
+ m_pMetadata = NULL;
+ m_metadataLength = 0;
+ }
+}
+
+EventPipeEvent::~EventPipeEvent()
+{
+ if (m_pMetadata != NULL)
+ {
+ delete[] m_pMetadata;
+ m_pMetadata = NULL;
+ }
}
EventPipeProvider* EventPipeEvent::GetProvider() const
@@ -76,6 +96,20 @@ bool EventPipeEvent::IsEnabled() const
return m_enabled;
}
+BYTE *EventPipeEvent::GetMetadata() const
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return m_pMetadata;
+}
+
+unsigned int EventPipeEvent::GetMetadataLength() const
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return m_metadataLength;
+}
+
void EventPipeEvent::RefreshState()
{
LIMITED_METHOD_CONTRACT;
diff --git a/src/vm/eventpipeevent.h b/src/vm/eventpipeevent.h
index 3076617f8a..c91c4bac8e 100644
--- a/src/vm/eventpipeevent.h
+++ b/src/vm/eventpipeevent.h
@@ -37,15 +37,22 @@ private:
// True if the event is current enabled.
Volatile<bool> m_enabled;
+ // Metadata
+ BYTE *m_pMetadata;
+
+ // Metadata length;
+ unsigned int m_metadataLength;
+
// Refreshes the runtime state for this event.
// Called by EventPipeProvider when the provider configuration changes.
void RefreshState();
// Only EventPipeProvider can create events.
// The provider is responsible for allocating and freeing events.
- EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack);
+ EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);
-public:
+ public:
+ ~EventPipeEvent();
// Get the provider associated with this event.
EventPipeProvider* GetProvider() const;
@@ -67,6 +74,12 @@ public:
// True if the event is currently enabled.
bool IsEnabled() const;
+
+ // Get metadata
+ BYTE *GetMetadata() const;
+
+ // Get metadata length
+ unsigned int GetMetadataLength() const;
};
#endif // FEATURE_PERFTRACING
diff --git a/src/vm/eventpipeprovider.cpp b/src/vm/eventpipeprovider.cpp
index beee6fc1db..3c2d25401e 100644
--- a/src/vm/eventpipeprovider.cpp
+++ b/src/vm/eventpipeprovider.cpp
@@ -128,7 +128,7 @@ void EventPipeProvider::SetConfiguration(bool providerEnabled, INT64 keywords, E
InvokeCallback();
}
-EventPipeEvent* EventPipeProvider::AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level)
+EventPipeEvent* EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, BYTE *pMetadata, unsigned int metadataLength)
{
CONTRACTL
{
@@ -138,10 +138,10 @@ EventPipeEvent* EventPipeProvider::AddEvent(INT64 keywords, unsigned int eventID
}
CONTRACTL_END;
- return AddEvent(keywords, eventID, eventVersion, level, true /* needStack */);
+ return AddEvent(eventID, keywords, eventVersion, level, true /* needStack */, pMetadata, metadataLength);
}
-EventPipeEvent* EventPipeProvider::AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack)
+EventPipeEvent* EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata, unsigned int metadataLength)
{
CONTRACTL
{
@@ -158,7 +158,9 @@ EventPipeEvent* EventPipeProvider::AddEvent(INT64 keywords, unsigned int eventID
eventID,
eventVersion,
level,
- needStack);
+ needStack,
+ pMetadata,
+ metadataLength);
// Add it to the list of events.
AddEvent(*pEvent);
diff --git a/src/vm/eventpipeprovider.h b/src/vm/eventpipeprovider.h
index 771af21b87..605a82b151 100644
--- a/src/vm/eventpipeprovider.h
+++ b/src/vm/eventpipeprovider.h
@@ -73,16 +73,16 @@ public:
bool EventEnabled(INT64 keywords, EventPipeEventLevel eventLevel) const;
// Create a new event.
- EventPipeEvent* AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level);
+ EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);
-private:
+ private:
// Create a new event, but allow needStack to be specified.
// In general, we want stack walking to be controlled by the consumer and not the producer of events.
// However, there are a couple of cases that we know we don't want to do a stackwalk that would affect performance significantly:
// 1. Sample profiler events: The sample profiler already does a stack walk of the target thread. Doing one of the sampler thread is a waste.
// 2. Metadata events: These aren't as painful but because we have to keep this functionality around, might as well use it.
- EventPipeEvent* AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack);
+ EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);
// Add an event to the provider.
void AddEvent(EventPipeEvent &event);
diff --git a/src/vm/sampleprofiler.cpp b/src/vm/sampleprofiler.cpp
index 3ed1a5b7fd..c7373bc088 100644
--- a/src/vm/sampleprofiler.cpp
+++ b/src/vm/sampleprofiler.cpp
@@ -36,8 +36,8 @@ void SampleProfiler::Enable()
{
s_pEventPipeProvider = new EventPipeProvider(s_providerID);
s_pThreadTimeEvent = s_pEventPipeProvider->AddEvent(
- 0, /* keywords */
0, /* eventID */
+ 0, /* keywords */
0, /* eventVersion */
EventPipeEventLevel::Informational,
false /* NeedStack */);