eebd2744a4a66a0c09011e2a8849e2f70cc9a7ae
[platform/upstream/coreclr.git] / src / vm / eventpipe.cpp
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 #include "clrtypes.h"
6 #include "safemath.h"
7 #include "common.h"
8 #include "eventpipe.h"
9 #include "eventpipebuffermanager.h"
10 #include "eventpipeconfiguration.h"
11 #include "eventpipeevent.h"
12 #include "eventpipefile.h"
13 #include "eventpipeprovider.h"
14 #include "eventpipejsonfile.h"
15 #include "sampleprofiler.h"
16
17 #ifdef FEATURE_PAL
18 #include "pal.h"
19 #endif // FEATURE_PAL
20
21 #ifdef FEATURE_PERFTRACING
22
23 CrstStatic EventPipe::s_configCrst;
24 bool EventPipe::s_tracingInitialized = false;
25 EventPipeConfiguration* EventPipe::s_pConfig = NULL;
26 EventPipeBufferManager* EventPipe::s_pBufferManager = NULL;
27 EventPipeFile* EventPipe::s_pFile = NULL;
28 #ifdef _DEBUG
29 EventPipeFile* EventPipe::s_pSyncFile = NULL;
30 EventPipeJsonFile* EventPipe::s_pJsonFile = NULL;
31 #endif // _DEBUG
32
33 #ifdef FEATURE_PAL
34 // This function is auto-generated from /src/scripts/genEventPipe.py
35 extern "C" void InitProvidersAndEvents();
36 #endif
37
38 #ifdef FEATURE_PAL
39 // This function is auto-generated from /src/scripts/genEventPipe.py
40 extern "C" void InitProvidersAndEvents();
41 #endif
42
43 EventPipeEventPayload::EventPipeEventPayload(BYTE *pData, unsigned int length)
44 {
45     CONTRACTL
46     {
47         NOTHROW;
48         GC_NOTRIGGER;
49         MODE_ANY;
50     }
51     CONTRACTL_END;
52
53     m_pData = pData;
54     m_pEventData = NULL;
55     m_eventDataCount = 0;
56     m_allocatedData = false;
57
58     m_size = length;
59 }
60
61 EventPipeEventPayload::EventPipeEventPayload(EventData **pEventData, unsigned int eventDataCount)
62 {
63     CONTRACTL
64     {
65         NOTHROW;
66         GC_NOTRIGGER;
67         MODE_ANY;
68     }
69     CONTRACTL_END;
70
71     m_pData = NULL;
72     m_pEventData = pEventData;
73     m_eventDataCount = eventDataCount;
74     m_allocatedData = false;
75
76     S_UINT32 tmp_size = S_UINT32(0);
77     for (unsigned int i=0; i<m_eventDataCount; i++)
78     {
79         tmp_size += S_UINT32((*m_pEventData)[i].Size);
80     }
81
82     if (tmp_size.IsOverflow())
83     {
84         // If there is an overflow, drop the data and create an empty payload
85         m_pEventData = NULL;
86         m_eventDataCount = 0;
87         m_size = 0;
88     }
89     else
90     {
91         m_size = tmp_size.Value();
92     }
93 }
94
95 EventPipeEventPayload::~EventPipeEventPayload()
96 {
97     CONTRACTL
98     {
99         NOTHROW;
100         GC_TRIGGERS;
101         MODE_ANY;
102     }
103     CONTRACTL_END;
104
105     if(m_allocatedData && m_pData != NULL)
106     {
107         delete[] m_pData;
108         m_pData = NULL;
109     }
110 }
111
112 void EventPipeEventPayload::Flatten()
113 {
114     CONTRACTL
115     {
116         NOTHROW;
117         GC_TRIGGERS;
118         MODE_ANY;
119     }
120     CONTRACTL_END;
121
122     if(m_size > 0)
123     {
124         if (!IsFlattened())
125         {
126             BYTE* tmp_pData = new (nothrow) BYTE[m_size];
127             if (tmp_pData != NULL)
128             {
129                 m_allocatedData = true;
130                 CopyData(tmp_pData);
131                 m_pData = tmp_pData;
132             }
133         }
134     }
135 }
136
137 void EventPipeEventPayload::CopyData(BYTE *pDst)
138 {
139     CONTRACTL
140     {
141         NOTHROW;
142         GC_NOTRIGGER;
143         MODE_ANY;
144     }
145     CONTRACTL_END;
146
147     if(m_size > 0)
148     {
149         if(IsFlattened())
150         {
151             memcpy(pDst, m_pData, m_size);
152         }
153
154         else if(m_pEventData != NULL)
155         {
156             unsigned int offset = 0;
157             for(unsigned int i=0; i<m_eventDataCount; i++)
158             {
159                 memcpy(pDst + offset, (BYTE*)(*m_pEventData)[i].Ptr, (*m_pEventData)[i].Size);
160                 offset += (*m_pEventData)[i].Size;
161             }
162         }
163     }
164 }
165
166 BYTE* EventPipeEventPayload::GetFlatData()
167 {
168     CONTRACTL
169     {
170         NOTHROW;
171         GC_TRIGGERS;
172         MODE_ANY;
173     }
174     CONTRACTL_END;
175
176     if (!IsFlattened())
177     {
178         Flatten();
179     }
180     return m_pData;
181 }
182
183 void EventPipe::Initialize()
184 {
185     STANDARD_VM_CONTRACT;
186
187     s_tracingInitialized = s_configCrst.InitNoThrow(
188         CrstEventPipe,
189         (CrstFlags)(CRST_REENTRANCY | CRST_TAKEN_DURING_SHUTDOWN | CRST_HOST_BREAKABLE));
190
191     s_pConfig = new EventPipeConfiguration();
192     s_pConfig->Initialize();
193
194     s_pBufferManager = new EventPipeBufferManager();
195
196 #ifdef FEATURE_PAL
197     // This calls into auto-generated code to initialize the runtime providers
198     // and events so that the EventPipe configuration lock isn't taken at runtime
199     InitProvidersAndEvents();
200 #endif
201 }
202
203 void EventPipe::EnableOnStartup()
204 {
205     CONTRACTL
206     {
207         THROWS;
208         GC_TRIGGERS;
209         MODE_ANY;
210     }
211     CONTRACTL_END;
212
213     // Test COMPLUS variable to enable tracing at start-up.
214     if((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PerformanceTracing) & 1) == 1)
215     {
216         SString outputPath;
217         outputPath.Printf("Process-%d.netperf", GetCurrentProcessId());
218         Enable(
219             outputPath.GetUnicode(),
220             1024 /* 1 GB circular buffer */,
221             NULL /* pProviders */,
222             0 /* numProviders */);
223     }
224 }
225
226 void EventPipe::Shutdown()
227 {
228     CONTRACTL
229     {
230         THROWS;
231         GC_TRIGGERS;
232         MODE_ANY;
233     }
234     CONTRACTL_END;
235
236     Disable();
237
238     if(s_pConfig != NULL)
239     {
240         delete(s_pConfig);
241         s_pConfig = NULL;
242     }
243     if(s_pBufferManager != NULL)
244     {
245         delete(s_pBufferManager);
246         s_pBufferManager = NULL;
247     }
248 }
249
250 void EventPipe::Enable(
251     LPCWSTR strOutputPath,
252     unsigned int circularBufferSizeInMB,
253     EventPipeProviderConfiguration *pProviders,
254     int numProviders)
255 {
256     CONTRACTL
257     {
258         THROWS;
259         GC_TRIGGERS;
260         MODE_ANY;
261     }
262     CONTRACTL_END;
263
264     // If tracing is not initialized or is already enabled, bail here.
265     if(!s_tracingInitialized || s_pConfig->Enabled())
266     {
267         return;
268     }
269
270     // Take the lock before enabling tracing.
271     CrstHolder _crst(GetLock());
272
273     // Create the event pipe file.
274     SString eventPipeFileOutputPath(strOutputPath);
275     s_pFile = new EventPipeFile(eventPipeFileOutputPath);
276
277 #ifdef _DEBUG
278     if((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PerformanceTracing) & 2) == 2)
279     {
280         // Create a synchronous file.
281         SString eventPipeSyncFileOutputPath;
282         eventPipeSyncFileOutputPath.Printf("Process-%d.sync.netperf", GetCurrentProcessId());
283         s_pSyncFile = new EventPipeFile(eventPipeSyncFileOutputPath);
284
285         // Create a JSON file.
286         SString outputFilePath;
287         outputFilePath.Printf("Process-%d.PerfView.json", GetCurrentProcessId());
288         s_pJsonFile = new EventPipeJsonFile(outputFilePath);
289     }
290 #endif // _DEBUG
291
292     // Enable tracing.
293     s_pConfig->Enable(circularBufferSizeInMB, pProviders, numProviders);
294
295     // Enable the sample profiler
296     SampleProfiler::Enable();
297 }
298
299 void EventPipe::Disable()
300 {
301     CONTRACTL
302     {
303         THROWS;
304         GC_TRIGGERS;
305         MODE_ANY;
306     }
307     CONTRACTL_END;
308
309     // Don't block GC during clean-up.
310     GCX_PREEMP();
311
312     // Take the lock before disabling tracing.
313     CrstHolder _crst(GetLock());
314
315     if(s_pConfig->Enabled())
316     {
317         // Disable the profiler.
318         SampleProfiler::Disable();
319
320         // Disable tracing.
321         s_pConfig->Disable();
322
323         // Flush all write buffers to make sure that all threads see the change.
324         FlushProcessWriteBuffers();
325
326         // Write to the file.
327         LARGE_INTEGER disableTimeStamp;
328         QueryPerformanceCounter(&disableTimeStamp);
329         s_pBufferManager->WriteAllBuffersToFile(s_pFile, disableTimeStamp);
330
331         // Before closing the file, do rundown.
332         s_pConfig->EnableRundown();
333
334         // Ask the runtime to emit rundown events.
335         if(g_fEEStarted && !g_fEEShutDown)
336         {
337             ETW::EnumerationLog::EndRundown();
338         }
339
340         // Disable the event pipe now that rundown is complete.
341         s_pConfig->Disable();
342
343         if(s_pFile != NULL)
344         {
345             delete(s_pFile);
346             s_pFile = NULL;
347         }
348 #ifdef _DEBUG
349         if(s_pSyncFile != NULL)
350         {
351             delete(s_pSyncFile);
352             s_pSyncFile = NULL;
353         }
354         if(s_pJsonFile != NULL)
355         {
356             delete(s_pJsonFile);
357             s_pJsonFile = NULL;
358         }
359 #endif // _DEBUG
360
361         // De-allocate buffers.
362         s_pBufferManager->DeAllocateBuffers();
363
364         // Delete deferred providers.
365         // Providers can't be deleted during tracing because they may be needed when serializing the file.
366         s_pConfig->DeleteDeferredProviders();
367     }
368 }
369
370 bool EventPipe::Enabled()
371 {
372     LIMITED_METHOD_CONTRACT;
373
374     bool enabled = false;
375     if(s_pConfig != NULL)
376     {
377         enabled = s_pConfig->Enabled();
378     }
379
380     return enabled;
381 }
382
383 EventPipeProvider* EventPipe::CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction, void *pCallbackData)
384 {
385     CONTRACTL
386     {
387         THROWS;
388         GC_TRIGGERS;
389         MODE_ANY;
390     }
391     CONTRACTL_END;
392
393     return new EventPipeProvider(providerName, pCallbackFunction, pCallbackData);
394 }
395
396 void EventPipe::DeleteProvider(EventPipeProvider *pProvider)
397 {
398     CONTRACTL
399     {
400         THROWS;
401         GC_TRIGGERS;
402         MODE_ANY;
403     }
404     CONTRACTL_END;
405
406     // Take the lock to make sure that we don't have a race
407     // between disabling tracing and deleting a provider
408     // where we hold a provider after tracing has been disabled.
409     CrstHolder _crst(GetLock());
410
411     if(pProvider != NULL)
412     {
413         if(Enabled())
414         {
415             // Save the provider until the end of the tracing session.
416             pProvider->SetDeleteDeferred();
417         }
418         else
419         {
420             // Delete the provider now.
421             // NOTE: This will remove it from all of the EventPipe data structures.
422             delete(pProvider);
423         }
424     }
425 }
426
427 void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length, LPCGUID pActivityId, LPCGUID pRelatedActivityId)
428 {
429     CONTRACTL
430     {
431         NOTHROW;
432         GC_NOTRIGGER;
433         MODE_ANY;
434     }
435     CONTRACTL_END;
436
437     EventPipeEventPayload payload(pData, length);
438     EventPipe::WriteEventInternal(event, payload, pActivityId, pRelatedActivityId);
439 }
440
441 void EventPipe::WriteEvent(EventPipeEvent &event, EventData **pEventData, unsigned int eventDataCount, LPCGUID pActivityId, LPCGUID pRelatedActivityId)
442 {
443     CONTRACTL
444     {
445         NOTHROW;
446         GC_NOTRIGGER;
447         MODE_ANY;
448     }
449     CONTRACTL_END;
450
451     EventPipeEventPayload payload(pEventData, eventDataCount);
452     EventPipe::WriteEventInternal(event, payload, pActivityId, pRelatedActivityId);
453 }
454
455 void EventPipe::WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload &payload, LPCGUID pActivityId, LPCGUID pRelatedActivityId)
456 {
457     CONTRACTL
458     {
459         NOTHROW;
460         GC_NOTRIGGER;
461         MODE_ANY;
462         PRECONDITION(s_pBufferManager != NULL);
463     }
464     CONTRACTL_END;
465
466     // Exit early if the event is not enabled.
467     if(!event.IsEnabled())
468     {
469         return;
470     }
471
472     // Get the current thread;
473     Thread *pThread = GetThread();
474     if(pThread == NULL)
475     {
476         // We can't write an event without the thread object.
477         return;
478     }
479
480     if(!s_pConfig->RundownEnabled() && s_pBufferManager != NULL)
481     {
482         if(!s_pBufferManager->WriteEvent(pThread, event, payload, pActivityId, pRelatedActivityId))
483         {
484             // This is used in DEBUG to make sure that we don't log an event synchronously that we didn't log to the buffer.
485             return;
486         }
487     }
488     else if(s_pConfig->RundownEnabled())
489     {
490         BYTE *pData = payload.GetFlatData();
491         if (pData != NULL)
492         {
493             // Write synchronously to the file.
494             // We're under lock and blocking the disabling thread.
495             EventPipeEventInstance instance(
496                 event,
497                 pThread->GetOSThreadId(),
498                 pData,
499                 payload.GetSize(),
500                 pActivityId,
501                 pRelatedActivityId);
502
503             if(s_pFile != NULL)
504             {
505                 s_pFile->WriteEvent(instance);
506             }
507         }
508     }
509
510 #ifdef _DEBUG
511     {
512         GCX_PREEMP();
513
514         BYTE *pData = payload.GetFlatData();
515         if (pData != NULL)
516         {
517             // Create an instance of the event for the synchronous path.
518             EventPipeEventInstance instance(
519                 event,
520                 pThread->GetOSThreadId(),
521                 pData,
522                 payload.GetSize(),
523                 pActivityId,
524                 pRelatedActivityId);
525
526             // Write to the EventPipeFile if it exists.
527             if(s_pSyncFile != NULL)
528             {
529                 s_pSyncFile->WriteEvent(instance);
530             }
531  
532             // Write to the EventPipeJsonFile if it exists.
533             if(s_pJsonFile != NULL)
534             {
535                 s_pJsonFile->WriteEvent(instance);
536             }
537         }
538     }
539 #endif // _DEBUG
540 }
541
542 void EventPipe::WriteSampleProfileEvent(Thread *pSamplingThread, EventPipeEvent *pEvent, Thread *pTargetThread, StackContents &stackContents, BYTE *pData, unsigned int length)
543 {
544     CONTRACTL
545     {
546         NOTHROW;
547         GC_TRIGGERS;
548         MODE_PREEMPTIVE;
549     }
550     CONTRACTL_END;
551
552     EventPipeEventPayload payload(pData, length);
553
554     // Write the event to the thread's buffer.
555     if(s_pBufferManager != NULL)
556     {
557         // Specify the sampling thread as the "current thread", so that we select the right buffer.
558         // Specify the target thread so that the event gets properly attributed.
559         if(!s_pBufferManager->WriteEvent(pSamplingThread, *pEvent, payload, NULL /* pActivityId */, NULL /* pRelatedActivityId */, pTargetThread, &stackContents))
560         {
561             // This is used in DEBUG to make sure that we don't log an event synchronously that we didn't log to the buffer.
562             return;
563         }
564     }
565
566 #ifdef _DEBUG
567     {
568         GCX_PREEMP();
569
570         // Create an instance for the synchronous path.
571         SampleProfilerEventInstance instance(*pEvent, pTargetThread, pData, length);
572         stackContents.CopyTo(instance.GetStack());
573
574         // Write to the EventPipeFile.
575         if(s_pSyncFile != NULL)
576         {
577             s_pSyncFile->WriteEvent(instance);
578         }
579
580         // Write to the EventPipeJsonFile if it exists.
581         if(s_pJsonFile != NULL)
582         {
583             s_pJsonFile->WriteEvent(instance);
584         }
585     }
586 #endif // _DEBUG
587 }
588
589 bool EventPipe::WalkManagedStackForCurrentThread(StackContents &stackContents)
590 {
591     CONTRACTL
592     {
593         NOTHROW;
594         GC_NOTRIGGER;
595         MODE_ANY;
596     }
597     CONTRACTL_END;
598
599     Thread *pThread = GetThread();
600     if(pThread != NULL)
601     {
602         return WalkManagedStackForThread(pThread, stackContents);
603     }
604
605     return false;
606 }
607
608 bool EventPipe::WalkManagedStackForThread(Thread *pThread, StackContents &stackContents)
609 {
610     CONTRACTL
611     {
612         NOTHROW;
613         GC_NOTRIGGER;
614         MODE_ANY;
615         PRECONDITION(pThread != NULL);
616     }
617     CONTRACTL_END;
618
619     stackContents.Reset();
620
621     StackWalkAction swaRet = pThread->StackWalkFrames(
622         (PSTACKWALKFRAMESCALLBACK) &StackWalkCallback,
623         &stackContents,
624         ALLOW_ASYNC_STACK_WALK | FUNCTIONSONLY | HANDLESKIPPEDFRAMES);
625
626     return ((swaRet == SWA_DONE) || (swaRet == SWA_CONTINUE));
627 }
628
629 StackWalkAction EventPipe::StackWalkCallback(CrawlFrame *pCf, StackContents *pData)
630 {
631     CONTRACTL
632     {
633         NOTHROW;
634         GC_NOTRIGGER;
635         MODE_PREEMPTIVE;
636         PRECONDITION(pCf != NULL);
637         PRECONDITION(pData != NULL);
638     }
639     CONTRACTL_END;
640
641     // Get the IP.
642     UINT_PTR controlPC = (UINT_PTR)pCf->GetRegisterSet()->ControlPC;
643     if(controlPC == 0)
644     {
645         if(pData->GetLength() == 0)
646         {
647             // This happens for pinvoke stubs on the top of the stack.
648             return SWA_CONTINUE;
649         }
650     }
651
652     _ASSERTE(controlPC != 0);
653
654     // Add the IP to the captured stack.
655     pData->Append(
656         controlPC,
657         pCf->GetFunction()
658         );
659
660     // Continue the stack walk.
661     return SWA_CONTINUE;
662 }
663
664 EventPipeConfiguration* EventPipe::GetConfiguration()
665 {
666     LIMITED_METHOD_CONTRACT;
667
668     return s_pConfig;
669 }
670
671 CrstStatic* EventPipe::GetLock()
672 {
673     LIMITED_METHOD_CONTRACT;
674
675     return &s_configCrst;
676 }
677
678 void QCALLTYPE EventPipeInternal::Enable(
679         __in_z LPCWSTR outputFile,
680         unsigned int circularBufferSizeInMB,
681         long profilerSamplingRateInNanoseconds,
682         EventPipeProviderConfiguration *pProviders,
683         int numProviders)
684 {
685     QCALL_CONTRACT;
686
687     BEGIN_QCALL;
688     SampleProfiler::SetSamplingRate(profilerSamplingRateInNanoseconds);
689     EventPipe::Enable(outputFile, circularBufferSizeInMB, pProviders, numProviders);
690     END_QCALL;
691 }
692
693 void QCALLTYPE EventPipeInternal::Disable()
694 {
695     QCALL_CONTRACT;
696
697     BEGIN_QCALL;
698     EventPipe::Disable();
699     END_QCALL;
700 }
701
702 INT_PTR QCALLTYPE EventPipeInternal::CreateProvider(
703     __in_z LPCWSTR providerName,
704     EventPipeCallback pCallbackFunc)
705 {
706     QCALL_CONTRACT;
707
708     EventPipeProvider *pProvider = NULL;
709
710     BEGIN_QCALL;
711
712     pProvider = EventPipe::CreateProvider(providerName, pCallbackFunc, NULL);
713
714     END_QCALL;
715
716     return reinterpret_cast<INT_PTR>(pProvider);
717 }
718
719 INT_PTR QCALLTYPE EventPipeInternal::DefineEvent(
720     INT_PTR provHandle,
721     unsigned int eventID,
722     __int64 keywords,
723     unsigned int eventVersion,
724     unsigned int level,
725     void *pMetadata,
726     unsigned int metadataLength)
727 {
728     QCALL_CONTRACT;
729
730     EventPipeEvent *pEvent = NULL;
731
732     BEGIN_QCALL;
733
734     _ASSERTE(provHandle != NULL);
735     _ASSERTE(pMetadata != NULL);
736     EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider *>(provHandle);
737     pEvent = pProvider->AddEvent(eventID, keywords, eventVersion, (EventPipeEventLevel)level, (BYTE *)pMetadata, metadataLength);
738     _ASSERTE(pEvent != NULL);
739
740     END_QCALL;
741
742     return reinterpret_cast<INT_PTR>(pEvent);
743 }
744
745 void QCALLTYPE EventPipeInternal::DeleteProvider(
746     INT_PTR provHandle)
747 {
748     QCALL_CONTRACT;
749     BEGIN_QCALL;
750
751     if(provHandle != NULL)
752     {
753         EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider*>(provHandle);
754         EventPipe::DeleteProvider(pProvider);
755     }
756
757     END_QCALL;
758 }
759
760 void QCALLTYPE EventPipeInternal::WriteEvent(
761     INT_PTR eventHandle,
762     unsigned int eventID,
763     void *pData,
764     unsigned int length,
765     LPCGUID pActivityId,
766     LPCGUID pRelatedActivityId)
767 {
768     QCALL_CONTRACT;
769     BEGIN_QCALL;
770
771     _ASSERTE(eventHandle != NULL);
772     EventPipeEvent *pEvent = reinterpret_cast<EventPipeEvent *>(eventHandle);
773     EventPipe::WriteEvent(*pEvent, (BYTE *)pData, length, pActivityId, pRelatedActivityId);
774
775     END_QCALL;
776 }
777
778 void QCALLTYPE EventPipeInternal::WriteEventData(
779     INT_PTR eventHandle,
780     unsigned int eventID,
781     EventData **pEventData,
782     unsigned int eventDataCount,
783     LPCGUID pActivityId,
784     LPCGUID pRelatedActivityId)
785 {
786     QCALL_CONTRACT;
787     BEGIN_QCALL;
788
789     _ASSERTE(eventHandle != NULL);
790     EventPipeEvent *pEvent = reinterpret_cast<EventPipeEvent *>(eventHandle);
791     EventPipe::WriteEvent(*pEvent, pEventData, eventDataCount, pActivityId, pRelatedActivityId);
792
793     END_QCALL;
794 }
795
796 #endif // FEATURE_PERFTRACING