EventPipe events should only be sent to sessions that are listening to the event...
authorAndrew Au <andrewau@microsoft.com>
Wed, 26 Jun 2019 22:21:39 +0000 (15:21 -0700)
committerGitHub <noreply@github.com>
Wed, 26 Jun 2019 22:21:39 +0000 (15:21 -0700)
src/vm/eventpipeconfiguration.cpp
src/vm/eventpipeconfiguration.h
src/vm/eventpipeevent.cpp
src/vm/eventpipeevent.h
src/vm/eventpipeprovider.cpp
src/vm/eventpipeprovider.h

index a1c91e8..412c447 100644 (file)
@@ -309,6 +309,39 @@ void EventPipeConfiguration::ComputeKeywordAndLevel(const EventPipeProvider& pro
     });
 }
 
+INT64 EventPipeConfiguration::ComputeEventEnabledMask(const EventPipeProvider& provider, INT64 keywords, EventPipeEventLevel eventLevel) const
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_TRIGGERS;
+        MODE_PREEMPTIVE;
+        PRECONDITION(EventPipe::IsLockOwnedByCurrentThread());
+    }
+    CONTRACTL_END;
+    INT64 result = 0;
+    EventPipe::ForEachSession([&](EventPipeSession &session) {
+        EventPipeSessionProvider *pSessionProvider = GetSessionProvider(session, &provider);
+        if (pSessionProvider != nullptr)
+        {
+            INT64 sessionKeyword = pSessionProvider->GetKeywords();
+            EventPipeEventLevel sessionLevel = pSessionProvider->GetLevel();
+            // The event is enabled if:
+            //  - The provider is enabled.
+            //  - The event keywords are unspecified in the manifest (== 0) or when masked with the enabled config are != 0.
+            //  - The event level is LogAlways or the provider's verbosity level is set to greater than the event's verbosity level in the manifest.
+            bool providerEnabled = provider.Enabled();
+            bool keywordEnabled = (keywords == 0) || ((sessionKeyword & keywords) != 0);
+            bool levelEnabled = ((eventLevel == EventPipeEventLevel::LogAlways) || (sessionLevel >= eventLevel));
+            if (providerEnabled && keywordEnabled && levelEnabled)
+            {
+                result = result | session.GetMask();
+            }
+        }
+    });
+    return result;
+}
+
 void EventPipeConfiguration::Enable(EventPipeSession &session, EventPipeProviderCallbackDataQueue *pEventPipeProviderCallbackDataQueue)
 {
     CONTRACTL
index 5f751ef..bdc9c52 100644 (file)
@@ -54,7 +54,9 @@ public:
 
     // Delete deferred providers.
     void DeleteDeferredProviders();
-
+    
+    // Compute the enabled bit mask, the ith bit is 1 iff an event with the given (provider, keywords, eventLevel) is enabled for the ith session.
+    INT64 ComputeEventEnabledMask(const EventPipeProvider& provider, INT64 keywords, EventPipeEventLevel eventLevel) const;
 private:
     // Get the provider without taking the lock.
     EventPipeProvider *GetProviderNoLock(const SString &providerID);
index 40ef588..e352afb 100644 (file)
@@ -22,7 +22,7 @@ EventPipeEvent::EventPipeEvent(
                                    m_eventVersion(eventVersion),
                                    m_level(level),
                                    m_needStack(needStack),
-                                   m_enabled(false),
+                                   m_enabledMask(0),
                                    m_pMetadata(nullptr)
 {
     CONTRACTL
@@ -138,7 +138,7 @@ bool EventPipeEvent::NeedStack() const
 bool EventPipeEvent::IsEnabled() const
 {
     LIMITED_METHOD_CONTRACT;
-    return m_enabled;
+    return m_enabledMask != 0;
 }
 
 BYTE *EventPipeEvent::GetMetadata() const
@@ -156,16 +156,15 @@ unsigned int EventPipeEvent::GetMetadataLength() const
 void EventPipeEvent::RefreshState()
 {
     LIMITED_METHOD_CONTRACT;
-    m_enabled = m_pProvider->EventEnabled(m_keywords, m_level);
+    _ASSERTE(EventPipe::IsLockOwnedByCurrentThread());
+    m_enabledMask = m_pProvider->ComputeEventEnabledMask(m_keywords, m_level);
 }
 
 bool EventPipeEvent::IsEnabled(uint64_t sessionMask) const
 {
     LIMITED_METHOD_CONTRACT;
-    _ASSERT(m_pProvider != nullptr);
-    const bool IsProviderEnabled = m_pProvider->IsEnabled(sessionMask);
-    const bool IsEventEnabled = m_pProvider->EventEnabled(m_keywords, m_level);
-    return (IsProviderEnabled && IsEventEnabled);
+    _ASSERTE(m_pProvider != nullptr);
+    return (m_pProvider->IsEnabled(sessionMask) && (m_enabledMask & sessionMask) != 0);
 }
 
 #endif // FEATURE_PERFTRACING
index 122c3be..f2dfe4e 100644 (file)
@@ -34,8 +34,8 @@ private:
     // True if a call stack should be captured when writing the event.
     const bool m_needStack;
 
-    // True if the event is current enabled.
-    Volatile<bool> m_enabled;
+    // The ith bit is 1 iff the event is enabled for the ith session
+    Volatile<INT64> m_enabledMask;
 
     // Metadata
     BYTE *m_pMetadata;
index e1681f7..4148aa1 100644 (file)
@@ -84,26 +84,18 @@ const SString &EventPipeProvider::GetProviderName() const
     return m_providerName;
 }
 
-bool EventPipeProvider::EventEnabled(INT64 keywords) const
+INT64 EventPipeProvider::ComputeEventEnabledMask(INT64 keywords, EventPipeEventLevel eventLevel) const
 {
-    LIMITED_METHOD_CONTRACT;
-
-    // The event is enabled if:
-    //  - The provider is enabled.
-    //  - The event keywords are unspecified in the manifest (== 0) or when masked with the enabled config are != 0.
-    return (Enabled() && ((keywords == 0) || ((m_keywords & keywords) != 0)));
-}
-
-bool EventPipeProvider::EventEnabled(INT64 keywords, EventPipeEventLevel eventLevel) const
-{
-    LIMITED_METHOD_CONTRACT;
+    CONTRACTL
+    {
+        THROWS;
+        GC_TRIGGERS;
+        MODE_PREEMPTIVE;
+        PRECONDITION(EventPipe::IsLockOwnedByCurrentThread());
+    }
+    CONTRACTL_END;
 
-    // The event is enabled if:
-    //  - The provider is enabled.
-    //  - The event keywords are unspecified in the manifest (== 0) or when masked with the enabled config are != 0.
-    //  - The event level is LogAlways or the provider's verbosity level is set to greater than the event's verbosity level in the manifest.
-    return (EventEnabled(keywords) &&
-            ((eventLevel == EventPipeEventLevel::LogAlways) || (m_providerLevel >= eventLevel)));
+    return m_pConfig->ComputeEventEnabledMask((*this), keywords, eventLevel);
 }
 
 EventPipeProviderCallbackData EventPipeProvider::SetConfiguration(
@@ -130,7 +122,7 @@ EventPipeProviderCallbackData EventPipeProvider::SetConfiguration(
     m_providerLevel = providerLevelForAllSessions;
 
     RefreshAllEvents();
-    return PrepareCallbackData(keywords, providerLevel, pFilterData);
+    return PrepareCallbackData(m_keywords, m_providerLevel, pFilterData);
 }
 
 EventPipeProviderCallbackData EventPipeProvider::UnsetConfiguration(
@@ -158,7 +150,7 @@ EventPipeProviderCallbackData EventPipeProvider::UnsetConfiguration(
     m_providerLevel = providerLevelForAllSessions;
 
     RefreshAllEvents();
-    return PrepareCallbackData(keywords, providerLevel, pFilterData);
+    return PrepareCallbackData(m_keywords, m_providerLevel, pFilterData);
 }
 
 EventPipeEvent *EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata, unsigned int metadataLength)
@@ -166,7 +158,7 @@ EventPipeEvent *EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords
     CONTRACTL
     {
         THROWS;
-        GC_NOTRIGGER;
+        GC_TRIGGERS;
         MODE_ANY;
     }
     CONTRACTL_END;
@@ -192,7 +184,7 @@ void EventPipeProvider::AddEvent(EventPipeEvent &event)
     CONTRACTL
     {
         THROWS;
-        GC_NOTRIGGER;
+        GC_TRIGGERS;
         MODE_ANY;
     }
     CONTRACTL_END;
@@ -304,7 +296,7 @@ void EventPipeProvider::RefreshAllEvents()
     CONTRACTL
     {
         THROWS;
-        GC_NOTRIGGER;
+        GC_TRIGGERS;
         MODE_ANY;
         PRECONDITION(EventPipe::IsLockOwnedByCurrentThread());
     }
index ad7663d..d842f18 100644 (file)
@@ -72,11 +72,8 @@ public:
         return ((m_sessions & sessionMask) != 0);
     }
 
-    // Determine if the specified keywords are enabled.
-    bool EventEnabled(INT64 keywords) const;
-
-    // Determine if the specified keywords and level match the configuration.
-    bool EventEnabled(INT64 keywords, EventPipeEventLevel eventLevel) const;
+    // Compute the enabled bit mask, the ith bit is 1 iff an event with the given (provider, keywords, eventLevel) is enabled for the ith session.
+    INT64 ComputeEventEnabledMask(INT64 keywords, EventPipeEventLevel eventLevel) const;
 
     // Create a new event.
     EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);