Postponing the managed callback so that they are called after the lock acquistion
authorAndrew Au <andrewau@microsoft.com>
Fri, 29 Mar 2019 00:07:16 +0000 (17:07 -0700)
committerAndrew Au <cshung@gmail.com>
Thu, 25 Apr 2019 07:12:34 +0000 (00:12 -0700)
src/vm/eventpipe.cpp
src/vm/eventpipe.h
src/vm/eventpipeconfiguration.cpp
src/vm/eventpipeconfiguration.h
src/vm/eventpipeprovider.cpp
src/vm/eventpipeprovider.h
src/vm/sampleprofiler.cpp
src/vm/sampleprofiler.h

index 6af54de..b5c5e09 100644 (file)
@@ -251,18 +251,30 @@ EventPipeSessionID EventPipe::Enable(
     }
     CONTRACTL_END;
 
-    // Take the lock before enabling tracing.
-    CrstHolder _crst(GetLock());
+    EventPipeSessionID sessionId;
+    EventPipeProviderCallbackDataQueue eventPipeProviderCallbackDataQueue;
+    EventPipeProviderCallbackData eventPipeProviderCallbackData;
+    {
+        // Take the lock before enabling tracing.
+        CrstHolder _crst(GetLock());
+
+        // Create a new session.
+        SampleProfiler::SetSamplingRate((unsigned long)profilerSamplingRateInNanoseconds);
+        EventPipeSession *pSession = s_pConfig->CreateSession(
+            (strOutputPath != NULL) ? EventPipeSessionType::File : EventPipeSessionType::Streaming,
+            circularBufferSizeInMB,
+            pProviders,
+            numProviders);
 
-    // Create a new session.
-    SampleProfiler::SetSamplingRate(static_cast<unsigned long>(profilerSamplingRateInNanoseconds));
-    EventPipeSession *pSession = s_pConfig->CreateSession(
-        sessionType,
-        circularBufferSizeInMB,
-        pProviders,
-        numProviders);
+        // Enable the session.
+        sessionId = Enable(strOutputPath, pSession, sessionType, pStream, &eventPipeProviderCallbackDataQueue);
+    }
+
+    while (eventPipeProviderCallbackDataQueue.TryDequeue(&eventPipeProviderCallbackData))
+    {
+        EventPipeProvider::InvokeCallback(eventPipeProviderCallbackData);
+    }
 
-    EventPipeSessionID sessionId = Enable(strOutputPath, pSession, sessionType, pStream);
     return sessionId;
 }
 
@@ -270,7 +282,8 @@ EventPipeSessionID EventPipe::Enable(
     LPCWSTR strOutputPath,
     EventPipeSession *const pSession,
     EventPipeSessionType sessionType,
-    IpcStream *const pStream)
+    IpcStream *const pStream,
+    EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue)
 {
     CONTRACTL
     {
@@ -322,10 +335,10 @@ EventPipeSessionID EventPipe::Enable(
     }
 
     // Enable tracing.
-    s_pConfig->Enable(s_pSession);
+    s_pConfig->Enable(s_pSession, pEventPipeProviderCallbackDataQueue);
 
     // Enable the sample profiler
-    SampleProfiler::Enable();
+    SampleProfiler::Enable(pEventPipeProviderCallbackDataQueue);
 
     // Return the session ID.
     return sessionId;
@@ -349,12 +362,21 @@ void EventPipe::Disable(EventPipeSessionID id)
     // Don't block GC during clean-up.
     GCX_PREEMP();
 
-    // Take the lock before disabling tracing.
-    CrstHolder _crst(GetLock());
-    DisableInternal(reinterpret_cast<EventPipeSessionID>(s_pSession));
+    EventPipeProviderCallbackDataQueue eventPipeProviderCallbackDataQueue;
+    EventPipeProviderCallbackData eventPipeProviderCallbackData;
+    {
+        // Take the lock before disabling tracing.
+        CrstHolder _crst(GetLock());
+        DisableInternal(reinterpret_cast<EventPipeSessionID>(s_pSession), &eventPipeProviderCallbackDataQueue);
+    }
+
+    while (eventPipeProviderCallbackDataQueue.TryDequeue(&eventPipeProviderCallbackData))
+    {
+        EventPipeProvider::InvokeCallback(eventPipeProviderCallbackData);
+    }
 }
 
-void EventPipe::DisableInternal(EventPipeSessionID id)
+void EventPipe::DisableInternal(EventPipeSessionID id, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue)
 {
     CONTRACTL
     {
@@ -377,7 +399,7 @@ void EventPipe::DisableInternal(EventPipeSessionID id)
         ETW::InfoLog::RuntimeInformation(ETW::InfoLog::InfoStructs::Normal);
 
         // Disable tracing.
-        s_pConfig->Disable(s_pSession);
+        s_pConfig->Disable(s_pSession, pEventPipeProviderCallbackDataQueue);
 
         // Delete the session.
         s_pConfig->DeleteSession(s_pSession);
@@ -410,14 +432,14 @@ void EventPipe::DisableInternal(EventPipeSessionID id)
                     1 /* circularBufferSizeInMB */,
                     RundownProviders,
                     sizeof(RundownProviders) / sizeof(EventPipeProviderConfiguration));
-                s_pConfig->EnableRundown(s_pSession);
+                s_pConfig->EnableRundown(s_pSession, pEventPipeProviderCallbackDataQueue);
 
                 // Ask the runtime to emit rundown events.
                 if (g_fEEStarted && !g_fEEShutDown)
                     ETW::EnumerationLog::EndRundown();
 
                 // Disable the event pipe now that rundown is complete.
-                s_pConfig->Disable(s_pSession);
+                s_pConfig->Disable(s_pSession, pEventPipeProviderCallbackDataQueue);
 
                 // Delete the rundown session.
                 s_pConfig->DeleteSession(s_pSession);
@@ -518,36 +540,45 @@ void WINAPI EventPipe::FlushTimer(PVOID parameter, BOOLEAN timerFired)
 
     GCX_PREEMP();
 
-    // Take the lock control lock to make sure that tracing isn't disabled during this operation.
-    CrstHolder _crst(GetLock());
+    EventPipeProviderCallbackDataQueue eventPipeProviderCallbackDataQueue;
+    EventPipeProviderCallbackData eventPipeProviderCallbackData;
+    {
+        // Take the lock control lock to make sure that tracing isn't disabled during this operation.
+        CrstHolder _crst(GetLock());
 
-    if (s_pSession == nullptr || s_pFile == nullptr)
-        return;
+        if (s_pSession == nullptr || s_pFile == nullptr)
+            return;
 
-    // Make sure that we should actually switch files.
-    if (!Enabled() || s_pSession->GetSessionType() != EventPipeSessionType::IpcStream)
-        return;
+        // Make sure that we should actually switch files.
+        if (!Enabled() || s_pSession->GetSessionType() != EventPipeSessionType::IpcStream)
+            return;
 
-    if (CLRGetTickCount64() > (s_lastFlushSwitchTime + 100))
-    {
-        // Get the current time stamp.
-        // WriteAllBuffersToFile will use this to ensure that no events after
-        // the current timestamp are written into the file.
-        LARGE_INTEGER stopTimeStamp;
-        QueryPerformanceCounter(&stopTimeStamp);
-        s_pBufferManager->WriteAllBuffersToFile(s_pFile, stopTimeStamp);
+        if (CLRGetTickCount64() > (s_lastFlushSwitchTime + 100))
+        {
+            // Get the current time stamp.
+            // WriteAllBuffersToFile will use this to ensure that no events after
+            // the current timestamp are written into the file.
+            LARGE_INTEGER stopTimeStamp;
+            QueryPerformanceCounter(&stopTimeStamp);
+            s_pBufferManager->WriteAllBuffersToFile(s_pFile, stopTimeStamp);
+
+            s_lastFlushSwitchTime = CLRGetTickCount64();
+        }
 
-        s_lastFlushSwitchTime = CLRGetTickCount64();
+        if (s_pFile->HasErrors())
+        {
+            EX_TRY
+            {
+                DisableInternal(reinterpret_cast<EventPipeSessionID>(s_pSession), &eventPipeProviderCallbackDataQueue);
+            }
+            EX_CATCH {}
+            EX_END_CATCH(SwallowAllExceptions);
+        }
     }
 
-    if (s_pFile->HasErrors())
+    while (eventPipeProviderCallbackDataQueue.TryDequeue(&eventPipeProviderCallbackData))
     {
-        EX_TRY
-        {
-            DisableInternal(reinterpret_cast<EventPipeSessionID>(s_pSession));
-        }
-        EX_CATCH {}
-        EX_END_CATCH(SwallowAllExceptions);
+        EventPipeProvider::InvokeCallback(eventPipeProviderCallbackData);
     }
 }
 
@@ -583,15 +614,41 @@ EventPipeProvider *EventPipe::CreateProvider(const SString &providerName, EventP
         THROWS;
         GC_TRIGGERS;
         MODE_ANY;
+        PRECONDITION(!GetLock()->OwnedByCurrentThread());
     }
     CONTRACTL_END;
+    
+    EventPipeProvider *pProvider = NULL;
+    EventPipeProviderCallbackDataQueue eventPipeProviderCallbackDataQueue;
+    EventPipeProviderCallbackData eventPipeProviderCallbackData;
+    {
+        CrstHolder _crst(GetLock());
+        pProvider = EventPipe::CreateProvider(providerName, pCallbackFunction, pCallbackData, &eventPipeProviderCallbackDataQueue);
+    }
+    while (eventPipeProviderCallbackDataQueue.TryDequeue(&eventPipeProviderCallbackData))
+    {
+        EventPipeProvider::InvokeCallback(eventPipeProviderCallbackData);
+    }
 
+    return pProvider;
+}
+
+EventPipeProvider *EventPipe::CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction, void *pCallbackData, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue)
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_TRIGGERS;
+        MODE_ANY;
+        PRECONDITION(GetLock()->OwnedByCurrentThread());
+    }
+    CONTRACTL_END;
+    
     EventPipeProvider *pProvider = NULL;
     if (s_pConfig != NULL)
     {
-        pProvider = s_pConfig->CreateProvider(providerName, pCallbackFunction, pCallbackData);
+        pProvider = s_pConfig->CreateProvider(providerName, pCallbackFunction, pCallbackData, pEventPipeProviderCallbackDataQueue);
     }
-
     return pProvider;
 }
 
index b40a0b7..842896e 100644 (file)
@@ -234,6 +234,8 @@ public:
 
 typedef UINT64 EventPipeSessionID;
 
+class EventPipeProviderCallbackDataQueue;
+
 class EventPipe
 {
     // Declare friends.
@@ -272,6 +274,8 @@ public:
     // Create a provider.
     static EventPipeProvider *CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction = NULL, void *pCallbackData = NULL);
 
+    static EventPipeProvider *CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction, void *pCallbackData, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue);
+
     // Get a provider.
     static EventPipeProvider *GetProvider(const SString &providerName);
 
@@ -305,14 +309,15 @@ private:
     // The counterpart to WriteEvent which after the payload is constructed
     static void WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload &payload, LPCGUID pActivityId = NULL, LPCGUID pRelatedActivityId = NULL);
 
-    static void DisableInternal(EventPipeSessionID id);
+    static void DisableInternal(EventPipeSessionID id, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue);
 
     // Enable the specified EventPipe session.
     static EventPipeSessionID Enable(
         LPCWSTR strOutputPath,
         EventPipeSession *const pSession,
         EventPipeSessionType sessionType,
-        IpcStream *const pStream);
+        IpcStream *const pStream,
+        EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue);
 
     static void CreateFlushTimerCallback();
 
index 9c7d396..9fb09b9 100644 (file)
@@ -91,9 +91,19 @@ void EventPipeConfiguration::Initialize()
         MODE_ANY;
     }
     CONTRACTL_END;
+    
+    EventPipeProviderCallbackDataQueue eventPipeProviderCallbackDataQueue;
+    EventPipeProviderCallbackData eventPipeProviderCallbackData;
+    {
+        CrstHolder _crst(EventPipe::GetLock());
 
-    // Create the configuration provider.
-    m_pConfigProvider = CreateProvider(SL(s_configurationProviderName), NULL, NULL);
+        // Create the configuration provider.
+        m_pConfigProvider = CreateProvider(SL(s_configurationProviderName), NULL, NULL, &eventPipeProviderCallbackDataQueue);
+    }
+    while (eventPipeProviderCallbackDataQueue.TryDequeue(&eventPipeProviderCallbackData))
+    {
+        EventPipeProvider::InvokeCallback(eventPipeProviderCallbackData);
+    }
 
     // Create the metadata event.
     m_pMetadataEvent = m_pConfigProvider->AddEvent(
@@ -104,13 +114,14 @@ void EventPipeConfiguration::Initialize()
         false); /* needStack */
 }
 
-EventPipeProvider *EventPipeConfiguration::CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction, void *pCallbackData)
+EventPipeProvider *EventPipeConfiguration::CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction, void *pCallbackData, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue)
 {
     CONTRACTL
     {
         THROWS;
         GC_TRIGGERS;
         MODE_ANY;
+        PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
     }
     CONTRACTL_END;
 
@@ -118,7 +129,7 @@ EventPipeProvider *EventPipeConfiguration::CreateProvider(const SString &provide
     EventPipeProvider *pProvider = new EventPipeProvider(this, providerName, pCallbackFunction, pCallbackData);
 
     // Register the provider with the configuration system.
-    RegisterProvider(*pProvider);
+    RegisterProvider(*pProvider, pEventPipeProviderCallbackDataQueue);
 
     return pProvider;
 }
@@ -144,19 +155,17 @@ void EventPipeConfiguration::DeleteProvider(EventPipeProvider *pProvider)
     delete pProvider;
 }
 
-bool EventPipeConfiguration::RegisterProvider(EventPipeProvider &provider)
+bool EventPipeConfiguration::RegisterProvider(EventPipeProvider &provider, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue)
 {
     CONTRACTL
     {
         THROWS;
         GC_TRIGGERS;
         MODE_ANY;
+        PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
     }
     CONTRACTL_END;
 
-    // Take the lock before manipulating the provider list.
-    CrstHolder _crst(EventPipe::GetLock());
-
     // See if we've already registered this provider.
     EventPipeProvider *pExistingProvider = GetProviderNoLock(provider.GetProviderName());
     if (pExistingProvider != NULL)
@@ -177,11 +186,12 @@ bool EventPipeConfiguration::RegisterProvider(EventPipeProvider &provider)
         EventPipeSessionProvider *pSessionProvider = GetSessionProvider(m_pSession, &provider);
         if (pSessionProvider != NULL)
         {
-            provider.SetConfiguration(
+            EventPipeProviderCallbackData eventPipeProviderCallbackData = provider.SetConfiguration(
                 true /* providerEnabled */,
                 pSessionProvider->GetKeywords(),
                 pSessionProvider->GetLevel(),
                 pSessionProvider->GetFilterData());
+            pEventPipeProviderCallbackDataQueue->Enqueue(&eventPipeProviderCallbackData);
         }
     }
 
@@ -350,7 +360,7 @@ void EventPipeConfiguration::DeleteSession(EventPipeSession *pSession)
     }
 }
 
-void EventPipeConfiguration::Enable(EventPipeSession *pSession)
+void EventPipeConfiguration::Enable(EventPipeSession *pSession, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue)
 {
     CONTRACTL
     {
@@ -363,6 +373,8 @@ void EventPipeConfiguration::Enable(EventPipeSession *pSession)
     }
     CONTRACTL_END;
 
+    EventPipeProviderCallbackData eventPipeProviderCallbackData;
+
     m_pSession = pSession;
     m_enabled = true;
 
@@ -378,11 +390,12 @@ void EventPipeConfiguration::Enable(EventPipeSession *pSession)
             EventPipeSessionProvider *pSessionProvider = GetSessionProvider(m_pSession, pProvider);
             if (pSessionProvider != NULL)
             {
-                pProvider->SetConfiguration(
+                eventPipeProviderCallbackData = pProvider->SetConfiguration(
                     true /* providerEnabled */,
                     pSessionProvider->GetKeywords(),
                     pSessionProvider->GetLevel(),
                     pSessionProvider->GetFilterData());
+                pEventPipeProviderCallbackDataQueue->Enqueue(&eventPipeProviderCallbackData);
             }
 
             pElem = m_pProviderList->GetNext(pElem);
@@ -390,7 +403,7 @@ void EventPipeConfiguration::Enable(EventPipeSession *pSession)
     }
 }
 
-void EventPipeConfiguration::Disable(EventPipeSession *pSession)
+void EventPipeConfiguration::Disable(EventPipeSession *pSession, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue)
 {
     CONTRACTL
     {
@@ -405,6 +418,8 @@ void EventPipeConfiguration::Disable(EventPipeSession *pSession)
     }
     CONTRACTL_END;
 
+    EventPipeProviderCallbackData eventPipeProviderCallbackData;
+
     // The provider list should be non-NULL, but can be NULL on shutdown.
     if (m_pProviderList != NULL)
     {
@@ -412,11 +427,12 @@ void EventPipeConfiguration::Disable(EventPipeSession *pSession)
         while (pElem != NULL)
         {
             EventPipeProvider *pProvider = pElem->GetValue();
-            pProvider->SetConfiguration(
+            eventPipeProviderCallbackData = pProvider->SetConfiguration(
                 false /* providerEnabled */,
                 0 /* keywords */,
                 EventPipeEventLevel::Critical /* level */,
                 NULL /* filterData */);
+            pEventPipeProviderCallbackDataQueue->Enqueue(&eventPipeProviderCallbackData);
 
             pElem = m_pProviderList->GetNext(pElem);
         }
@@ -440,7 +456,7 @@ bool EventPipeConfiguration::RundownEnabled() const
     return m_rundownEnabled;
 }
 
-void EventPipeConfiguration::EnableRundown(EventPipeSession *pSession)
+void EventPipeConfiguration::EnableRundown(EventPipeSession *pSession, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue)
 {
     CONTRACTL
     {
@@ -463,7 +479,7 @@ void EventPipeConfiguration::EnableRundown(EventPipeSession *pSession)
     m_rundownEnabled = true;
 
     // Enable tracing.
-    Enable(pSession);
+    Enable(pSession, pEventPipeProviderCallbackDataQueue);
 }
 
 EventPipeEventInstance *EventPipeConfiguration::BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance, unsigned int metadataId)
index 270ed44..bc88e36 100644 (file)
@@ -26,6 +26,36 @@ enum class EventPipeEventLevel
     Verbose
 };
 
+struct EventPipeProviderCallbackData
+{
+    LPCWSTR pFilterData;
+    EventPipeCallback pCallbackFunction;
+    bool enabled;
+    INT64 keywords;
+    EventPipeEventLevel providerLevel;
+    void* pCallbackData;
+};
+
+struct EventPipeProviderCallbackDataNode
+{
+    EventPipeProviderCallbackData* value;
+    EventPipeProviderCallbackDataNode* prev;
+};
+
+class EventPipeProviderCallbackDataQueue
+{
+public:
+    EventPipeProviderCallbackDataQueue();
+
+    void Enqueue(EventPipeProviderCallbackData* pEventPipeProviderCallbackData);
+
+    bool TryDequeue(EventPipeProviderCallbackData* pEventPipeProviderCallbackData);
+
+private:
+    EventPipeProviderCallbackDataNode* front;
+    EventPipeProviderCallbackDataNode* back;
+};
+
 class EventPipeConfiguration
 {
 public:
@@ -36,13 +66,13 @@ public:
     void Initialize();
 
     // Create a new provider.
-    EventPipeProvider *CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction, void *pCallbackData);
+    EventPipeProvider *CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction, void *pCallbackData, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue);
 
     // Delete a provider.
     void DeleteProvider(EventPipeProvider *pProvider);
 
     // Register a provider.
-    bool RegisterProvider(EventPipeProvider &provider);
+    bool RegisterProvider(EventPipeProvider &provider, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue);
 
     // Unregister a provider.
     bool UnregisterProvider(EventPipeProvider &provider);
@@ -64,10 +94,10 @@ public:
     size_t GetCircularBufferSize() const;
 
     // Enable a session in the event pipe.
-    void Enable(EventPipeSession *pSession);
+    void Enable(EventPipeSession *pSession, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue);
 
     // Disable a session in the event pipe.
-    void Disable(EventPipeSession *pSession);
+    void Disable(EventPipeSession *pSession, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue);
 
     // Get the status of the event pipe.
     bool Enabled() const;
@@ -76,7 +106,7 @@ public:
     bool RundownEnabled() const;
 
     // Enable rundown using the specified configuration.
-    void EnableRundown(EventPipeSession *pSession);
+    void EnableRundown(EventPipeSession *pSession, EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue);
 
     // Get the event used to write metadata to the event stream.
     EventPipeEventInstance *BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance, unsigned int metdataId);
index 4c6eabc..96bde58 100644 (file)
 
 #ifdef FEATURE_PERFTRACING
 
+EventPipeProviderCallbackDataQueue::EventPipeProviderCallbackDataQueue()
+{
+    this->front = this->back = NULL;
+}
+
+void EventPipeProviderCallbackDataQueue::Enqueue(EventPipeProviderCallbackData* pEventPipeProviderCallbackData)
+{
+    EventPipeProviderCallbackDataNode* newNode = new EventPipeProviderCallbackDataNode(); // throws
+    newNode->prev = NULL;
+    newNode->value = new EventPipeProviderCallbackData(); // throws
+    *(newNode->value) = *pEventPipeProviderCallbackData;
+    if (this->back == NULL)
+    {
+        this->front = this->back = newNode;
+    }
+    else
+    {
+        this->back->prev = newNode;
+        this->back = newNode;
+    }
+}
+
+bool EventPipeProviderCallbackDataQueue::TryDequeue(EventPipeProviderCallbackData* pEventPipeProviderCallbackData)
+{
+    if (this->front == nullptr)
+    {
+        return false;
+    }
+
+    EventPipeProviderCallbackDataNode* oldNode = this->front;
+    this->front = this->front->prev;
+    if (this->front == nullptr)
+    {
+        this->back = nullptr;
+    }
+    
+    *pEventPipeProviderCallbackData = *(oldNode->value);
+    delete oldNode;
+    return true;
+}
+
 EventPipeProvider::EventPipeProvider(EventPipeConfiguration *pConfig, const SString &providerName, EventPipeCallback pCallbackFunction, void *pCallbackData)
 {
     CONTRACTL
@@ -111,7 +152,7 @@ bool EventPipeProvider::EventEnabled(INT64 keywords, EventPipeEventLevel eventLe
         ((eventLevel == EventPipeEventLevel::LogAlways) || (m_providerLevel >= eventLevel)));
 }
 
-void EventPipeProvider::SetConfiguration(bool providerEnabled, INT64 keywords, EventPipeEventLevel providerLevel, LPCWSTR pFilterData)
+EventPipeProviderCallbackData EventPipeProvider::SetConfiguration(bool providerEnabled, INT64 keywords, EventPipeEventLevel providerLevel, LPCWSTR pFilterData)
 {
     CONTRACTL
     {
@@ -127,7 +168,7 @@ void EventPipeProvider::SetConfiguration(bool providerEnabled, INT64 keywords, E
     m_providerLevel = providerLevel;
 
     RefreshAllEvents();
-    InvokeCallback(pFilterData);
+    return PrepareCallbackData(pFilterData);
 }
 
 EventPipeEvent* EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata, unsigned int metadataLength)
@@ -173,17 +214,23 @@ void EventPipeProvider::AddEvent(EventPipeEvent &event)
     event.RefreshState();
 }
 
-void EventPipeProvider::InvokeCallback(LPCWSTR pFilterData)
+/* static */ void EventPipeProvider::InvokeCallback(EventPipeProviderCallbackData eventPipeProviderCallbackData)
 {
     CONTRACTL
     {
         THROWS;
         GC_TRIGGERS;
         MODE_ANY;
-        PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
+        PRECONDITION(!EventPipe::GetLock()->OwnedByCurrentThread());
     }
     CONTRACTL_END;
 
+    LPCWSTR pFilterData = eventPipeProviderCallbackData.pFilterData;
+    EventPipeCallback pCallbackFunction = eventPipeProviderCallbackData.pCallbackFunction;
+    bool enabled = eventPipeProviderCallbackData.enabled;
+    INT64 keywords = eventPipeProviderCallbackData.keywords;
+    EventPipeEventLevel providerLevel = eventPipeProviderCallbackData.providerLevel;
+    void* pCallbackData = eventPipeProviderCallbackData.pCallbackData;
 
     bool isEventFilterDescriptorInitialized = false;
     EventFilterDescriptor eventFilterDescriptor{};
@@ -211,21 +258,42 @@ void EventPipeProvider::InvokeCallback(LPCWSTR pFilterData)
         isEventFilterDescriptorInitialized = true;
     }
 
-    if(m_pCallbackFunction != NULL && !g_fEEShutDown)
+    if(pCallbackFunction != NULL && !g_fEEShutDown)
     {
-        (*m_pCallbackFunction)(
+        (*pCallbackFunction)(
             NULL, /* providerId */
-            m_enabled,
-            (UCHAR) m_providerLevel,
-            m_keywords,
+            enabled,
+            (UCHAR) providerLevel,
+            keywords,
             0 /* matchAllKeywords */,
             isEventFilterDescriptorInitialized ? &eventFilterDescriptor : NULL,
-            m_pCallbackData /* CallbackContext */);
+            pCallbackData /* CallbackContext */);
     }
 
     buffer.Destroy();
 }
 
+EventPipeProviderCallbackData EventPipeProvider::PrepareCallbackData(LPCWSTR pFilterData)
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_TRIGGERS;
+        MODE_ANY;
+        PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
+    }
+    CONTRACTL_END;
+
+    EventPipeProviderCallbackData result;
+    result.pFilterData = pFilterData;
+    result.pCallbackFunction = m_pCallbackFunction;
+    result.enabled = m_enabled;
+    result.providerLevel = m_providerLevel;
+    result.keywords = m_keywords;
+    result.pCallbackData = m_pCallbackData;
+    return result;
+}
+
 bool EventPipeProvider::GetDeleteDeferred() const
 {
     LIMITED_METHOD_CONTRACT;
index 6da1ec7..d20b492 100644 (file)
@@ -78,13 +78,16 @@ private:
 
     // Set the provider configuration (enable and disable sets of events).
     // This is called by EventPipeConfiguration.
-    void SetConfiguration(bool providerEnabled, INT64 keywords, EventPipeEventLevel providerLevel, LPCWSTR pFilterData);
+    EventPipeProviderCallbackData SetConfiguration(bool providerEnabled, INT64 keywords, EventPipeEventLevel providerLevel, LPCWSTR pFilterData);
 
     // Refresh the runtime state of all events.
     void RefreshAllEvents();
 
+    // Prepare the data required for invoking callback
+    EventPipeProviderCallbackData PrepareCallbackData(LPCWSTR pFilterData);
+
     // Invoke the provider callback.
-    void InvokeCallback(LPCWSTR pFilterData);
+    static void InvokeCallback(EventPipeProviderCallbackData eventPipeProviderCallbackData);
 
     // Specifies whether or not the provider was deleted, but that deletion
     // was deferred until after tracing is stopped.
index 44ab2f8..4b8e8b5 100644 (file)
@@ -36,7 +36,7 @@ HINSTANCE SampleProfiler::s_hMultimediaLib = NULL;
 typedef MMRESULT (WINAPI *TimePeriodFnPtr) (UINT uPeriod);
 #endif //FEATURE_PAL
 
-void SampleProfiler::Enable()
+void SampleProfiler::Enable(EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue)
 {
     CONTRACTL
     {
@@ -53,7 +53,7 @@ void SampleProfiler::Enable()
 
     if(s_pEventPipeProvider == NULL)
     {
-        s_pEventPipeProvider = EventPipe::CreateProvider(SL(s_providerName));
+        s_pEventPipeProvider = EventPipe::CreateProvider(SL(s_providerName), nullptr, nullptr, pEventPipeProviderCallbackDataQueue);
         s_pThreadTimeEvent = s_pEventPipeProvider->AddEvent(
             0, /* eventID */
             0, /* keywords */
index 00c20f3..dd8009b 100644 (file)
@@ -26,7 +26,7 @@ class SampleProfiler
     public:
 
         // Enable profiling.
-        static void Enable();
+        static void Enable(EventPipeProviderCallbackDataQueue* pEventPipeProviderCallbackDataQueue);
 
         // Disable profiling.
         static void Disable();