diff options
author | Brian Robbins <brianrob@microsoft.com> | 2017-05-06 12:36:08 -0700 |
---|---|---|
committer | Vance Morrison <vancem@microsoft.com> | 2017-05-06 12:36:08 -0700 |
commit | 72ac46450bec8ea88ed023d9c1faf5a04556c834 (patch) | |
tree | 59085824f4268257d041ed9870f038216cd8ed45 /src/vm/eventpipeprovider.cpp | |
parent | 3ababc21ab334a2e37c6ba4115c946ea26a6f2fb (diff) | |
download | coreclr-72ac46450bec8ea88ed023d9c1faf5a04556c834.tar.gz coreclr-72ac46450bec8ea88ed023d9c1faf5a04556c834.tar.bz2 coreclr-72ac46450bec8ea88ed023d9c1faf5a04556c834.zip |
Log Events to EventPipe on Linux (#11433)
* Implement the EventPipe object model for providers and events.
* Plumb Runtime Events into EventPipe (#11145)
Plumb runtime ETW events into the EventPipe.
* Fix bug where all events except for SampleProfiler events were never enabled.
* Plumb EventPipeEventInstance through the EventPipe.
* Implement EventPipeFile and FastSerializer.
* Write event contents to the EventPipeFile.
* Only build EventPipe on Linux.
* Conditionally add a sentinel value marking event end.
* Send SampleProfiler events to the EventPipeFile.
* Fix provider ID printing to JSON file.
* Write the start date/time, timestamp, and clock frequency into the trace file.
* Support unloading of EventPipeProviders.
* Handle failure cases when we can't walk the stack or are shutting down.
* Fix a bug where we pass a null src pointer to memcpy.
Diffstat (limited to 'src/vm/eventpipeprovider.cpp')
-rw-r--r-- | src/vm/eventpipeprovider.cpp | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/src/vm/eventpipeprovider.cpp b/src/vm/eventpipeprovider.cpp new file mode 100644 index 0000000000..da185334a9 --- /dev/null +++ b/src/vm/eventpipeprovider.cpp @@ -0,0 +1,253 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "common.h" +#include "eventpipe.h" +#include "eventpipeconfiguration.h" +#include "eventpipeevent.h" +#include "eventpipeprovider.h" + +#ifdef FEATURE_PERFTRACING + +EventPipeProvider::EventPipeProvider(const GUID &providerID) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + m_providerID = providerID; + m_enabled = false; + m_keywords = 0; + m_providerLevel = EventPipeEventLevel::Critical; + m_pEventList = new SList<SListElem<EventPipeEvent*>>(); + m_pCallbackFunction = NULL; + m_pCallbackData = NULL; + + // Register the provider. + EventPipeConfiguration* pConfig = EventPipe::GetConfiguration(); + _ASSERTE(pConfig != NULL); + pConfig->RegisterProvider(*this); +} + +EventPipeProvider::~EventPipeProvider() +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + // Unregister the provider. + // This call is re-entrant. + EventPipeConfiguration* pConfig = EventPipe::GetConfiguration(); + _ASSERTE(pConfig != NULL); + pConfig->UnregisterProvider(*this); + + // Free all of the events. + if(m_pEventList != NULL) + { + // Take the lock before manipulating the list. + CrstHolder _crst(EventPipe::GetLock()); + + SListElem<EventPipeEvent*> *pElem = m_pEventList->GetHead(); + while(pElem != NULL) + { + EventPipeEvent *pEvent = pElem->GetValue(); + delete pEvent; + + pElem = m_pEventList->GetNext(pElem); + } + + delete m_pEventList; + m_pEventList = NULL; + } +} + +const GUID& EventPipeProvider::GetProviderID() const +{ + LIMITED_METHOD_CONTRACT; + + return m_providerID; +} + +bool EventPipeProvider::Enabled() const +{ + LIMITED_METHOD_CONTRACT; + + return m_enabled; +} + +bool EventPipeProvider::EventEnabled(INT64 keywords) 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; + + // 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))); +} + +void EventPipeProvider::SetConfiguration(bool providerEnabled, INT64 keywords, EventPipeEventLevel providerLevel) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread()); + } + CONTRACTL_END; + + m_enabled = providerEnabled; + m_keywords = keywords; + m_providerLevel = providerLevel; + + RefreshAllEvents(); + InvokeCallback(); +} + +EventPipeEvent* EventPipeProvider::AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + // Create the event. + EventPipeEvent *pEvent = new EventPipeEvent( + *this, + keywords, + eventID, + eventVersion, + level, + needStack); + + // Add it to the list of events. + AddEvent(*pEvent); + return pEvent; +} + +void EventPipeProvider::AddEvent(EventPipeEvent &event) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + // Take the config lock before inserting a new event. + CrstHolder _crst(EventPipe::GetLock()); + + m_pEventList->InsertTail(new SListElem<EventPipeEvent*>(&event)); +} + +void EventPipeProvider::RegisterCallback(EventPipeCallback pCallbackFunction, void *pData) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + // Take the config lock before setting the callback. + CrstHolder _crst(EventPipe::GetLock()); + + if(m_pCallbackFunction == NULL) + { + m_pCallbackFunction = pCallbackFunction; + m_pCallbackData = pData; + } +} + +void EventPipeProvider::UnregisterCallback(EventPipeCallback pCallbackFunction) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + // Take the config lock before setting the callback. + CrstHolder _crst(EventPipe::GetLock()); + + if(m_pCallbackFunction == pCallbackFunction) + { + m_pCallbackFunction = NULL; + m_pCallbackData = NULL; + } +} + +void EventPipeProvider::InvokeCallback() +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread()); + } + CONTRACTL_END; + + if(m_pCallbackFunction != NULL) + { + (*m_pCallbackFunction)( + &m_providerID, + m_enabled, + (UCHAR) m_providerLevel, + m_keywords, + 0 /* matchAllKeywords */, + NULL /* FilterData */, + m_pCallbackData /* CallbackContext */); + } +} + +void EventPipeProvider::RefreshAllEvents() +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread()); + } + CONTRACTL_END; + + SListElem<EventPipeEvent*> *pElem = m_pEventList->GetHead(); + while(pElem != NULL) + { + EventPipeEvent *pEvent = pElem->GetValue(); + pEvent->RefreshState(); + + pElem = m_pEventList->GetNext(pElem); + } +} + +#endif // FEATURE_PERFTRACING |