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.
7 #include "eventpipeconfiguration.h"
8 #include "eventpipeevent.h"
9 #include "eventpipefile.h"
10 #include "eventpipeprovider.h"
11 #include "eventpipejsonfile.h"
12 #include "sampleprofiler.h"
18 #ifdef FEATURE_PERFTRACING
20 CrstStatic EventPipe::s_configCrst;
21 bool EventPipe::s_tracingInitialized = false;
22 EventPipeConfiguration* EventPipe::s_pConfig = NULL;
23 EventPipeFile* EventPipe::s_pFile = NULL;
24 EventPipeJsonFile* EventPipe::s_pJsonFile = NULL;
27 // This function is auto-generated from /src/scripts/genEventPipe.py
28 extern "C" void InitProvidersAndEvents();
31 void EventPipe::Initialize()
35 s_tracingInitialized = s_configCrst.InitNoThrow(
37 (CrstFlags)(CRST_REENTRANCY | CRST_TAKEN_DURING_SHUTDOWN));
39 s_pConfig = new EventPipeConfiguration();
40 s_pConfig->Initialize();
43 // This calls into auto-generated code to initialize the runtime providers
44 // and events so that the EventPipe configuration lock isn't taken at runtime
45 InitProvidersAndEvents();
49 void EventPipe::EnableOnStartup()
59 // Test COMPLUS variable to enable tracing at start-up.
60 if(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PerformanceTracing) != 0)
66 void EventPipe::Shutdown()
79 void EventPipe::Enable()
89 if(!s_tracingInitialized)
94 // Take the lock before enabling tracing.
95 CrstHolder _crst(GetLock());
97 // Create the event pipe file.
98 SString eventPipeFileOutputPath;
99 eventPipeFileOutputPath.Printf("Process-%d.netperf", GetCurrentProcessId());
100 s_pFile = new EventPipeFile(eventPipeFileOutputPath);
102 if(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PerformanceTracing) == 2)
104 // File placed in current working directory.
105 SString outputFilePath;
106 outputFilePath.Printf("Process-%d.PerfView.json", GetCurrentProcessId());
107 s_pJsonFile = new EventPipeJsonFile(outputFilePath);
113 // Enable the sample profiler
114 SampleProfiler::Enable();
116 // TODO: Iterate through the set of providers, enable them as appropriate.
117 // This in-turn will iterate through all of the events and set their isEnabled bits.
120 void EventPipe::Disable()
130 // Don't block GC during clean-up.
133 // Take the lock before disabling tracing.
134 CrstHolder _crst(GetLock());
136 // Disable the profiler.
137 SampleProfiler::Disable();
140 s_pConfig->Disable();
142 if(s_pJsonFile != NULL)
154 if(s_pConfig != NULL)
161 void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length)
171 // Exit early if the event is not enabled.
172 if(!event.IsEnabled())
177 DWORD threadID = GetCurrentThreadId();
179 // Create an instance of the event.
180 EventPipeEventInstance instance(
186 // Write to the EventPipeFile.
187 _ASSERTE(s_pFile != NULL);
188 s_pFile->WriteEvent(instance);
190 // Write to the EventPipeJsonFile if it exists.
191 if(s_pJsonFile != NULL)
193 s_pJsonFile->WriteEvent(instance);
197 void EventPipe::WriteSampleProfileEvent(SampleProfilerEventInstance &instance)
207 // Write to the EventPipeFile.
210 s_pFile->WriteEvent(instance);
213 // Write to the EventPipeJsonFile if it exists.
214 if(s_pJsonFile != NULL)
216 s_pJsonFile->WriteEvent(instance);
220 bool EventPipe::WalkManagedStackForCurrentThread(StackContents &stackContents)
230 Thread *pThread = GetThread();
233 return WalkManagedStackForThread(pThread, stackContents);
239 bool EventPipe::WalkManagedStackForThread(Thread *pThread, StackContents &stackContents)
246 PRECONDITION(pThread != NULL);
250 stackContents.Reset();
252 StackWalkAction swaRet = pThread->StackWalkFrames(
253 (PSTACKWALKFRAMESCALLBACK) &StackWalkCallback,
255 ALLOW_ASYNC_STACK_WALK | FUNCTIONSONLY | HANDLESKIPPEDFRAMES);
257 return ((swaRet == SWA_DONE) || (swaRet == SWA_CONTINUE));
260 StackWalkAction EventPipe::StackWalkCallback(CrawlFrame *pCf, StackContents *pData)
267 PRECONDITION(pCf != NULL);
268 PRECONDITION(pData != NULL);
273 UINT_PTR controlPC = (UINT_PTR)pCf->GetRegisterSet()->ControlPC;
276 if(pData->GetLength() == 0)
278 // This happens for pinvoke stubs on the top of the stack.
283 _ASSERTE(controlPC != 0);
285 // Add the IP to the captured stack.
291 // Continue the stack walk.
295 EventPipeConfiguration* EventPipe::GetConfiguration()
297 LIMITED_METHOD_CONTRACT;
302 CrstStatic* EventPipe::GetLock()
304 LIMITED_METHOD_CONTRACT;
306 return &s_configCrst;
309 #endif // FEATURE_PERFTRACING