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.
189 s_pFile->WriteEvent(instance);
192 // Write to the EventPipeJsonFile if it exists.
193 if(s_pJsonFile != NULL)
195 s_pJsonFile->WriteEvent(instance);
199 void EventPipe::WriteSampleProfileEvent(SampleProfilerEventInstance &instance)
209 // Write to the EventPipeFile.
212 s_pFile->WriteEvent(instance);
215 // Write to the EventPipeJsonFile if it exists.
216 if(s_pJsonFile != NULL)
218 s_pJsonFile->WriteEvent(instance);
222 bool EventPipe::WalkManagedStackForCurrentThread(StackContents &stackContents)
232 Thread *pThread = GetThread();
235 return WalkManagedStackForThread(pThread, stackContents);
241 bool EventPipe::WalkManagedStackForThread(Thread *pThread, StackContents &stackContents)
248 PRECONDITION(pThread != NULL);
252 stackContents.Reset();
254 StackWalkAction swaRet = pThread->StackWalkFrames(
255 (PSTACKWALKFRAMESCALLBACK) &StackWalkCallback,
257 ALLOW_ASYNC_STACK_WALK | FUNCTIONSONLY | HANDLESKIPPEDFRAMES);
259 return ((swaRet == SWA_DONE) || (swaRet == SWA_CONTINUE));
262 StackWalkAction EventPipe::StackWalkCallback(CrawlFrame *pCf, StackContents *pData)
269 PRECONDITION(pCf != NULL);
270 PRECONDITION(pData != NULL);
275 UINT_PTR controlPC = (UINT_PTR)pCf->GetRegisterSet()->ControlPC;
278 if(pData->GetLength() == 0)
280 // This happens for pinvoke stubs on the top of the stack.
285 _ASSERTE(controlPC != 0);
287 // Add the IP to the captured stack.
293 // Continue the stack walk.
297 EventPipeConfiguration* EventPipe::GetConfiguration()
299 LIMITED_METHOD_CONTRACT;
304 CrstStatic* EventPipe::GetLock()
306 LIMITED_METHOD_CONTRACT;
308 return &s_configCrst;
311 INT_PTR QCALLTYPE EventPipeInternal::CreateProvider(
313 EventPipeCallback pCallbackFunc)
317 EventPipeProvider *pProvider = NULL;
321 pProvider = new EventPipeProvider(providerID, pCallbackFunc, NULL);
325 return reinterpret_cast<INT_PTR>(pProvider);
328 INT_PTR QCALLTYPE EventPipeInternal::AddEvent(
331 unsigned int eventID,
332 unsigned int eventVersion,
346 void QCALLTYPE EventPipeInternal::DeleteProvider(
352 if(provHandle != NULL)
354 EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider*>(provHandle);
361 void QCALLTYPE EventPipeInternal::WriteEvent(
374 #endif // FEATURE_PERFTRACING