@@ -686,6 +686,106 @@ protected EventSource(EventSourceSettings settings, params string[] traits)
686686 Initialize ( eventSourceGuid , eventSourceName , traits ) ;
687687 }
688688
689+ #if FEATURE_PERFTRACING
690+ // Generate the serialized blobs that describe events for all strongly typed events (that is events that define strongly
691+ // typed event methods. Dynamically defined events (that use Write) hare defined on the fly and are handled elsewhere.
692+ private unsafe void DefineEventPipeEvents ( )
693+ {
694+ Debug . Assert ( m_eventData != null ) ;
695+ Debug . Assert ( m_provider != null ) ;
696+ int cnt = m_eventData . Length ;
697+ for ( int i = 0 ; i < cnt ; i ++ )
698+ {
699+ uint eventID = ( uint ) m_eventData [ i ] . Descriptor . EventId ;
700+ if ( eventID == 0 )
701+ continue ;
702+
703+ string eventName = m_eventData [ i ] . Name ;
704+ Int64 keywords = m_eventData [ i ] . Descriptor . Keywords ;
705+ uint eventVersion = m_eventData [ i ] . Descriptor . Version ;
706+ uint level = m_eventData [ i ] . Descriptor . Level ;
707+
708+ // evnetID : 4 bytes
709+ // eventName : (eventName.Length + 1) * 2 bytes
710+ // keywords : 8 bytes
711+ // eventVersion : 4 bytes
712+ // level : 4 bytes
713+ // parameterCount : 4 bytes
714+ uint metadataLength = 24 + ( ( uint ) eventName . Length + 1 ) * 2 ;
715+
716+ // Increase the metadataLength for the types of all parameters.
717+ metadataLength += ( uint ) m_eventData [ i ] . Parameters . Length * 4 ;
718+
719+ // Increase the metadataLength for the names of all parameters.
720+ foreach ( var parameter in m_eventData [ i ] . Parameters )
721+ {
722+ string parameterName = parameter . Name ;
723+ metadataLength = metadataLength + ( ( uint ) parameterName . Length + 1 ) * 2 ;
724+ }
725+
726+ byte [ ] metadata = new byte [ metadataLength ] ;
727+
728+ // Write metadata: evnetID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
729+ fixed ( byte * pMetadata = metadata )
730+ {
731+ uint offset = 0 ;
732+ WriteToBuffer ( pMetadata , metadataLength , ref offset , eventID ) ;
733+ fixed( char * pEventName = eventName )
734+ {
735+ WriteToBuffer ( pMetadata , metadataLength , ref offset , ( byte * ) pEventName , ( ( uint ) eventName . Length + 1 ) * 2 ) ;
736+ }
737+ WriteToBuffer ( pMetadata , metadataLength , ref offset , keywords ) ;
738+ WriteToBuffer ( pMetadata , metadataLength , ref offset , eventVersion ) ;
739+ WriteToBuffer ( pMetadata , metadataLength , ref offset , level ) ;
740+ WriteToBuffer ( pMetadata , metadataLength , ref offset , ( uint ) m_eventData [ i ] . Parameters . Length ) ;
741+ foreach ( var parameter in m_eventData [ i ] . Parameters )
742+ {
743+ // Write parameter type.
744+ WriteToBuffer ( pMetadata , metadataLength , ref offset , ( uint ) Type . GetTypeCode ( parameter . ParameterType ) ) ;
745+
746+ // Write parameter name.
747+ string parameterName = parameter . Name ;
748+ fixed ( char * pParameterName = parameterName )
749+ {
750+ WriteToBuffer ( pMetadata , metadataLength , ref offset , ( byte * ) pParameterName , ( ( uint ) parameterName . Length + 1 ) * 2 ) ;
751+ }
752+ }
753+ Debug . Assert ( metadataLength == offset ) ;
754+ IntPtr eventHandle = m_provider . m_eventProvider . DefineEventHandle ( eventID , eventName , keywords , eventVersion , level , pMetadata , metadataLength ) ;
755+ m_eventData [ i ] . EventHandle = eventHandle ;
756+ }
757+ }
758+ }
759+
760+ // Copy src to buffer and modify the offset.
761+ // Note: We know the buffer size ahead of time to make sure no buffer overflow.
762+ private static unsafe void WriteToBuffer ( byte * buffer , uint bufferLength , ref uint offset , byte * src , uint srcLength )
763+ {
764+ Debug . Assert ( bufferLength >= ( offset + srcLength ) ) ;
765+ for ( int i = 0 ; i < srcLength ; i ++ )
766+ {
767+ * ( byte * ) ( buffer + offset + i ) = * ( byte * ) ( src + i ) ;
768+ }
769+ offset += srcLength ;
770+ }
771+
772+ // Copy uint value to buffer.
773+ private static unsafe void WriteToBuffer ( byte * buffer , uint bufferLength , ref uint offset , uint value )
774+ {
775+ Debug . Assert ( bufferLength >= ( offset + 4 ) ) ;
776+ * ( uint * ) ( buffer + offset ) = value;
777+ offset += 4 ;
778+ }
779+
780+ // Copy long value to buffer.
781+ private static unsafe void WriteToBuffer ( byte * buffer , uint bufferLength , ref uint offset , long value )
782+ {
783+ Debug . Assert ( bufferLength >= ( offset + 8 ) ) ;
784+ * ( long * ) ( buffer + offset ) = value;
785+ offset += 8 ;
786+ }
787+ #endif
788+
689789 internal virtual void GetMetadata ( out Guid eventSourceGuid , out string eventSourceName , out EventMetadata [ ] eventData , out byte [ ] manifestBytes )
690790 {
691791 //
@@ -1179,7 +1279,7 @@ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* rel
11791279 // by default the Descriptor.Keyword will have the perEventSourceSessionId bit
11801280 // mask set to 0x0f so, when all ETW sessions want the event we don't need to
11811281 // synthesize a new one
1182- if ( ! m_provider . WriteEvent ( ref m_eventData [ eventId ] . Descriptor , pActivityId , relatedActivityId , eventDataCount , ( IntPtr ) data ) )
1282+ if ( ! m_provider . WriteEvent ( ref m_eventData [ eventId ] . Descriptor , m_eventData [ eventId ] . EventHandle , pActivityId , relatedActivityId , eventDataCount , ( IntPtr ) data ) )
11831283 ThrowEventSourceException ( m_eventData [ eventId ] . Name ) ;
11841284 }
11851285 else
@@ -1199,7 +1299,7 @@ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* rel
11991299 m_eventData [ eventId ] . Descriptor . Task ,
12001300 unchecked ( ( long ) etwSessions . ToEventKeywords ( ) | origKwd ) ) ;
12011301
1202- if ( ! m_provider . WriteEvent ( ref desc , pActivityId , relatedActivityId , eventDataCount , ( IntPtr ) data ) )
1302+ if ( ! m_provider . WriteEvent ( ref desc , m_eventData [ eventId ] . EventHandle , pActivityId , relatedActivityId , eventDataCount , ( IntPtr ) data ) )
12031303 ThrowEventSourceException ( m_eventData [ eventId ] . Name ) ;
12041304 }
12051305 }
@@ -1229,7 +1329,7 @@ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* rel
12291329#else
12301330 if ( ! SelfDescribingEvents )
12311331 {
1232- if ( ! m_provider . WriteEvent ( ref m_eventData [ eventId ] . Descriptor , pActivityId , relatedActivityId , eventDataCount , ( IntPtr ) data ) )
1332+ if ( ! m_provider . WriteEvent ( ref m_eventData [ eventId ] . Descriptor , m_eventData [ eventId ] . EventHandle , pActivityId , relatedActivityId , eventDataCount , ( IntPtr ) data ) )
12331333 ThrowEventSourceException ( m_eventData [ eventId ] . Name ) ;
12341334 }
12351335 else
@@ -1489,7 +1589,6 @@ private unsafe void Initialize(Guid eventSourceGuid, string eventSourceName, str
14891589 }
14901590#endif // PLATFORM_WINDOWS
14911591#endif // FEATURE_MANAGED_ETW
1492-
14931592 Debug . Assert ( ! m_eventSourceEnabled ) ; // We can't be enabled until we are completely initted.
14941593 // We are logically completely initialized at this point.
14951594 m_completelyInited = true ;
@@ -1941,7 +2040,7 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object
19412040 // by default the Descriptor.Keyword will have the perEventSourceSessionId bit
19422041 // mask set to 0x0f so, when all ETW sessions want the event we don't need to
19432042 // synthesize a new one
1944- if ( ! m_provider . WriteEvent ( ref m_eventData [ eventId ] . Descriptor , pActivityId , childActivityID , args ) )
2043+ if ( ! m_provider . WriteEvent ( ref m_eventData [ eventId ] . Descriptor , m_eventData [ eventId ] . EventHandle , pActivityId , childActivityID , args ) )
19452044 ThrowEventSourceException( m_eventData [ eventId ] . Name ) ;
19462045 }
19472046 else
@@ -1958,7 +2057,7 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object
19582057 m_eventData [ eventId ] . Descriptor . Task ,
19592058 unchecked ( ( long ) etwSessions . ToEventKeywords ( ) | origKwd ) ) ;
19602059
1961- if ( ! m_provider . WriteEvent ( ref desc , pActivityId , childActivityID , args ) )
2060+ if ( ! m_provider . WriteEvent ( ref desc , m_eventData [ eventId ] . EventHandle , pActivityId , childActivityID , args ) )
19622061 ThrowEventSourceException( m_eventData [ eventId ] . Name ) ;
19632062 }
19642063 }
@@ -1988,7 +2087,7 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object
19882087#else
19892088 if ( ! SelfDescribingEvents )
19902089 {
1991- if ( ! m_provider . WriteEvent ( ref m_eventData [ eventId ] . Descriptor , pActivityId , childActivityID , args ) )
2090+ if ( ! m_provider . WriteEvent ( ref m_eventData [ eventId ] . Descriptor , m_eventData [ eventId ] . EventHandle , pActivityId , childActivityID , args ) )
19922091 ThrowEventSourceException( m_eventData [ eventId ] . Name ) ;
19932092 }
19942093 else
@@ -2232,7 +2331,7 @@ private unsafe void WriteEventString(EventLevel level, long keywords, string msg
22322331 data. Ptr = ( ulong ) msgStringPtr ;
22332332 data. Size = ( uint ) ( 2 * ( msgString . Length + 1 ) ) ;
22342333 data. Reserved = 0 ;
2235- m_provider. WriteEvent ( ref descr , null , null , 1 , ( IntPtr ) ( ( void * ) & data ) ) ;
2334+ m_provider. WriteEvent ( ref descr , m_eventData [ 0 ] . EventHandle , null , null , 1 , ( IntPtr ) ( ( void * ) & data ) ) ;
22362335 }
22372336 }
22382337 }
@@ -2517,6 +2616,7 @@ root them and modify shared library definition to force export them.
25172616 partial struct EventMetadata
25182617 {
25192618 public EventDescriptor Descriptor ;
2619+ public IntPtr EventHandle ; // EventPipeEvent handle.
25202620 public EventTags Tags ;
25212621 public bool EnabledForAnyListener ; // true if any dispatcher has this event turned on
25222622 public bool EnabledForETW ; // is this event on for the OS ETW data dispatcher?
@@ -3065,6 +3165,10 @@ private void EnsureDescriptorsInitialized()
30653165 dispatcher . m_EventEnabled = new bool [ m_eventData . Length ] ;
30663166 dispatcher = dispatcher . m_Next ;
30673167 }
3168+ #if FEATURE_PERFTRACING
3169+ // Initialize the EventPipe event handles.
3170+ DefineEventPipeEvents ( ) ;
3171+ #endif
30683172 }
30693173 if ( s_currentPid == 0 )
30703174 {
@@ -3119,7 +3223,7 @@ private unsafe bool SendManifest(byte[] rawManifest)
31193223 dataDescrs [ 1 ] . Size = ( uint ) Math . Min ( dataLeft , chunkSize ) ;
31203224 if ( m_provider != null )
31213225 {
3122- if ( ! m_provider . WriteEvent ( ref manifestDescr , null , null , 2 , ( IntPtr ) dataDescrs ) )
3226+ if ( ! m_provider . WriteEvent ( ref manifestDescr , IntPtr . Zero , null , null , 2 , ( IntPtr ) dataDescrs ) )
31233227 {
31243228 // Turns out that if users set the BufferSize to something less than 64K then WriteEvent
31253229 // can fail. If we get this failure on the first chunk try again with something smaller
@@ -3597,7 +3701,11 @@ private static byte[] CreateManifestAndDescriptors(Type eventSourceType, string
35973701 throw new ArgumentException ( msg , exception ) ;
35983702 }
35993703
3704+ #if FEATURE_PERFTRACING
3705+ return null ;
3706+ #else
36003707 return bNeedsManifest ? res : null ;
3708+ #endif
36013709 }
36023710
36033711 private static bool RemoveFirstArgIfRelatedActivityId ( ref ParameterInfo [ ] args )
@@ -3686,6 +3794,7 @@ private static void AddEventDescriptor(ref EventMetadata[] eventData, string eve
36863794 eventData [ eventAttribute . EventId ] . Message = eventAttribute . Message ;
36873795 eventData [ eventAttribute . EventId ] . ActivityOptions = eventAttribute . ActivityOptions ;
36883796 eventData [ eventAttribute . EventId ] . HasRelatedActivityID = hasRelatedActivityID ;
3797+ eventData [ eventAttribute . EventId ] . EventHandle = IntPtr . Zero ;
36893798 }
36903799
36913800 // Helper used by code:CreateManifestAndDescriptors that trims the m_eventData array to the correct
0 commit comments