diff options
Diffstat (limited to 'src/vm/eventpipe.h')
-rw-r--r-- | src/vm/eventpipe.h | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/vm/eventpipe.h b/src/vm/eventpipe.h new file mode 100644 index 0000000000..2978412325 --- /dev/null +++ b/src/vm/eventpipe.h @@ -0,0 +1,154 @@ +// 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. + +#ifndef __EVENTPIPE_H__ +#define __EVENTPIPE_H__ + +#include "common.h" + +class EventPipeJsonFile; + +// The data fields common to every event. +struct CommonEventFields +{ + // Timestamp generated by QueryPerformanceCounter. + LARGE_INTEGER TimeStamp; + + // Thread ID. + DWORD ThreadID; +}; + +class StackContents +{ +private: + + const static unsigned int MAX_STACK_DEPTH = 100; + + // Array of IP values from a stack crawl. + // Top of stack is at index 0. + UINT_PTR m_stackFrames[MAX_STACK_DEPTH]; + + // Parallel array of MethodDesc pointers. + // Used for debug-only stack printing. + MethodDesc* m_methods[MAX_STACK_DEPTH]; + + // The next available slot in StackFrames. + unsigned int m_nextAvailableFrame; + +public: + + StackContents() + { + LIMITED_METHOD_CONTRACT; + + Reset(); + } + + void Reset() + { + LIMITED_METHOD_CONTRACT; + + m_nextAvailableFrame = 0; + } + + bool IsEmpty() + { + LIMITED_METHOD_CONTRACT; + + return (m_nextAvailableFrame == 0); + } + + unsigned int GetLength() + { + LIMITED_METHOD_CONTRACT; + + return m_nextAvailableFrame; + } + + UINT_PTR GetIP(unsigned int frameIndex) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(frameIndex < MAX_STACK_DEPTH); + + if (frameIndex >= MAX_STACK_DEPTH) + { + return 0; + } + + return m_stackFrames[frameIndex]; + } + + MethodDesc* GetMethod(unsigned int frameIndex) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(frameIndex < MAX_STACK_DEPTH); + + if (frameIndex >= MAX_STACK_DEPTH) + { + return NULL; + } + + return m_methods[frameIndex]; + } + + void Append(UINT_PTR controlPC, MethodDesc *pMethod) + { + LIMITED_METHOD_CONTRACT; + + if(m_nextAvailableFrame < MAX_STACK_DEPTH) + { + m_stackFrames[m_nextAvailableFrame] = controlPC; + m_methods[m_nextAvailableFrame] = pMethod; + m_nextAvailableFrame++; + } + } +}; + +class EventPipe +{ + public: + + // Initialize the event pipe. + static void Initialize(); + + // Shutdown the event pipe. + static void Shutdown(); + + // Enable tracing from the start-up path based on COMPLUS variable. + static void EnableOnStartup(); + + // Enable tracing via the event pipe. + static void Enable(); + + // Disable tracing via the event pipe. + static void Disable(); + + // Determine whether or not the specified provider/keyword combination is enabled. + static bool EventEnabled(GUID& providerID, INT64 keyword); + + // Write out an event. The event is identified by the providerID/eventID pair. + // Data is written as a serialized blob matching the ETW serialization conventions. + static void WriteEvent(GUID& providerID, INT64 eventID, BYTE *pData, size_t length, bool sampleStack); + + // Write out a sample profile event with the specified stack. + static void WriteSampleProfileEvent(Thread *pThread, StackContents &stackContents); + + // Get the managed call stack for the current thread. + static bool WalkManagedStackForCurrentThread(StackContents &stackContents); + + // Get the managed call stack for the specified thread. + static bool WalkManagedStackForThread(Thread *pThread, StackContents &stackContents); + + private: + + // Callback function for the stack walker. For each frame walked, this callback is invoked. + static StackWalkAction StackWalkCallback(CrawlFrame *pCf, StackContents *pData); + + static CrstStatic s_initCrst; + static bool s_tracingInitialized; + static bool s_tracingEnabled; + static EventPipeJsonFile *s_pJsonFile; +}; + +#endif // __EVENTPIPE_H__ |