summaryrefslogtreecommitdiff
path: root/src/vm/eventpipe.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/eventpipe.h')
-rw-r--r--src/vm/eventpipe.h154
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__