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.
9 #include "eventpipebuffermanager.h"
10 #include "eventpipeconfiguration.h"
11 #include "eventpipeevent.h"
12 #include "eventpipeeventsource.h"
13 #include "eventpipefile.h"
14 #include "eventpipeprovider.h"
15 #include "eventpipesession.h"
16 #include "eventpipejsonfile.h"
17 #include "eventtracebase.h"
18 #include "sampleprofiler.h"
24 #ifdef FEATURE_PERFTRACING
26 CrstStatic EventPipe::s_configCrst;
27 bool EventPipe::s_tracingInitialized = false;
28 EventPipeConfiguration* EventPipe::s_pConfig = NULL;
29 EventPipeSession* EventPipe::s_pSession = NULL;
30 EventPipeBufferManager* EventPipe::s_pBufferManager = NULL;
31 EventPipeFile* EventPipe::s_pFile = NULL;
32 EventPipeEventSource* EventPipe::s_pEventSource = NULL;
33 LPCWSTR EventPipe::s_pCommandLine = NULL;
35 EventPipeFile* EventPipe::s_pSyncFile = NULL;
36 EventPipeJsonFile* EventPipe::s_pJsonFile = NULL;
40 // This function is auto-generated from /src/scripts/genEventPipe.py
41 extern "C" void InitProvidersAndEvents();
43 void InitProvidersAndEvents();
46 EventPipeEventPayload::EventPipeEventPayload(BYTE *pData, unsigned int length)
59 m_allocatedData = false;
64 EventPipeEventPayload::EventPipeEventPayload(EventData *pEventData, unsigned int eventDataCount)
75 m_pEventData = pEventData;
76 m_eventDataCount = eventDataCount;
77 m_allocatedData = false;
79 S_UINT32 tmp_size = S_UINT32(0);
80 for (unsigned int i=0; i<m_eventDataCount; i++)
82 tmp_size += S_UINT32(m_pEventData[i].Size);
85 if (tmp_size.IsOverflow())
87 // If there is an overflow, drop the data and create an empty payload
94 m_size = tmp_size.Value();
98 EventPipeEventPayload::~EventPipeEventPayload()
108 if(m_allocatedData && m_pData != NULL)
115 void EventPipeEventPayload::Flatten()
129 BYTE* tmp_pData = new (nothrow) BYTE[m_size];
130 if (tmp_pData != NULL)
132 m_allocatedData = true;
140 void EventPipeEventPayload::CopyData(BYTE *pDst)
154 memcpy(pDst, m_pData, m_size);
157 else if(m_pEventData != NULL)
159 unsigned int offset = 0;
160 for(unsigned int i=0; i<m_eventDataCount; i++)
162 memcpy(pDst + offset, (BYTE*) m_pEventData[i].Ptr, m_pEventData[i].Size);
163 offset += m_pEventData[i].Size;
169 BYTE* EventPipeEventPayload::GetFlatData()
186 void EventPipe::Initialize()
188 STANDARD_VM_CONTRACT;
190 s_tracingInitialized = s_configCrst.InitNoThrow(
192 (CrstFlags)(CRST_REENTRANCY | CRST_TAKEN_DURING_SHUTDOWN | CRST_HOST_BREAKABLE));
194 s_pConfig = new EventPipeConfiguration();
195 s_pConfig->Initialize();
197 s_pBufferManager = new EventPipeBufferManager();
199 s_pEventSource = new EventPipeEventSource();
201 // This calls into auto-generated code to initialize the runtime providers
202 // and events so that the EventPipe configuration lock isn't taken at runtime
203 InitProvidersAndEvents();
206 void EventPipe::EnableOnStartup()
216 // Test COMPLUS variable to enable tracing at start-up.
217 if((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EnableEventPipe) & 1) == 1)
220 outputPath.Printf("Process-%d.netperf", GetCurrentProcessId());
222 // Create a new session.
223 EventPipeSession *pSession = new EventPipeSession(
224 EventPipeSessionType::File,
225 1024 /* 1 GB circular buffer */,
226 NULL, /* pProviders */
227 0 /* numProviders */);
229 // Get the configuration from the environment.
230 GetConfigurationFromEnvironment(outputPath, pSession);
232 // Enable the session.
233 Enable(outputPath, pSession);
237 void EventPipe::Shutdown()
247 // Mark tracing as no longer initialized.
248 s_tracingInitialized = false;
250 // We are shutting down, so if disabling EventPipe throws, we need to move along anyway.
256 EX_END_CATCH(SwallowAllExceptions);
258 // Save pointers to the configuration and buffer manager.
259 EventPipeConfiguration *pConfig = s_pConfig;
260 EventPipeBufferManager *pBufferManager = s_pBufferManager;
262 // Set the static pointers to NULL so that the rest of the EventPipe knows that they are no longer available.
263 // Flush process write buffers to make sure other threads can see the change.
265 s_pBufferManager = NULL;
266 FlushProcessWriteBuffers();
270 delete(pBufferManager);
271 delete(s_pEventSource);
272 s_pEventSource = NULL;
274 // On Windows, this is just a pointer to the return value from
275 // GetCommandLineW(), so don't attempt to free it.
277 delete[](s_pCommandLine);
278 s_pCommandLine = NULL;
282 void EventPipe::Enable(
283 LPCWSTR strOutputPath,
284 unsigned int circularBufferSizeInMB,
285 EventPipeProviderConfiguration *pProviders,
296 // Create a new session.
297 EventPipeSession *pSession = s_pConfig->CreateSession(
298 (strOutputPath != NULL) ? EventPipeSessionType::File : EventPipeSessionType::Streaming,
299 circularBufferSizeInMB,
301 static_cast<unsigned int>(numProviders));
303 // Enable the session.
304 Enable(strOutputPath, pSession);
307 void EventPipe::Enable(LPCWSTR strOutputPath, EventPipeSession *pSession)
314 PRECONDITION(pSession != NULL);
318 // If tracing is not initialized or is already enabled, bail here.
319 if(!s_tracingInitialized || s_pConfig == NULL || s_pConfig->Enabled())
324 // If the state or arguments are invalid, bail here.
325 if(pSession == NULL || !pSession->IsValid())
330 // Enable the EventPipe EventSource.
331 s_pEventSource->Enable(pSession);
333 // Take the lock before enabling tracing.
334 CrstHolder _crst(GetLock());
336 // Create the event pipe file.
337 // A NULL output path means that we should not write the results to a file.
338 // This is used in the EventListener streaming case.
339 if (strOutputPath != NULL)
341 SString eventPipeFileOutputPath(strOutputPath);
342 s_pFile = new EventPipeFile(eventPipeFileOutputPath);
346 if((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EnableEventPipe) & 2) == 2)
348 // Create a synchronous file.
349 SString eventPipeSyncFileOutputPath;
350 eventPipeSyncFileOutputPath.Printf("Process-%d.sync.netperf", GetCurrentProcessId());
351 s_pSyncFile = new EventPipeFile(eventPipeSyncFileOutputPath);
353 // Create a JSON file.
354 SString outputFilePath;
355 outputFilePath.Printf("Process-%d.PerfView.json", GetCurrentProcessId());
356 s_pJsonFile = new EventPipeJsonFile(outputFilePath);
361 s_pSession = pSession;
364 s_pConfig->Enable(s_pSession);
366 // Enable the sample profiler
367 SampleProfiler::Enable();
370 void EventPipe::Disable()
380 // Don't block GC during clean-up.
383 // Take the lock before disabling tracing.
384 CrstHolder _crst(GetLock());
386 if(s_pConfig != NULL && s_pConfig->Enabled())
388 // Disable the profiler.
389 SampleProfiler::Disable();
391 // Log the process information event.
392 s_pEventSource->SendProcessInfo(s_pCommandLine);
394 // Log the runtime information event.
395 ETW::InfoLog::RuntimeInformation(ETW::InfoLog::InfoStructs::Normal);
398 s_pConfig->Disable(s_pSession);
400 // Delete the session.
401 s_pConfig->DeleteSession(s_pSession);
404 // Flush all write buffers to make sure that all threads see the change.
405 FlushProcessWriteBuffers();
407 // Write to the file.
410 LARGE_INTEGER disableTimeStamp;
411 QueryPerformanceCounter(&disableTimeStamp);
412 s_pBufferManager->WriteAllBuffersToFile(s_pFile, disableTimeStamp);
414 if(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeRundown) > 0)
416 // Before closing the file, do rundown.
417 const unsigned int numRundownProviders = 2;
418 EventPipeProviderConfiguration rundownProviders[] =
420 { W("Microsoft-Windows-DotNETRuntime"), 0x80020138, static_cast<unsigned int>(EventPipeEventLevel::Verbose) }, // Public provider.
421 { W("Microsoft-Windows-DotNETRuntimeRundown"), 0x80020138, static_cast<unsigned int>(EventPipeEventLevel::Verbose) } // Rundown provider.
423 // The circular buffer size doesn't matter because all events are written synchronously during rundown.
424 s_pSession = s_pConfig->CreateSession(EventPipeSessionType::File, 1 /* circularBufferSizeInMB */, rundownProviders, numRundownProviders);
425 s_pConfig->EnableRundown(s_pSession);
427 // Ask the runtime to emit rundown events.
428 if(g_fEEStarted && !g_fEEShutDown)
430 ETW::EnumerationLog::EndRundown();
433 // Disable the event pipe now that rundown is complete.
434 s_pConfig->Disable(s_pSession);
436 // Delete the rundown session.
437 s_pConfig->DeleteSession(s_pSession);
445 if(s_pSyncFile != NULL)
450 if(s_pJsonFile != NULL)
457 // De-allocate buffers.
458 s_pBufferManager->DeAllocateBuffers();
460 // Delete deferred providers.
461 // Providers can't be deleted during tracing because they may be needed when serializing the file.
462 s_pConfig->DeleteDeferredProviders();
466 bool EventPipe::Enabled()
468 LIMITED_METHOD_CONTRACT;
470 bool enabled = false;
471 if(s_pConfig != NULL)
473 enabled = s_pConfig->Enabled();
479 EventPipeProvider* EventPipe::CreateProvider(const SString &providerName, EventPipeCallback pCallbackFunction, void *pCallbackData)
489 EventPipeProvider *pProvider = NULL;
490 if (s_pConfig != NULL)
492 pProvider = s_pConfig->CreateProvider(providerName, pCallbackFunction, pCallbackData);
499 EventPipeProvider* EventPipe::GetProvider(const SString &providerName)
509 EventPipeProvider *pProvider = NULL;
510 if (s_pConfig != NULL)
512 pProvider = s_pConfig->GetProvider(providerName);
518 void EventPipe::DeleteProvider(EventPipeProvider *pProvider)
528 // Take the lock to make sure that we don't have a race
529 // between disabling tracing and deleting a provider
530 // where we hold a provider after tracing has been disabled.
531 CrstHolder _crst(GetLock());
533 if(pProvider != NULL)
537 // Save the provider until the end of the tracing session.
538 pProvider->SetDeleteDeferred();
542 // Delete the provider now.
543 if (s_pConfig != NULL)
545 s_pConfig->DeleteProvider(pProvider);
551 void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length, LPCGUID pActivityId, LPCGUID pRelatedActivityId)
561 EventPipeEventPayload payload(pData, length);
562 EventPipe::WriteEventInternal(event, payload, pActivityId, pRelatedActivityId);
565 void EventPipe::WriteEvent(EventPipeEvent &event, EventData *pEventData, unsigned int eventDataCount, LPCGUID pActivityId, LPCGUID pRelatedActivityId)
575 EventPipeEventPayload payload(pEventData, eventDataCount);
576 EventPipe::WriteEventInternal(event, payload, pActivityId, pRelatedActivityId);
579 void EventPipe::WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload &payload, LPCGUID pActivityId, LPCGUID pRelatedActivityId)
589 // Exit early if the event is not enabled.
590 if(!event.IsEnabled())
595 // Get the current thread;
596 Thread *pThread = GetThread();
599 // We can't write an event without the thread object.
603 if(s_pConfig == NULL)
605 // We can't procede without a configuration
608 _ASSERTE(s_pSession != NULL);
610 // If the activity id isn't specified, pull it from the current thread.
611 if(pActivityId == NULL)
613 pActivityId = pThread->GetActivityId();
616 if(!s_pConfig->RundownEnabled() && s_pBufferManager != NULL)
618 if(!s_pBufferManager->WriteEvent(pThread, *s_pSession, event, payload, pActivityId, pRelatedActivityId))
620 // This is used in DEBUG to make sure that we don't log an event synchronously that we didn't log to the buffer.
624 else if(s_pConfig->RundownEnabled())
626 // It is possible that some events that are enabled on rundown can be emitted from other threads.
627 // We're not interested in these events and they can cause corrupted trace files because rundown
628 // events are written synchronously and not under lock.
629 // If we encounter an event that did not originate on the thread that is doing rundown, ignore it.
630 if(!s_pConfig->IsRundownThread(pThread))
635 BYTE *pData = payload.GetFlatData();
638 // Write synchronously to the file.
639 // We're under lock and blocking the disabling thread.
640 // This copy occurs here (rather than at file write) because
641 // A) The FastSerializer API would need to change if we waited
642 // B) It is unclear there is a benefit to multiple file write calls
643 // as opposed a a buffer copy here
644 EventPipeEventInstance instance(
647 pThread->GetOSThreadId(),
655 // EventPipeFile::WriteEvent needs to allocate a metadata event
656 // and can therefore throw. In this context we will silently
657 // fail rather than disrupt the caller
660 s_pFile->WriteEvent(instance);
663 EX_END_CATCH(SwallowAllExceptions);
668 // This section requires a call to GCX_PREEMP which violates the GC_NOTRIGGER contract
669 // It should only be enabled when debugging this specific component and contracts are off
670 #ifdef DEBUG_JSON_EVENT_FILE
674 BYTE *pData = payload.GetFlatData();
677 // Create an instance of the event for the synchronous path.
678 EventPipeEventInstance instance(
680 pThread->GetOSThreadId(),
686 // Write to the EventPipeFile if it exists.
687 if(s_pSyncFile != NULL)
689 s_pSyncFile->WriteEvent(instance);
692 // Write to the EventPipeJsonFile if it exists.
693 if(s_pJsonFile != NULL)
695 s_pJsonFile->WriteEvent(instance);
699 #endif // DEBUG_JSON_EVENT_FILE
702 void EventPipe::WriteSampleProfileEvent(Thread *pSamplingThread, EventPipeEvent *pEvent, Thread *pTargetThread, StackContents &stackContents, BYTE *pData, unsigned int length)
712 EventPipeEventPayload payload(pData, length);
714 // Write the event to the thread's buffer.
715 if(s_pBufferManager != NULL)
717 // Specify the sampling thread as the "current thread", so that we select the right buffer.
718 // Specify the target thread so that the event gets properly attributed.
719 if(!s_pBufferManager->WriteEvent(pSamplingThread, *s_pSession, *pEvent, payload, NULL /* pActivityId */, NULL /* pRelatedActivityId */, pTargetThread, &stackContents))
721 // This is used in DEBUG to make sure that we don't log an event synchronously that we didn't log to the buffer.
730 // Create an instance for the synchronous path.
731 SampleProfilerEventInstance instance(*s_pSession, *pEvent, pTargetThread, pData, length);
732 stackContents.CopyTo(instance.GetStack());
734 // Write to the EventPipeFile.
735 if(s_pSyncFile != NULL)
737 s_pSyncFile->WriteEvent(instance);
740 // Write to the EventPipeJsonFile if it exists.
741 if(s_pJsonFile != NULL)
743 s_pJsonFile->WriteEvent(instance);
749 bool EventPipe::WalkManagedStackForCurrentThread(StackContents &stackContents)
759 Thread *pThread = GetThread();
762 return WalkManagedStackForThread(pThread, stackContents);
768 bool EventPipe::WalkManagedStackForThread(Thread *pThread, StackContents &stackContents)
775 PRECONDITION(pThread != NULL);
779 // Calling into StackWalkFrames in preemptive mode violates the host contract,
780 // but this contract is not used on CoreCLR.
781 CONTRACT_VIOLATION( HostViolation );
783 stackContents.Reset();
785 StackWalkAction swaRet = pThread->StackWalkFrames(
786 (PSTACKWALKFRAMESCALLBACK) &StackWalkCallback,
788 ALLOW_ASYNC_STACK_WALK | FUNCTIONSONLY | HANDLESKIPPEDFRAMES);
790 return ((swaRet == SWA_DONE) || (swaRet == SWA_CONTINUE));
793 StackWalkAction EventPipe::StackWalkCallback(CrawlFrame *pCf, StackContents *pData)
800 PRECONDITION(pCf != NULL);
801 PRECONDITION(pData != NULL);
806 UINT_PTR controlPC = (UINT_PTR)pCf->GetRegisterSet()->ControlPC;
809 if(pData->GetLength() == 0)
811 // This happens for pinvoke stubs on the top of the stack.
816 _ASSERTE(controlPC != 0);
818 // Add the IP to the captured stack.
824 // Continue the stack walk.
828 EventPipeConfiguration* EventPipe::GetConfiguration()
830 LIMITED_METHOD_CONTRACT;
835 CrstStatic* EventPipe::GetLock()
837 LIMITED_METHOD_CONTRACT;
839 return &s_configCrst;
842 void EventPipe::GetConfigurationFromEnvironment(SString &outputPath, EventPipeSession *pSession)
844 LIMITED_METHOD_CONTRACT;
846 // Set the output path if specified.
847 CLRConfigStringHolder wszOutputPath(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeOutputFile));
848 if(wszOutputPath != NULL)
850 outputPath.Set(wszOutputPath);
853 // Read the the provider configuration from the environment if specified.
854 CLRConfigStringHolder wszConfig(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeConfig));
855 if(wszConfig == NULL)
857 pSession->EnableAllEvents();
861 size_t len = wcslen(wszConfig);
864 pSession->EnableAllEvents();
868 // Parses a string with the following format:
870 // ProviderName:Keywords:Level[,]*
874 // Microsoft-Windows-DotNETRuntime:0xCAFEBABE:2,Microsoft-Windows-DotNETRuntimePrivate:0xDEADBEEF:1
876 // Each provider configuration is separated by a ',' and each component within the configuration is
877 // separated by a ':'.
879 const WCHAR ProviderSeparatorChar = ',';
880 const WCHAR ComponentSeparatorChar = ':';
882 WCHAR *pProviderName = NULL;
884 EventPipeEventLevel level = EventPipeEventLevel::Critical;
888 WCHAR * pCurrentChunk = &wszConfig[index];
889 size_t currentChunkStartIndex = index;
890 size_t currentChunkEndIndex = 0;
892 // Find the next chunk.
893 while(index < len && wszConfig[index] != ProviderSeparatorChar)
897 currentChunkEndIndex = index++;
899 // Split the chunk into components.
900 size_t chunkIndex = currentChunkStartIndex;
902 // Get the provider name.
903 size_t provNameStartIndex = chunkIndex;
904 size_t provNameEndIndex = currentChunkEndIndex;
906 while(chunkIndex < currentChunkEndIndex && wszConfig[chunkIndex] != ComponentSeparatorChar)
910 provNameEndIndex = chunkIndex++;
912 size_t provNameLen = provNameEndIndex - provNameStartIndex;
913 pProviderName = new WCHAR[provNameLen+1];
914 memcpy(pProviderName, &wszConfig[provNameStartIndex], provNameLen*sizeof(WCHAR));
915 pProviderName[provNameLen] = '\0';
918 size_t keywordsStartIndex = chunkIndex;
919 size_t keywordsEndIndex = currentChunkEndIndex;
921 while(chunkIndex < currentChunkEndIndex && wszConfig[chunkIndex] != ComponentSeparatorChar)
925 keywordsEndIndex = chunkIndex++;
927 size_t keywordsLen = keywordsEndIndex - keywordsStartIndex;
928 WCHAR *wszKeywords = new WCHAR[keywordsLen+1];
929 memcpy(wszKeywords, &wszConfig[keywordsStartIndex], keywordsLen*sizeof(WCHAR));
930 wszKeywords[keywordsLen] = '\0';
931 keywords = _wcstoui64(wszKeywords, NULL, 16);
932 delete[] wszKeywords;
936 size_t levelStartIndex = chunkIndex;
937 size_t levelEndIndex = currentChunkEndIndex;
939 while(chunkIndex < currentChunkEndIndex && wszConfig[chunkIndex] != ComponentSeparatorChar)
943 levelEndIndex = chunkIndex++;
945 size_t levelLen = levelEndIndex - levelStartIndex;
946 WCHAR *wszLevel = new WCHAR[levelLen+1];
947 memcpy(wszLevel, &wszConfig[levelStartIndex], levelLen*sizeof(WCHAR));
948 wszLevel[levelLen] = '\0';
949 level = (EventPipeEventLevel) wcstoul(wszLevel, NULL, 16);
953 // Add a new EventPipeSessionProvider.
954 EventPipeSessionProvider *pSessionProvider = new EventPipeSessionProvider(pProviderName, keywords, level);
955 pSession->AddSessionProvider(pSessionProvider);
957 // Free the provider name string.
958 if(pProviderName != NULL)
960 delete[] pProviderName;
961 pProviderName = NULL;
966 void EventPipe::SaveCommandLine(LPCWSTR pwzAssemblyPath, int argc, LPCWSTR *argv)
973 PRECONDITION(pwzAssemblyPath != NULL);
974 PRECONDITION(argc <= 0 || argv != NULL);
978 // Get the command line.
979 LPCWSTR osCommandLine = GetCommandLineW();
982 // On Windows, osCommandLine contains the executable and all arguments.
983 s_pCommandLine = osCommandLine;
985 // On UNIX, the PAL doesn't have the command line arguments, so we must build the command line.
986 // osCommandLine contains the full path to the executable.
987 SString commandLine(osCommandLine);
988 commandLine.Append((WCHAR)' ');
989 commandLine.Append(pwzAssemblyPath);
991 for(int i=0; i<argc; i++)
993 commandLine.Append((WCHAR)' ');
994 commandLine.Append(argv[i]);
997 // Allocate a new string for the command line.
998 SIZE_T commandLineLen = commandLine.GetCount();
999 WCHAR *pCommandLine = new WCHAR[commandLineLen + 1];
1000 wcsncpy(pCommandLine, commandLine.GetUnicode(), commandLineLen);
1001 pCommandLine[commandLineLen] = '\0';
1003 s_pCommandLine = pCommandLine;
1007 EventPipeEventInstance* EventPipe::GetNextEvent()
1017 EventPipeEventInstance *pInstance = NULL;
1019 // Only fetch the next event if a tracing session exists.
1020 // The buffer manager is not disposed until the process is shutdown.
1021 if (s_pSession != NULL)
1023 pInstance = s_pBufferManager->GetNextEvent();
1029 void QCALLTYPE EventPipeInternal::Enable(
1030 __in_z LPCWSTR outputFile,
1031 UINT32 circularBufferSizeInMB,
1032 INT64 profilerSamplingRateInNanoseconds,
1033 EventPipeProviderConfiguration *pProviders,
1039 SampleProfiler::SetSamplingRate((unsigned long)profilerSamplingRateInNanoseconds);
1040 EventPipe::Enable(outputFile, circularBufferSizeInMB, pProviders, numProviders);
1044 void QCALLTYPE EventPipeInternal::Disable()
1049 EventPipe::Disable();
1053 INT_PTR QCALLTYPE EventPipeInternal::CreateProvider(
1054 __in_z LPCWSTR providerName,
1055 EventPipeCallback pCallbackFunc)
1059 EventPipeProvider *pProvider = NULL;
1063 pProvider = EventPipe::CreateProvider(providerName, pCallbackFunc, NULL);
1067 return reinterpret_cast<INT_PTR>(pProvider);
1070 INT_PTR QCALLTYPE EventPipeInternal::DefineEvent(
1074 UINT32 eventVersion,
1077 UINT32 metadataLength)
1081 EventPipeEvent *pEvent = NULL;
1085 _ASSERTE(provHandle != NULL);
1086 EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider *>(provHandle);
1087 pEvent = pProvider->AddEvent(eventID, keywords, eventVersion, (EventPipeEventLevel)level, (BYTE *)pMetadata, metadataLength);
1088 _ASSERTE(pEvent != NULL);
1092 return reinterpret_cast<INT_PTR>(pEvent);
1095 INT_PTR QCALLTYPE EventPipeInternal::GetProvider(
1096 __in_z LPCWSTR providerName)
1100 EventPipeProvider *pProvider = NULL;
1104 pProvider = EventPipe::GetProvider(providerName);
1108 return reinterpret_cast<INT_PTR>(pProvider);
1111 void QCALLTYPE EventPipeInternal::DeleteProvider(
1117 if(provHandle != NULL)
1119 EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider*>(provHandle);
1120 EventPipe::DeleteProvider(pProvider);
1126 int QCALLTYPE EventPipeInternal::EventActivityIdControl(
1137 Thread *pThread = GetThread();
1138 if(pThread == NULL || pActivityId == NULL)
1144 ActivityControlCode activityControlCode = (ActivityControlCode)controlCode;
1145 GUID currentActivityId;
1146 switch(activityControlCode)
1148 case ActivityControlCode::EVENT_ACTIVITY_CONTROL_GET_ID:
1150 *pActivityId = *pThread->GetActivityId();
1153 case ActivityControlCode::EVENT_ACTIVITY_CONTROL_SET_ID:
1155 pThread->SetActivityId(pActivityId);
1158 case ActivityControlCode::EVENT_ACTIVITY_CONTROL_CREATE_ID:
1160 CoCreateGuid(pActivityId);
1163 case ActivityControlCode::EVENT_ACTIVITY_CONTROL_GET_SET_ID:
1165 currentActivityId = *pThread->GetActivityId();
1166 pThread->SetActivityId(pActivityId);
1167 *pActivityId = currentActivityId;
1171 case ActivityControlCode::EVENT_ACTIVITY_CONTROL_CREATE_SET_ID:
1173 *pActivityId = *pThread->GetActivityId();
1174 CoCreateGuid(¤tActivityId);
1175 pThread->SetActivityId(¤tActivityId);
1187 void QCALLTYPE EventPipeInternal::WriteEvent(
1188 INT_PTR eventHandle,
1192 LPCGUID pActivityId,
1193 LPCGUID pRelatedActivityId)
1198 _ASSERTE(eventHandle != NULL);
1199 EventPipeEvent *pEvent = reinterpret_cast<EventPipeEvent *>(eventHandle);
1200 EventPipe::WriteEvent(*pEvent, (BYTE *)pData, length, pActivityId, pRelatedActivityId);
1205 void QCALLTYPE EventPipeInternal::WriteEventData(
1206 INT_PTR eventHandle,
1208 EventData *pEventData,
1209 UINT32 eventDataCount,
1210 LPCGUID pActivityId,
1211 LPCGUID pRelatedActivityId)
1216 _ASSERTE(eventHandle != NULL);
1217 EventPipeEvent *pEvent = reinterpret_cast<EventPipeEvent *>(eventHandle);
1218 EventPipe::WriteEvent(*pEvent, pEventData, eventDataCount, pActivityId, pRelatedActivityId);
1223 bool QCALLTYPE EventPipeInternal::GetNextEvent(
1224 EventPipeEventInstanceData *pInstance)
1228 EventPipeEventInstance *pNextInstance = NULL;
1231 _ASSERTE(pInstance != NULL);
1233 pNextInstance = EventPipe::GetNextEvent();
1236 pInstance->ProviderID = pNextInstance->GetEvent()->GetProvider();
1237 pInstance->EventID = pNextInstance->GetEvent()->GetEventID();
1238 pInstance->Payload = pNextInstance->GetData();
1239 pInstance->PayloadLength = pNextInstance->GetDataLength();
1243 return pNextInstance != NULL;
1246 #endif // FEATURE_PERFTRACING