diff options
Diffstat (limited to 'src/inc/profilepriv.inl')
-rw-r--r-- | src/inc/profilepriv.inl | 826 |
1 files changed, 826 insertions, 0 deletions
diff --git a/src/inc/profilepriv.inl b/src/inc/profilepriv.inl new file mode 100644 index 0000000000..e7c82074be --- /dev/null +++ b/src/inc/profilepriv.inl @@ -0,0 +1,826 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// ProfilePriv.inl +// + +// +// Inlined functions used by the Profiling API and throughout the EE. Most notably are +// the CORProfilerTrack* functions that test whether a profiler is active and responding +// to various callbacks +// + +// ====================================================================================== +#ifndef _ProfilePriv_inl_ +#define _ProfilePriv_inl_ + +#include "eetoprofinterfaceimpl.h" +#ifdef PROFILING_SUPPORTED +#include "profilinghelper.h" +BOOL CORProfilerBypassSecurityChecks(); +#endif // PROFILING_SUPPORTED + +//--------------------------------------------------------------------------------------- +// CurrentProfilerStatus +//--------------------------------------------------------------------------------------- + +inline void CurrentProfilerStatus::Init() +{ + LIMITED_METHOD_CONTRACT; + m_profStatus = kProfStatusNone; +} + +inline ProfilerStatus CurrentProfilerStatus::Get() +{ + LIMITED_METHOD_DAC_CONTRACT; + return m_profStatus; +} + +//--------------------------------------------------------------------------------------- +// ProfControlBlock +//--------------------------------------------------------------------------------------- + +inline void ProfControlBlock::Init() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + curProfStatus.Init(); + + fGCInProgress = FALSE; + fBaseSystemClassesLoaded = FALSE; +#ifdef PROF_TEST_ONLY_FORCE_ELT + fTestOnlyForceEnterLeave = FALSE; +#endif + +#ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED + fTestOnlyForceObjectAllocated = FALSE; +#endif + +#ifdef _DEBUG + fTestOnlyEnableICorProfilerInfo = FALSE; +#endif // _DEBUG + + fConcurrentGCDisabledForAttach = FALSE; + + ResetPerSessionStatus(); +} + +// Reset those variables that is only for the current attach session +inline void ProfControlBlock::ResetPerSessionStatus() +{ + LIMITED_METHOD_CONTRACT; + + pProfInterface = NULL; + dwEventMask = COR_PRF_MONITOR_NONE; + dwEventMaskHigh = COR_PRF_HIGH_MONITOR_NONE; +} + +//--------------------------------------------------------------------------------------- +// Inlined helpers used throughout the runtime to check for the profiler's load status +// and what features it enabled callbacks for. +//--------------------------------------------------------------------------------------- + + +// CORProfilerPresent() returns whether or not a CLR Profiler is actively loaded +// (meaning it's initialized and ready to receive callbacks). +inline BOOL CORProfilerPresent() +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ((&g_profControlBlock)->curProfStatus.Get() == kProfStatusActive); +} + +// These return whether a CLR Profiler is actively loaded AND has requested the +// specified callback or functionality + +inline BOOL CORProfilerFunctionIDMapperEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ( + ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper() != NULL) || + ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper2() != NULL) + )); +} + +inline BOOL CORProfilerTrackJITInfo() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_JIT_COMPILATION)); +} + +inline BOOL CORProfilerTrackCacheSearches() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CACHE_SEARCHES)); +} + +inline BOOL CORProfilerTrackModuleLoads() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_MODULE_LOADS)); +} + +inline BOOL CORProfilerTrackAssemblyLoads() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ASSEMBLY_LOADS)); +} + +inline BOOL CORProfilerTrackAppDomainLoads() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_APPDOMAIN_LOADS)); +} + +inline BOOL CORProfilerTrackThreads() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_THREADS)); +} + +inline BOOL CORProfilerTrackClasses() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CLASS_LOADS)); +} + +inline BOOL CORProfilerTrackGC() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_GC)); +} + +inline BOOL CORProfilerTrackAllocationsEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return + ( +#ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED + (&g_profControlBlock)->fTestOnlyForceObjectAllocated || +#endif + (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_OBJECT_ALLOCATED)) + ); +} + +inline BOOL CORProfilerTrackAllocations() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return + (CORProfilerTrackAllocationsEnabled() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_OBJECT_ALLOCATED)); +} + +inline BOOL CORProfilerEnableRejit() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_REJIT)); +} + +inline BOOL CORProfilerTrackExceptions() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_EXCEPTIONS)); +} + +inline BOOL CORProfilerTrackCLRExceptions() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CLR_EXCEPTIONS)); +} + +inline BOOL CORProfilerTrackTransitions() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CODE_TRANSITIONS)); +} + +inline BOOL CORProfilerTrackEnterLeave() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + +#ifdef PROF_TEST_ONLY_FORCE_ELT + if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) + return TRUE; +#endif // PROF_TEST_ONLY_FORCE_ELT + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ENTERLEAVE)); +} + +inline BOOL CORProfilerTrackCCW() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CCW)); +} + +inline BOOL CORProfilerTrackRemoting() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING)); +} + +inline BOOL CORProfilerTrackRemotingCookie() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return + (CORProfilerPresent() && + (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_COOKIE) + == COR_PRF_MONITOR_REMOTING_COOKIE)); +} + +inline BOOL CORProfilerTrackRemotingAsync() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return + (CORProfilerPresent() && + (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_ASYNC) + == COR_PRF_MONITOR_REMOTING_ASYNC)); +} + +inline BOOL CORProfilerTrackSuspends() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_SUSPENDS)); +} + +inline BOOL CORProfilerDisableInlining() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_INLINING)); +} + +inline BOOL CORProfilerJITMapEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_JIT_MAPS)); +} + +inline BOOL CORProfilerDisableOptimizations() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_OPTIMIZATIONS)); +} + +inline BOOL CORProfilerUseProfileImages() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + +#ifdef PROF_TEST_ONLY_FORCE_ELT + if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) + return TRUE; +#endif // PROF_TEST_ONLY_FORCE_ELT + + if (!CORProfilerPresent()) + return FALSE; + + if (((&g_profControlBlock)->dwEventMask & + COR_PRF_REQUIRE_PROFILE_IMAGE) == 0) + return FALSE; + + return TRUE; +} + +inline BOOL CORProfilerDisableAllNGenImages() +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_ALL_NGEN_IMAGES)); +} + +inline BOOL CORProfilerTrackConditionalWeakTableElements() +{ + LIMITED_METHOD_DAC_CONTRACT; + + return CORProfilerTrackGC() && (&g_profControlBlock)->pProfInterface->IsCallback5Supported(); +} + +// CORProfilerPresentOrInitializing() returns nonzero iff a CLR Profiler is actively +// loaded and ready to receive callbacks OR a CLR Profiler has loaded just enough that it +// is ready to receive (or is currently executing inside) its Initialize() callback. +// Typically, you'll want to use code:CORProfilerPresent instead of this. But there is +// some internal profiling API code that wants to test for event flags for a profiler +// that may still be initializing, and this function is appropriate for that code. +inline BOOL CORProfilerPresentOrInitializing() +{ + LIMITED_METHOD_DAC_CONTRACT; + return ((&g_profControlBlock)->curProfStatus.Get() > kProfStatusDetaching); +} + +// These return whether a CLR Profiler has requested the specified functionality. +// +// Note that, unlike the above functions, a profiler that's not done loading (and is +// still somewhere in the initialization phase) still counts. This is only safe because +// these functions are not used to determine whether to issue a callback. These functions +// are used primarily during the initialization path to choose between slow / fast-path +// ELT hooks (and later on as part of asserts). + +inline BOOL CORProfilerELT3SlowPathEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); +} + +inline BOOL CORProfilerELT3SlowPathEnterEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))); +} + +inline BOOL CORProfilerELT3SlowPathLeaveEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); +} + +inline BOOL CORProfilerELT3SlowPathTailcallEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FRAME_INFO))); +} + +inline BOOL CORProfilerELT2FastPathEnterEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)))); +} + +inline BOOL CORProfilerELT2FastPathLeaveEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)))); +} + +inline BOOL CORProfilerELT2FastPathTailcallEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO)))); +} + +inline BOOL CORProfilerFunctionArgsEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_ARGS)); +} + +inline BOOL CORProfilerFunctionReturnValueEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_RETVAL)); +} + +inline BOOL CORProfilerFrameInfoEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FRAME_INFO)); +} + +inline BOOL CORProfilerStackSnapshotEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_STACK_SNAPSHOT)); +} + +inline BOOL CORProfilerAddsAssemblyReferences() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES)); +} + +inline BOOL CORProfilerInMemorySymbolsUpdatesEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SO_NOT_MAINLINE; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED)); +} + +#if defined(PROFILING_SUPPORTED) && !defined(CROSSGEN_COMPILE) + +#if defined(FEATURE_PROFAPI_ATTACH_DETACH) + +//--------------------------------------------------------------------------------------- +// When EE calls into the profiler, an EvacuationCounterHolder object is instantiated on +// the stack to increment the evacuation counter inside the EE Thread. Upon returning to +// EE, this EvacuationCounterHolder object when being destroyed decreases the evacuation +// counter by one. +// +// Do not use this object directly. Use BEGIN_PIN_PROFILER / END_PIN_PROFILER defined +// below. +// +// See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization. +// +typedef Wrapper<Thread *, ProfilingAPIUtility::IncEvacuationCounter, ProfilingAPIUtility::DecEvacuationCounter, + (UINT_PTR)0, CompareDefault<Thread *>, HSV_NoValidation> EvacuationCounterHolder; + + +//--------------------------------------------------------------------------------------- +// These macros must be placed around any access to g_profControlBlock.pProfInterface by +// the EE. Example: +// { +// BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads()); +// g_profControlBlock.pProfInterface->AppDomainCreationStarted(MyAppDomainID); +// END_PIN_PROFILER(); +// } +// The parameter to the BEGIN_PIN_PROFILER is the condition you want to check for, to +// determine whether the profiler is loaded and requesting the callback you're about to +// issue. Typically, this will be a call to one of the inline functions in +// profilepriv.inl. If the condition is true, the macro will increment an evacuation +// counter that effectively pins the profiler, recheck the condition, and (if still +// true), execute whatever code you place inside the BEGIN/END_PIN_PROFILER block. If +// your condition is more complex than a simple profiler status check, then place the +// profiler status check as parameter to the macro, and add a separate if inside the +// block. Example: +// +// { +// BEGIN_PIN_PROFILER(CORProfilerTrackTransitions()); +// if (!pNSL->pMD->IsQCall()) +// { +// g_profControlBlock.pProfInterface-> +// ManagedToUnmanagedTransition((FunctionID) pNSL->pMD, +// COR_PRF_TRANSITION_CALL); +// } +// END_PIN_PROFILER(); +// } +// +// This ensures that the extra condition check (in this case "if +// (!pNSL->pMD->IsQCall())") is only evaluated if the profiler is loaded. That way, we're +// not executing extra, unnecessary instructions when no profiler is present. +// +// See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization +// for more details about how the synchronization works. +#define BEGIN_PIN_PROFILER(condition) \ + /* Do a cheap check of the condition (dirty-read) */ \ + if (condition) \ + { \ + EvacuationCounterHolder __evacuationCounter(GetThreadNULLOk()); \ + /* Now that the evacuation counter is incremented, the condition re-check */ \ + /* below is a clean read. There's no MemoryBarrier() here, but that's ok */ \ + /* as writes to the profiler status force a FlushStoreBuffers(). */ \ + if (condition) \ + { +#define END_PIN_PROFILER() } } + +#else // FEATURE_PROFAPI_ATTACH_DETACH + +// For builds that include profiling but not attach / detach (e.g., Silverlight 2), the +// *PIN_PROFILER macros should just check the condition without using the evacuation +// counters. + +#define BEGIN_PIN_PROFILER(condition) if (condition) { +#define END_PIN_PROFILER() } + +#endif // FEATURE_PROFAPI_ATTACH_DETACH + +#else // PROFILING_SUPPORTED && !CROSSGEN_COMPILE + +// Profiling feature not supported + +#define BEGIN_PIN_PROFILER(condition) if (false) { +#define END_PIN_PROFILER() } + +#endif // PROFILING_SUPPORTED && !CROSSGEN_COMPILE + +#endif // _ProfilePriv_inl_ + |