Re-Factor EventSource to Support Writing to EventPipe (#11435)
[platform/upstream/coreclr.git] / src / vm / eventpipe.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 #ifndef __EVENTPIPE_H__
6 #define __EVENTPIPE_H__
7
8 #ifdef FEATURE_PERFTRACING
9
10 #include "crst.h"
11 #include "eventpipeprovider.h"
12 #include "stackwalk.h"
13
14 class EventPipeConfiguration;
15 class EventPipeEvent;
16 class EventPipeFile;
17 class EventPipeJsonFile;
18 class MethodDesc;
19 class SampleProfilerEventInstance;
20
21 class StackContents
22 {
23 private:
24
25     const static unsigned int MAX_STACK_DEPTH = 100;
26
27     // Array of IP values from a stack crawl.
28     // Top of stack is at index 0.
29     UINT_PTR m_stackFrames[MAX_STACK_DEPTH];
30
31     // Parallel array of MethodDesc pointers.
32     // Used for debug-only stack printing.
33     MethodDesc* m_methods[MAX_STACK_DEPTH];
34
35     // The next available slot in StackFrames.
36     unsigned int m_nextAvailableFrame;
37
38 public:
39
40     StackContents()
41     {
42         LIMITED_METHOD_CONTRACT;
43
44         Reset();
45     }
46
47     void Reset()
48     {
49         LIMITED_METHOD_CONTRACT;
50
51         m_nextAvailableFrame = 0;
52     }
53
54     bool IsEmpty()
55     {
56         LIMITED_METHOD_CONTRACT;
57
58         return (m_nextAvailableFrame == 0);
59     }
60
61     unsigned int GetLength()
62     {
63         LIMITED_METHOD_CONTRACT;
64
65         return m_nextAvailableFrame;
66     }
67
68     UINT_PTR GetIP(unsigned int frameIndex)
69     {
70         LIMITED_METHOD_CONTRACT;
71         _ASSERTE(frameIndex < MAX_STACK_DEPTH);
72
73         if (frameIndex >= MAX_STACK_DEPTH)
74         {
75             return 0;
76         }
77
78         return m_stackFrames[frameIndex];
79     }
80
81     MethodDesc* GetMethod(unsigned int frameIndex)
82     {
83         LIMITED_METHOD_CONTRACT;
84         _ASSERTE(frameIndex < MAX_STACK_DEPTH);
85
86         if (frameIndex >= MAX_STACK_DEPTH)
87         {
88             return NULL;
89         }
90
91         return m_methods[frameIndex];
92     }
93
94     void Append(UINT_PTR controlPC, MethodDesc *pMethod)
95     {
96         LIMITED_METHOD_CONTRACT;
97
98         if(m_nextAvailableFrame < MAX_STACK_DEPTH)
99         {
100             m_stackFrames[m_nextAvailableFrame] = controlPC;
101             m_methods[m_nextAvailableFrame] = pMethod;
102             m_nextAvailableFrame++;
103         }
104     }
105
106     BYTE* GetPointer() const
107     {
108         LIMITED_METHOD_CONTRACT;
109
110         return (BYTE*)m_stackFrames;
111     }
112
113     unsigned int GetSize() const
114     {
115         LIMITED_METHOD_CONTRACT;
116
117         return (m_nextAvailableFrame * sizeof(UINT_PTR));
118     }
119 };
120
121 class EventPipe
122 {
123     // Declare friends.
124     friend class EventPipeConfiguration;
125     friend class EventPipeFile;
126     friend class EventPipeProvider;
127     friend class SampleProfiler;
128
129     public:
130
131         // Initialize the event pipe.
132         static void Initialize();
133
134         // Shutdown the event pipe.
135         static void Shutdown();
136
137         // Enable tracing from the start-up path based on COMPLUS variable.
138         static void EnableOnStartup();
139
140         // Enable tracing via the event pipe.
141         static void Enable();
142
143         // Disable tracing via the event pipe.
144         static void Disable();
145
146         // Write out an event.
147         // Data is written as a serialized blob matching the ETW serialization conventions.
148         static void WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length);
149
150         // Write out a sample profile event.
151         static void WriteSampleProfileEvent(SampleProfilerEventInstance &instance);
152         
153         // Get the managed call stack for the current thread.
154         static bool WalkManagedStackForCurrentThread(StackContents &stackContents);
155
156         // Get the managed call stack for the specified thread.
157         static bool WalkManagedStackForThread(Thread *pThread, StackContents &stackContents);
158
159     private:
160
161         // Callback function for the stack walker.  For each frame walked, this callback is invoked.
162         static StackWalkAction StackWalkCallback(CrawlFrame *pCf, StackContents *pData);
163
164         // Get the configuration object.
165         // This is called directly by the EventPipeProvider constructor to register the new provider.
166         static EventPipeConfiguration* GetConfiguration();
167
168         // Get the event pipe configuration lock.
169         static CrstStatic* GetLock();
170
171         static CrstStatic s_configCrst;
172         static bool s_tracingInitialized;
173         static EventPipeConfiguration *s_pConfig;
174         static EventPipeFile *s_pFile;
175         static EventPipeJsonFile *s_pJsonFile;
176 };
177
178 class EventPipeInternal
179 {
180
181 public:
182
183     static INT_PTR QCALLTYPE CreateProvider(
184         GUID providerID,
185         EventPipeCallback pCallbackFunc);
186
187     static INT_PTR QCALLTYPE AddEvent(
188         INT_PTR provHandle,
189         __int64 keywords,
190         unsigned int eventID,
191         unsigned int eventVersion,
192         unsigned int level,
193         bool needStack);
194
195     static void QCALLTYPE DeleteProvider(
196         INT_PTR provHandle);
197
198     static void QCALLTYPE WriteEvent(
199         INT_PTR eventHandle,
200         void *pData,
201         unsigned int length);
202 };
203
204 #endif // FEATURE_PERFTRACING
205
206 #endif // __EVENTPIPE_H__