WriteEventImpl.append(
" EventPipeProvider" +
providerPrettyName +
- " = new EventPipeProvider(" +
+ " = EventPipe::CreateProvider(" +
providerPrettyName +
"GUID);\n")
for eventNode in eventNodes:
// De-allocate buffers.
s_pBufferManager->DeAllocateBuffers();
+
+ // Delete deferred providers.
+ // Providers can't be deleted during tracing because they may be needed when serializing the file.
+ s_pConfig->DeleteDeferredProviders();
}
}
return enabled;
}
+EventPipeProvider* EventPipe::CreateProvider(const GUID &providerID, EventPipeCallback pCallbackFunction, void *pCallbackData)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ return new EventPipeProvider(providerID, pCallbackFunction, pCallbackData);
+}
+
+void EventPipe::DeleteProvider(EventPipeProvider *pProvider)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ // Take the lock to make sure that we don't have a race
+ // between disabling tracing and deleting a provider
+ // where we hold a provider after tracing has been disabled.
+ CrstHolder _crst(GetLock());
+
+ if(pProvider != NULL)
+ {
+ if(Enabled())
+ {
+ // Save the provider until the end of the tracing session.
+ pProvider->SetDeleteDeferred();
+ }
+ else
+ {
+ // Delete the provider now.
+ // NOTE: This will remove it from all of the EventPipe data structures.
+ delete(pProvider);
+ }
+ }
+}
+
void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length)
{
CONTRACTL
BEGIN_QCALL;
- pProvider = new EventPipeProvider(providerID, pCallbackFunc, NULL);
+ pProvider = EventPipe::CreateProvider(providerID, pCallbackFunc, NULL);
END_QCALL;
if(provHandle != NULL)
{
EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider*>(provHandle);
- delete pProvider;
+ EventPipe::DeleteProvider(pProvider);
}
END_QCALL;
class EventPipeJsonFile;
class EventPipeBuffer;
class EventPipeBufferManager;
+class EventPipeProvider;
class MethodDesc;
class SampleProfilerEventInstance;
struct EventPipeProviderConfiguration;
// Specifies whether or not the event pipe is enabled.
static bool Enabled();
+ // Create a provider.
+ static EventPipeProvider* CreateProvider(const GUID &providerID, EventPipeCallback pCallbackFunction = NULL, void *pCallbackData = NULL);
+
+ // Delete a provider.
+ static void DeleteProvider(EventPipeProvider *pProvider);
+
// Write out an event.
// Data is written as a serialized blob matching the ETW serialization conventions.
static void WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length);
CONTRACTL_END;
// Create the configuration provider.
- m_pConfigProvider = new EventPipeProvider(s_configurationProviderID);
+ m_pConfigProvider = EventPipe::CreateProvider(s_configurationProviderID);
// Create the metadata event.
m_pMetadataEvent = m_pConfigProvider->AddEvent(
return pInstance;
}
+void EventPipeConfiguration::DeleteDeferredProviders()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ // Lock must be held by EventPipe::Disable.
+ PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
+
+ }
+ CONTRACTL_END;
+
+ SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
+ while(pElem != NULL)
+ {
+ EventPipeProvider *pProvider = pElem->GetValue();
+ if(pProvider->GetDeleteDeferred())
+ {
+ // The act of deleting the provider unregisters it and removes it from the list.
+ delete(pProvider);
+ }
+
+ pElem = m_pProviderList->GetNext(pElem);
+ }
+}
+
EventPipeEnabledProviderList::EventPipeEnabledProviderList(
EventPipeProviderConfiguration *pConfigs,
unsigned int numConfigs)
// Get the event used to write metadata to the event stream.
EventPipeEventInstance* BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance);
+ // Delete deferred providers.
+ void DeleteDeferredProviders();
+
private:
// Get the provider without taking the lock.
}
}
+bool EventPipeProvider::GetDeleteDeferred() const
+{
+ LIMITED_METHOD_CONTRACT;
+ return m_deleteDeferred;
+}
+
+void EventPipeProvider::SetDeleteDeferred()
+{
+ LIMITED_METHOD_CONTRACT;
+ m_deleteDeferred = true;
+}
+
void EventPipeProvider::RefreshAllEvents()
{
CONTRACTL
class EventPipeProvider
{
// Declare friends.
+ friend class EventPipe;
friend class EventPipeConfiguration;
friend class SampleProfiler;
// The configuration object.
EventPipeConfiguration *m_pConfig;
-public:
+ // True if the provider has been deleted, but that deletion
+ // has been deferred until tracing is stopped.
+ bool m_deleteDeferred;
+ // Private constructor because all providers are created through EventPipe::CreateProvider.
EventPipeProvider(const GUID &providerID, EventPipeCallback pCallbackFunction = NULL, void *pCallbackData = NULL);
+
+public:
+
~EventPipeProvider();
// Get the provider ID.
// Invoke the provider callback.
void InvokeCallback();
+
+ // Specifies whether or not the provider was deleted, but that deletion
+ // was deferred until after tracing is stopped.
+ bool GetDeleteDeferred() const;
+
+ // Defer deletion of the provider.
+ void SetDeleteDeferred();
};
#endif // FEATURE_PERFTRACING
if(s_pEventPipeProvider == NULL)
{
- s_pEventPipeProvider = new EventPipeProvider(s_providerID);
+ s_pEventPipeProvider = EventPipe::CreateProvider(s_providerID);
s_pThreadTimeEvent = s_pEventPipeProvider->AddEvent(
0, /* eventID */
0, /* keywords */