diff options
author | Xiangyang (Mark) Guo <xiangyang.guo@intel.com> | 2017-05-15 13:05:32 -0700 |
---|---|---|
committer | Brian Robbins <brianrob@microsoft.com> | 2017-05-15 13:05:32 -0700 |
commit | a7fae647fc09448cce04276a87a2873c09d31d42 (patch) | |
tree | 8f8afd1e440ec2ee802da1751ae8efee3497c015 /src | |
parent | 37168aeaf5d70de2d7af52d102002fc29b9feaf1 (diff) | |
download | coreclr-a7fae647fc09448cce04276a87a2873c09d31d42.tar.gz coreclr-a7fae647fc09448cce04276a87a2873c09d31d42.tar.bz2 coreclr-a7fae647fc09448cce04276a87a2873c09d31d42.zip |
Write EventSource events with metadata to EventPipe (#11577)
* Fix EventPipe initialization.
* rebase code with master, add prototype of event source metadata
* fix define event
* add null ptr checking
* move WriteEvent metadata serialization to managed side
* Fix enabled keywords for COMPlus_PerformanceTracing=1.
* put parameter name into metadata, use WriteToBuffer
* Write event metadata to the file.
* allocate buffer in EventPipeEvent ctor
* prevent double free
* refactor code
* AddEvent params reorder
Diffstat (limited to 'src')
-rw-r--r-- | src/mscorlib/shared/System/Diagnostics/Tracing/EventProvider.cs | 28 | ||||
-rw-r--r-- | src/mscorlib/shared/System/Diagnostics/Tracing/EventSource.cs | 127 | ||||
-rw-r--r-- | src/mscorlib/shared/System/Diagnostics/Tracing/IEventProvider.cs | 4 | ||||
-rw-r--r-- | src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs | 4 | ||||
-rw-r--r-- | src/mscorlib/src/System/Diagnostics/Eventing/EventPipeEventProvider.cs | 50 | ||||
-rw-r--r-- | src/scripts/genEventPipe.py | 2 | ||||
-rw-r--r-- | src/vm/ecalllist.h | 2 | ||||
-rw-r--r-- | src/vm/eventpipe.cpp | 23 | ||||
-rw-r--r-- | src/vm/eventpipe.h | 8 | ||||
-rw-r--r-- | src/vm/eventpipeconfiguration.cpp | 8 | ||||
-rw-r--r-- | src/vm/eventpipeconfiguration.h | 2 | ||||
-rw-r--r-- | src/vm/eventpipeevent.cpp | 36 | ||||
-rw-r--r-- | src/vm/eventpipeevent.h | 17 | ||||
-rw-r--r-- | src/vm/eventpipeprovider.cpp | 10 | ||||
-rw-r--r-- | src/vm/eventpipeprovider.h | 6 | ||||
-rw-r--r-- | src/vm/sampleprofiler.cpp | 2 |
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 */); |