Add the concept of "notification profilers" to the runtime (#53122)
authorDavid Mason <davmason@microsoft.com>
Tue, 15 Jun 2021 18:54:02 +0000 (11:54 -0700)
committerGitHub <noreply@github.com>
Tue, 15 Jun 2021 18:54:02 +0000 (11:54 -0700)
55 files changed:
src/coreclr/dlls/mscorrc/mscorrc.rc
src/coreclr/dlls/mscorrc/resource.h
src/coreclr/gc/gcinterface.ee.h
src/coreclr/inc/CrstTypes.def
src/coreclr/inc/clrconfigvalues.h
src/coreclr/inc/corprof.idl
src/coreclr/inc/profilepriv.h
src/coreclr/inc/profilepriv.inl
src/coreclr/inc/sarray.inl
src/coreclr/pal/prebuilt/idl/corprof_i.cpp
src/coreclr/pal/prebuilt/inc/corprof.h
src/coreclr/vm/ClrEtwAll.man
src/coreclr/vm/appdomain.cpp
src/coreclr/vm/assembly.cpp
src/coreclr/vm/ceeload.cpp
src/coreclr/vm/ceemain.cpp
src/coreclr/vm/class.cpp
src/coreclr/vm/clsload.cpp
src/coreclr/vm/comcallablewrapper.cpp
src/coreclr/vm/comsynchronizable.cpp
src/coreclr/vm/crossgencompile.cpp
src/coreclr/vm/eetoprofinterfaceimpl.cpp
src/coreclr/vm/eetoprofinterfaceimpl.h
src/coreclr/vm/eetoprofinterfaceimpl.inl
src/coreclr/vm/eetoprofinterfacewrapper.inl
src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h
src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h
src/coreclr/vm/eventpipeadapter.h
src/coreclr/vm/eventpipeinternal.cpp
src/coreclr/vm/eventtrace.cpp
src/coreclr/vm/gcenv.ee.cpp
src/coreclr/vm/gchandleutilities.cpp
src/coreclr/vm/genanalysis.cpp
src/coreclr/vm/jitinterface.cpp
src/coreclr/vm/prestub.cpp
src/coreclr/vm/profdetach.cpp
src/coreclr/vm/profdetach.h
src/coreclr/vm/profilinghelper.cpp
src/coreclr/vm/profilinghelper.h
src/coreclr/vm/proftoeeinterfaceimpl.cpp
src/coreclr/vm/proftoeeinterfaceimpl.h
src/coreclr/vm/readytoruninfo.cpp
src/coreclr/vm/rejit.cpp
src/coreclr/vm/rejit.inl
src/coreclr/vm/runtimehandles.cpp
src/coreclr/vm/threads.cpp
src/coreclr/vm/threads.h
src/coreclr/vm/threadsuspend.cpp
src/mono/mono/component/event_pipe.c
src/native/eventpipe/ds-eventpipe-protocol.c
src/native/eventpipe/ep-session.c
src/native/eventpipe/ep-session.h
src/native/eventpipe/ep-types-forward.h
src/native/eventpipe/ep.c
src/native/eventpipe/ep.h

index 20390ae..0b4247c 100644 (file)
@@ -745,7 +745,10 @@ BEGIN
         IDS_PROF_V2PROFILER_DISABLED            "Loading profiler failed.   The profiler that was configured to load was designed for an older version of the CLR.  You can use the COMPlus_ProfAPI_ProfilerCompatibilitySetting environment variable to allow older profilers to be loaded by the current version of the CLR.  Please consult the documentation for information on how to use this environment variable, and the risks associated with it.  Profiler CLSID: '%s'."
         IDS_PROF_V2PROFILER_ENABLED             "A profiler designed for an older version of the CLR was loaded because of the environment variable setting below.  Older profilers will continue to work in many cases, but if you encounter problems, please consider upgrading the profiler or changing the setting of the environment variable.  Please consult the documentation for information on how to use this environment variable, and the risks associated with it.  Environment variable setting: %s=%s.  Profiler CLSID: '%s'."
         IDS_PROF_PROFILER_DISABLED              "Profilers will not be loaded by the current version of the CLR because of the environment variable setting below.  Please consult the documentation for information on how to use this environment variable, and the risks associated with it.  Environment variable setting: %s=%s. Profiler CLSID: '%s'."
+        IDS_E_PROF_NOTIFICATION_DISABLED        "Profiler was prevented from loading notification profiler due to app settings."
+        IDS_E_PROF_NOTIFICATION_LIMIT_EXCEEDED  "Notification profiler was prevented from loading because the limit of notification profilers was reached."
         IDS_E_PROF_TIMEOUT_WAITING_FOR_CONCURRENT_GC    "Profiler timed out on waiting for concurrent GC to finish after '%d' milliseconds. Please configure your profiler to increase its attaching time out value or consult the documentation for the COMPlus_ProfAPI_AttachProfilerMinTimeoutInMs environment variable and try again. Profiler CLSID: '%s'."
+        IDS_PROF_ALREADY_LOADED                 "A request was made to load a profiler when a profiler was already loaded."
   END
 
 
index b26dc85..8038665 100644 (file)
 #define IDS_PROF_SUPPLEMENTARY_INFO             0x2506
 #define IDS_PROF_LOAD_COMPLETE                  0x2507
 #define IDS_E_PROF_BAD_PATH                     0x2508
+#define IDS_E_PROF_NOTIFICATION_DISABLED        0x2509
+#define IDS_PROF_ALREADY_LOADED                 0x250A
+#define IDS_E_PROF_NOTIFICATION_LIMIT_EXCEEDED  0x250B
 #define IDS_E_PROF_NOT_ATTACHABLE               0x250E
 #define IDS_E_PROF_UNHANDLED_EXCEPTION_ON_LOAD  0x250F
 #define IDS_PROF_ATTACH_REQUEST_RECEIVED        0x2512
index 4b04827..ea5f2d2 100644 (file)
@@ -4,7 +4,7 @@
 #ifndef _GCINTERFACE_EE_H_
 #define _GCINTERFACE_EE_H_
 
-enum EtwGCRootFlags
+enum EtwGCRootFlags: int32_t
 {
     kEtwGCRootFlagsPinning =            0x1,
     kEtwGCRootFlagsWeakRef =            0x2,
@@ -12,7 +12,7 @@ enum EtwGCRootFlags
     kEtwGCRootFlagsRefCounted =         0x8,
 };
 
-enum EtwGCRootKind
+enum EtwGCRootKind: int32_t
 {
     kEtwGCRootKindStack =               0,
     kEtwGCRootKindFinalizer =           1,
index 185a590..c48872a 100644 (file)
@@ -433,7 +433,7 @@ Crst SingleUseLock
 End
 
 Crst UnwindInfoTableLock
-       AcquiredAfter StubUnwindInfoHeapSegments SingleUseLock
+    AcquiredAfter StubUnwindInfoHeapSegments SingleUseLock
     AcquiredBefore StressLog
 End
 
index 5dc7e5d..3f21e41 100644 (file)
@@ -504,6 +504,10 @@ RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_32, W("CORECLR_PROFI
 RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_64, W("CORECLR_PROFILER_PATH_64"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 64 process", CLRConfig::LookupOptions::DontPrependPrefix)
 RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_ARM32, W("CORECLR_PROFILER_PATH_ARM32"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running ARM32 process", CLRConfig::LookupOptions::DontPrependPrefix)
 RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_ARM64, W("CORECLR_PROFILER_PATH_ARM64"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running ARM64 process", CLRConfig::LookupOptions::DontPrependPrefix)
+RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_CORECLR_ENABLE_NOTIFICATION_PROFILERS, W("CORECLR_ENABLE_NOTIFICATION_PROFILERS"), 0, "Set to 0 to disable loading notification profilers.", CLRConfig::LookupOptions::DontPrependPrefix)
+RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_64, W("CORECLR_NOTIFICATION_PROFILERS_64"), "A semi-colon separated list of notification profilers to load in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix)
+RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_32, W("CORECLR_NOTIFICATION_PROFILERS_32"), "A semi-colon separated list of notification profilers to load in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix)
+RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS, W("CORECLR_NOTIFICATION_PROFILERS"), "A semi-colon separated list of notification profilers to load in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix)
 RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_ProfAPI_ProfilerCompatibilitySetting, W("ProfAPI_ProfilerCompatibilitySetting"), "Specifies the profiler loading policy (the default is not to load a V2 profiler in V4)", CLRConfig::LookupOptions::TrimWhiteSpaceFromStringValue)
 RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMinSleepMs, W("ProfAPI_DetachMinSleepMs"), 0, "The minimum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.")
 RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMaxSleepMs, W("ProfAPI_DetachMaxSleepMs"), 0, "The maximum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.")
index 74fb809..8fc965a 100644 (file)
@@ -475,6 +475,7 @@ typedef enum
     // and ThreadNameChanged callbacks.
     COR_PRF_MONITOR_THREADS             = 0x00000200,
 
+    // CORECLR DEPRECATION WARNING: Remoting no longer exists in coreclr
     // MONITOR_REMOTING controls the Remoting*
     // callbacks.
     COR_PRF_MONITOR_REMOTING            = 0x00000400,
@@ -492,10 +493,12 @@ typedef enum
     // callbacks.
     COR_PRF_MONITOR_CCW                 = 0x00002000,
 
+    // CORECLR DEPRECATION WARNING: Remoting no longer exists in coreclr
     // MONITOR_REMOTING_COOKIE controls whether
     // a cookie will be passed to the Remoting* callbacks
     COR_PRF_MONITOR_REMOTING_COOKIE     = 0x00004000 | COR_PRF_MONITOR_REMOTING,
 
+    // CORECLR DEPRECATION WARNING: Remoting no longer exists in coreclr
     // MONITOR_REMOTING_ASYNC controls whether
     // the Remoting* callbacks will monitor async events
     COR_PRF_MONITOR_REMOTING_ASYNC      = 0x00008000 | COR_PRF_MONITOR_REMOTING,
@@ -594,6 +597,28 @@ typedef enum
                                           COR_PRF_MONITOR_JIT_COMPILATION |
                                           COR_PRF_ENABLE_REJIT,
 
+    COR_PRF_ALLOWABLE_NOTIFICATION_PROFILER
+                                        =     COR_PRF_MONITOR_FUNCTION_UNLOADS |
+                                              COR_PRF_MONITOR_CLASS_LOADS |
+                                              COR_PRF_MONITOR_MODULE_LOADS |
+                                              COR_PRF_MONITOR_ASSEMBLY_LOADS |
+                                              COR_PRF_MONITOR_APPDOMAIN_LOADS |
+                                              COR_PRF_MONITOR_JIT_COMPILATION |
+                                              COR_PRF_MONITOR_EXCEPTIONS |
+                                              COR_PRF_MONITOR_OBJECT_ALLOCATED |
+                                              COR_PRF_MONITOR_THREADS |
+                                              COR_PRF_MONITOR_CODE_TRANSITIONS |
+                                              COR_PRF_MONITOR_CCW |
+                                              COR_PRF_MONITOR_SUSPENDS |
+                                              COR_PRF_MONITOR_CACHE_SEARCHES |
+                                              COR_PRF_DISABLE_INLINING |
+                                              COR_PRF_DISABLE_OPTIMIZATIONS |
+                                              COR_PRF_ENABLE_OBJECT_ALLOCATED |
+                                              COR_PRF_MONITOR_CLR_EXCEPTIONS |
+                                              COR_PRF_ENABLE_STACK_SNAPSHOT |
+                                              COR_PRF_USE_PROFILE_IMAGES |
+                                              COR_PRF_DISABLE_ALL_NGEN_IMAGES,
+
     // MONITOR_IMMUTABLE represents all flags that may only be set during initialization.
     // Trying to change any of these flags elsewhere will result in a
     // failed HRESULT.
@@ -621,6 +646,7 @@ typedef enum
 {
     COR_PRF_HIGH_MONITOR_NONE                       = 0x00000000,
 
+    // CORECLR DEPRECATION WARNING: This flag is no longer checked by the runtime
     COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES            = 0x00000001,
 
     COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED          = 0x00000002,
@@ -648,6 +674,15 @@ typedef enum
                                                       COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED |
                                                       COR_PRF_HIGH_MONITOR_EVENT_PIPE,
 
+    COR_PRF_HIGH_ALLOWABLE_NOTIFICATION_PROFILER
+                                        =     COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED |
+                                              COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS |
+                                              COR_PRF_HIGH_DISABLE_TIERED_COMPILATION |
+                                              COR_PRF_HIGH_BASIC_GC |
+                                              COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS |
+                                              COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED |
+                                              COR_PRF_HIGH_MONITOR_EVENT_PIPE,
+
     // MONITOR_IMMUTABLE represents all flags that may only be set during initialization.
     // Trying to change any of these flags elsewhere will result in a
     // failed HRESULT.
@@ -2433,6 +2468,7 @@ interface ICorProfilerCallback5 : ICorProfilerCallback4
 ]
 interface ICorProfilerCallback6 : ICorProfilerCallback5
 {
+    // CORECLR DEPRECATION WARNING: This callback does not occur on coreclr.
     // Controlled by the COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES event mask flag.
     // Notifies the profiler of a very early stage in the loading of an Assembly, where the CLR
     // performs an assembly reference closure walk.  This is useful ONLY if the profiler will need
@@ -2555,6 +2591,17 @@ interface ICorProfilerCallback10 : ICorProfilerCallback9
     HRESULT EventPipeProviderCreated([in] EVENTPIPE_PROVIDER provider);
 }
 
+[
+    object,
+    uuid(42350846-AAED-47F7-B128-FD0C98881CDE),
+    pointer_default(unique),
+    local
+]
+interface ICorProfilerCallback11 : ICorProfilerCallback10
+{
+    HRESULT LoadAsNotficationOnly(BOOL *pbNotificationOnly);
+}
+
 /*
  * COR_PRF_CODEGEN_FLAGS controls various flags and hooks for a specific
  * method.  A combination of COR_PRF_CODEGEN_FLAGS is provided by the
index bd5533f..75d1c3d 100644 (file)
 
 // Forward declarations
 class EEToProfInterfaceImpl;
+class ProfToEEInterfaceImpl;
 class Object;
 struct ScanContext;
+enum EtwGCRootFlags: int32_t;
+enum EtwGCRootKind: int32_t;
+struct IAssemblyBindingClosure;
+struct AssemblyReferenceClosureWalkContextForProfAPI;
+
+#include "eventpipeadaptertypes.h"
 
 #if defined (PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED)
 #ifndef PROFILING_SUPPORTED_DATA
@@ -25,6 +32,9 @@ struct ScanContext;
 #endif  // PROFILING_SUPPORTED_DATA
 
 #include "corprof.h"
+#include "slist.h"
+
+#define MAX_NOTIFICATION_PROFILERS 32
 
 //---------------------------------------------------------------------------------------
 // Enumerates the various init states of profiling.
@@ -55,33 +65,183 @@ public:
     void Set(ProfilerStatus profStatus);
 };
 
-// ---------------------------------------------------------------------------------------
-// Global struct that lets the EE see the load status of the profiler, and provides a
-// pointer (pProfInterface) through which profiler calls can be made
-//
-// When you are adding new session, please refer to
-// code:ProfControlBlock::ResetPerSessionStatus#ProfileResetSessionStatus for more details.
-struct ProfControlBlock
+class EventMask
 {
+    friend class ProfControlBlock;
+private:
+    const UINT64 EventMaskLowMask           = 0x00000000FFFFFFFF;
+    const UINT64 EventMaskHighShiftAmount   = 32;
+    const UINT64 EventMaskHighMask          = 0xFFFFFFFF00000000;
+
+    Volatile<UINT64> m_eventMask;
+
+public:
+    EventMask() :
+        m_eventMask(0)
+    {
+
+    }
+
+    EventMask& operator=(const EventMask& other);
+
+    BOOL IsEventMaskSet(DWORD eventMask);
+    DWORD GetEventMask();
+    void SetEventMask(DWORD eventMask);
+    BOOL IsEventMaskHighSet(DWORD eventMaskHigh);
+    DWORD GetEventMaskHigh();
+    void SetEventMaskHigh(DWORD eventMaskHigh);
+};
+
+class ProfilerInfo
+{
+public:
     // **** IMPORTANT!! ****
     // All uses of pProfInterface must be properly synchronized to avoid the profiler
     // from detaching while the EE attempts to call into it.  The recommended way to do
-    // this is to use the (lockless) BEGIN_PIN_PROFILER / END_PIN_PROFILER macros.  See
-    // code:BEGIN_PIN_PROFILER for instructions.  For full details on how the
+    // this is to use the (lockless) BEGIN_PROFILER_CALLBACK / END_PROFILER_CALLBACK macros.  See
+    // code:BEGIN_PROFILER_CALLBACK for instructions.  For full details on how the
     // synchronization works, see
     // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization
     VolatilePtr<EEToProfInterfaceImpl> pProfInterface;
     // **** IMPORTANT!! ****
 
-    DWORD dwEventMask;          // Original low event mask bits
-    DWORD dwEventMaskHigh;      // New high event mask bits
     CurrentProfilerStatus curProfStatus;
+    
+    EventMask eventMask;
+
+    //---------------------------------------------------------------
+    // m_dwProfilerEvacuationCounter keeps track of how many profiler
+    // callback calls remain on the stack
+    //---------------------------------------------------------------
+    // Why volatile?
+    // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization.
+    Volatile<DWORD> dwProfilerEvacuationCounter;
+
+    Volatile<BOOL> inUse;
+
+    // Reset those variables that is only for the current attach session
+    void ResetPerSessionStatus();
+    void Init();
+};
+
+enum class ProfilerCallbackType
+{
+    Active,
+    ActiveOrInitializing
+};
+
+// We need a way to track which profilers are in active calls, to synchronize with detach.
+// If we detached a profiler while it was actively in a callback there would be issues.
+// However, we don't want to pin all profilers, because then a chatty profiler could
+// cause another profiler to not be able to detach. We can't just check the event masks
+// before and after the call because it is legal for a profiler to change its event mask,
+// and then it would be possible for a profiler to permanently prevent itself from detaching.
+// 
+// WHEN IS EvacuationCounterHolder REQUIRED?
+// Answer: any time you access a ProfilerInfo *. There is a specific sequence that must be followed:
+//   - Do a dirty read of the Profiler interface
+//   - Increment an evacuation counter by using EvacuationCounterHolder as a RAII guard class
+//   - Now do a clean read of the ProfilerInfo's status - this will be changed during detach and
+//     is always read with a memory barrier
+//
+// The DoProfilerCallback/IterateProfilers functions automate this process for you, you should use
+// them unless you are absoultely sure you know what you're doing
+class EvacuationCounterHolder
+{
+private:
+    ProfilerInfo *m_pProfilerInfo;
+
+public:
+    EvacuationCounterHolder(ProfilerInfo *pProfilerInfo) :
+        m_pProfilerInfo(pProfilerInfo)
+    {
+        _ASSERTE(m_pProfilerInfo != NULL);
+        InterlockedIncrement((LONG *)(m_pProfilerInfo->dwProfilerEvacuationCounter.GetPointer()));
+    }
+
+    ~EvacuationCounterHolder()
+    {
+        InterlockedDecrement((LONG *)(m_pProfilerInfo->dwProfilerEvacuationCounter.GetPointer()));
+    }
+};
+
+struct StoredProfilerNode
+{
+    CLSID guid;
+    SString path;
+    SLink m_Link;
+};
+
+typedef SList<StoredProfilerNode, true> STOREDPROFILERLIST;
+// ---------------------------------------------------------------------------------------
+// Global struct that lets the EE see the load status of the profiler, and provides a
+// pointer (pProfInterface) through which profiler calls can be made
+//
+// When you are adding new session, please refer to
+// code:ProfControlBlock::ResetPerSessionStatus#ProfileResetSessionStatus for more details.
+class ProfControlBlock
+{
+private:
+    // IsProfilerPresent(pProfilerInfo) returns whether or not a CLR Profiler is actively loaded
+    // (meaning it's initialized and ready to receive callbacks).
+    FORCEINLINE BOOL IsProfilerPresent(ProfilerInfo *pProfilerInfo)
+    {
+        LIMITED_METHOD_DAC_CONTRACT;
+
+        return pProfilerInfo->curProfStatus.Get() >= kProfStatusActive;
+    }
+
+    FORCEINLINE BOOL IsProfilerPresentOrInitializing(ProfilerInfo *pProfilerInfo)
+    {
+        return pProfilerInfo->curProfStatus.Get() > kProfStatusDetaching;
+    }
+
+    template<typename Func, typename... Args>
+    FORCEINLINE VOID DoOneProfilerIteration(ProfilerInfo *pProfilerInfo, ProfilerCallbackType callbackType, Func callback, Args... args)
+    {
+        // This is the dirty read
+        if (pProfilerInfo->pProfInterface.Load() != NULL)
+        {
+#ifdef FEATURE_PROFAPI_ATTACH_DETACH
+            // Now indicate we are accessing the profiler
+            EvacuationCounterHolder evacuationCounter(pProfilerInfo);
+#endif // FEATURE_PROFAPI_ATTACH_DETACH
+            
+            if ((callbackType == ProfilerCallbackType::Active && IsProfilerPresent(pProfilerInfo))
+                || (callbackType == ProfilerCallbackType::ActiveOrInitializing && IsProfilerPresentOrInitializing(pProfilerInfo)))
+            {
+                callback(pProfilerInfo, args...);
+            }
+        }
+    }
+
+    template<typename Func, typename... Args>
+    FORCEINLINE VOID IterateProfilers(ProfilerCallbackType callbackType, Func callback, Args... args)
+    {
+        DoOneProfilerIteration(&mainProfilerInfo, callbackType, callback, args...);
+        
+        if (notificationProfilerCount > 0)
+        {
+            for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i)
+            {
+                ProfilerInfo *current = &(notificationOnlyProfilers[i]);
+                DoOneProfilerIteration(current, callbackType, callback, args...);
+            }
+        }
+    }
+
+public:
     BOOL fGCInProgress;
     BOOL fBaseSystemClassesLoaded;
 
-    BOOL fIsStoredProfilerRegistered;
-    CLSID clsStoredProfilerGuid;
-    SString sStoredProfilerPath;
+    STOREDPROFILERLIST storedProfilers;
+
+    ProfilerInfo mainProfilerInfo;
+
+    ProfilerInfo notificationOnlyProfilers[MAX_NOTIFICATION_PROFILERS];
+    Volatile<LONG> notificationProfilerCount;
+
+    EventMask globalEventMask;
 
 #ifdef PROF_TEST_ONLY_FORCE_ELT_DATA
     // #TestOnlyELT This implements a test-only (and debug-only) hook that allows a test
@@ -118,14 +278,128 @@ struct ProfControlBlock
 #endif // _DEBUG
 
     // Whether we've turned off concurrent GC during attach
-    BOOL fConcurrentGCDisabledForAttach;
+    Volatile<BOOL> fConcurrentGCDisabledForAttach;
 
     Volatile<BOOL> fProfControlBlockInitialized;
 
     Volatile<BOOL> fProfilerRequestedRuntimeSuspend;
 
     void Init();
-    void ResetPerSessionStatus();
+    BOOL IsMainProfiler(EEToProfInterfaceImpl *pEEToProf);
+    BOOL IsMainProfiler(ProfToEEInterfaceImpl *pProfToEE);
+    ProfilerInfo *GetProfilerInfo(ProfToEEInterfaceImpl *pProfToEE);
+
+    template<typename ConditionFunc, typename CallbackFunc, typename Data = void, typename... Args>
+    FORCEINLINE HRESULT DoProfilerCallback(ProfilerCallbackType callbackType, ConditionFunc condition, Data *additionalData, CallbackFunc callback, Args... args)
+    {
+        HRESULT hr = S_OK;
+        IterateProfilers(callbackType,
+                         [](ProfilerInfo *pProfilerInfo, ConditionFunc condition, Data *additionalData, CallbackFunc callback, HRESULT *pHR, Args... args)
+                            {
+                                if (condition(pProfilerInfo))
+                                {
+                                    HRESULT innerHR = callback(additionalData, pProfilerInfo->pProfInterface, args...);
+                                    if (FAILED(innerHR))
+                                    {
+                                        *pHR = innerHR;
+                                    }
+                                }
+                            },
+                         condition, additionalData, callback, &hr, args...);
+        return hr;
+    }
+
+#ifndef DACCESS_COMPILE
+    ProfilerInfo *FindNextFreeProfilerInfoSlot();
+    void DeRegisterProfilerInfo(ProfilerInfo *pProfilerInfo);
+    void UpdateGlobalEventMask();
+#endif // DACCESS_COMPILE
+
+    BOOL IsCallback3Supported();
+    BOOL IsCallback5Supported();
+    BOOL IsDisableTransparencySet();
+    BOOL RequiresGenericsContextForEnterLeave();
+    UINT_PTR EEFunctionIDMapper(FunctionID funcId, BOOL * pbHookFunction);
+    
+    void ThreadCreated(ThreadID threadID);
+    void ThreadDestroyed(ThreadID threadID);
+    void ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId);
+    void ThreadNameChanged(ThreadID managedThreadId, ULONG cchName, WCHAR name[]);
+    void Shutdown();
+    void FunctionUnloadStarted(FunctionID functionId);
+    void JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock);
+    void JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock);
+    void DynamicMethodJITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader);
+    void DynamicMethodJITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock);
+    void DynamicMethodUnloaded(FunctionID functionId);
+    void JITCachedFunctionSearchStarted(FunctionID functionId, BOOL *pbUseCachedFunction);
+    void JITCachedFunctionSearchFinished(FunctionID functionId, COR_PRF_JIT_CACHE result);
+    HRESULT JITInlining(FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline);
+    void ReJITCompilationStarted(FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock);
+    HRESULT GetReJITParameters(ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl);
+    void ReJITCompilationFinished(FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock);
+    void ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus);
+    void ModuleLoadStarted(ModuleID moduleId);
+    void ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus);
+    void ModuleUnloadStarted(ModuleID moduleId);
+    void ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus);
+    void ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId);
+    void ModuleInMemorySymbolsUpdated(ModuleID moduleId);
+    void ClassLoadStarted(ClassID classId);
+    void ClassLoadFinished(ClassID classId, HRESULT hrStatus);
+    void ClassUnloadStarted(ClassID classId);
+    void ClassUnloadFinished(ClassID classId, HRESULT hrStatus);
+    void AppDomainCreationStarted(AppDomainID appDomainId);
+    void AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus);
+    void AppDomainShutdownStarted(AppDomainID appDomainId);
+    void AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus);
+    void AssemblyLoadStarted(AssemblyID assemblyId);
+    void AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus);
+    void AssemblyUnloadStarted(AssemblyID assemblyId);
+    void AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus);
+    void UnmanagedToManagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason);
+    void ManagedToUnmanagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason);
+    void ExceptionThrown(ObjectID thrownObjectId);
+    void ExceptionSearchFunctionEnter(FunctionID functionId);
+    void ExceptionSearchFunctionLeave();
+    void ExceptionSearchFilterEnter(FunctionID funcId);
+    void ExceptionSearchFilterLeave();
+    void ExceptionSearchCatcherFound(FunctionID functionId);
+    void ExceptionOSHandlerEnter(FunctionID funcId);
+    void ExceptionOSHandlerLeave(FunctionID funcId);
+    void ExceptionUnwindFunctionEnter(FunctionID functionId);
+    void ExceptionUnwindFunctionLeave();
+    void ExceptionUnwindFinallyEnter(FunctionID functionId);
+    void ExceptionUnwindFinallyLeave();
+    void ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId);
+    void ExceptionCatcherLeave();
+    void COMClassicVTableCreated(ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots);
+    void RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason);
+    void RuntimeSuspendFinished();
+    void RuntimeSuspendAborted();
+    void RuntimeResumeStarted();
+    void RuntimeResumeFinished();
+    void RuntimeThreadSuspended(ThreadID suspendedThreadId);
+    void RuntimeThreadResumed(ThreadID resumedThreadId);
+    void ObjectAllocated(ObjectID objectId, ClassID classId);
+    void FinalizeableObjectQueued(BOOL isCritical, ObjectID objectID);
+    void MovedReference(BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting);
+    void EndMovedReferences(void *pHeapId);
+    void RootReference2(BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId);
+    void EndRootReferences2(void *pHeapId);
+    void ConditionalWeakTableElementReference(BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId);
+    void EndConditionalWeakTableElementReferences(void *pHeapId);
+    void AllocByClass(ObjectID objId, ClassID classId, void *pHeapId);
+    void EndAllocByClass(void *pHeapId);
+    HRESULT ObjectReference(ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef);
+    void HandleCreated(UINT_PTR handleId, ObjectID initialObjectId);
+    void HandleDestroyed(UINT_PTR handleId);
+    void GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason);
+    void GarbageCollectionFinished();
+    void GetAssemblyReferences(LPCWSTR wszAssemblyPath, IAssemblyBindingClosure *pClosure, AssemblyReferenceClosureWalkContextForProfAPI *pContext);
+    void EventPipeEventDelivered(EventPipeProvider *provider, DWORD eventId, DWORD eventVersion, ULONG cbMetadataBlob, LPCBYTE metadataBlob, ULONG cbEventData, 
+                                 LPCBYTE eventData, LPCGUID pActivityId, LPCGUID pRelatedActivityId, Thread *pEventThread, ULONG numStackFrames, UINT_PTR stackFrames[]);
+    void EventPipeProviderCreated(EventPipeProvider *provider);
 };
 
 
index 41e0bf3..08ba58f 100644 (file)
@@ -17,7 +17,6 @@
 #include "eetoprofinterfaceimpl.h"
 #ifdef PROFILING_SUPPORTED
 #include "profilinghelper.h"
-BOOL CORProfilerBypassSecurityChecks();
 #endif // PROFILING_SUPPORTED
 
 //---------------------------------------------------------------------------------------
@@ -36,11 +35,1260 @@ inline ProfilerStatus CurrentProfilerStatus::Get()
     return m_profStatus;
 }
 
+inline EventMask& EventMask::operator=(const EventMask& other)
+{
+    m_eventMask = other.m_eventMask;
+    return *this;
+}
+
+inline BOOL EventMask::IsEventMaskSet(DWORD eventMask)
+{
+    return (GetEventMask() & eventMask) != 0;
+}
+
+inline DWORD EventMask::GetEventMask()
+{
+    return (DWORD)(m_eventMask & EventMaskLowMask);
+}
+
+inline void EventMask::SetEventMask(DWORD eventMask)
+{
+    m_eventMask = (m_eventMask & EventMaskHighMask) | (UINT64)eventMask;
+}
+
+inline BOOL EventMask::IsEventMaskHighSet(DWORD eventMaskHigh)
+{
+    return (GetEventMaskHigh() & eventMaskHigh) != 0;
+}
+
+inline DWORD EventMask::GetEventMaskHigh()
+{
+    return (DWORD)((m_eventMask & EventMaskHighMask) >> EventMaskHighShiftAmount);
+}
+
+inline void EventMask::SetEventMaskHigh(DWORD eventMaskHigh)
+{
+    m_eventMask = (m_eventMask & EventMaskLowMask) | ((UINT64)eventMaskHigh << EventMaskHighShiftAmount);
+}
+
+// Reset those variables that is only for the current attach session
+inline void ProfilerInfo::ResetPerSessionStatus()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    pProfInterface = NULL;
+    eventMask.SetEventMask(COR_PRF_MONITOR_NONE);
+    eventMask.SetEventMaskHigh(COR_PRF_HIGH_MONITOR_NONE);
+}
+
+inline void ProfilerInfo::Init()
+{
+    curProfStatus.Init();
+    dwProfilerEvacuationCounter = 0;
+    ResetPerSessionStatus();
+    inUse = FALSE;
+}
+
+template<typename ConditionFunc>
+inline BOOL AnyProfilerPassesCondition(ConditionFunc condition)
+{
+    BOOL anyPassed = FALSE;
+    (&g_profControlBlock)->DoProfilerCallback(ProfilerCallbackType::ActiveOrInitializing,
+                                              condition, 
+                                              &anyPassed,
+                                              [](BOOL *pAnyPassed, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                                              {
+                                                   *pAnyPassed = TRUE;
+                                                   return S_OK;
+                                              });
+
+    return anyPassed;
+}
+
 //---------------------------------------------------------------------------------------
 // ProfControlBlock
 //---------------------------------------------------------------------------------------
 
-inline void ProfControlBlock::Init()
+inline void ProfControlBlock::Init()
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    mainProfilerInfo.Init();
+
+    for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i)
+    {
+        notificationOnlyProfilers[i].Init();
+    }
+
+    globalEventMask.SetEventMask(COR_PRF_MONITOR_NONE);
+    globalEventMask.SetEventMaskHigh(COR_PRF_HIGH_MONITOR_NONE);
+
+    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;
+
+    mainProfilerInfo.ResetPerSessionStatus();
+
+    fProfControlBlockInitialized = TRUE;
+
+    fProfilerRequestedRuntimeSuspend = FALSE;
+}
+
+
+inline BOOL ProfControlBlock::IsMainProfiler(EEToProfInterfaceImpl *pEEToProf)
+{
+    EEToProfInterfaceImpl *pProfInterface = mainProfilerInfo.pProfInterface.Load();
+    return pProfInterface == pEEToProf;
+}
+
+inline BOOL ProfControlBlock::IsMainProfiler(ProfToEEInterfaceImpl *pProfToEE)
+{
+    EEToProfInterfaceImpl *pProfInterface = mainProfilerInfo.pProfInterface.Load();
+    return pProfInterface != NULL && pProfInterface->m_pProfToEE == pProfToEE;
+}
+
+inline ProfilerInfo *ProfControlBlock::GetProfilerInfo(ProfToEEInterfaceImpl *pProfToEE)
+{
+    ProfilerInfo *pProfilerInfo = NULL;
+    IterateProfilers(ProfilerCallbackType::Active,
+                    [](ProfilerInfo *pProfilerInfo, ProfToEEInterfaceImpl *pProfToEE, ProfilerInfo **ppFoundProfilerInfo)
+                      {
+                          if (pProfilerInfo->pProfInterface->m_pProfToEE == pProfToEE)
+                          {
+                              *ppFoundProfilerInfo = pProfilerInfo;
+                          }
+                      },
+                      pProfToEE,
+                      &pProfilerInfo);
+
+    return pProfilerInfo;
+}
+
+#ifndef DACCESS_COMPILE
+inline ProfilerInfo *ProfControlBlock::FindNextFreeProfilerInfoSlot()
+{
+    for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i)
+    {
+        if (InterlockedCompareExchange((LONG *)notificationOnlyProfilers[i].inUse.GetPointer(), TRUE, FALSE) == FALSE) 
+        {
+            InterlockedIncrement(notificationProfilerCount.GetPointer());
+            return &(notificationOnlyProfilers[i]);
+        }
+    }
+
+    return NULL;
+}
+
+inline void ProfControlBlock::DeRegisterProfilerInfo(ProfilerInfo *pProfilerInfo)
+{
+    pProfilerInfo->inUse = FALSE;
+    InterlockedDecrement(notificationProfilerCount.GetPointer());
+}
+
+inline void ProfControlBlock::UpdateGlobalEventMask()
+{
+    while (true)
+    {
+        UINT64 originalEventMask = globalEventMask.m_eventMask;
+        UINT64 qwEventMask = 0;
+
+        IterateProfilers(ProfilerCallbackType::ActiveOrInitializing,
+                        [](ProfilerInfo *pProfilerInfo, UINT64 *pEventMask)
+                          {
+                              *pEventMask |= pProfilerInfo->eventMask.m_eventMask;
+                          },
+                          &qwEventMask);
+        
+        // We are relying on the memory barrier introduced by InterlockedCompareExchange64 to observer any
+        // change to the global event mask.
+        if ((UINT64)InterlockedCompareExchange64((LONG64 *)&(globalEventMask.m_eventMask), (LONG64)qwEventMask, (LONG64)originalEventMask) == originalEventMask)
+        {
+            break;
+        }
+    }
+}
+#endif // DACCESS_COMPILE
+
+inline BOOL ProfControlBlock::IsCallback3Supported()
+{
+    return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->IsCallback3Supported(); });
+}
+
+inline BOOL ProfControlBlock::IsCallback5Supported()
+{
+    return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->IsCallback5Supported(); });
+}
+
+inline BOOL ProfControlBlock::IsDisableTransparencySet()
+{
+    return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST); });
+}
+
+inline BOOL ProfControlBlock::RequiresGenericsContextForEnterLeave()
+{
+    return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->RequiresGenericsContextForEnterLeave(); }); 
+}
+
+inline bool DoesProfilerWantEEFunctionIDMapper(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return ((pProfilerInfo->pProfInterface->GetFunctionIDMapper()  != NULL) ||
+             (pProfilerInfo->pProfInterface->GetFunctionIDMapper2() != NULL));
+}
+
+inline UINT_PTR ProfControlBlock::EEFunctionIDMapper(FunctionID funcId, BOOL *pbHookFunction)
+{
+    LIMITED_METHOD_CONTRACT;
+    UINT_PTR ptr = NULL;
+    DoOneProfilerIteration(&mainProfilerInfo,
+                          ProfilerCallbackType::Active,
+                          [](ProfilerInfo *pProfilerInfo, FunctionID funcId, BOOL *pbHookFunction, UINT_PTR *pPtr)
+                          {
+                               if (DoesProfilerWantEEFunctionIDMapper(pProfilerInfo))
+                               {
+                                   *pPtr = pProfilerInfo->pProfInterface->EEFunctionIDMapper(funcId, pbHookFunction);
+                               }
+                          },
+                          funcId, pbHookFunction, &ptr);
+
+    return ptr;
+}
+
+inline BOOL IsProfilerTrackingThreads(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_THREADS);
+}
+
+inline void ProfControlBlock::ThreadCreated(ThreadID threadID)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingThreads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID threadID)
+                        {
+                            return profInterface->ThreadCreated(threadID);
+                        },
+                        threadID);
+}
+
+inline void ProfControlBlock::ThreadDestroyed(ThreadID threadID)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingThreads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID threadID)
+                        {
+                            return profInterface->ThreadDestroyed(threadID);
+                        },
+                        threadID);
+}
+
+inline void ProfControlBlock::ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingThreads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID managedThreadId, DWORD osThreadId)
+                        {
+                            return profInterface->ThreadAssignedToOSThread(managedThreadId, osThreadId);
+                        },
+                        managedThreadId, osThreadId);
+}
+
+inline void ProfControlBlock::ThreadNameChanged(ThreadID managedThreadId, ULONG cchName, WCHAR name[])
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingThreads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID managedThreadId, ULONG cchName, WCHAR name[])
+                        {
+                            return profInterface->ThreadNameChanged(managedThreadId, cchName, name);
+                        },
+                        managedThreadId, cchName, name);
+}
+
+inline void ProfControlBlock::Shutdown()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       [](ProfilerInfo *pProfilerInfo) { return true; },
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->Shutdown();
+                        });
+}
+
+inline BOOL IsProfilerTrackingJITInfo(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION);
+}
+
+inline void ProfControlBlock::JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingJITInfo,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock)
+                        {
+                            return profInterface->JITCompilationFinished(functionId, hrStatus, fIsSafeToBlock);
+                        },
+                        functionId, hrStatus, fIsSafeToBlock);
+}
+
+inline void ProfControlBlock::JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingJITInfo,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, BOOL fIsSafeToBlock)
+                        {
+                            return profInterface->JITCompilationStarted(functionId, fIsSafeToBlock);
+                        },
+                        functionId, fIsSafeToBlock);
+}
+
+inline void ProfControlBlock::DynamicMethodJITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingJITInfo,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader)
+                        {
+                            return profInterface->DynamicMethodJITCompilationStarted(functionId, fIsSafeToBlock, pILHeader, cbILHeader);
+                        },
+                        functionId, fIsSafeToBlock, pILHeader, cbILHeader);
+}
+
+inline void ProfControlBlock::DynamicMethodJITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingJITInfo,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock)
+                        {
+                            return profInterface->DynamicMethodJITCompilationFinished(functionId, hrStatus, fIsSafeToBlock);
+                        },
+                        functionId, hrStatus, fIsSafeToBlock);
+}
+
+inline BOOL IsProfilerMonitoringDynamicFunctionUnloads(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS);
+}
+
+inline void ProfControlBlock::DynamicMethodUnloaded(FunctionID functionId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerMonitoringDynamicFunctionUnloads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId)
+                        {
+                            return profInterface->DynamicMethodUnloaded(functionId);
+                        },
+                        functionId);
+}
+
+inline BOOL IsProfilerTrackingCacheSearches(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CACHE_SEARCHES);
+}
+
+inline void ProfControlBlock::JITCachedFunctionSearchStarted(FunctionID functionId, BOOL *pbUseCachedFunction)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    BOOL allTrue = TRUE;
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingCacheSearches,
+                       &allTrue,
+                       [](BOOL *pAllTrue, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, BOOL *pbUseCachedFunction)
+                        {
+                            HRESULT hr = profInterface->JITCachedFunctionSearchStarted(functionId, pbUseCachedFunction);
+                            *pAllTrue &= *pbUseCachedFunction;
+                            return hr;
+                        },
+                        functionId, pbUseCachedFunction);
+
+    // If any reject it, consider it rejected.
+    *pbUseCachedFunction = allTrue;
+}
+
+inline void ProfControlBlock::JITCachedFunctionSearchFinished(FunctionID functionId, COR_PRF_JIT_CACHE result)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingCacheSearches,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, COR_PRF_JIT_CACHE result)
+                        {
+                            return profInterface->JITCachedFunctionSearchFinished(functionId, result);
+                        },
+                        functionId, result);
+}
+
+inline HRESULT ProfControlBlock::JITInlining(FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    BOOL allTrue = TRUE;
+    HRESULT hr =  DoProfilerCallback(ProfilerCallbackType::Active,
+                                     IsProfilerTrackingJITInfo,
+                                     &allTrue,
+                                     [](BOOL *pAllTrue, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline)
+                                      {
+                                          HRESULT hr = profInterface->JITInlining(callerId, calleeId, pfShouldInline);
+                                          *pAllTrue &= *pfShouldInline;
+                                          return hr;
+                                      },
+                                      callerId, calleeId, pfShouldInline);
+
+    // If any reject it, consider it rejected.
+    *pfShouldInline = allTrue;
+    return hr;
+}
+
+inline BOOL IsRejitEnabled(ProfilerInfo *pProfilerInfo)
+{
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_ENABLE_REJIT);
+}
+
+inline void ProfControlBlock::ReJITCompilationStarted(FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock)
+{
+    LIMITED_METHOD_CONTRACT;
+    DoOneProfilerIteration(&mainProfilerInfo,
+                          ProfilerCallbackType::Active,
+                          [](ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock)
+                          {
+                               if (IsRejitEnabled(pProfilerInfo))
+                               {
+                                   pProfilerInfo->pProfInterface->ReJITCompilationStarted(functionId, reJitId, fIsSafeToBlock);
+                               }
+                          },
+                          functionId, reJitId, fIsSafeToBlock);
+}
+
+inline HRESULT ProfControlBlock::GetReJITParameters(ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl)
+{
+    LIMITED_METHOD_CONTRACT;
+    HRESULT hr = S_OK;
+    DoOneProfilerIteration(&mainProfilerInfo,
+                          ProfilerCallbackType::Active,
+                          [](ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl, HRESULT *pHr)
+                          {
+                               if (IsRejitEnabled(pProfilerInfo))
+                               {
+                                   *pHr = pProfilerInfo->pProfInterface->GetReJITParameters(moduleId, methodId, pFunctionControl);
+                               }
+                          },
+                          moduleId, methodId, pFunctionControl, &hr);
+    return hr;
+}
+
+inline void ProfControlBlock::ReJITCompilationFinished(FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock)
+{
+    LIMITED_METHOD_CONTRACT;
+    DoOneProfilerIteration(&mainProfilerInfo,
+                          ProfilerCallbackType::Active,
+                          [](ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock)
+                          {
+                               if (IsRejitEnabled(pProfilerInfo))
+                               {
+                                   pProfilerInfo->pProfInterface->ReJITCompilationFinished(functionId, reJitId, hrStatus, fIsSafeToBlock);
+                               }
+                          },
+                          functionId, reJitId, hrStatus, fIsSafeToBlock);
+}
+
+inline void ProfControlBlock::ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus)
+{
+    LIMITED_METHOD_CONTRACT;
+    DoOneProfilerIteration(&mainProfilerInfo,
+                          ProfilerCallbackType::Active,
+                          [](ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus)
+                          {
+                               if (IsRejitEnabled(pProfilerInfo))
+                               {
+                                   pProfilerInfo->pProfInterface->ReJITError(moduleId, methodId, functionId, hrStatus);
+                               }
+                          },
+                          moduleId, methodId, functionId, hrStatus);
+}
+
+inline BOOL IsProfilerTrackingModuleLoads(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_MODULE_LOADS);
+}
+
+inline void ProfControlBlock::ModuleLoadStarted(ModuleID moduleId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingModuleLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId)
+                        {
+                            return profInterface->ModuleLoadStarted(moduleId);
+                        },
+                        moduleId);
+}
+
+inline void ProfControlBlock::ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingModuleLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId, HRESULT hrStatus)
+                        {
+                            return profInterface->ModuleLoadFinished(moduleId, hrStatus);
+                        },
+                        moduleId, hrStatus);
+}
+
+inline void ProfControlBlock::ModuleUnloadStarted(ModuleID moduleId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingModuleLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId)
+                        {
+                            return profInterface->ModuleUnloadStarted(moduleId);
+                        },
+                        moduleId);
+}
+
+inline void ProfControlBlock::ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingModuleLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId, HRESULT hrStatus)
+                        {
+                            return profInterface->ModuleUnloadFinished(moduleId, hrStatus);
+                        },
+                        moduleId, hrStatus);
+}
+
+inline void ProfControlBlock::ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingModuleLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId, AssemblyID AssemblyId)
+                        {
+                            return profInterface->ModuleAttachedToAssembly(moduleId, AssemblyId);
+                        },
+                        moduleId, AssemblyId);
+}
+
+inline BOOL IsProfilerTrackingInMemorySymbolsUpdatesEnabled(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED);
+}
+
+inline void ProfControlBlock::ModuleInMemorySymbolsUpdated(ModuleID moduleId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingInMemorySymbolsUpdatesEnabled,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId)
+                        {
+                            return profInterface->ModuleInMemorySymbolsUpdated(moduleId);
+                        },
+                        moduleId);
+}
+
+inline BOOL IsProfilerTrackingClasses(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CLASS_LOADS);
+}
+
+inline void ProfControlBlock::ClassLoadStarted(ClassID classId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingClasses,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID classId)
+                        {
+                            return profInterface->ClassLoadStarted(classId);
+                        },
+                        classId);
+}
+
+inline void ProfControlBlock::ClassLoadFinished(ClassID classId, HRESULT hrStatus)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingClasses,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID classId, HRESULT hrStatus)
+                        {
+                            return profInterface->ClassLoadFinished(classId, hrStatus);
+                        },
+                        classId, hrStatus);
+}
+
+inline void ProfControlBlock::ClassUnloadStarted(ClassID classId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingClasses,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID classId)
+                        {
+                            return profInterface->ClassUnloadStarted(classId);
+                        },
+                        classId);
+}
+
+inline void ProfControlBlock::ClassUnloadFinished(ClassID classId, HRESULT hrStatus)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingClasses,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID classId, HRESULT hrStatus)
+                        {
+                            return profInterface->ClassUnloadFinished(classId, hrStatus);
+                        },
+                        classId, hrStatus);
+}
+
+inline BOOL IsProfilerTrackingAppDomainLoads(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_APPDOMAIN_LOADS);
+}
+
+inline void ProfControlBlock::AppDomainCreationStarted(AppDomainID appDomainId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingAppDomainLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AppDomainID appDomainId)
+                        {
+                            return profInterface->AppDomainCreationStarted(appDomainId);
+                        },
+                        appDomainId);
+}
+
+inline void ProfControlBlock::AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingAppDomainLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AppDomainID appDomainId, HRESULT hrStatus)
+                        {
+                            return profInterface->AppDomainCreationFinished(appDomainId, hrStatus);
+                        },
+                        appDomainId, hrStatus);
+}
+
+inline void ProfControlBlock::AppDomainShutdownStarted(AppDomainID appDomainId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingAppDomainLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AppDomainID appDomainId)
+                        {
+                            return profInterface->AppDomainShutdownStarted(appDomainId);
+                        },
+                        appDomainId);
+}
+
+inline void ProfControlBlock::AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingAppDomainLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AppDomainID appDomainId, HRESULT hrStatus)
+                        {
+                            return profInterface->AppDomainShutdownFinished(appDomainId, hrStatus);
+                        },
+                        appDomainId, hrStatus);
+}
+
+inline BOOL IsProfilerTrackingAssemblyLoads(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_ASSEMBLY_LOADS);
+}
+
+inline void ProfControlBlock::AssemblyLoadStarted(AssemblyID assemblyId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingAssemblyLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AssemblyID assemblyId)
+                        {
+                            return profInterface->AssemblyLoadStarted(assemblyId);
+                        },
+                        assemblyId);
+}
+
+inline void ProfControlBlock::AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingAssemblyLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AssemblyID assemblyId, HRESULT hrStatus)
+                        {
+                            return profInterface->AssemblyLoadFinished(assemblyId, hrStatus);
+                        },
+                        assemblyId, hrStatus);
+}
+
+inline void ProfControlBlock::AssemblyUnloadStarted(AssemblyID assemblyId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingAssemblyLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AssemblyID assemblyId)
+                        {
+                            return profInterface->AssemblyUnloadStarted(assemblyId);
+                        },
+                        assemblyId);
+}
+
+inline void ProfControlBlock::AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingAssemblyLoads,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AssemblyID assemblyId, HRESULT hrStatus)
+                        {
+                            return profInterface->AssemblyUnloadFinished(assemblyId, hrStatus);
+                        },
+                        assemblyId, hrStatus);
+}
+
+inline BOOL IsProfilerTrackingTransitions(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CODE_TRANSITIONS);
+}
+
+inline void ProfControlBlock::UnmanagedToManagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingTransitions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason)
+                        {
+                            return profInterface->UnmanagedToManagedTransition(functionId, reason);
+                        },
+                        functionId, reason);
+}
+
+inline void ProfControlBlock::ManagedToUnmanagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingTransitions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason)
+                        {
+                            return profInterface->ManagedToUnmanagedTransition(functionId, reason);
+                        },
+                        functionId, reason);
+}
+
+inline BOOL IsProfilerTrackingExceptions(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_EXCEPTIONS);
+}
+
+inline void ProfControlBlock::ExceptionThrown(ObjectID thrownObjectId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ObjectID thrownObjectId)
+                        {
+                            return profInterface->ExceptionThrown(thrownObjectId);
+                        },
+                        thrownObjectId);
+}
+
+inline void ProfControlBlock::ExceptionSearchFunctionEnter(FunctionID functionId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId)
+                        {
+                            return profInterface->ExceptionSearchFunctionEnter(functionId);
+                        },
+                        functionId);
+}
+
+inline void ProfControlBlock::ExceptionSearchFunctionLeave()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->ExceptionSearchFunctionLeave();
+                        });
+}
+
+inline void ProfControlBlock::ExceptionSearchFilterEnter(FunctionID funcId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID funcId)
+                        {
+                            return profInterface->ExceptionSearchFilterEnter(funcId);
+                        },
+                        funcId);
+}
+
+inline void ProfControlBlock::ExceptionSearchFilterLeave()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->ExceptionSearchFilterLeave();
+                        });
+}
+
+inline void ProfControlBlock::ExceptionSearchCatcherFound(FunctionID functionId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId)
+                        {
+                            return profInterface->ExceptionSearchCatcherFound(functionId);
+                        },
+                        functionId);
+}
+
+inline void ProfControlBlock::ExceptionOSHandlerEnter(FunctionID funcId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID funcId)
+                        {
+                            return profInterface->ExceptionOSHandlerEnter(funcId);
+                        },
+                        funcId);
+}
+
+inline void ProfControlBlock::ExceptionOSHandlerLeave(FunctionID funcId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID funcId)
+                        {
+                            return profInterface->ExceptionOSHandlerLeave(funcId);
+                        },
+                        funcId);
+}
+
+inline void ProfControlBlock::ExceptionUnwindFunctionEnter(FunctionID functionId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId)
+                        {
+                            return profInterface->ExceptionUnwindFunctionEnter(functionId);
+                        },
+                        functionId);
+}
+
+inline void ProfControlBlock::ExceptionUnwindFunctionLeave()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->ExceptionUnwindFunctionLeave();
+                        });
+}
+
+inline void ProfControlBlock::ExceptionUnwindFinallyEnter(FunctionID functionId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId)
+                        {
+                            return profInterface->ExceptionUnwindFinallyEnter(functionId);
+                        },
+                        functionId);
+}
+
+inline void ProfControlBlock::ExceptionUnwindFinallyLeave()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->ExceptionUnwindFinallyLeave();
+                        });
+}
+
+inline void ProfControlBlock::ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, ObjectID objectId)
+                        {
+                            return profInterface->ExceptionCatcherEnter(functionId, objectId);
+                        },
+                        functionId, objectId);
+}
+
+inline void ProfControlBlock::ExceptionCatcherLeave()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingExceptions,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->ExceptionCatcherLeave();
+                        });
+}
+
+inline BOOL IsProfilerTrackingCCW(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CCW);
+}
+
+inline void ProfControlBlock::COMClassicVTableCreated(ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingCCW,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots)
+                        {
+                            return profInterface->COMClassicVTableCreated(wrappedClassId, implementedIID, pVTable, cSlots);
+                        },
+                        wrappedClassId, implementedIID, pVTable, cSlots);
+}
+
+inline BOOL IsProfilerTrackingSuspends(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_SUSPENDS);
+}
+
+inline void ProfControlBlock::RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingSuspends,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, COR_PRF_SUSPEND_REASON suspendReason)
+                        {
+                            return profInterface->RuntimeSuspendStarted(suspendReason);
+                        },
+                        suspendReason);
+}
+
+inline void ProfControlBlock::RuntimeSuspendFinished()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingSuspends,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->RuntimeSuspendFinished();
+                        });
+}
+
+inline void ProfControlBlock::RuntimeSuspendAborted()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingSuspends,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->RuntimeSuspendAborted();
+                        });
+}
+
+inline void ProfControlBlock::RuntimeResumeStarted()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingSuspends,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->RuntimeResumeStarted();
+                        });
+}
+
+inline void ProfControlBlock::RuntimeResumeFinished()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingSuspends,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->RuntimeResumeFinished();
+                        });
+}
+
+inline void ProfControlBlock::RuntimeThreadSuspended(ThreadID suspendedThreadId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingSuspends,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID suspendedThreadId)
+                        {
+                            return profInterface->RuntimeThreadSuspended(suspendedThreadId);
+                        },
+                        suspendedThreadId);
+}
+
+inline void ProfControlBlock::RuntimeThreadResumed(ThreadID resumedThreadId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingSuspends,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID resumedThreadId)
+                        {
+                            return profInterface->RuntimeThreadResumed(resumedThreadId);
+                        },
+                        resumedThreadId);
+}
+
+inline BOOL IsProfilerTrackingAllocations(ProfilerInfo *pProfilerInfo)
 {
     CONTRACTL
     {
@@ -50,39 +1298,365 @@ inline void ProfControlBlock::Init()
     }
     CONTRACTL_END;
 
-    curProfStatus.Init();
+    return (pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_ENABLE_OBJECT_ALLOCATED)
+                || pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED));
+}
 
-    fGCInProgress = FALSE;
-    fBaseSystemClassesLoaded = FALSE;
-#ifdef PROF_TEST_ONLY_FORCE_ELT
-    fTestOnlyForceEnterLeave = FALSE;
-#endif
+inline void ProfControlBlock::ObjectAllocated(ObjectID objectId, ClassID classId)
+{
+    LIMITED_METHOD_CONTRACT;
 
-#ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED
-    fTestOnlyForceObjectAllocated = FALSE;
-#endif
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingAllocations,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ObjectID objectId, ClassID classId)
+                        {
+                            return profInterface->ObjectAllocated(objectId, classId);
+                        },
+                        objectId, classId);
+}
 
-#ifdef _DEBUG
-    fTestOnlyEnableICorProfilerInfo = FALSE;
-#endif // _DEBUG
 
-    fConcurrentGCDisabledForAttach = FALSE;
+inline BOOL IsProfilerTrackingGC(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
 
-    ResetPerSessionStatus();
+    return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_GC);
+}
 
-    fProfControlBlockInitialized = TRUE;
+inline void ProfControlBlock::FinalizeableObjectQueued(BOOL isCritical, ObjectID objectID)
+{
+    LIMITED_METHOD_CONTRACT;
 
-    fProfilerRequestedRuntimeSuspend = FALSE;
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, BOOL isCritical, ObjectID objectID)
+                        {
+                            return profInterface->FinalizeableObjectQueued(isCritical, objectID);
+                        },
+                        isCritical, objectID);
 }
 
-// Reset those variables that is only for the current attach session
-inline void ProfControlBlock::ResetPerSessionStatus()
+inline void ProfControlBlock::MovedReference(BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting)
 {
     LIMITED_METHOD_CONTRACT;
 
-    pProfInterface = NULL;
-    dwEventMask = COR_PRF_MONITOR_NONE;
-    dwEventMaskHigh = COR_PRF_HIGH_MONITOR_NONE;
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting)
+                        {
+                            return profInterface->MovedReference(pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting);
+                        },
+                        pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting);
+}
+
+inline void ProfControlBlock::EndMovedReferences(void *pHeapId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, void *pHeapId)
+                        {
+                            return profInterface->EndMovedReferences(pHeapId);
+                        },
+                        pHeapId);
+}
+
+inline void ProfControlBlock::RootReference2(BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId)
+                        {
+                            return profInterface->RootReference2(objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId);
+                        },
+                        objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId);
+}
+
+inline void ProfControlBlock::EndRootReferences2(void *pHeapId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, void *pHeapId)
+                        {
+                            return profInterface->EndRootReferences2(pHeapId);
+                        },
+                        pHeapId);
+}
+
+inline void ProfControlBlock::ConditionalWeakTableElementReference(BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId)
+                        {
+                            if (!profInterface->IsCallback5Supported())
+                            {
+                                return S_OK;
+                            }
+
+                            return profInterface->ConditionalWeakTableElementReference(primaryObjectId, secondaryObjectId, rootID, pHeapId);
+                        },
+                        primaryObjectId, secondaryObjectId, rootID, pHeapId);
+}
+
+inline void ProfControlBlock::EndConditionalWeakTableElementReferences(void *pHeapId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, void *pHeapId)
+                        {
+                            if (!profInterface->IsCallback5Supported())
+                            {
+                                return S_OK;
+                            }
+
+                            return profInterface->EndConditionalWeakTableElementReferences(pHeapId);
+                        },
+                        pHeapId);
+}
+
+inline void ProfControlBlock::AllocByClass(ObjectID objId, ClassID classId, void *pHeapId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ObjectID objId, ClassID classId, void *pHeapId)
+                        {
+                            return profInterface->AllocByClass(objId, classId, pHeapId);
+                        },
+                        objId, classId, pHeapId);
+}
+
+inline void ProfControlBlock::EndAllocByClass(void *pHeapId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, void *pHeapId)
+                        {
+                            return profInterface->EndAllocByClass(pHeapId);
+                        },
+                        pHeapId);
+}
+
+inline HRESULT ProfControlBlock::ObjectReference(ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    return DoProfilerCallback(ProfilerCallbackType::Active,
+                              IsProfilerTrackingGC,
+                              (void *)NULL,
+                              [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef)
+                               {
+                                   return profInterface->ObjectReference(objId, classId, cNumRefs, arrObjRef);
+                               },
+                               objId, classId, cNumRefs, arrObjRef);
+}
+
+inline void ProfControlBlock::HandleCreated(UINT_PTR handleId, ObjectID initialObjectId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, UINT_PTR handleId, ObjectID initialObjectId)
+                        {
+                            return profInterface->HandleCreated(handleId, initialObjectId);
+                        },
+                        handleId, initialObjectId);
+}
+
+inline void ProfControlBlock::HandleDestroyed(UINT_PTR handleId)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, UINT_PTR handleId)
+                        {
+                            return profInterface->HandleDestroyed(handleId);
+                        },
+                        handleId);
+}
+
+
+inline BOOL IsProfilerTrackingBasicGC(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_BASIC_GC);
+}
+
+inline BOOL IsProfilerTrackingMovedObjects(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS);
+}
+
+inline BOOL IsProfilerTrackingGCOrBasicGC(ProfilerInfo *pProfilerInfo)
+{
+    return IsProfilerTrackingGC(pProfilerInfo) || IsProfilerTrackingBasicGC(pProfilerInfo);
+}
+
+inline BOOL IsProfilerTrackingGCOrMovedObjects(ProfilerInfo *pProfilerInfo)
+{
+    return IsProfilerTrackingGC(pProfilerInfo) || IsProfilerTrackingMovedObjects(pProfilerInfo);
+}
+
+inline void ProfControlBlock::GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGCOrBasicGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason)
+                        {
+                            return profInterface->GarbageCollectionStarted(cGenerations, generationCollected, reason);
+                        },
+                        cGenerations, generationCollected, reason);
+}
+
+inline void ProfControlBlock::GarbageCollectionFinished()
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerTrackingGCOrBasicGC,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface)
+                        {
+                            return profInterface->GarbageCollectionFinished();
+                        });
+}
+
+
+inline BOOL IsProfilerMonitoringEventPipe(ProfilerInfo *pProfilerInfo)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_EVENT_PIPE);
+}
+
+
+inline void ProfControlBlock::EventPipeEventDelivered(EventPipeProvider *provider,
+                                                      DWORD eventId,
+                                                      DWORD eventVersion,
+                                                      ULONG cbMetadataBlob,
+                                                      LPCBYTE metadataBlob,
+                                                      ULONG cbEventData,
+                                                      LPCBYTE eventData,
+                                                      LPCGUID pActivityId,
+                                                      LPCGUID pRelatedActivityId,
+                                                      Thread *pEventThread,
+                                                      ULONG numStackFrames,
+                                                      UINT_PTR stackFrames[])
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerMonitoringEventPipe,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, EventPipeProvider *provider,
+                          DWORD eventId,
+                          DWORD eventVersion,
+                          ULONG cbMetadataBlob,
+                          LPCBYTE metadataBlob,
+                          ULONG cbEventData,
+                          LPCBYTE eventData,
+                          LPCGUID pActivityId,
+                          LPCGUID pRelatedActivityId,
+                          Thread *pEventThread,
+                          ULONG numStackFrames,
+                          UINT_PTR stackFrames[])
+                        {
+                            return profInterface->EventPipeEventDelivered(provider,
+                                                                   eventId,
+                                                                   eventVersion,
+                                                                   cbMetadataBlob,
+                                                                   metadataBlob,
+                                                                   cbEventData,
+                                                                   eventData,
+                                                                   pActivityId,
+                                                                   pRelatedActivityId,
+                                                                   pEventThread,
+                                                                   numStackFrames,
+                                                                   stackFrames);
+                        },
+                        provider,
+                        eventId,
+                        eventVersion,
+                        cbMetadataBlob,
+                        metadataBlob,
+                        cbEventData,
+                        eventData,
+                        pActivityId,
+                        pRelatedActivityId,
+                        pEventThread,
+                        numStackFrames,
+                        stackFrames);
+}
+
+inline void ProfControlBlock::EventPipeProviderCreated(EventPipeProvider *provider)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    DoProfilerCallback(ProfilerCallbackType::Active,
+                       IsProfilerMonitoringEventPipe,
+                       (void *)NULL,
+                       [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, EventPipeProvider *provider)
+                        {
+                            return profInterface->EventPipeProviderCreated(provider);
+                        },
+                        provider);
 }
 
 //---------------------------------------------------------------------------------------
@@ -90,14 +1664,18 @@ inline void ProfControlBlock::ResetPerSessionStatus()
 // 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);
+    return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->curProfStatus.Get() >= kProfStatusActive; });
+}
+
+inline BOOL CORMainProfilerPresent()
+{
+    LIMITED_METHOD_DAC_CONTRACT;
+
+    return (&g_profControlBlock)->mainProfilerInfo.curProfStatus.Get() >= kProfStatusActive;
 }
 
 // These return whether a CLR Profiler is actively loaded AND has requested the
@@ -113,10 +1691,10 @@ inline BOOL CORProfilerFunctionIDMapperEnabled()
     }
     CONTRACTL_END;
 
-    return (CORProfilerPresent() &&
+    return (CORMainProfilerPresent() &&
         (
-         ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper()  != NULL) ||
-         ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper2() != NULL)
+         ((&g_profControlBlock)->mainProfilerInfo.pProfInterface->GetFunctionIDMapper()  != NULL) ||
+         ((&g_profControlBlock)->mainProfilerInfo.pProfInterface->GetFunctionIDMapper2() != NULL)
         ));
 }
 
@@ -131,7 +1709,7 @@ inline BOOL CORProfilerTrackJITInfo()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_JIT_COMPILATION));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION));
 }
 
 inline BOOL CORProfilerTrackCacheSearches()
@@ -145,7 +1723,7 @@ inline BOOL CORProfilerTrackCacheSearches()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CACHE_SEARCHES));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CACHE_SEARCHES));
 }
 
 inline BOOL CORProfilerTrackModuleLoads()
@@ -159,7 +1737,7 @@ inline BOOL CORProfilerTrackModuleLoads()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_MODULE_LOADS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_MODULE_LOADS));
 }
 
 inline BOOL CORProfilerTrackAssemblyLoads()
@@ -173,7 +1751,7 @@ inline BOOL CORProfilerTrackAssemblyLoads()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ASSEMBLY_LOADS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ASSEMBLY_LOADS));
 }
 
 inline BOOL CORProfilerTrackAppDomainLoads()
@@ -187,7 +1765,7 @@ inline BOOL CORProfilerTrackAppDomainLoads()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_APPDOMAIN_LOADS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_APPDOMAIN_LOADS));
 }
 
 inline BOOL CORProfilerTrackThreads()
@@ -201,7 +1779,7 @@ inline BOOL CORProfilerTrackThreads()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_THREADS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_THREADS));
 }
 
 inline BOOL CORProfilerTrackClasses()
@@ -215,7 +1793,7 @@ inline BOOL CORProfilerTrackClasses()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CLASS_LOADS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CLASS_LOADS));
 }
 
 inline BOOL CORProfilerTrackGC()
@@ -229,7 +1807,7 @@ inline BOOL CORProfilerTrackGC()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_GC));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_GC));
 }
 
 inline BOOL CORProfilerTrackAllocationsEnabled()
@@ -248,7 +1826,7 @@ inline BOOL CORProfilerTrackAllocationsEnabled()
             (&g_profControlBlock)->fTestOnlyForceObjectAllocated ||
 #endif
             (CORProfilerPresent() &&
-                ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_OBJECT_ALLOCATED))
+                (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_OBJECT_ALLOCATED))
         );
 }
 
@@ -264,7 +1842,7 @@ inline BOOL CORProfilerTrackAllocations()
 
     return
             (CORProfilerTrackAllocationsEnabled() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_OBJECT_ALLOCATED));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_OBJECT_ALLOCATED));
 }
 
 inline BOOL CORProfilerTrackLargeAllocations()
@@ -279,7 +1857,7 @@ inline BOOL CORProfilerTrackLargeAllocations()
 
     return
             (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED));
 }
 
 inline BOOL CORProfilerEnableRejit()
@@ -292,8 +1870,8 @@ inline BOOL CORProfilerEnableRejit()
     }
     CONTRACTL_END;
 
-    return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_REJIT));
+    return (CORMainProfilerPresent() &&
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_REJIT));
 }
 
 inline BOOL CORProfilerTrackExceptions()
@@ -307,7 +1885,7 @@ inline BOOL CORProfilerTrackExceptions()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_EXCEPTIONS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_EXCEPTIONS));
 }
 
 inline BOOL CORProfilerTrackTransitions()
@@ -321,7 +1899,7 @@ inline BOOL CORProfilerTrackTransitions()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CODE_TRANSITIONS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CODE_TRANSITIONS));
 }
 
 inline BOOL CORProfilerTrackEnterLeave()
@@ -340,7 +1918,7 @@ inline BOOL CORProfilerTrackEnterLeave()
 #endif // PROF_TEST_ONLY_FORCE_ELT
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ENTERLEAVE));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ENTERLEAVE));
 }
 
 inline BOOL CORProfilerTrackCCW()
@@ -354,53 +1932,7 @@ inline BOOL CORProfilerTrackCCW()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CCW));
-}
-
-inline BOOL CORProfilerTrackRemoting()
-{
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        CANNOT_TAKE_LOCK;
-    }
-    CONTRACTL_END;
-
-    return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING));
-}
-
-inline BOOL CORProfilerTrackRemotingCookie()
-{
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        CANNOT_TAKE_LOCK;
-    }
-    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;
-    }
-    CONTRACTL_END;
-
-    return
-        (CORProfilerPresent() &&
-        (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_ASYNC)
-                             == COR_PRF_MONITOR_REMOTING_ASYNC));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CCW));
 }
 
 inline BOOL CORProfilerTrackSuspends()
@@ -414,7 +1946,7 @@ inline BOOL CORProfilerTrackSuspends()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_SUSPENDS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_SUSPENDS));
 }
 
 inline BOOL CORProfilerDisableInlining()
@@ -428,21 +1960,7 @@ inline BOOL CORProfilerDisableInlining()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_INLINING));
-}
-
-inline BOOL CORProfilerJITMapEnabled()
-{
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        CANNOT_TAKE_LOCK;
-    }
-    CONTRACTL_END;
-
-    return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_JIT_MAPS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_INLINING));
 }
 
 inline BOOL CORProfilerDisableOptimizations()
@@ -457,7 +1975,7 @@ inline BOOL CORProfilerDisableOptimizations()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_OPTIMIZATIONS));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_OPTIMIZATIONS));
 }
 
 inline BOOL CORProfilerUseProfileImages()
@@ -475,14 +1993,8 @@ inline BOOL CORProfilerUseProfileImages()
         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;
+    return (CORProfilerPresent() &&
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_REQUIRE_PROFILE_IMAGE));
 }
 
 inline BOOL CORProfilerDisableAllNGenImages()
@@ -490,14 +2002,14 @@ inline BOOL CORProfilerDisableAllNGenImages()
     LIMITED_METHOD_DAC_CONTRACT;
 
     return (CORProfilerPresent() &&
-            ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_ALL_NGEN_IMAGES));
+            (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_ALL_NGEN_IMAGES));
 }
 
 inline BOOL CORProfilerTrackConditionalWeakTableElements()
 {
     LIMITED_METHOD_DAC_CONTRACT;
 
-    return CORProfilerTrackGC() && (&g_profControlBlock)->pProfInterface->IsCallback5Supported();
+    return CORProfilerTrackGC() && (&g_profControlBlock)->IsCallback5Supported();
 }
 
 // CORProfilerPresentOrInitializing() returns nonzero iff a CLR Profiler is actively
@@ -508,8 +2020,8 @@ inline BOOL CORProfilerTrackConditionalWeakTableElements()
 // 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);
+    LIMITED_METHOD_CONTRACT;
+    return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->curProfStatus.Get() > kProfStatusDetaching; });
 }
 
 // These return whether a CLR Profiler has requested the specified functionality.
@@ -531,7 +2043,7 @@ inline BOOL CORProfilerELT3SlowPathEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)));
 }
 
 inline BOOL CORProfilerELT3SlowPathEnterEnabled()
@@ -545,7 +2057,7 @@ inline BOOL CORProfilerELT3SlowPathEnterEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)));
 }
 
 inline BOOL CORProfilerELT3SlowPathLeaveEnabled()
@@ -559,7 +2071,7 @@ inline BOOL CORProfilerELT3SlowPathLeaveEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)));
 }
 
 inline BOOL CORProfilerELT3SlowPathTailcallEnabled()
@@ -573,7 +2085,7 @@ inline BOOL CORProfilerELT3SlowPathTailcallEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FRAME_INFO)));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FRAME_INFO)));
 }
 
 inline BOOL CORProfilerELT2FastPathEnterEnabled()
@@ -587,7 +2099,7 @@ inline BOOL CORProfilerELT2FastPathEnterEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))));
+        !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))));
 }
 
 inline BOOL CORProfilerELT2FastPathLeaveEnabled()
@@ -601,7 +2113,7 @@ inline BOOL CORProfilerELT2FastPathLeaveEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))));
+        !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))));
 }
 
 inline BOOL CORProfilerELT2FastPathTailcallEnabled()
@@ -615,7 +2127,7 @@ inline BOOL CORProfilerELT2FastPathTailcallEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO))));
+        !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO))));
 }
 
 inline BOOL CORProfilerFunctionArgsEnabled()
@@ -629,7 +2141,7 @@ inline BOOL CORProfilerFunctionArgsEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_ARGS));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_ARGS));
 }
 
 inline BOOL CORProfilerFunctionReturnValueEnabled()
@@ -643,7 +2155,7 @@ inline BOOL CORProfilerFunctionReturnValueEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_RETVAL));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_RETVAL));
 }
 
 inline BOOL CORProfilerFrameInfoEnabled()
@@ -657,7 +2169,7 @@ inline BOOL CORProfilerFrameInfoEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FRAME_INFO));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FRAME_INFO));
 }
 
 inline BOOL CORProfilerStackSnapshotEnabled()
@@ -671,21 +2183,7 @@ inline BOOL CORProfilerStackSnapshotEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresentOrInitializing() &&
-        ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_STACK_SNAPSHOT));
-}
-
-inline BOOL CORProfilerAddsAssemblyReferences()
-{
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        CANNOT_TAKE_LOCK;
-    }
-    CONTRACTL_END;
-
-    return (CORProfilerPresent() &&
-        ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_STACK_SNAPSHOT));
 }
 
 inline BOOL CORProfilerInMemorySymbolsUpdatesEnabled()
@@ -699,10 +2197,10 @@ inline BOOL CORProfilerInMemorySymbolsUpdatesEnabled()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-        ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED));
 }
 
-inline BOOL CORProfilerIsMonitoringDynamicFunctionUnloads()
+inline BOOL CORProfilerTrackDynamicFunctionUnloads()
 {
     CONTRACTL
     {
@@ -713,7 +2211,7 @@ inline BOOL CORProfilerIsMonitoringDynamicFunctionUnloads()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-        ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS));
 }
 
 inline BOOL CORProfilerDisableTieredCompilation()
@@ -728,7 +2226,7 @@ inline BOOL CORProfilerDisableTieredCompilation()
 
 
     return (CORProfilerPresent() &&
-         ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_DISABLE_TIERED_COMPILATION));
+         (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_DISABLE_TIERED_COMPILATION));
 }
 
 inline BOOL CORProfilerTrackBasicGC()
@@ -742,7 +2240,7 @@ inline BOOL CORProfilerTrackBasicGC()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-         ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_BASIC_GC));
+         (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_BASIC_GC));
 }
 
 inline BOOL CORProfilerTrackGCMovedObjects()
@@ -756,10 +2254,10 @@ inline BOOL CORProfilerTrackGCMovedObjects()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-         ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS));
+         (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS));
 }
 
-inline BOOL CORProfilerIsMonitoringEventPipe()
+inline BOOL CORProfilerTrackEventPipe()
 {
     CONTRACTL
     {
@@ -770,55 +2268,38 @@ inline BOOL CORProfilerIsMonitoringEventPipe()
     CONTRACTL_END;
 
     return (CORProfilerPresent() &&
-        ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_EVENT_PIPE));
+        (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_EVENT_PIPE));
 }
 
 #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 *>> EvacuationCounterHolder;
-
-
 //---------------------------------------------------------------------------------------
-// These macros must be placed around any access to g_profControlBlock.pProfInterface by
+// These macros must be placed around any callbacks to g_profControlBlock by
 // the EE. Example:
 //    {
-//        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
-//        g_profControlBlock.pProfInterface->AppDomainCreationStarted(MyAppDomainID);
-//        END_PIN_PROFILER();
+//        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads;
+//        g_profControlBlock.AppDomainCreationStarted(MyAppDomainID);
+//        END_PROFILER_CALLBACK();
 //    }
-// The parameter to the BEGIN_PIN_PROFILER is the condition you want to check for, to
+// The parameter to the BEGIN_PROFILER_CALLBACK 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
+// true), execute whatever code you place inside the BEGIN/END_PROFILER_CALLBACK 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());
+//        BEGIN_PROFILER_CALLBACK(CorProfilerTrackTransitions);
 //        if (!pNSL->pMD->IsQCall())
 //        {
-//            g_profControlBlock.pProfInterface->
+//            g_profControlBlock.
 //                ManagedToUnmanagedTransition((FunctionID) pNSL->pMD,
 //                COR_PRF_TRANSITION_CALL);
 //        }
-//        END_PIN_PROFILER();
+//        END_PROFILER_CALLBACK();
 //    }
 //
 // This ensures that the extra condition check (in this case "if
@@ -827,35 +2308,19 @@ typedef Wrapper<Thread *, ProfilingAPIUtility::IncEvacuationCounter, ProfilingAP
 //
 // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization
 // for more details about how the synchronization works.
-#define BEGIN_PIN_PROFILER(condition)                                                       \
+#define BEGIN_PROFILER_CALLBACK(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
+#define END_PROFILER_CALLBACK()  }
 
 #else // PROFILING_SUPPORTED && !CROSSGEN_COMPILE
 
 // Profiling feature not supported
 
-#define BEGIN_PIN_PROFILER(condition)       if (false) {
-#define END_PIN_PROFILER()                  }
+#define BEGIN_PROFILER_CALLBACK(condition)       if (false) {
+#define END_PROFILER_CALLBACK()                  }
 
 #endif // PROFILING_SUPPORTED && !CROSSGEN_COMPILE
 
index b375b6a..7d6a5b6 100644 (file)
@@ -247,7 +247,7 @@ inline void SArray<ELEMENT, BITWISE_COPY>::Delete(const Iterator &i, COUNT_T cou
 }
 
 template <typename ELEMENT, BOOL BITWISE_COPY>
-inline void SArray<ELEMENT, BITWISE_COPY>:: Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount)
+inline void SArray<ELEMENT, BITWISE_COPY>::Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount)
 {
     WRAPPER_NO_CONTRACT;
     DestructBuffer(i, deleteCount);
index 498c52b..07b78a4 100644 (file)
@@ -90,6 +90,9 @@ MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback9,0x27583EC3,0xC8F5,0x482F,0x80,0x
 MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback10,0xCEC5B60E,0xC69C,0x495F,0x87,0xF6,0x84,0xD2,0x8E,0xE1,0x6F,0xFB);
 
 
+MIDL_DEFINE_GUID(IID, IID_ICorProfilerCallback11,0x42350846,0xAAED,0x47F7,0xB1,0x28,0xFD,0x0C,0x98,0x88,0x1C,0xDE);
+
+
 MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo,0x28B5557D,0x3F3F,0x48b4,0x90,0xB2,0x5F,0x9E,0xEA,0x2F,0x6C,0x48);
 
 
@@ -141,6 +144,9 @@ MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo11,0x06398876,0x8987,0x4154,0xB6,0x21,
 MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo12,0x27b24ccd,0x1cb1,0x47c5,0x96,0xee,0x98,0x19,0x0d,0xc3,0x09,0x59);
 
 
+MIDL_DEFINE_GUID(IID, IID_ICorProfilerInfo13,0x19C4179D,0xF92C,0x4D25,0x9F,0x20,0x5F,0xEB,0xFB,0xBD,0x29,0x78);
+
+
 MIDL_DEFINE_GUID(IID, IID_ICorProfilerMethodEnum,0xFCCEE788,0x0088,0x454B,0xA8,0x11,0xC9,0x9F,0x29,0x8D,0x19,0x42);
 
 
index 2311aa5..85ce868 100644 (file)
@@ -4,10 +4,8 @@
 
 
  /* File created by MIDL compiler version 8.01.0622 */
-/* at Mon Jan 18 19:14:07 2038
- */
-/* Compiler settings for C:/git/runtime/src/coreclr/inc/corprof.idl:
-    Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 
+/* Compiler settings for corprof.idl:
+    Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 
     protocol : dce , ms_ext, c_ext, robust
     error checks: allocation ref bounds_check enum stub_data 
     VC __declspec() decoration level: 
@@ -115,6 +113,13 @@ typedef interface ICorProfilerCallback10 ICorProfilerCallback10;
 #endif  /* __ICorProfilerCallback10_FWD_DEFINED__ */
 
 
+#ifndef __ICorProfilerCallback11_FWD_DEFINED__
+#define __ICorProfilerCallback11_FWD_DEFINED__
+typedef interface ICorProfilerCallback11 ICorProfilerCallback11;
+
+#endif  /* __ICorProfilerCallback11_FWD_DEFINED__ */
+
+
 #ifndef __ICorProfilerInfo_FWD_DEFINED__
 #define __ICorProfilerInfo_FWD_DEFINED__
 typedef interface ICorProfilerInfo ICorProfilerInfo;
@@ -552,6 +557,7 @@ enum __MIDL___MIDL_itf_corprof_0000_0000_0005
         COR_PRF_ALL = 0x8fffffff,
         COR_PRF_REQUIRE_PROFILE_IMAGE   = ( ( COR_PRF_USE_PROFILE_IMAGES | COR_PRF_MONITOR_CODE_TRANSITIONS )  | COR_PRF_MONITOR_ENTERLEAVE ) ,
         COR_PRF_ALLOWABLE_AFTER_ATTACH  = ( ( ( ( ( ( ( ( ( ( COR_PRF_MONITOR_THREADS | COR_PRF_MONITOR_MODULE_LOADS )  | COR_PRF_MONITOR_ASSEMBLY_LOADS )  | COR_PRF_MONITOR_APPDOMAIN_LOADS )  | COR_PRF_ENABLE_STACK_SNAPSHOT )  | COR_PRF_MONITOR_GC )  | COR_PRF_MONITOR_SUSPENDS )  | COR_PRF_MONITOR_CLASS_LOADS )  | COR_PRF_MONITOR_EXCEPTIONS )  | COR_PRF_MONITOR_JIT_COMPILATION )  | COR_PRF_ENABLE_REJIT ) ,
+        COR_PRF_ALLOWABLE_NOTIFICATION_PROFILER = ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( COR_PRF_MONITOR_FUNCTION_UNLOADS | COR_PRF_MONITOR_CLASS_LOADS )  | COR_PRF_MONITOR_MODULE_LOADS )  | COR_PRF_MONITOR_ASSEMBLY_LOADS )  | COR_PRF_MONITOR_APPDOMAIN_LOADS )  | COR_PRF_MONITOR_JIT_COMPILATION )  | COR_PRF_MONITOR_EXCEPTIONS )  | COR_PRF_MONITOR_OBJECT_ALLOCATED )  | COR_PRF_MONITOR_THREADS )  | COR_PRF_MONITOR_CODE_TRANSITIONS )  | COR_PRF_MONITOR_CCW )  | COR_PRF_MONITOR_SUSPENDS )  | COR_PRF_MONITOR_CACHE_SEARCHES )  | COR_PRF_DISABLE_INLINING )  | COR_PRF_DISABLE_OPTIMIZATIONS )  | COR_PRF_ENABLE_OBJECT_ALLOCATED )  | COR_PRF_MONITOR_CLR_EXCEPTIONS )  | COR_PRF_ENABLE_STACK_SNAPSHOT )  | COR_PRF_USE_PROFILE_IMAGES )  | COR_PRF_DISABLE_ALL_NGEN_IMAGES ) ,
         COR_PRF_MONITOR_IMMUTABLE   = ( ( ( ( ( ( ( ( ( ( ( ( ( ( COR_PRF_MONITOR_CODE_TRANSITIONS | COR_PRF_MONITOR_REMOTING )  | COR_PRF_MONITOR_REMOTING_COOKIE )  | COR_PRF_MONITOR_REMOTING_ASYNC )  | COR_PRF_ENABLE_INPROC_DEBUGGING )  | COR_PRF_ENABLE_JIT_MAPS )  | COR_PRF_DISABLE_OPTIMIZATIONS )  | COR_PRF_DISABLE_INLINING )  | COR_PRF_ENABLE_OBJECT_ALLOCATED )  | COR_PRF_ENABLE_FUNCTION_ARGS )  | COR_PRF_ENABLE_FUNCTION_RETVAL )  | COR_PRF_ENABLE_FRAME_INFO )  | COR_PRF_USE_PROFILE_IMAGES )  | COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST )  | COR_PRF_DISABLE_ALL_NGEN_IMAGES ) 
     }   COR_PRF_MONITOR;
 
@@ -569,6 +575,7 @@ enum __MIDL___MIDL_itf_corprof_0000_0000_0006
         COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED  = 0x40,
         COR_PRF_HIGH_MONITOR_EVENT_PIPE = 0x80,
         COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = ( ( ( ( ( COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS )  | COR_PRF_HIGH_BASIC_GC )  | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS )  | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED )  | COR_PRF_HIGH_MONITOR_EVENT_PIPE ) ,
+        COR_PRF_HIGH_ALLOWABLE_NOTIFICATION_PROFILER    = ( ( ( ( ( ( COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS )  | COR_PRF_HIGH_DISABLE_TIERED_COMPILATION )  | COR_PRF_HIGH_BASIC_GC )  | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS )  | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED )  | COR_PRF_HIGH_MONITOR_EVENT_PIPE ) ,
         COR_PRF_HIGH_MONITOR_IMMUTABLE  = COR_PRF_HIGH_DISABLE_TIERED_COMPILATION
     }   COR_PRF_HIGH_MONITOR;
 
@@ -8351,11 +8358,829 @@ EXTERN_C const IID IID_ICorProfilerCallback10;
 #endif  /* __ICorProfilerCallback10_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_corprof_0000_0010 */
+#ifndef __ICorProfilerCallback11_INTERFACE_DEFINED__
+#define __ICorProfilerCallback11_INTERFACE_DEFINED__
+
+/* interface ICorProfilerCallback11 */
+/* [local][unique][uuid][object] */ 
+
+
+EXTERN_C const IID IID_ICorProfilerCallback11;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+    
+    MIDL_INTERFACE("42350846-AAED-47F7-B128-FD0C98881CDE")
+    ICorProfilerCallback11 : public ICorProfilerCallback10
+    {
+    public:
+        virtual HRESULT STDMETHODCALLTYPE LoadAsNotficationOnly( 
+            BOOL *pbNotificationOnly) = 0;
+        
+    };
+    
+    
+#else   /* C style interface */
+
+    typedef struct ICorProfilerCallback11Vtbl
+    {
+        BEGIN_INTERFACE
+        
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ REFIID riid,
+            /* [annotation][iid_is][out] */ 
+            _COM_Outptr_  void **ppvObject);
+        
+        ULONG ( STDMETHODCALLTYPE *AddRef )( 
+            ICorProfilerCallback11 * This);
+        
+        ULONG ( STDMETHODCALLTYPE *Release )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *Initialize )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ IUnknown *pICorProfilerInfoUnk);
+        
+        HRESULT ( STDMETHODCALLTYPE *Shutdown )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ AppDomainID appDomainId);
+        
+        HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ AppDomainID appDomainId,
+            /* [in] */ HRESULT hrStatus);
+        
+        HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ AppDomainID appDomainId);
+        
+        HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ AppDomainID appDomainId,
+            /* [in] */ HRESULT hrStatus);
+        
+        HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ AssemblyID assemblyId);
+        
+        HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ AssemblyID assemblyId,
+            /* [in] */ HRESULT hrStatus);
+        
+        HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ AssemblyID assemblyId);
+        
+        HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ AssemblyID assemblyId,
+            /* [in] */ HRESULT hrStatus);
+        
+        HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ModuleID moduleId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ModuleID moduleId,
+            /* [in] */ HRESULT hrStatus);
+        
+        HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ModuleID moduleId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ModuleID moduleId,
+            /* [in] */ HRESULT hrStatus);
+        
+        HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ModuleID moduleId,
+            /* [in] */ AssemblyID AssemblyId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ClassID classId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ClassID classId,
+            /* [in] */ HRESULT hrStatus);
+        
+        HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ClassID classId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ClassID classId,
+            /* [in] */ HRESULT hrStatus);
+        
+        HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId);
+        
+        HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ BOOL fIsSafeToBlock);
+        
+        HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ HRESULT hrStatus,
+            /* [in] */ BOOL fIsSafeToBlock);
+        
+        HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [out] */ BOOL *pbUseCachedFunction);
+        
+        HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ COR_PRF_JIT_CACHE result);
+        
+        HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId);
+        
+        HRESULT ( STDMETHODCALLTYPE *JITInlining )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID callerId,
+            /* [in] */ FunctionID calleeId,
+            /* [out] */ BOOL *pfShouldInline);
+        
+        HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ThreadID threadId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ThreadID threadId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ThreadID managedThreadId,
+            /* [in] */ DWORD osThreadId);
+        
+        HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ GUID *pCookie,
+            /* [in] */ BOOL fIsAsync);
+        
+        HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ GUID *pCookie,
+            /* [in] */ BOOL fIsAsync);
+        
+        HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ GUID *pCookie,
+            /* [in] */ BOOL fIsAsync);
+        
+        HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ GUID *pCookie,
+            /* [in] */ BOOL fIsAsync);
+        
+        HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ COR_PRF_TRANSITION_REASON reason);
+        
+        HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ COR_PRF_TRANSITION_REASON reason);
+        
+        HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ COR_PRF_SUSPEND_REASON suspendReason);
+        
+        HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ThreadID threadId);
+        
+        HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ThreadID threadId);
+        
+        HRESULT ( STDMETHODCALLTYPE *MovedReferences )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ULONG cMovedObjectIDRanges,
+            /* [size_is][in] */ ObjectID oldObjectIDRangeStart[  ],
+            /* [size_is][in] */ ObjectID newObjectIDRangeStart[  ],
+            /* [size_is][in] */ ULONG cObjectIDRangeLength[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ObjectID objectId,
+            /* [in] */ ClassID classId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ULONG cClassCount,
+            /* [size_is][in] */ ClassID classIds[  ],
+            /* [size_is][in] */ ULONG cObjects[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ObjectID objectId,
+            /* [in] */ ClassID classId,
+            /* [in] */ ULONG cObjectRefs,
+            /* [size_is][in] */ ObjectID objectRefIds[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *RootReferences )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ULONG cRootRefs,
+            /* [size_is][in] */ ObjectID rootRefIds[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ObjectID thrownObjectId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ UINT_PTR __unused);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ UINT_PTR __unused);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ ObjectID objectId);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ClassID wrappedClassId,
+            /* [in] */ REFGUID implementedIID,
+            /* [in] */ void *pVTable,
+            /* [in] */ ULONG cSlots);
+        
+        HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ClassID wrappedClassId,
+            /* [in] */ REFGUID implementedIID,
+            /* [in] */ void *pVTable);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ThreadID threadId,
+            /* [in] */ ULONG cchName,
+            /* [annotation][in] */ 
+            _In_reads_opt_(cchName)  WCHAR name[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ int cGenerations,
+            /* [size_is][in] */ BOOL generationCollected[  ],
+            /* [in] */ COR_PRF_GC_REASON reason);
+        
+        HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ULONG cSurvivingObjectIDRanges,
+            /* [size_is][in] */ ObjectID objectIDRangeStart[  ],
+            /* [size_is][in] */ ULONG cObjectIDRangeLength[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ DWORD finalizerFlags,
+            /* [in] */ ObjectID objectID);
+        
+        HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ULONG cRootRefs,
+            /* [size_is][in] */ ObjectID rootRefIds[  ],
+            /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[  ],
+            /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[  ],
+            /* [size_is][in] */ UINT_PTR rootIds[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *HandleCreated )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ GCHandleID handleId,
+            /* [in] */ ObjectID initialObjectId);
+        
+        HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ GCHandleID handleId);
+        
+        HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ IUnknown *pCorProfilerInfoUnk,
+            /* [in] */ void *pvClientData,
+            /* [in] */ UINT cbClientData);
+        
+        HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( 
+            ICorProfilerCallback11 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ ReJITID rejitId,
+            /* [in] */ BOOL fIsSafeToBlock);
+        
+        HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ModuleID moduleId,
+            /* [in] */ mdMethodDef methodId,
+            /* [in] */ ICorProfilerFunctionControl *pFunctionControl);
+        
+        HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ ReJITID rejitId,
+            /* [in] */ HRESULT hrStatus,
+            /* [in] */ BOOL fIsSafeToBlock);
+        
+        HRESULT ( STDMETHODCALLTYPE *ReJITError )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ModuleID moduleId,
+            /* [in] */ mdMethodDef methodId,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ HRESULT hrStatus);
+        
+        HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ULONG cMovedObjectIDRanges,
+            /* [size_is][in] */ ObjectID oldObjectIDRangeStart[  ],
+            /* [size_is][in] */ ObjectID newObjectIDRangeStart[  ],
+            /* [size_is][in] */ SIZE_T cObjectIDRangeLength[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ULONG cSurvivingObjectIDRanges,
+            /* [size_is][in] */ ObjectID objectIDRangeStart[  ],
+            /* [size_is][in] */ SIZE_T cObjectIDRangeLength[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ ULONG cRootRefs,
+            /* [size_is][in] */ ObjectID keyRefIds[  ],
+            /* [size_is][in] */ ObjectID valueRefIds[  ],
+            /* [size_is][in] */ GCHandleID rootIds[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( 
+            ICorProfilerCallback11 * This,
+            /* [string][in] */ const WCHAR *wszAssemblyPath,
+            /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider);
+        
+        HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( 
+            ICorProfilerCallback11 * This,
+            ModuleID moduleId);
+        
+        HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationStarted )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ BOOL fIsSafeToBlock,
+            /* [in] */ LPCBYTE pILHeader,
+            /* [in] */ ULONG cbILHeader);
+        
+        HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationFinished )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId,
+            /* [in] */ HRESULT hrStatus,
+            /* [in] */ BOOL fIsSafeToBlock);
+        
+        HRESULT ( STDMETHODCALLTYPE *DynamicMethodUnloaded )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ FunctionID functionId);
+        
+        HRESULT ( STDMETHODCALLTYPE *EventPipeEventDelivered )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ EVENTPIPE_PROVIDER provider,
+            /* [in] */ DWORD eventId,
+            /* [in] */ DWORD eventVersion,
+            /* [in] */ ULONG cbMetadataBlob,
+            /* [size_is][in] */ LPCBYTE metadataBlob,
+            /* [in] */ ULONG cbEventData,
+            /* [size_is][in] */ LPCBYTE eventData,
+            /* [in] */ LPCGUID pActivityId,
+            /* [in] */ LPCGUID pRelatedActivityId,
+            /* [in] */ ThreadID eventThread,
+            /* [in] */ ULONG numStackFrames,
+            /* [length_is][in] */ UINT_PTR stackFrames[  ]);
+        
+        HRESULT ( STDMETHODCALLTYPE *EventPipeProviderCreated )( 
+            ICorProfilerCallback11 * This,
+            /* [in] */ EVENTPIPE_PROVIDER provider);
+        
+        HRESULT ( STDMETHODCALLTYPE *LoadAsNotficationOnly )( 
+            ICorProfilerCallback11 * This,
+            BOOL *pbNotificationOnly);
+        
+        END_INTERFACE
+    } ICorProfilerCallback11Vtbl;
+
+    interface ICorProfilerCallback11
+    {
+        CONST_VTBL struct ICorProfilerCallback11Vtbl *lpVtbl;
+    };
+
+    
+
+#ifdef COBJMACROS
+
+
+#define ICorProfilerCallback11_QueryInterface(This,riid,ppvObject)  \
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) 
+
+#define ICorProfilerCallback11_AddRef(This) \
+    ( (This)->lpVtbl -> AddRef(This) ) 
+
+#define ICorProfilerCallback11_Release(This)    \
+    ( (This)->lpVtbl -> Release(This) ) 
+
+
+#define ICorProfilerCallback11_Initialize(This,pICorProfilerInfoUnk)    \
+    ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) 
+
+#define ICorProfilerCallback11_Shutdown(This)   \
+    ( (This)->lpVtbl -> Shutdown(This) ) 
+
+#define ICorProfilerCallback11_AppDomainCreationStarted(This,appDomainId)   \
+    ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) 
+
+#define ICorProfilerCallback11_AppDomainCreationFinished(This,appDomainId,hrStatus) \
+    ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) 
+
+#define ICorProfilerCallback11_AppDomainShutdownStarted(This,appDomainId)   \
+    ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) 
+
+#define ICorProfilerCallback11_AppDomainShutdownFinished(This,appDomainId,hrStatus) \
+    ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) 
+
+#define ICorProfilerCallback11_AssemblyLoadStarted(This,assemblyId) \
+    ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) 
+
+#define ICorProfilerCallback11_AssemblyLoadFinished(This,assemblyId,hrStatus)   \
+    ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) 
+
+#define ICorProfilerCallback11_AssemblyUnloadStarted(This,assemblyId)   \
+    ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) 
+
+#define ICorProfilerCallback11_AssemblyUnloadFinished(This,assemblyId,hrStatus) \
+    ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) 
+
+#define ICorProfilerCallback11_ModuleLoadStarted(This,moduleId) \
+    ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) 
+
+#define ICorProfilerCallback11_ModuleLoadFinished(This,moduleId,hrStatus)   \
+    ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) 
+
+#define ICorProfilerCallback11_ModuleUnloadStarted(This,moduleId)   \
+    ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) 
+
+#define ICorProfilerCallback11_ModuleUnloadFinished(This,moduleId,hrStatus) \
+    ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) 
+
+#define ICorProfilerCallback11_ModuleAttachedToAssembly(This,moduleId,AssemblyId)   \
+    ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) 
+
+#define ICorProfilerCallback11_ClassLoadStarted(This,classId)   \
+    ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) 
+
+#define ICorProfilerCallback11_ClassLoadFinished(This,classId,hrStatus) \
+    ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) 
+
+#define ICorProfilerCallback11_ClassUnloadStarted(This,classId) \
+    ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) 
+
+#define ICorProfilerCallback11_ClassUnloadFinished(This,classId,hrStatus)   \
+    ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) 
+
+#define ICorProfilerCallback11_FunctionUnloadStarted(This,functionId)   \
+    ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) 
+
+#define ICorProfilerCallback11_JITCompilationStarted(This,functionId,fIsSafeToBlock)    \
+    ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) 
+
+#define ICorProfilerCallback11_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock)  \
+    ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) 
+
+#define ICorProfilerCallback11_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction)  \
+    ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) 
+
+#define ICorProfilerCallback11_JITCachedFunctionSearchFinished(This,functionId,result)  \
+    ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) 
+
+#define ICorProfilerCallback11_JITFunctionPitched(This,functionId)  \
+    ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) 
+
+#define ICorProfilerCallback11_JITInlining(This,callerId,calleeId,pfShouldInline)   \
+    ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) 
+
+#define ICorProfilerCallback11_ThreadCreated(This,threadId) \
+    ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) 
+
+#define ICorProfilerCallback11_ThreadDestroyed(This,threadId)   \
+    ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) 
+
+#define ICorProfilerCallback11_ThreadAssignedToOSThread(This,managedThreadId,osThreadId)    \
+    ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) 
+
+#define ICorProfilerCallback11_RemotingClientInvocationStarted(This)    \
+    ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) 
+
+#define ICorProfilerCallback11_RemotingClientSendingMessage(This,pCookie,fIsAsync)  \
+    ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) 
+
+#define ICorProfilerCallback11_RemotingClientReceivingReply(This,pCookie,fIsAsync)  \
+    ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) 
+
+#define ICorProfilerCallback11_RemotingClientInvocationFinished(This)   \
+    ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) 
+
+#define ICorProfilerCallback11_RemotingServerReceivingMessage(This,pCookie,fIsAsync)    \
+    ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) 
+
+#define ICorProfilerCallback11_RemotingServerInvocationStarted(This)    \
+    ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) 
+
+#define ICorProfilerCallback11_RemotingServerInvocationReturned(This)   \
+    ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) 
+
+#define ICorProfilerCallback11_RemotingServerSendingReply(This,pCookie,fIsAsync)    \
+    ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) 
+
+#define ICorProfilerCallback11_UnmanagedToManagedTransition(This,functionId,reason) \
+    ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) 
+
+#define ICorProfilerCallback11_ManagedToUnmanagedTransition(This,functionId,reason) \
+    ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) 
+
+#define ICorProfilerCallback11_RuntimeSuspendStarted(This,suspendReason)    \
+    ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) 
+
+#define ICorProfilerCallback11_RuntimeSuspendFinished(This) \
+    ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) 
+
+#define ICorProfilerCallback11_RuntimeSuspendAborted(This)  \
+    ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) 
+
+#define ICorProfilerCallback11_RuntimeResumeStarted(This)   \
+    ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) 
+
+#define ICorProfilerCallback11_RuntimeResumeFinished(This)  \
+    ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) 
+
+#define ICorProfilerCallback11_RuntimeThreadSuspended(This,threadId)    \
+    ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) 
+
+#define ICorProfilerCallback11_RuntimeThreadResumed(This,threadId)  \
+    ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) 
+
+#define ICorProfilerCallback11_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength)  \
+    ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) 
+
+#define ICorProfilerCallback11_ObjectAllocated(This,objectId,classId)   \
+    ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) 
+
+#define ICorProfilerCallback11_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects)  \
+    ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) 
+
+#define ICorProfilerCallback11_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \
+    ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) 
+
+#define ICorProfilerCallback11_RootReferences(This,cRootRefs,rootRefIds)    \
+    ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) 
+
+#define ICorProfilerCallback11_ExceptionThrown(This,thrownObjectId) \
+    ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) 
+
+#define ICorProfilerCallback11_ExceptionSearchFunctionEnter(This,functionId)    \
+    ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) 
+
+#define ICorProfilerCallback11_ExceptionSearchFunctionLeave(This)   \
+    ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) 
+
+#define ICorProfilerCallback11_ExceptionSearchFilterEnter(This,functionId)  \
+    ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) 
+
+#define ICorProfilerCallback11_ExceptionSearchFilterLeave(This) \
+    ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) 
+
+#define ICorProfilerCallback11_ExceptionSearchCatcherFound(This,functionId) \
+    ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) 
+
+#define ICorProfilerCallback11_ExceptionOSHandlerEnter(This,__unused)   \
+    ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) 
+
+#define ICorProfilerCallback11_ExceptionOSHandlerLeave(This,__unused)   \
+    ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) 
+
+#define ICorProfilerCallback11_ExceptionUnwindFunctionEnter(This,functionId)    \
+    ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) 
+
+#define ICorProfilerCallback11_ExceptionUnwindFunctionLeave(This)   \
+    ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) 
+
+#define ICorProfilerCallback11_ExceptionUnwindFinallyEnter(This,functionId) \
+    ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) 
+
+#define ICorProfilerCallback11_ExceptionUnwindFinallyLeave(This)    \
+    ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) 
+
+#define ICorProfilerCallback11_ExceptionCatcherEnter(This,functionId,objectId)  \
+    ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) 
+
+#define ICorProfilerCallback11_ExceptionCatcherLeave(This)  \
+    ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) 
+
+#define ICorProfilerCallback11_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots)   \
+    ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) 
+
+#define ICorProfilerCallback11_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable)    \
+    ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) 
+
+#define ICorProfilerCallback11_ExceptionCLRCatcherFound(This)   \
+    ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) 
+
+#define ICorProfilerCallback11_ExceptionCLRCatcherExecute(This) \
+    ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) 
+
+
+#define ICorProfilerCallback11_ThreadNameChanged(This,threadId,cchName,name)    \
+    ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) 
+
+#define ICorProfilerCallback11_GarbageCollectionStarted(This,cGenerations,generationCollected,reason)   \
+    ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) 
+
+#define ICorProfilerCallback11_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength)   \
+    ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) 
+
+#define ICorProfilerCallback11_GarbageCollectionFinished(This)  \
+    ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) 
+
+#define ICorProfilerCallback11_FinalizeableObjectQueued(This,finalizerFlags,objectID)   \
+    ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) 
+
+#define ICorProfilerCallback11_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds)   \
+    ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) 
+
+#define ICorProfilerCallback11_HandleCreated(This,handleId,initialObjectId) \
+    ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) 
+
+#define ICorProfilerCallback11_HandleDestroyed(This,handleId)   \
+    ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) 
+
+
+#define ICorProfilerCallback11_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData)  \
+    ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) 
+
+#define ICorProfilerCallback11_ProfilerAttachComplete(This) \
+    ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) 
+
+#define ICorProfilerCallback11_ProfilerDetachSucceeded(This)    \
+    ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) 
+
+
+#define ICorProfilerCallback11_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock)  \
+    ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) 
+
+#define ICorProfilerCallback11_GetReJITParameters(This,moduleId,methodId,pFunctionControl)  \
+    ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) 
+
+#define ICorProfilerCallback11_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock)    \
+    ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) 
+
+#define ICorProfilerCallback11_ReJITError(This,moduleId,methodId,functionId,hrStatus)   \
+    ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) 
+
+#define ICorProfilerCallback11_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \
+    ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) 
+
+#define ICorProfilerCallback11_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength)  \
+    ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) 
+
+
+#define ICorProfilerCallback11_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds)  \
+    ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) 
+
+
+#define ICorProfilerCallback11_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider)  \
+    ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) 
+
+
+#define ICorProfilerCallback11_ModuleInMemorySymbolsUpdated(This,moduleId)  \
+    ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) 
+
+
+#define ICorProfilerCallback11_DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader)  \
+    ( (This)->lpVtbl -> DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) ) 
+
+#define ICorProfilerCallback11_DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \
+    ( (This)->lpVtbl -> DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) 
+
+
+#define ICorProfilerCallback11_DynamicMethodUnloaded(This,functionId)   \
+    ( (This)->lpVtbl -> DynamicMethodUnloaded(This,functionId) ) 
+
+
+#define ICorProfilerCallback11_EventPipeEventDelivered(This,provider,eventId,eventVersion,cbMetadataBlob,metadataBlob,cbEventData,eventData,pActivityId,pRelatedActivityId,eventThread,numStackFrames,stackFrames)  \
+    ( (This)->lpVtbl -> EventPipeEventDelivered(This,provider,eventId,eventVersion,cbMetadataBlob,metadataBlob,cbEventData,eventData,pActivityId,pRelatedActivityId,eventThread,numStackFrames,stackFrames) ) 
+
+#define ICorProfilerCallback11_EventPipeProviderCreated(This,provider)  \
+    ( (This)->lpVtbl -> EventPipeProviderCreated(This,provider) ) 
+
+
+#define ICorProfilerCallback11_LoadAsNotficationOnly(This,pbNotificationOnly)   \
+    ( (This)->lpVtbl -> LoadAsNotficationOnly(This,pbNotificationOnly) ) 
+
+#endif /* COBJMACROS */
+
+
+#endif  /* C style interface */
+
+
+
+
+#endif  /* __ICorProfilerCallback11_INTERFACE_DEFINED__ */
+
+
+/* interface __MIDL_itf_corprof_0000_0011 */
 /* [local] */ 
 
 typedef /* [public] */ 
-enum __MIDL___MIDL_itf_corprof_0000_0010_0001
+enum __MIDL___MIDL_itf_corprof_0000_0011_0001
     {
         COR_PRF_CODEGEN_DISABLE_INLINING    = 0x1,
         COR_PRF_CODEGEN_DISABLE_ALL_OPTIMIZATIONS   = 0x2
@@ -8363,8 +9188,8 @@ enum __MIDL___MIDL_itf_corprof_0000_0010_0001
 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0010_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0010_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0011_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0011_v0_0_s_ifspec;
 
 #ifndef __ICorProfilerInfo_INTERFACE_DEFINED__
 #define __ICorProfilerInfo_INTERFACE_DEFINED__
index 79e1f17..d8a275c 100644 (file)
@@ -87,6 +87,8 @@
                              message="$(string.RuntimePublisher.TypeDiagnosticKeywordMessage)" symbol="CLR_TYPEDIAGNOSTIC_KEYWORD" />
                     <keyword name="JitInstrumentationDataKeyword" mask="0x10000000000"
                              message="$(string.RuntimePublisher.JitInstrumentationDataKeywordMessage)" symbol="CLR_JITINSTRUMENTEDDATA_KEYWORD" />
+                    <keyword name="ProfilerKeyword" mask="0x20000000000"
+                             message="$(string.RuntimePublisher.ProfilerKeywordMessage)" symbol="CLR_PROFILER_KEYWORD" />
                 </keywords>
                 <!--Tasks-->
                 <tasks>
                             <opcode name="ExecutionCheckpoint" message="$(string.RuntimePublisher.ExecutionCheckpointOpcodeMessage)" symbol="CLR_EXECUTIONCHECKPOINT_OPCODE" value="11"> </opcode>
                         </opcodes>
                     </task>
-                <!--Next available ID is 36-->
+                    <task name="Profiler" symbol="CLR_PROFILER_TASK"
+                          value="36" eventGUID="{68895E46-FD03-4528-89D2-5E1FBB1D3BCF}"
+                          message="$(string.RuntimePublisher.ProfilerTaskMessage)">
+                        <opcodes>
+                            <opcode name="Profiler" message="$(string.RuntimePublisher.ProfilerOpcodeMessage)" symbol="CLR_PROFILER_OPCODE" value="11"/>
+                        </opcodes>
+                    </task>
+                <!--Next available ID is 37-->
                 </tasks>
                 <!--Maps-->
                 <maps>
                             </ExecutionCheckpoint>
                         </UserData>
                     </template>
+
+                    <template tid="ProfilerMessage">
+                      <data name="ClrInstanceID" inType="win:UInt16"/>
+                      <data name="Message" inType="win:UnicodeString" />
+                      <UserData>
+                        <Settings xmlns="myNs">
+                          <ClrInstanceID> %1 </ClrInstanceID>
+                          <Message> %2 </Message>
+                        </Settings>
+                      </UserData>
+                    </template>
                 </templates>
 
                 <events>
                            task="JitInstrumentationData"
                            symbol="JitInstrumentationDataVerbose" message="$(string.RuntimePublisher.JitInstrumentationDataEventMessage)"/>
 
+                    <event value="299" version="0" level="win:Informational"  template="ProfilerMessage"
+                           keywords ="ProfilerKeyword" opcode="Profiler"
+                           task="Profiler"
+                           symbol="ProfilerMessage" message="$(string.RuntimePublisher.ProfilerEventMessage)"/>
+
                     <!-- Execution Checkpoint event 300 -->
                     <event value="300" version="0" level="win:Informational"  template="ExecutionCheckpoint"
                            keywords ="PerfTrackKeyword" opcode="ExecutionCheckpoint" task="ExecutionCheckpoint" symbol="ExecutionCheckpoint"
                 <string id="RuntimePublisher.AssemblyLoadFromResolveHandlerInvokedEventMessage" value="ClrInstanceID=%1;%nAssemblyName=%2;%nIsTrackedLoad=%3;%nRequestingAssemblyPath=%4;%nComputedRequestedAssemblyPath=%5" />
                 <string id="RuntimePublisher.KnownPathProbedEventMessage" value="ClrInstanceID=%1;%nFilePath=%2;%nSource=%3;%nResult=%4" />
                 <string id="RuntimePublisher.JitInstrumentationDataEventMessage" value="%MethodId=%4" />
+                <string id="RuntimePublisher.ProfilerEventMessage" value="%Message=%2" />
                 <string id="RuntimePublisher.ResolutionAttemptedEventMessage" value="ClrInstanceID=%1;%nAssemblyName=%2;%nStage=%3;%nAssemblyLoadContext=%4;%nResult=%5;%nResultAssemblyName=%6;%nResultAssemblyPath=%7;%nErrorMessage=%8" />
                 <string id="RuntimePublisher.StackEventMessage" value="ClrInstanceID=%1;%nReserved1=%2;%nReserved2=%3;%nFrameCount=%4;%nStack=%5" />
                 <string id="RuntimePublisher.AppDomainMemAllocatedEventMessage" value="AppDomainID=%1;%nAllocated=%2;%nClrInstanceID=%3" />
                 <string id="RuntimePublisher.TypeLoadTaskMessage" value="TypeLoad" />
                 <string id="RuntimePublisher.JitInstrumentationDataTaskMessage" value="JitInstrumentationData" />
                 <string id="RuntimePublisher.ExecutionCheckpointTaskMessage" value="ExecutionCheckpoint" />
+                <string id="RuntimePublisher.ProfilerTaskMessage" value="Profiler" />
 
                 <string id="RundownPublisher.EEStartupTaskMessage" value="Runtime" />
                 <string id="RundownPublisher.MethodTaskMessage" value="Method" />
                 <string id="RuntimePublisher.MethodDiagnosticKeywordMessage" value="MethodDiagnostic" />
                 <string id="RuntimePublisher.TypeDiagnosticKeywordMessage" value="TypeDiagnostic" />
                 <string id="RuntimePublisher.JitInstrumentationDataKeywordMessage" value="JitInstrumentationData" />
+                <string id="RuntimePublisher.ProfilerKeywordMessage" value="Profiler" />
                 <string id="RuntimePublisher.GenAwareBeginEventMessage" value="NONE" />
                 <string id="RuntimePublisher.GenAwareEndEventMessage" value="NONE" />
                 <string id="RundownPublisher.LoaderKeywordMessage" value="Loader" />
 
                 <string id="RuntimePublisher.ExecutionCheckpointOpcodeMessage" value="ExecutionCheckpoint" />
 
+                <string id="RuntimePublisher.ProfilerOpcodeMessage" value="ProfilerMessage" />
+
                 <string id="RundownPublisher.MethodDCStartOpcodeMessage" value="DCStart" />
                 <string id="RundownPublisher.MethodDCEndOpcodeMessage" value="DCStop" />
                 <string id="RundownPublisher.MethodDCStartVerboseOpcodeMessage" value="DCStartVerbose" />
index 3f7c4de..f7bf57c 100644 (file)
@@ -2034,31 +2034,31 @@ void SystemDomain::NotifyProfilerStartup()
     CONTRACTL_END;
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
         _ASSERTE(System());
-        g_profControlBlock.pProfInterface->AppDomainCreationStarted((AppDomainID) System());
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AppDomainCreationStarted((AppDomainID) System());
+        END_PROFILER_CALLBACK();
     }
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
         _ASSERTE(System());
-        g_profControlBlock.pProfInterface->AppDomainCreationFinished((AppDomainID) System(), S_OK);
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AppDomainCreationFinished((AppDomainID) System(), S_OK);
+        END_PROFILER_CALLBACK();
     }
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
         _ASSERTE(System()->DefaultDomain());
-        g_profControlBlock.pProfInterface->AppDomainCreationStarted((AppDomainID) System()->DefaultDomain());
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AppDomainCreationStarted((AppDomainID) System()->DefaultDomain());
+        END_PROFILER_CALLBACK();
     }
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
         _ASSERTE(System()->DefaultDomain());
-        g_profControlBlock.pProfInterface->AppDomainCreationFinished((AppDomainID) System()->DefaultDomain(), S_OK);
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AppDomainCreationFinished((AppDomainID) System()->DefaultDomain(), S_OK);
+        END_PROFILER_CALLBACK();
     }
 }
 
@@ -2073,31 +2073,31 @@ HRESULT SystemDomain::NotifyProfilerShutdown()
     CONTRACTL_END;
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
         _ASSERTE(System());
-        g_profControlBlock.pProfInterface->AppDomainShutdownStarted((AppDomainID) System());
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AppDomainShutdownStarted((AppDomainID) System());
+        END_PROFILER_CALLBACK();
     }
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
         _ASSERTE(System());
-        g_profControlBlock.pProfInterface->AppDomainShutdownFinished((AppDomainID) System(), S_OK);
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AppDomainShutdownFinished((AppDomainID) System(), S_OK);
+        END_PROFILER_CALLBACK();
     }
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
         _ASSERTE(System()->DefaultDomain());
-        g_profControlBlock.pProfInterface->AppDomainShutdownStarted((AppDomainID) System()->DefaultDomain());
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AppDomainShutdownStarted((AppDomainID) System()->DefaultDomain());
+        END_PROFILER_CALLBACK();
     }
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
         _ASSERTE(System()->DefaultDomain());
-        g_profControlBlock.pProfInterface->AppDomainShutdownFinished((AppDomainID) System()->DefaultDomain(), S_OK);
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AppDomainShutdownFinished((AppDomainID) System()->DefaultDomain(), S_OK);
+        END_PROFILER_CALLBACK();
     }
     return (S_OK);
 }
index 6f45022..9d4cd4a 100644 (file)
@@ -270,10 +270,10 @@ void ProfilerCallAssemblyUnloadStarted(Assembly* assemblyUnloaded)
 {
     WRAPPER_NO_CONTRACT;
     {
-        BEGIN_PIN_PROFILER(CORProfilerPresent());
+        BEGIN_PROFILER_CALLBACK(CORProfilerPresent());
         GCX_PREEMP();
-        g_profControlBlock.pProfInterface->AssemblyUnloadStarted((AssemblyID)assemblyUnloaded);
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AssemblyUnloadStarted((AssemblyID)assemblyUnloaded);
+        END_PROFILER_CALLBACK();
     }
 }
 
@@ -281,10 +281,10 @@ void ProfilerCallAssemblyUnloadFinished(Assembly* assemblyUnloaded)
 {
     WRAPPER_NO_CONTRACT;
     {
-        BEGIN_PIN_PROFILER(CORProfilerPresent());
+        BEGIN_PROFILER_CALLBACK(CORProfilerPresent());
         GCX_PREEMP();
-        g_profControlBlock.pProfInterface->AssemblyUnloadFinished((AssemblyID) assemblyUnloaded, S_OK);
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AssemblyUnloadFinished((AssemblyID) assemblyUnloaded, S_OK);
+        END_PROFILER_CALLBACK();
     }
 }
 #endif
@@ -347,10 +347,10 @@ Assembly * Assembly::Create(
 
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAssemblyLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAssemblyLoads());
         GCX_COOP();
-        g_profControlBlock.pProfInterface->AssemblyLoadStarted((AssemblyID)(Assembly *) pAssembly);
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->AssemblyLoadStarted((AssemblyID)(Assembly *) pAssembly);
+        END_PROFILER_CALLBACK();
     }
 
     // Need TRY/HOOK instead of holder so we can get HR of exception thrown for profiler callback
@@ -363,11 +363,11 @@ Assembly * Assembly::Create(
     EX_HOOK
     {
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackAssemblyLoads());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackAssemblyLoads());
             GCX_COOP();
-            g_profControlBlock.pProfInterface->AssemblyLoadFinished((AssemblyID)(Assembly *) pAssembly,
+            (&g_profControlBlock)->AssemblyLoadFinished((AssemblyID)(Assembly *) pAssembly,
                                                                     GET_EXCEPTION()->GetHR());
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
     EX_END_HOOK;
index 1dff1e9..a41ed4c 100644 (file)
@@ -163,10 +163,10 @@ void Module::DoInit(AllocMemTracker *pamTracker, LPCWSTR szName)
 
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackModuleLoads());
         GCX_COOP();
-        g_profControlBlock.pProfInterface->ModuleLoadStarted((ModuleID) this);
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->ModuleLoadStarted((ModuleID) this);
+        END_PROFILER_CALLBACK();
     }
     // Need TRY/HOOK instead of holder so we can get HR of exception thrown for profiler callback
     EX_TRY
@@ -180,9 +180,9 @@ void Module::DoInit(AllocMemTracker *pamTracker, LPCWSTR szName)
     EX_HOOK
     {
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
-            g_profControlBlock.pProfInterface->ModuleLoadFinished((ModuleID) this, GET_EXCEPTION()->GetHR());
-            END_PIN_PROFILER();
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackModuleLoads());
+            (&g_profControlBlock)->ModuleLoadFinished((ModuleID) this, GET_EXCEPTION()->GetHR());
+            END_PROFILER_CALLBACK();
         }
     }
     EX_END_HOOK;
@@ -291,20 +291,20 @@ void Module::NotifyProfilerLoadFinished(HRESULT hr)
         BOOL profilerCallbackHappened = FALSE;
         // Notify the profiler, this may cause metadata to be updated
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackModuleLoads());
             {
                 GCX_PREEMP();
-                g_profControlBlock.pProfInterface->ModuleLoadFinished((ModuleID) this, hr);
+                (&g_profControlBlock)->ModuleLoadFinished((ModuleID) this, hr);
 
                 if (SUCCEEDED(hr))
                 {
-                    g_profControlBlock.pProfInterface->ModuleAttachedToAssembly((ModuleID) this,
+                    (&g_profControlBlock)->ModuleAttachedToAssembly((ModuleID) this,
                                                                                 (AssemblyID)m_pAssembly);
                 }
 
                 profilerCallbackHappened = TRUE;
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
 
         // If there are more types than before, add these new types to the
@@ -315,13 +315,13 @@ void Module::NotifyProfilerLoadFinished(HRESULT hr)
         }
 
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackAssemblyLoads());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackAssemblyLoads());
             if (IsManifest())
             {
                 GCX_COOP();
-                g_profControlBlock.pProfInterface->AssemblyLoadFinished((AssemblyID) m_pAssembly, hr);
+                (&g_profControlBlock)->AssemblyLoadFinished((AssemblyID) m_pAssembly, hr);
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 }
@@ -1219,7 +1219,7 @@ void Module::Destruct()
     LOG((LF_EEMEM, INFO3, "Deleting module %x\n", this));
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackModuleLoads());
         if (!IsBeingUnloaded())
         {
             // Profiler is causing some peripheral class loads. Probably this just needs
@@ -1227,14 +1227,14 @@ void Module::Destruct()
             EX_TRY
             {
                 GCX_PREEMP();
-                g_profControlBlock.pProfInterface->ModuleUnloadStarted((ModuleID) this);
+                (&g_profControlBlock)->ModuleUnloadStarted((ModuleID) this);
             }
             EX_CATCH
             {
             }
             EX_END_CATCH(SwallowAllExceptions);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -1277,19 +1277,19 @@ void Module::Destruct()
 
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackModuleLoads());
         // Profiler is causing some peripheral class loads. Probably this just needs
         // to be turned into a Fault_not_fatal and moved to a specific place inside the profiler.
         EX_TRY
         {
             GCX_PREEMP();
-            g_profControlBlock.pProfInterface->ModuleUnloadFinished((ModuleID) this, S_OK);
+            (&g_profControlBlock)->ModuleUnloadFinished((ModuleID) this, S_OK);
         }
         EX_CATCH
         {
         }
         EX_END_CATCH(SwallowAllExceptions);
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 
     if (m_pValidatedEmitter.Load() != NULL)
@@ -3129,7 +3129,7 @@ void Module::StartUnload()
     WRAPPER_NO_CONTRACT;
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackModuleLoads());
         if (!IsBeingUnloaded())
         {
             // Profiler is causing some peripheral class loads. Probably this just needs
@@ -3137,14 +3137,14 @@ void Module::StartUnload()
             EX_TRY
             {
                 GCX_PREEMP();
-                g_profControlBlock.pProfInterface->ModuleUnloadStarted((ModuleID) this);
+                (&g_profControlBlock)->ModuleUnloadStarted((ModuleID) this);
             }
             EX_CATCH
             {
             }
             EX_END_CATCH(SwallowAllExceptions);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -3607,11 +3607,11 @@ void Module::SetSymbolBytes(LPCBYTE pbSyms, DWORD cbSyms)
     IfFailThrow(HRESULT_FROM_WIN32(dwError));
 
 #if PROFILING_SUPPORTED && !defined(CROSSGEN_COMPILE)
-    BEGIN_PIN_PROFILER(CORProfilerInMemorySymbolsUpdatesEnabled());
+    BEGIN_PROFILER_CALLBACK(CORProfilerInMemorySymbolsUpdatesEnabled());
     {
-        g_profControlBlock.pProfInterface->ModuleInMemorySymbolsUpdated((ModuleID) this);
+        (&g_profControlBlock)->ModuleInMemorySymbolsUpdated((ModuleID) this);
     }
-    END_PIN_PROFILER();
+    END_PROFILER_CALLBACK();
 #endif //PROFILING_SUPPORTED && !defined(CROSSGEN_COMPILE)
 
     ETW::CodeSymbolLog::EmitCodeSymbols(this);
index 14e9dd9..cdc5925 100644 (file)
@@ -703,11 +703,6 @@ void EEStartupHelper()
         }
 #endif
 
-#ifdef PROFILING_SUPPORTED
-        // The diagnostics server might register a profiler for delayed startup, indicate here that 
-        // it is not currently set. This will be set to TRUE if a profiler is registered.
-       g_profControlBlock.fIsStoredProfilerRegistered = FALSE;
-#endif // PROFILING_SUPPORTED
 #ifdef FEATURE_PERFTRACING
         DiagnosticServerAdapter::Initialize();
         DiagnosticServerAdapter::PauseForDiagnosticsMonitor();
@@ -1404,10 +1399,10 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading)
             // Don't call back in to the profiler if we are being torn down, it might be unloaded
             if (!fIsDllUnloading)
             {
-                BEGIN_PIN_PROFILER(CORProfilerPresent());
+                BEGIN_PROFILER_CALLBACK(CORProfilerPresent());
                 GCX_PREEMP();
-                g_profControlBlock.pProfInterface->Shutdown();
-                END_PIN_PROFILER();
+                (&g_profControlBlock)->Shutdown();
+                END_PROFILER_CALLBACK();
             }
 
             g_fEEShutDown |= ShutDown_Profiler;
index 17417e0..6f2da9d 100644 (file)
@@ -94,7 +94,7 @@ void EEClass::Destruct(MethodTable * pOwningMT)
 #ifdef PROFILING_SUPPORTED
     // If profiling, then notify the class is getting unloaded.
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackClasses());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackClasses());
         {
             // Calls to the profiler callback may throw, or otherwise fail, if
             // the profiler AVs/throws an unhandled exception/etc. We don't want
@@ -115,7 +115,7 @@ void EEClass::Destruct(MethodTable * pOwningMT)
             {
                 GCX_PREEMP();
 
-                g_profControlBlock.pProfInterface->ClassUnloadStarted((ClassID) pOwningMT);
+                (&g_profControlBlock)->ClassUnloadStarted((ClassID) pOwningMT);
             }
             EX_CATCH
             {
@@ -125,7 +125,7 @@ void EEClass::Destruct(MethodTable * pOwningMT)
             }
             EX_END_CATCH(RethrowTerminalExceptions);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -178,7 +178,7 @@ void EEClass::Destruct(MethodTable * pOwningMT)
 #ifdef PROFILING_SUPPORTED
     // If profiling, then notify the class is getting unloaded.
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackClasses());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackClasses());
         {
             // See comments in the call to ClassUnloadStarted for details on this
             // FAULT_NOT_FATAL marker and exception swallowing.
@@ -186,14 +186,14 @@ void EEClass::Destruct(MethodTable * pOwningMT)
             EX_TRY
             {
                 GCX_PREEMP();
-                g_profControlBlock.pProfInterface->ClassUnloadFinished((ClassID) pOwningMT, S_OK);
+                (&g_profControlBlock)->ClassUnloadFinished((ClassID) pOwningMT, S_OK);
             }
             EX_CATCH
             {
             }
             EX_END_CATCH(RethrowTerminalExceptions);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
index 6569222..62eccc0 100644 (file)
@@ -3452,7 +3452,7 @@ void ClassLoader::Notify(TypeHandle typeHnd)
 
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackClasses());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackClasses());
         // We don't tell profilers about typedescs, as per IF above.  Also, we don't
         // tell profilers about:
         if (
@@ -3465,7 +3465,7 @@ void ClassLoader::Notify(TypeHandle typeHnd)
         {
             LOG((LF_CLASSLOADER, LL_INFO1000, "Notifying profiler of Started1 %p %s\n", pMT, pMT->GetDebugClassName()));
             // Record successful load of the class for the profiler
-            g_profControlBlock.pProfInterface->ClassLoadStarted(TypeHandleToClassID(typeHnd));
+            (&g_profControlBlock)->ClassLoadStarted(TypeHandleToClassID(typeHnd));
 
             //
             // Profiler can turn off TrackClasses during the Started() callback.  Need to
@@ -3474,11 +3474,11 @@ void ClassLoader::Notify(TypeHandle typeHnd)
             if (CORProfilerTrackClasses())
             {
                 LOG((LF_CLASSLOADER, LL_INFO1000, "Notifying profiler of Finished1 %p %s\n", pMT, pMT->GetDebugClassName()));
-                g_profControlBlock.pProfInterface->ClassLoadFinished(TypeHandleToClassID(typeHnd),
+                (&g_profControlBlock)->ClassLoadFinished(TypeHandleToClassID(typeHnd),
                     S_OK);
             }
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif //PROFILING_SUPPORTED
 
index eb5b5ab..dfee278 100644 (file)
@@ -3725,7 +3725,7 @@ BOOL ComMethodTable::LayOutInterfaceMethodTable(MethodTable* pClsMT)
 #ifdef PROFILING_SUPPORTED
     // Notify profiler of the CCW, so it can avoid double-counting.
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackCCW());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackCCW());
 #if defined(_DEBUG)
         WCHAR rIID[40]; // {00000000-0000-0000-0000-000000000000}
         GuidToLPWSTR(m_IID, rIID, lengthof(rIID));
@@ -3735,11 +3735,11 @@ BOOL ComMethodTable::LayOutInterfaceMethodTable(MethodTable* pClsMT)
         LOG((LF_CORPROF, LL_INFO100, "COMClassicVTableCreated Class:%#x, IID:{%08x-...}, vTbl:%#08x\n",
              pItfClass, m_IID.Data1, pUnkVtable));
 #endif
-        g_profControlBlock.pProfInterface->COMClassicVTableCreated((ClassID) TypeHandle(pItfClass).AsPtr(),
+        (&g_profControlBlock)->COMClassicVTableCreated((ClassID) TypeHandle(pItfClass).AsPtr(),
                                                                    m_IID,
                                                                    pUnkVtable,
                                                                    m_cbSlots+cbExtraSlots);
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
    }
 #endif // PROFILING_SUPPORTED
 
@@ -4858,7 +4858,7 @@ ComCallWrapperTemplate* ComCallWrapperTemplate::CreateTemplate(TypeHandle thClas
         // Notify profiler of the CCW, so it can avoid double-counting.
         if (pTemplate->SupportsIClassX())
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackCCW());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackCCW());
             // When under the profiler, we'll eagerly generate the IClassX CMT.
             pTemplate->GetClassComMT();
 
@@ -4880,11 +4880,11 @@ ComCallWrapperTemplate* ComCallWrapperTemplate::CreateTemplate(TypeHandle thClas
             LOG((LF_CORPROF, LL_INFO100, "COMClassicVTableCreated TypeHandle:%#x, IID:{%08x-...}, vTbl:%#08x\n",
                  thClass.AsPtr(), IClassXIID.Data1, pComVtable));
 #endif
-            g_profControlBlock.pProfInterface->COMClassicVTableCreated(
+            (&g_profControlBlock)->COMClassicVTableCreated(
                 (ClassID) thClass.AsPtr(), IClassXIID, pComVtable,
                 pTemplate->m_pClassComMT->m_cbSlots +
                     ComMethodTable::GetNumExtraSlots(pTemplate->m_pClassComMT->GetInterfaceType()));
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
 #endif // PROFILING_SUPPORTED
         RETURN pTemplate;
index bc79ffc..39f00d0 100644 (file)
@@ -1009,16 +1009,16 @@ void QCALLTYPE ThreadNative::InformThreadNameChange(QCall::ThreadHandle thread,
 
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackThreads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackThreads());
         if (name == NULL)
         {
-            g_profControlBlock.pProfInterface->ThreadNameChanged((ThreadID)pThread, 0, NULL);
+            (&g_profControlBlock)->ThreadNameChanged((ThreadID)pThread, 0, NULL);
         }
         else
         {
-            g_profControlBlock.pProfInterface->ThreadNameChanged((ThreadID)pThread, len, (WCHAR*)name);
+            (&g_profControlBlock)->ThreadNameChanged((ThreadID)pThread, len, (WCHAR*)name);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
index 1e14e79..df3555e 100644 (file)
@@ -123,7 +123,7 @@ DWORD GetCurrentExceptionCode()
 // disable PROFILING_SUPPORTED for crossgen because of it affects data layout and FCall tables.
 //
 
-UINT_PTR EEToProfInterfaceImpl::EEFunctionIDMapper(FunctionID funcId, BOOL * pbHookFunction)
+UINT_PTR EEToProfInterfaceImpl::EEFunctionIDMapper(FunctionID funcId, BOOL *pbHookFunction)
 {
     UNREACHABLE();
 }
index 34cd147..745f2b6 100644 (file)
@@ -103,15 +103,17 @@ enum ClrToProfEntrypointFlags
 };
 
 #define ASSERT_EVAC_COUNTER_NONZERO()   \
-    _ASSERTE((GetThreadNULLOk() == NULL) ||                                             \
-             (GetThreadNULLOk()->GetProfilerEvacuationCounter() != 0U))
+    _ASSERTE(m_pProfilerInfo->dwProfilerEvacuationCounter.Load() > 0)
 
 #define CHECK_PROFILER_STATUS(ee2pFlags)                                                \
     /* If one of these asserts fires, perhaps you forgot to use                     */  \
-    /* BEGIN/END_PIN_PROFILER                                                       */  \
+    /* BEGIN/END_PROFILER_CALLBACK                                                  */  \
     ASSERT_EVAC_COUNTER_NONZERO();                                                      \
-    _ASSERTE(g_profControlBlock.pProfInterface.Load() != NULL);                         \
-    _ASSERTE(g_profControlBlock.pProfInterface == this);                                \
+    /* Either we are initializing, or we have the ProfToEEInterfaceImpl             */  \
+    _ASSERTE((((ee2pFlags) & kEE2PAllowableWhileInitializing) != 0) || (m_pProfilerInfo->pProfInterface.Load() != NULL));   \
+    /* If we are initializing, null is fine. Otherwise we want to make sure we haven't messed up the association between */ \
+    /* EEToProfInterfaceImpl/ProfToEEInterfaceImpl somehow.                         */  \
+    _ASSERTE((((ee2pFlags) & kEE2PAllowableWhileInitializing) != 0) || (m_pProfilerInfo->pProfInterface == this));          \
     /* Early abort if...                                                            */  \
     if (                                                                                \
         /* Profiler isn't active,                                                   */  \
@@ -121,7 +123,7 @@ enum ClrToProfEntrypointFlags
         /* on a detaching profiler, and b) the profiler is detaching                */  \
         !(                                                                              \
             (((ee2pFlags) & kEE2PAllowableWhileDetaching) != 0) &&                      \
-            (g_profControlBlock.curProfStatus.Get() == kProfStatusDetaching)            \
+            (m_pProfilerInfo->curProfStatus.Get() == kProfStatusDetaching)            \
          ) &&                                                                           \
                                                                                         \
         /* and it's not the case that both a) this callback is allowed              */  \
@@ -129,9 +131,9 @@ enum ClrToProfEntrypointFlags
         !(                                                                              \
             (((ee2pFlags) & kEE2PAllowableWhileInitializing) != 0) &&                   \
             (                                                                           \
-              (g_profControlBlock.curProfStatus.Get()                                   \
+              (m_pProfilerInfo->curProfStatus.Get()                                   \
                   == kProfStatusInitializingForStartupLoad) ||                          \
-              (g_profControlBlock.curProfStatus.Get()                                   \
+              (m_pProfilerInfo->curProfStatus.Get()                                   \
                   == kProfStatusInitializingForAttachLoad)                              \
             )                                                                           \
          )                                                                              \
@@ -412,14 +414,13 @@ EEToProfInterfaceImpl::EEToProfInterfaceImpl() :
     m_pCallback8(NULL),
     m_pCallback9(NULL),
     m_pCallback10(NULL),
+    m_pCallback11(NULL),
     m_hmodProfilerDLL(NULL),
     m_fLoadedViaAttach(FALSE),
     m_pProfToEE(NULL),
     m_pProfilersFuncIDMapper(NULL),
     m_pProfilersFuncIDMapper2(NULL),
     m_pProfilersFuncIDMapper2ClientData(NULL),
-    m_GUID(k_guidZero),
-    m_lGUIDCount(0),
     m_pGCRefDataFreeList(NULL),
     m_csGCRefDataFreeList(NULL),
     m_pEnter(NULL),
@@ -437,6 +438,7 @@ EEToProfInterfaceImpl::EEToProfInterfaceImpl() :
     m_pTailcall3WithInfo(NULL),
     m_fUnrevertiblyModifiedIL(FALSE),
     m_fModifiedRejitState(FALSE),
+    m_pProfilerInfo(NULL),
     m_pFunctionIDHashTable(NULL),
     m_pFunctionIDHashTableRWLock(NULL),
     m_dwConcurrentGCWaitTimeoutInMs(INFINITE),
@@ -585,6 +587,12 @@ HRESULT EEToProfInterfaceImpl::Init(
     return S_OK;
 }
 
+void EEToProfInterfaceImpl::SetProfilerInfo(ProfilerInfo *pProfilerInfo)
+{
+    LIMITED_METHOD_CONTRACT;
+    m_pProfilerInfo = pProfilerInfo;
+    m_pProfToEE->SetProfilerInfo(pProfilerInfo);
+}
 
 //---------------------------------------------------------------------------------------
 //
@@ -660,18 +668,39 @@ HRESULT EEToProfInterfaceImpl::CreateProfiler(
 
     // ATTENTION: Please update EEToProfInterfaceImpl::~EEToProfInterfaceImpl() after adding the next ICorProfilerCallback interface here !!!
 
-    // The profiler may optionally support ICorProfilerCallback3,4,5,6,7,8,9,10.  Let's check.
-    ReleaseHolder<ICorProfilerCallback10> pCallback10;
+    // The profiler may optionally support ICorProfilerCallback3,4,5,6,7,8,9,10,11.  Let's check.
+    ReleaseHolder<ICorProfilerCallback11> pCallback11;
     hr = m_pCallback2->QueryInterface(
-        IID_ICorProfilerCallback10,
-        (LPVOID *)&pCallback10);
-    if (SUCCEEDED(hr) && (pCallback10 != NULL))
+        IID_ICorProfilerCallback11,
+        (LPVOID *)&pCallback11);
+    if (SUCCEEDED(hr) && (pCallback11 != NULL))
+    {
+        _ASSERTE(m_pCallback11 == NULL);
+        m_pCallback11 = pCallback11.Extract();
+        pCallback11 = NULL;
+    }
+
+    if (m_pCallback11 == NULL)
+    {
+        ReleaseHolder<ICorProfilerCallback10> pCallback10;
+        hr = m_pCallback2->QueryInterface(
+            IID_ICorProfilerCallback10,
+            (LPVOID *)&pCallback10);
+        if (SUCCEEDED(hr) && (pCallback10 != NULL))
+        {
+            _ASSERTE(m_pCallback10 == NULL);
+            m_pCallback10 = pCallback10.Extract();
+            pCallback10 = NULL;
+        }
+    }
+    else
     {
         _ASSERTE(m_pCallback10 == NULL);
-        m_pCallback10 = pCallback10.Extract();
-        pCallback10 = NULL;
+        m_pCallback10 = static_cast<ICorProfilerCallback10 *>(m_pCallback11);
+        m_pCallback10->AddRef();
     }
 
+
     // Due to inheritance, if we have an interface we must also have
     // all the previous versions
     if (m_pCallback10 == NULL)
@@ -847,7 +876,7 @@ EEToProfInterfaceImpl::~EEToProfInterfaceImpl()
     // scan through list of detaching profilers to make sure none of them give a
     // GetEEToProfPtr() equal to this
 #ifdef FEATURE_PROFAPI_ATTACH_DETACH
-    _ASSERTE(ProfilingAPIDetach::GetEEToProfPtr() == NULL);
+    _ASSERTE(!ProfilingAPIDetach::IsEEToProfPtrRegisteredForDetach(this));
 #endif // FEATURE_PROFAPI_ATTACH_DETACH
 
     // Release user-specified profiler DLL
@@ -912,6 +941,12 @@ EEToProfInterfaceImpl::~EEToProfInterfaceImpl()
             m_pCallback10 = NULL;
         }
 
+        if (m_pCallback11 != NULL)
+        {
+            m_pCallback11->Release();
+            m_pCallback11 = NULL;
+        }
+
         // Only unload the V4 profiler if this is not part of shutdown.  This protects
         // Whidbey profilers that aren't used to being FreeLibrary'd.
         if (fIsV4Profiler && !g_fEEShutDown)
@@ -972,8 +1007,6 @@ EEToProfInterfaceImpl::~EEToProfInterfaceImpl()
         m_pSavedAllocDataBlock = NULL;
     }
 
-    m_GUID = k_guidZero;
-
     if (m_csGCRefDataFreeList != NULL)
     {
         ClrDeleteCriticalSection(m_csGCRefDataFreeList);
@@ -993,70 +1026,6 @@ EEToProfInterfaceImpl::~EEToProfInterfaceImpl()
     }
 }
 
-
-
-//---------------------------------------------------------------------------------------
-//
-// Initialize the GUID used for the cookie in remoting callbacks.  If already
-// initialized, this just does nothing and returns S_OK.
-//
-// Return Value:
-//      HRESULT indicating success or failure.  If the GUID was already initialized,
-//      just returns S_OK
-//
-//
-
-HRESULT EEToProfInterfaceImpl::InitGUID()
-{
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        CANNOT_TAKE_LOCK;
-        ASSERT_NO_EE_LOCKS_HELD();
-    }
-    CONTRACTL_END;
-
-    if (IsEqualGUID(m_GUID, k_guidZero))
-    {
-        return CoCreateGuid(&m_GUID);
-    }
-
-    return S_OK;
-}
-
-//---------------------------------------------------------------------------------------
-//
-// Returns a GUID suitable for use as a remoting callback cookie for this thread.
-// The GUID is based on the template GUID (m_GUID), the current thread, and
-// a counter.
-//
-// Arguments:
-//      pGUID - [out] The GUID requested
-//
-
-void EEToProfInterfaceImpl::GetGUID(GUID * pGUID)
-{
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        ASSERT_NO_EE_LOCKS_HELD();
-    }
-    CONTRACTL_END;
-
-    // the member GUID and the argument should both be valid
-    _ASSERTE(!(IsEqualGUID(m_GUID, k_guidZero)));
-    _ASSERTE(pGUID);
-
-    // Copy the contents of the template GUID
-    memcpy(pGUID, &m_GUID, sizeof(GUID));
-
-    // Adjust the last two bytes
-    pGUID->Data4[6] = (BYTE) GetCurrentThreadId();
-    pGUID->Data4[7] = (BYTE) InterlockedIncrement((LPLONG)&m_lGUIDCount);
-}
-
 //---------------------------------------------------------------------------------------
 //
 // Wrapper around calling profiler's FunctionIDMapper hook.  Called by JIT.
@@ -1955,14 +1924,13 @@ HRESULT EEToProfInterfaceImpl::EnsureProfilerDetachable()
 {
     LIMITED_METHOD_CONTRACT;
 
-    if (((g_profControlBlock.dwEventMask & COR_PRF_MONITOR_IMMUTABLE) != 0) ||
-        ((g_profControlBlock.dwEventMaskHigh & COR_PRF_HIGH_MONITOR_IMMUTABLE) != 0))
+    if (m_pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_IMMUTABLE) ||
+        m_pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_IMMUTABLE))
     {
         LOG((
             LF_CORPROF,
             LL_ERROR,
-            "**PROF: Profiler may not detach because it set an immutable flag.  Flags = 0x%x.\n",
-            g_profControlBlock.dwEventMask));
+            "**PROF: Profiler may not detach because it set an immutable flag.\n"));
 
         return CORPROF_E_IMMUTABLE_FLAGS_SET;
     }
@@ -2172,6 +2140,15 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
     }
     CONTRACTL_END;
 
+    BOOL isMainProfiler = g_profControlBlock.IsMainProfiler(this);
+
+    if (!isMainProfiler &&
+        ((dwEventMask & ~COR_PRF_ALLOWABLE_NOTIFICATION_PROFILER)
+            || (dwEventMaskHigh & ~COR_PRF_HIGH_ALLOWABLE_NOTIFICATION_PROFILER)))
+    {
+        return E_INVALIDARG;
+    }
+
     static const DWORD kEventFlagsRequiringSlowPathEnterLeaveHooks =
         COR_PRF_ENABLE_FUNCTION_ARGS   |
         COR_PRF_ENABLE_FUNCTION_RETVAL |
@@ -2222,17 +2199,17 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
     // not trying to set an immutable attribute
     // FUTURE: If we add immutable flags to the high event mask, this would be a good
     // place to check for them as well.
-    if (g_profControlBlock.curProfStatus.Get() != kProfStatusInitializingForStartupLoad)
+    if (m_pProfilerInfo->curProfStatus.Get() != kProfStatusInitializingForStartupLoad)
     {
 #ifdef _DEBUG
         if (((dwEventMask & dwImmutableEventFlags) !=
-                (g_profControlBlock.dwEventMask & dwImmutableEventFlags)) ||
+                (m_pProfilerInfo->eventMask.GetEventMask() & dwImmutableEventFlags)) ||
 #else //!_DEBUG
         if (((dwEventMask & COR_PRF_MONITOR_IMMUTABLE) !=
-                (g_profControlBlock.dwEventMask & COR_PRF_MONITOR_IMMUTABLE)) ||
+                (m_pProfilerInfo->eventMask.GetEventMask() & COR_PRF_MONITOR_IMMUTABLE)) ||
 #endif //_DEBUG
             ((dwEventMaskHigh & COR_PRF_HIGH_MONITOR_IMMUTABLE) !=
-                (g_profControlBlock.dwEventMaskHigh & COR_PRF_HIGH_MONITOR_IMMUTABLE)))
+                (m_pProfilerInfo->eventMask.GetEventMaskHigh() & COR_PRF_HIGH_MONITOR_IMMUTABLE)))
         {
             // FUTURE: Should we have a dedicated HRESULT for setting immutable flag?
             return E_FAIL;
@@ -2254,7 +2231,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
 
     // After fast path ELT hooks are set in Initial callback, the startup profiler is not allowed to change flags
     // that require slow path ELT hooks or disable ELT hooks.
-    if ((g_profControlBlock.curProfStatus.Get() == kProfStatusInitializingForStartupLoad) &&
+    if ((m_pProfilerInfo->curProfStatus.Get() == kProfStatusInitializingForStartupLoad) &&
         (
             (m_pEnter3    != NULL) ||
             (m_pLeave3    != NULL) ||
@@ -2266,13 +2243,13 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
         )
        )
     {
-        _ASSERTE((g_profControlBlock.dwEventMask & kEventFlagsRequiringSlowPathEnterLeaveHooks) == 0);
+        _ASSERTE(!m_pProfilerInfo->eventMask.IsEventMaskSet(kEventFlagsRequiringSlowPathEnterLeaveHooks));
         return CORPROF_E_INCONSISTENT_WITH_FLAGS;
     }
 
     // After slow path ELT hooks are set in Initial callback, the startup profiler is not allowed to remove
     // all flags that require slow path ELT hooks or to change the flag to disable the ELT hooks.
-    if ((g_profControlBlock.curProfStatus.Get() == kProfStatusInitializingForStartupLoad) &&
+    if ((m_pProfilerInfo->curProfStatus.Get() == kProfStatusInitializingForStartupLoad) &&
         (
             (m_pEnter3WithInfo    != NULL) ||
             (m_pLeave3WithInfo    != NULL) ||
@@ -2284,7 +2261,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
         )
        )
     {
-        _ASSERTE((g_profControlBlock.dwEventMask & kEventFlagsRequiringSlowPathEnterLeaveHooks) != 0);
+        _ASSERTE(m_pProfilerInfo->eventMask.IsEventMaskSet(kEventFlagsRequiringSlowPathEnterLeaveHooks));
         return CORPROF_E_INCONSISTENT_WITH_FLAGS;
     }
 
@@ -2295,7 +2272,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
         (
             (
                 // Old flags
-                ((g_profControlBlock.dwEventMask & kEventFlagsAffectingEnterLeaveHooks) ^
+                ((m_pProfilerInfo->eventMask.GetEventMask() & kEventFlagsAffectingEnterLeaveHooks) ^
                 // XORed w/ the new flags
                 (dwEventMask & kEventFlagsAffectingEnterLeaveHooks))
             ) != 0
@@ -2316,13 +2293,18 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
             (m_pTailcall          != NULL)
         );
 
+    if (fEnterLeaveHooksAffected && !isMainProfiler)
+    {
+        return E_INVALIDARG;
+    }
+
     BOOL fNeedToTurnOffConcurrentGC = FALSE;
 
     if (((dwEventMask & COR_PRF_MONITOR_GC) != 0) &&
-        ((g_profControlBlock.dwEventMask & COR_PRF_MONITOR_GC) == 0))
+        ((m_pProfilerInfo->eventMask.GetEventMask() & COR_PRF_MONITOR_GC) == 0))
     {
         // We don't need to worry about startup load as we'll turn off concurrent GC later
-        if (g_profControlBlock.curProfStatus.Get() != kProfStatusInitializingForStartupLoad)
+        if (m_pProfilerInfo->curProfStatus.Get() != kProfStatusInitializingForStartupLoad)
         {
             // Since we're not an initializing startup profiler, the EE must be fully started up
             // so we can check whether concurrent GC is on
@@ -2341,7 +2323,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
 
             // If we are attaching and we are turning on COR_PRF_MONITOR_GC, turn off concurrent GC later
             // in this function
-            if (g_profControlBlock.curProfStatus.Get() == kProfStatusInitializingForAttachLoad)
+            if (m_pProfilerInfo->curProfStatus.Get() == kProfStatusInitializingForAttachLoad)
             {
                 if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled())
                 {
@@ -2375,12 +2357,12 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
 
     if ((dwEventMask & COR_PRF_ENABLE_REJIT) != 0)
     {
-        if ((g_profControlBlock.curProfStatus.Get() != kProfStatusInitializingForStartupLoad) && !ReJitManager::IsReJITEnabled())
+        if ((m_pProfilerInfo->curProfStatus.Get() != kProfStatusInitializingForStartupLoad) && !ReJitManager::IsReJITEnabled())
         {
             return CORPROF_E_REJIT_NOT_ENABLED;
         }
 
-        g_profControlBlock.pProfInterface->SetModifiedRejitState();
+        m_pProfilerInfo->pProfInterface->SetModifiedRejitState();
     }
 
     // High event bits
@@ -2398,8 +2380,10 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
     }
 
     // Now save the modified masks
-    g_profControlBlock.dwEventMask = dwEventMask;
-    g_profControlBlock.dwEventMaskHigh = dwEventMaskHigh;
+    m_pProfilerInfo->eventMask.SetEventMask(dwEventMask);
+    m_pProfilerInfo->eventMask.SetEventMaskHigh(dwEventMaskHigh);
+
+    g_profControlBlock.UpdateGlobalEventMask();
 
     if (fEnterLeaveHooksAffected)
     {
@@ -2410,26 +2394,13 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
         }
     }
 
-    if (g_profControlBlock.curProfStatus.Get() == kProfStatusInitializingForStartupLoad)
-    {
-        // If the profiler has requested remoting cookies so that it can
-        // track logical call stacks, then we must initialize the cookie
-        // template.
-        if ((g_profControlBlock.dwEventMask & COR_PRF_MONITOR_REMOTING_COOKIE)
-            == COR_PRF_MONITOR_REMOTING_COOKIE)
-        {
-            hr = InitGUID();
-            if (FAILED(hr))
-            {
-                return hr;
-            }
-        }
-    }
-
     // Turn off concurrent GC as the last step so that we don't need to turn it back on if something
     // else failed after that
     if (fNeedToTurnOffConcurrentGC)
     {
+        // Remember that we've turned off concurrent GC and we'll turn it back on in TerminateProfiling
+        g_profControlBlock.fConcurrentGCDisabledForAttach = TRUE;
+
         // Turn off concurrent GC if it is on so that user can walk the heap safely in GC callbacks
         IGCHeap * pGCHeap = GCHeapUtilities::GetGCHeap();
 
@@ -2460,13 +2431,14 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
                 m_bHasTimedOutWaitingForConcurrentGC = TRUE;
             }
 
+            // TODO: think about race conditions... I am pretty sure there is one
+            // Remember that we've turned off concurrent GC and we'll turn it back on in TerminateProfiling
+            g_profControlBlock.fConcurrentGCDisabledForAttach = FALSE;
             pGCHeap->TemporaryEnableConcurrentGC();
+            
             return hr;
         }
 
-        // Remember that we've turned off concurrent GC and we'll turn it back on in TerminateProfiling
-        g_profControlBlock.fConcurrentGCDisabledForAttach = TRUE;
-
         LOG((LF_CORPROF, LL_INFO10, "**PROF: Concurrent GC has been turned off at attach.\n"));
     }
 
@@ -5339,290 +5311,6 @@ HRESULT EEToProfInterfaceImpl::RuntimeThreadResumed(ThreadID resumedThreadId)
 }
 
 //---------------------------------------------------------------------------------------
-// REMOTING
-//
-
-HRESULT EEToProfInterfaceImpl::RemotingClientInvocationStarted()
-{
-    CONTRACTL
-    {
-        // Yay!
-        NOTHROW;
-
-        // Yay!
-        GC_TRIGGERS;
-
-        // Yay!
-        MODE_PREEMPTIVE;
-
-        // Yay!
-        CAN_TAKE_LOCK;
-
-        // Yay!
-        ASSERT_NO_EE_LOCKS_HELD();
-
-    }
-    CONTRACTL_END;
-
-    CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
-                                LL_INFO1000,
-                                "**PROF: RemotingClientInvocationStarted. ThreadID: 0x%p\n",
-                                GetThreadNULLOk()));
-
-    {
-        // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
-        // whose try/catch blocks aren't visible to the contract system
-        PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
-        return m_pCallback2->RemotingClientInvocationStarted();
-    }
-}
-
-HRESULT EEToProfInterfaceImpl::RemotingClientSendingMessage(GUID *pCookie, BOOL fIsAsync)
-{
-    CONTRACTL
-    {
-        // Yay!
-        NOTHROW;
-
-        // Yay!
-        GC_TRIGGERS;
-
-        // Yay!
-        MODE_PREEMPTIVE;
-
-        // Yay!
-        CAN_TAKE_LOCK;
-
-        // Yay!
-        ASSERT_NO_EE_LOCKS_HELD();
-
-    }
-    CONTRACTL_END;
-
-    CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
-                                LL_INFO1000,
-                                "**PROF: RemotingClientSendingMessage. ThreadID: 0x%p\n",
-                                GetThreadNULLOk()));
-
-    {
-        // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
-        // whose try/catch blocks aren't visible to the contract system
-        PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
-        return m_pCallback2->RemotingClientSendingMessage(pCookie, fIsAsync);
-    }
-}
-
-HRESULT EEToProfInterfaceImpl::RemotingClientReceivingReply(GUID * pCookie, BOOL fIsAsync)
-{
-    CONTRACTL
-    {
-        // Yay!
-        NOTHROW;
-
-        // Yay!
-        GC_TRIGGERS;
-
-        // Yay!
-        MODE_PREEMPTIVE;
-
-        // Yay!
-        CAN_TAKE_LOCK;
-
-        // Yay!
-        ASSERT_NO_EE_LOCKS_HELD();
-
-    }
-    CONTRACTL_END;
-
-    CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
-                                LL_INFO1000,
-                                "**PROF: RemotingClientReceivingReply. ThreadID: 0x%p\n",
-                                GetThreadNULLOk()));
-
-    {
-        // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
-        // whose try/catch blocks aren't visible to the contract system
-        PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
-        return m_pCallback2->RemotingClientReceivingReply(pCookie, fIsAsync);
-    }
-}
-
-HRESULT EEToProfInterfaceImpl::RemotingClientInvocationFinished()
-{
-    CONTRACTL
-    {
-        // Yay!
-        NOTHROW;
-
-        // Yay!
-        GC_TRIGGERS;
-
-        // Yay!
-        MODE_PREEMPTIVE;
-
-        // Yay!
-        CAN_TAKE_LOCK;
-
-        // Yay!
-        ASSERT_NO_EE_LOCKS_HELD();
-
-    }
-    CONTRACTL_END;
-
-    CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
-                                LL_INFO1000,
-                                "**PROF: RemotingClientInvocationFinished. ThreadID: 0x%p\n",
-                                GetThreadNULLOk()));
-
-    {
-        // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
-        // whose try/catch blocks aren't visible to the contract system
-        PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
-        return m_pCallback2->RemotingClientInvocationFinished();
-    }
-}
-
-HRESULT EEToProfInterfaceImpl::RemotingServerReceivingMessage(GUID *pCookie, BOOL fIsAsync)
-{
-    CONTRACTL
-    {
-        // Yay!
-        NOTHROW;
-
-        // Yay!
-        GC_TRIGGERS;
-
-        // Yay!
-        MODE_PREEMPTIVE;
-
-        // Yay!
-        CAN_TAKE_LOCK;
-
-        // Yay!
-        ASSERT_NO_EE_LOCKS_HELD();
-
-    }
-    CONTRACTL_END;
-
-    CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
-                                LL_INFO1000,
-                                "**PROF: RemotingServerReceivingMessage. ThreadID: 0x%p\n",
-                                GetThreadNULLOk()));
-
-    {
-        // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
-        // whose try/catch blocks aren't visible to the contract system
-        PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
-        return m_pCallback2->RemotingServerReceivingMessage(pCookie, fIsAsync);
-    }
-}
-
-HRESULT EEToProfInterfaceImpl::RemotingServerInvocationStarted()
-{
-    CONTRACTL
-    {
-        // Yay!
-        NOTHROW;
-
-        // Yay!
-        GC_TRIGGERS;
-
-        // Yay!
-        MODE_PREEMPTIVE;
-
-        // Yay!
-        CAN_TAKE_LOCK;
-
-        // Yay!
-        ASSERT_NO_EE_LOCKS_HELD();
-
-    }
-    CONTRACTL_END;
-
-    CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
-                                LL_INFO1000,
-                                "**PROF: RemotingServerInvocationStarted. ThreadID: 0x%p\n",
-                                GetThreadNULLOk()));
-
-    {
-        // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
-        // whose try/catch blocks aren't visible to the contract system
-        PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
-        return m_pCallback2->RemotingServerInvocationStarted();
-    }
-}
-
-HRESULT EEToProfInterfaceImpl::RemotingServerInvocationReturned()
-{
-    CONTRACTL
-    {
-        // Yay!
-        NOTHROW;
-
-        // Yay!
-        GC_TRIGGERS;
-
-        // Yay!
-        MODE_PREEMPTIVE;
-
-        // Yay!
-        CAN_TAKE_LOCK;
-
-        // Yay!
-        ASSERT_NO_EE_LOCKS_HELD();
-
-    }
-    CONTRACTL_END;
-
-    CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
-                                LL_INFO1000,
-                                "**PROF: RemotingServerInvocationReturned. ThreadID: 0x%p\n",
-                                GetThreadNULLOk()));
-
-    {
-        // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
-        // whose try/catch blocks aren't visible to the contract system
-        PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
-        return m_pCallback2->RemotingServerInvocationReturned();
-    }
-}
-
-HRESULT EEToProfInterfaceImpl::RemotingServerSendingReply(GUID *pCookie, BOOL fIsAsync)
-{
-    CONTRACTL
-    {
-        // Yay!
-        NOTHROW;
-
-        // Yay!
-        GC_TRIGGERS;
-
-        // Yay!
-        MODE_PREEMPTIVE;
-
-        // Yay!
-        CAN_TAKE_LOCK;
-
-        // Yay!
-        ASSERT_NO_EE_LOCKS_HELD();
-
-    }
-    CONTRACTL_END;
-
-    CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
-                                LL_INFO1000,
-                                "**PROF: RemotingServerSendingReply. ThreadID: 0x%p\n",
-                                GetThreadNULLOk()));
-
-    {
-        // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
-        // whose try/catch blocks aren't visible to the contract system
-        PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
-        return m_pCallback2->RemotingServerSendingReply(pCookie, fIsAsync);
-    }
-}
-
-//---------------------------------------------------------------------------------------
 // GC EVENTS
 //
 
@@ -6354,4 +6042,31 @@ HRESULT EEToProfInterfaceImpl::EventPipeProviderCreated(EventPipeProvider *provi
 #endif // FEATURE_PERFTRACING
 }
 
+HRESULT EEToProfInterfaceImpl::LoadAsNotficationOnly(BOOL *pbNotificationOnly)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        MODE_ANY;
+    }
+    CONTRACTL_END;
+
+    // This one API is special, we call in to the profiler before we've set up any of our 
+    // machinery to do asserts (m_pProfilerInfo in specific). So we can't use 
+    // CLR_TO_PROFILER_ENTRYPOINT here.
+
+    LOG((LF_CORPROF,
+        LL_INFO1000,
+        "**PROF: LoadAsNotficationOnly.\n"));
+
+    if (m_pCallback11 == NULL)
+    {
+        *pbNotificationOnly = FALSE;
+        return S_OK;
+    }
+
+    return m_pCallback11->LoadAsNotficationOnly(pbNotificationOnly);
+}
+
 #endif // PROFILING_SUPPORTED
index c43b859..4ec468a 100644 (file)
@@ -33,10 +33,9 @@ class ProfToEEInterfaceImpl;
 interface IAssemblyBindingClosure;
 struct AssemblyReferenceClosureWalkContextForProfAPI;
 
-const GUID k_guidZero = {0};
-
 class EEToProfInterfaceImpl
 {
+    friend class ProfControlBlock;
 public:
 
     //
@@ -54,6 +53,8 @@ public:
         BOOL fLoadedViaAttach,
         DWORD dwConcurrentGCWaitTimeoutInMs);
 
+    void SetProfilerInfo(ProfilerInfo *pProfilerInfo);
+    
     BOOL IsCallback3Supported();
     BOOL IsCallback4Supported();
     BOOL IsCallback5Supported();
@@ -118,15 +119,6 @@ public:
 
     UINT_PTR EEFunctionIDMapper(FunctionID funcId, BOOL * pbHookFunction);
 
-    // This fills in the non call-specific portions of the cookie GUID.
-    // This should only be called once at startup if necessary.
-    HRESULT InitGUID();
-
-    // This will assign a mostly-unique GUID.  If enough calls to GetGUID
-    // are made from the same thread, then the GUIDs will cycle.
-    // (Current, it will cycle every 256 calls)
-    void GetGUID(GUID * pGUID);
-
     //
     // Initialize callback
     //
@@ -377,31 +369,6 @@ public:
         /* [in] */ void * pVTable);
 
     //
-    // Remoting Events
-    //
-
-    HRESULT RemotingClientInvocationStarted();
-
-    HRESULT RemotingClientSendingMessage(GUID * pCookie,
-                                         BOOL fIsAsync);
-
-    HRESULT RemotingClientReceivingReply(GUID * pCookie,
-                                         BOOL fIsAsync);
-
-    HRESULT RemotingClientInvocationFinished();
-
-    HRESULT RemotingServerReceivingMessage(GUID * pCookie,
-                                           BOOL fIsAsync);
-
-    HRESULT RemotingServerInvocationStarted();
-
-    HRESULT RemotingServerInvocationReturned();
-
-    HRESULT RemotingServerSendingReply(GUID * pCookie,
-                                       BOOL fIsAsync);
-
-
-    //
     // GC Events
     //
 
@@ -507,6 +474,8 @@ public:
 
     HRESULT EventPipeProviderCreated(EventPipeProvider *provider);
 
+    HRESULT LoadAsNotficationOnly(BOOL *pbNotificationOnly);
+
 private:
 
     //
@@ -578,6 +547,7 @@ private:
     ICorProfilerCallback8  * m_pCallback8;
     ICorProfilerCallback9  * m_pCallback9;
     ICorProfilerCallback10 * m_pCallback10;
+    ICorProfilerCallback11 * m_pCallback11;
 
     HMODULE                 m_hmodProfilerDLL;
 
@@ -589,13 +559,6 @@ private:
     FunctionIDMapper2 * m_pProfilersFuncIDMapper2;
     void * m_pProfilersFuncIDMapper2ClientData;
 
-    // This is used as a cookie template for remoting calls
-    GUID m_GUID;
-
-    // This is an incrementing counter for constructing unique GUIDS from
-    // m_GUID
-    LONG m_lGUIDCount;
-
     // This will contain a list of free ref data structs, so they
     // don't have to be re-allocated on every GC
     GCReferencesData * m_pGCRefDataFreeList;
@@ -628,6 +591,7 @@ private:
 
     // Remember whether the profiler has enabled Rejit, and prevent detach if it has.
     BOOL                    m_fModifiedRejitState;
+    ProfilerInfo           *m_pProfilerInfo;
 
     GCReferencesData * AllocateMovedReferencesData();
 
index 48a07b5..1ed73db 100644 (file)
@@ -247,7 +247,7 @@ inline BOOL EEToProfInterfaceImpl::RequiresGenericsContextForEnterLeave()
 
     return
         CORProfilerPresent() &&
-        ((g_profControlBlock.dwEventMask & COR_PRF_ENABLE_FRAME_INFO) != 0) &&
+        ((&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FRAME_INFO)) &&
         (
             (m_pEnter2            != NULL) ||
             (m_pLeave2            != NULL) ||
index bdf328e..afa0000 100644 (file)
@@ -32,15 +32,15 @@ class EEToProfilerExceptionInterfaceWrapper
     {
         WRAPPER_NO_CONTRACT;
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             _ASSERTE(pThread->PreemptiveGCDisabled());
 
             // Get a reference to the object that won't move
             OBJECTREF thrown = pThread->GetThrowable();
 
-            g_profControlBlock.pProfInterface->ExceptionThrown(
+            (&g_profControlBlock)->ExceptionThrown(
                 reinterpret_cast<ObjectID>((*(BYTE **)&thrown)));
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -53,14 +53,14 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler of the function being searched for a handler.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             if (!pFunction->IsNoMetadata())
             {
                 GCX_PREEMP();
-                g_profControlBlock.pProfInterface->ExceptionSearchFunctionEnter(
+                (&g_profControlBlock)->ExceptionSearchFunctionEnter(
                     (FunctionID) pFunction);
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -69,13 +69,13 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler of the function being searched for a handler.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             if (!pFunction->IsNoMetadata())
             {
                 GCX_PREEMP();
-                g_profControlBlock.pProfInterface->ExceptionSearchFunctionLeave();
+                (&g_profControlBlock)->ExceptionSearchFunctionLeave();
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -84,14 +84,14 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler of the filter.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             if (!pFunc->IsNoMetadata())
             {
                 GCX_PREEMP();
-                g_profControlBlock.pProfInterface->ExceptionSearchFilterEnter(
+                (&g_profControlBlock)->ExceptionSearchFilterEnter(
                     (FunctionID) pFunc);
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -100,10 +100,10 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler of the filter.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             GCX_PREEMP();
-            g_profControlBlock.pProfInterface->ExceptionSearchFilterLeave();
-            END_PIN_PROFILER();
+            (&g_profControlBlock)->ExceptionSearchFilterLeave();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -111,14 +111,14 @@ class EEToProfilerExceptionInterfaceWrapper
     {
         WRAPPER_NO_CONTRACT;
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             if (!pFunc->IsNoMetadata())
             {
                 GCX_PREEMP();
-                g_profControlBlock.pProfInterface->ExceptionSearchCatcherFound(
+                (&g_profControlBlock)->ExceptionSearchCatcherFound(
                     (FunctionID) pFunc);
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -130,13 +130,13 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler of the function being searched for a handler.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             if (!pFunc->IsNoMetadata())
             {
-                g_profControlBlock.pProfInterface->ExceptionUnwindFunctionEnter(
+                (&g_profControlBlock)->ExceptionUnwindFunctionEnter(
                     (FunctionID) pFunc);
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -145,12 +145,12 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler that searching this function is over.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             if (!pFunction->IsNoMetadata())
             {
-                g_profControlBlock.pProfInterface->ExceptionUnwindFunctionLeave();
+                (&g_profControlBlock)->ExceptionUnwindFunctionLeave();
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -159,13 +159,13 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler of the function being searched for a handler.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             if (!pFunc->IsNoMetadata())
             {
-                g_profControlBlock.pProfInterface->ExceptionUnwindFinallyEnter(
+                (&g_profControlBlock)->ExceptionUnwindFinallyEnter(
                     (FunctionID) pFunc);
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -174,9 +174,9 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler of the function being searched for a handler.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
-            g_profControlBlock.pProfInterface->ExceptionUnwindFinallyLeave();
-            END_PIN_PROFILER();
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
+            (&g_profControlBlock)->ExceptionUnwindFinallyLeave();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -185,7 +185,7 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
             if (!pFunc->IsNoMetadata())
             {
                 // <TODO>Remove the thrown variable as well as the
@@ -197,13 +197,13 @@ class EEToProfilerExceptionInterfaceWrapper
                 GCPROTECT_BEGIN(thrown);
                 thrown = pThread->GetThrowable();
                 {
-                    g_profControlBlock.pProfInterface->ExceptionCatcherEnter(
+                    (&g_profControlBlock)->ExceptionCatcherEnter(
                         (FunctionID) pFunc,
                         reinterpret_cast<ObjectID>((*(BYTE **)&thrown)));
                 }
                 GCPROTECT_END();
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 
@@ -212,9 +212,9 @@ class EEToProfilerExceptionInterfaceWrapper
         WRAPPER_NO_CONTRACT;
         // Notify the profiler of the function being searched for a handler.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackExceptions());
-            g_profControlBlock.pProfInterface->ExceptionCatcherLeave();
-            END_PIN_PROFILER();
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackExceptions());
+            (&g_profControlBlock)->ExceptionCatcherLeave();
+            END_PROFILER_CALLBACK();
         }
     }
 
index 58263ae..8094d7b 100644 (file)
@@ -310,10 +310,12 @@ ds_rt_profiler_startup (DiagnosticsStartupProfilerCommandPayload *payload)
        STATIC_CONTRACT_NOTHROW;
 
        HRESULT hr = S_OK;
-       EX_TRY {
-               memcpy(&(g_profControlBlock.clsStoredProfilerGuid), reinterpret_cast<const CLSID *>(ds_startup_profiler_command_payload_get_profiler_guid_cref (payload)), sizeof(CLSID));
-               g_profControlBlock.sStoredProfilerPath.Set(reinterpret_cast<LPCWSTR>(ds_startup_profiler_command_payload_get_profiler_path (payload)));
-               g_profControlBlock.fIsStoredProfilerRegistered = TRUE;
+       EX_TRY {        
+               StoredProfilerNode *profilerData = new StoredProfilerNode();
+               profilerData->guid = *(reinterpret_cast<const CLSID *>(ds_startup_profiler_command_payload_get_profiler_guid_cref (payload)));
+               profilerData->path.Set(reinterpret_cast<LPCWSTR>(ds_startup_profiler_command_payload_get_profiler_path (payload)));
+
+               g_profControlBlock.storedProfilers.InsertHead(profilerData);
        }
        EX_CATCH_HRESULT (hr);
 
index be90259..607286d 100644 (file)
@@ -1661,9 +1661,9 @@ ep_rt_notify_profiler_provider_created (EventPipeProvider *provider)
 
 #ifndef DACCESS_COMPILE
                // Let the profiler know the provider has been created so it can register if it wants to
-               BEGIN_PIN_PROFILER (CORProfilerIsMonitoringEventPipe ());
-               g_profControlBlock.pProfInterface->EventPipeProviderCreated (provider);
-               END_PIN_PROFILER ();
+               BEGIN_PROFILER_CALLBACK (CORProfilerTrackEventPipe ());
+               (&g_profControlBlock)->EventPipeProviderCreated (provider);
+               END_PROFILER_CALLBACK ();
 #endif // DACCESS_COMPILE
 }
 
index 1510622..28a0c9f 100644 (file)
@@ -200,7 +200,8 @@ public:
                EventPipeSerializationFormat format,
                const bool rundownRequested,
                IpcStream *const stream,
-               EventPipeSessionSynchronousCallback callback)
+               EventPipeSessionSynchronousCallback callback,
+               void *callbackAdditionalData)
        {
                CONTRACTL
                {
@@ -222,7 +223,8 @@ public:
                        format,
                        rundownRequested,
                        stream,
-                       callback);
+                       callback,
+                       callbackAdditionalData);
                ep_rt_utf8_string_free (outputPathUTF8);
                return result;
        }
index 7d0e429..7097cb6 100644 (file)
@@ -42,6 +42,7 @@ UINT64 QCALLTYPE EventPipeInternal::Enable(
             format,
             true,
             nullptr,
+            nullptr,
             nullptr);
         EventPipeAdapter::StartStreaming(sessionID);
     }
index 99620ac..14bd225 100644 (file)
@@ -682,13 +682,13 @@ void ETW::GCLog::MovedReference(
     // ProfAPI
     if (fAllowProfApiNotification)
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackGC() || CORProfilerTrackGCMovedObjects());
-        g_profControlBlock.pProfInterface->MovedReference(pbMemBlockStart,
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC() || CORProfilerTrackGCMovedObjects());
+        (&g_profControlBlock)->MovedReference(pbMemBlockStart,
                                                           pbMemBlockEnd,
                                                           cbRelocDistance,
                                                           &(pCtxForEtwAndProfapi->pctxProfAPI),
                                                           fCompacting);
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -808,9 +808,9 @@ VOID ETW::GCLog::EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiN
     // ProfAPI
     if (fAllowProfApiNotification)
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackGC() || CORProfilerTrackGCMovedObjects());
-        g_profControlBlock.pProfInterface->EndMovedReferences(&(pCtxForEtwAndProfapi->pctxProfAPI));
-        END_PIN_PROFILER();
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC() || CORProfilerTrackGCMovedObjects());
+        (&g_profControlBlock)->EndMovedReferences(&(pCtxForEtwAndProfapi->pctxProfAPI));
+        END_PROFILER_CALLBACK();
     }
 #endif //PROFILING_SUPPORTED
 
index 4df3e3a..5be5bc2 100644 (file)
@@ -559,7 +559,7 @@ BOOL ProfilerShouldTrackConditionalWeakTableElements()
 void ProfilerEndConditionalWeakTableElementReferences(void* heapId)
 {
 #if defined (GC_PROFILING)
-    g_profControlBlock.pProfInterface->EndConditionalWeakTableElementReferences(heapId);
+    (&g_profControlBlock)->EndConditionalWeakTableElementReferences(heapId);
 #else
     UNREFERENCED_PARAMETER(heapId);
 #endif // defined (GC_PROFILING)
@@ -570,7 +570,7 @@ void ProfilerEndConditionalWeakTableElementReferences(void* heapId)
 void ProfilerEndRootReferences2(void* heapId)
 {
 #if defined (GC_PROFILING)
-    g_profControlBlock.pProfInterface->EndRootReferences2(heapId);
+    (&g_profControlBlock)->EndRootReferences2(heapId);
 #else
     UNREFERENCED_PARAMETER(heapId);
 #endif // defined (GC_PROFILING)
@@ -603,24 +603,24 @@ void ScanHandleForProfilerAndETW(Object** pRef, Object* pSec, uint32_t flags, Sc
     {
         if (!isDependent)
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackGC());
-            g_profControlBlock.pProfInterface->RootReference2(
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC());
+            (&g_profControlBlock)->RootReference2(
                 (uint8_t *)*pRef,
                 kEtwGCRootKindHandle,
                 (EtwGCRootFlags)flags,
                 pRef,
                 &pSC->pHeapId);
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
         else
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackConditionalWeakTableElements());
-            g_profControlBlock.pProfInterface->ConditionalWeakTableElementReference(
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackConditionalWeakTableElements());
+            (&g_profControlBlock)->ConditionalWeakTableElementReference(
                 (uint8_t*)*pRef,
                 (uint8_t*)pSec,
                 pRef,
                 &pSC->pHeapId);
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 #endif // GC_PROFILING
@@ -739,10 +739,10 @@ void GCProfileWalkHeap(bool etwOnly)
 
 #if defined (GC_PROFILING)
     {
-        BEGIN_PIN_PROFILER(!etwOnly && CORProfilerTrackGC());
+        BEGIN_PROFILER_CALLBACK(!etwOnly && CORProfilerTrackGC());
         GCProfileWalkHeapWorker(TRUE /* fProfilerPinned */, fShouldWalkHeapRootsForEtw, fShouldWalkHeapObjectsForEtw);
         fWalkedHeapForProfiler = TRUE;
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // defined (GC_PROFILING)
 
@@ -759,7 +759,7 @@ void GCProfileWalkHeap(bool etwOnly)
 
 void WalkFReachableObjects(bool isCritical, void* objectID)
 {
-       g_profControlBlock.pProfInterface->FinalizeableObjectQueued(isCritical, (ObjectID)objectID);
+       (&g_profControlBlock)->FinalizeableObjectQueued(isCritical, (ObjectID)objectID);
 }
 
 static fq_walk_fn g_FQWalkFn = &WalkFReachableObjects;
@@ -770,7 +770,7 @@ void GCToEEInterface::DiagGCStart(int gen, bool isInduced)
     DiagUpdateGenerationBounds();
     GarbageCollectionStartedCallback(gen, isInduced);
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackGC());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC());
         size_t context = 0;
 
         // When we're walking objects allocated by class, then we don't want to walk the large
@@ -778,8 +778,8 @@ void GCToEEInterface::DiagGCStart(int gen, bool isInduced)
         GCHeapUtilities::GetGCHeap()->DiagWalkHeap(&AllocByClassHelper, (void *)&context, 0, false);
 
         // Notify that we've reached the end of the Gen 0 scan
-        g_profControlBlock.pProfInterface->EndAllocByClass(&context);
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->EndAllocByClass(&context);
+        END_PROFILER_CALLBACK();
     }
 
 #endif // GC_PROFILING
@@ -815,12 +815,9 @@ void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurr
 void GCToEEInterface::DiagWalkFReachableObjects(void* gcContext)
 {
 #ifdef GC_PROFILING
-    if (CORProfilerTrackGC())
-    {
-        BEGIN_PIN_PROFILER(CORProfilerPresent());
-        GCHeapUtilities::GetGCHeap()->DiagWalkFinalizeQueue(gcContext, g_FQWalkFn);
-        END_PIN_PROFILER();
-    }
+    BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC());
+    GCHeapUtilities::GetGCHeap()->DiagWalkFinalizeQueue(gcContext, g_FQWalkFn);
+    END_PROFILER_CALLBACK();
 #endif //GC_PROFILING
 }
 
index 2086dac..dcc3682 100644 (file)
@@ -22,9 +22,9 @@ void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef)
 void DiagHandleCreated(OBJECTHANDLE handle, OBJECTREF objRef)
 {
 #ifdef GC_PROFILING
-    BEGIN_PIN_PROFILER(CORProfilerTrackGC());
-    g_profControlBlock.pProfInterface->HandleCreated((uintptr_t)handle, (ObjectID)OBJECTREF_TO_UNCHECKED_OBJECTREF(objRef));
-    END_PIN_PROFILER();
+    BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC());
+    (&g_profControlBlock)->HandleCreated((uintptr_t)handle, (ObjectID)OBJECTREF_TO_UNCHECKED_OBJECTREF(objRef));
+    END_PROFILER_CALLBACK();
 #else
     UNREFERENCED_PARAMETER(handle);
     UNREFERENCED_PARAMETER(objRef);
@@ -34,9 +34,9 @@ void DiagHandleCreated(OBJECTHANDLE handle, OBJECTREF objRef)
 void DiagHandleDestroyed(OBJECTHANDLE handle)
 {
 #ifdef GC_PROFILING
-    BEGIN_PIN_PROFILER(CORProfilerTrackGC());
-    g_profControlBlock.pProfInterface->HandleDestroyed((uintptr_t)handle);
-    END_PIN_PROFILER();
+    BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC());
+    (&g_profControlBlock)->HandleDestroyed((uintptr_t)handle);
+    END_PROFILER_CALLBACK();
 #else
     UNREFERENCED_PARAMETER(handle);
 #endif // GC_PROFILING
index 29cb5fc..fa2fcdf 100644 (file)
@@ -81,6 +81,7 @@ uint32_t gcGenAnalysisBufferMB = 0;
         EP_SERIALIZATION_FORMAT_NETTRACE_V4,
         false,
         nullptr,
+        nullptr,
         nullptr
     );
     if (gcGenAnalysisEventPipeSessionId > 0)
index 9250f43..cb5fe80 100644 (file)
@@ -7738,12 +7738,12 @@ getMethodInfoHelper(
 #if defined(PROFILING_SUPPORTED)
         BOOL fProfilerRequiresGenericsContextForEnterLeave = FALSE;
         {
-            BEGIN_PIN_PROFILER(CORProfilerPresent());
-            if (g_profControlBlock.pProfInterface->RequiresGenericsContextForEnterLeave())
+            BEGIN_PROFILER_CALLBACK(CORProfilerPresent());
+            if ((&g_profControlBlock)->RequiresGenericsContextForEnterLeave())
             {
                 fProfilerRequiresGenericsContextForEnterLeave = TRUE;
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
         if (fProfilerRequiresGenericsContextForEnterLeave)
         {
@@ -8134,7 +8134,7 @@ CorInfoInline CEEInfo::canInline (CORINFO_METHOD_HANDLE hCaller,
         // profiler that this inlining is going to take place, and give them a
         // chance to prevent it.
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackJITInfo());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackJITInfo());
             if (pCaller->IsILStub() || pCallee->IsILStub())
             {
                 // do nothing
@@ -8142,7 +8142,7 @@ CorInfoInline CEEInfo::canInline (CORINFO_METHOD_HANDLE hCaller,
             else
             {
                 BOOL fShouldInline;
-                HRESULT hr = g_profControlBlock.pProfInterface->JITInlining(
+                HRESULT hr = (&g_profControlBlock)->JITInlining(
                     (FunctionID)pCaller,
                     (FunctionID)pCallee,
                     &fShouldInline);
@@ -8154,7 +8154,7 @@ CorInfoInline CEEInfo::canInline (CORINFO_METHOD_HANDLE hCaller,
                     goto exit;
                 }
             }
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
     }
 #endif // PROFILING_SUPPORTED
@@ -11184,9 +11184,9 @@ void CEEJitInfo::GetProfilingHandle(bool                      *pbHookFunction,
         void * profilerHandle = m_pMethodBeingCompiled;
 
         {
-            BEGIN_PIN_PROFILER(CORProfilerFunctionIDMapperEnabled());
-            profilerHandle = (void *)g_profControlBlock.pProfInterface->EEFunctionIDMapper((FunctionID) m_pMethodBeingCompiled, &bHookFunction);
-            END_PIN_PROFILER();
+            BEGIN_PROFILER_CALLBACK(CORProfilerFunctionIDMapperEnabled());
+            profilerHandle = (void *)(&g_profControlBlock)->EEFunctionIDMapper((FunctionID) m_pMethodBeingCompiled, &bHookFunction);
+            END_PROFILER_CALLBACK();
         }
 
         m_gphCache.m_pvGphProfilerHandle = profilerHandle;
@@ -13961,9 +13961,9 @@ BOOL LoadDynamicInfoEntry(Module *currentModule,
             CORINFO_PROFILING_HANDLE profilerHandle = (CORINFO_PROFILING_HANDLE)funId;
 
             {
-                BEGIN_PIN_PROFILER(CORProfilerFunctionIDMapperEnabled());
-                profilerHandle = (CORINFO_PROFILING_HANDLE) g_profControlBlock.pProfInterface->EEFunctionIDMapper(funId, &bHookFunction);
-                END_PIN_PROFILER();
+                BEGIN_PROFILER_CALLBACK(CORProfilerFunctionIDMapperEnabled());
+                profilerHandle = (CORINFO_PROFILING_HANDLE)(&g_profControlBlock)->EEFunctionIDMapper(funId, &bHookFunction);
+                END_PROFILER_CALLBACK();
             }
 
             // Profiling handle is opaque token. It does not have to be aligned thus we can not store it in the same location as token.
index f75d62b..20f5cbf 100644 (file)
@@ -537,9 +537,9 @@ PCODE MethodDesc::GetPrecompiledNgenCode(PrepareCodeConfig* pConfig)
     {
         BOOL fShouldSearchCache = TRUE;
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackCacheSearches());
-            g_profControlBlock.pProfInterface->JITCachedFunctionSearchStarted((FunctionID)this, &fShouldSearchCache);
-            END_PIN_PROFILER();
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackCacheSearches());
+            (&g_profControlBlock)->JITCachedFunctionSearchStarted((FunctionID)this, &fShouldSearchCache);
+            END_PROFILER_CALLBACK();
         }
 
         if (!fShouldSearchCache)
@@ -585,10 +585,10 @@ PCODE MethodDesc::GetPrecompiledNgenCode(PrepareCodeConfig* pConfig)
         * cached jitted function has been made.
         */
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackCacheSearches());
-            g_profControlBlock.pProfInterface->
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackCacheSearches());
+            (&g_profControlBlock)->
                 JITCachedFunctionSearchFinished((FunctionID)this, COR_PRF_CACHED_FUNCTION_FOUND);
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
 #endif // PROFILING_SUPPORTED
 
@@ -866,7 +866,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
 
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackJITInfo());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackJITInfo());
         // For methods with non-zero rejit id we send ReJITCompilationStarted, otherwise
         // JITCompilationStarted. It isn't clear if this is the ideal policy for these
         // notifications yet.
@@ -875,7 +875,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
         if (rejitId != 0)
         {
             _ASSERTE(!nativeCodeVersion.IsDefaultVersion());
-            g_profControlBlock.pProfInterface->ReJITCompilationStarted((FunctionID)this,
+            (&g_profControlBlock)->ReJITCompilationStarted((FunctionID)this,
                 rejitId,
                 TRUE);
         }
@@ -886,7 +886,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
         {
             if (!IsNoMetadata())
             {
-                g_profControlBlock.pProfInterface->JITCompilationStarted((FunctionID)this, TRUE);
+                (&g_profControlBlock)->JITCompilationStarted((FunctionID)this, TRUE);
 
             }
             else
@@ -895,7 +895,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
                 CorInfoOptions corOptions;
                 LPCBYTE ilHeaderPointer = this->AsDynamicMethodDesc()->GetResolver()->GetCodeInfo(&ilSize, &unused, &corOptions, &unused);
 
-                g_profControlBlock.pProfInterface->DynamicMethodJITCompilationStarted((FunctionID)this, TRUE, ilHeaderPointer, ilSize);
+                (&g_profControlBlock)->DynamicMethodJITCompilationStarted((FunctionID)this, TRUE, ilHeaderPointer, ilSize);
             }
 
             if (nativeCodeVersion.IsDefaultVersion())
@@ -903,7 +903,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
                 pConfig->SetProfilerMayHaveActivatedNonDefaultCodeVersion();
             }
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -955,7 +955,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
 
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackJITInfo());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackJITInfo());
         // For methods with non-zero rejit id we send ReJITCompilationFinished, otherwise
         // JITCompilationFinished. It isn't clear if this is the ideal policy for these
         // notifications yet.
@@ -964,7 +964,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
         if (rejitId != 0)
         {
             _ASSERTE(!nativeCodeVersion.IsDefaultVersion());
-            g_profControlBlock.pProfInterface->ReJITCompilationFinished((FunctionID)this,
+            (&g_profControlBlock)->ReJITCompilationFinished((FunctionID)this,
                 rejitId,
                 S_OK,
                 TRUE);
@@ -976,14 +976,14 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
         {
             if (!IsNoMetadata())
             {
-                g_profControlBlock.pProfInterface->
+                (&g_profControlBlock)->
                     JITCompilationFinished((FunctionID)this,
                         pEntry->m_hrResultCode,
                         TRUE);
             }
             else
             {
-                g_profControlBlock.pProfInterface->DynamicMethodJITCompilationFinished((FunctionID)this, pEntry->m_hrResultCode, TRUE);
+                (&g_profControlBlock)->DynamicMethodJITCompilationFinished((FunctionID)this, pEntry->m_hrResultCode, TRUE);
             }
 
             if (nativeCodeVersion.IsDefaultVersion())
@@ -991,7 +991,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
                 pConfig->SetProfilerMayHaveActivatedNonDefaultCodeVersion();
             }
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
index 392fde6..0161bef 100644 (file)
@@ -19,9 +19,9 @@
 #include "eetoprofinterfaceimpl.inl"
 
 // Class static member variables
-ProfilerDetachInfo ProfilingAPIDetach::s_profilerDetachInfo;
-CLREvent           ProfilingAPIDetach::s_eventDetachWorkAvailable;
-
+CQuickArrayList<ProfilerDetachInfo> ProfilingAPIDetach::s_profilerDetachInfos;
+CLREvent                            ProfilingAPIDetach::s_eventDetachWorkAvailable;
+Volatile<BOOL>                      ProfilingAPIDetach::s_profilerDetachThreadCreated;
 
 // ---------------------------------------------------------------------------------------
 // ProfilerDetachInfo constructor
@@ -49,7 +49,7 @@ void ProfilerDetachInfo::Init()
     // use real contracts, as this requires that utilcode has been initialized.
     STATIC_CONTRACT_LEAF;
 
-    m_pEEToProf = NULL;
+    m_pProfilerInfo = NULL;
     m_ui64DetachStartTime = 0;
     m_dwExpectedCompletionMilliseconds = 0;
 }
@@ -145,7 +145,7 @@ HRESULT ProfilingAPIDetach::Initialize()
 //
 
 // static
-HRESULT ProfilingAPIDetach::RequestProfilerDetach(DWORD dwExpectedCompletionMilliseconds)
+HRESULT ProfilingAPIDetach::RequestProfilerDetach(ProfilerInfo *pProfilerInfo, DWORD dwExpectedCompletionMilliseconds)
 {
     CONTRACTL
     {
@@ -178,14 +178,19 @@ HRESULT ProfilingAPIDetach::RequestProfilerDetach(DWORD dwExpectedCompletionMill
     {
         CRITSEC_Holder csh(ProfilingAPIUtility::GetStatusCrst());
 
-        // return immediately if detach is in progress
+        EEToProfInterfaceImpl *pEEToProf = pProfilerInfo->pProfInterface;
 
-        if (s_profilerDetachInfo.m_pEEToProf != NULL)
+        // return immediately if detach is in progress
+        for (SIZE_T pos = 0; pos < s_profilerDetachInfos.Size(); ++pos)
         {
-            return CORPROF_E_PROFILER_DETACHING;
+            ProfilerDetachInfo &current = s_profilerDetachInfos[pos];
+            if (current.m_pProfilerInfo->pProfInterface == pEEToProf)
+            {
+                return CORPROF_E_PROFILER_DETACHING;
+            }
         }
 
-        ProfilerStatus curProfStatus = g_profControlBlock.curProfStatus.Get();
+        ProfilerStatus curProfStatus = pProfilerInfo->curProfStatus.Get();
 
         if ((curProfStatus == kProfStatusInitializingForStartupLoad) ||
             (curProfStatus == kProfStatusInitializingForAttachLoad))
@@ -201,8 +206,6 @@ HRESULT ProfilingAPIDetach::RequestProfilerDetach(DWORD dwExpectedCompletionMill
             return CORPROF_E_PROFILER_DETACHING;
         }
 
-        EEToProfInterfaceImpl * pEEToProf = g_profControlBlock.pProfInterface;
-
         // Since prof status was active after entering the lock, the profiler must not
         // have unloaded out from under us.
         _ASSERTE(pEEToProf != NULL);
@@ -219,13 +222,25 @@ HRESULT ProfilingAPIDetach::RequestProfilerDetach(DWORD dwExpectedCompletionMill
         {
             return hr;
         }
-        s_profilerDetachInfo.m_pEEToProf = pEEToProf;
-        s_profilerDetachInfo.m_ui64DetachStartTime = CLRGetTickCount64();
-        s_profilerDetachInfo.m_dwExpectedCompletionMilliseconds = dwExpectedCompletionMilliseconds;
+
+        EX_TRY
+        {
+            ProfilerDetachInfo detachInfo;
+            detachInfo.m_pProfilerInfo = pProfilerInfo;
+            detachInfo.m_ui64DetachStartTime = CLRGetTickCount64();
+            detachInfo.m_dwExpectedCompletionMilliseconds = dwExpectedCompletionMilliseconds;
+            s_profilerDetachInfos.Push(detachInfo);
+        }
+        EX_CATCH_HRESULT(hr);
+        
+        if (FAILED(hr))
+        {
+            return hr;
+        }
 
         // Ok, time to seal the profiler from receiving or making calls with the CLR.
         // (This will force a FlushStoreBuffers().)
-        g_profControlBlock.curProfStatus.Set(kProfStatusDetaching);
+        pProfilerInfo->curProfStatus.Set(kProfStatusDetaching);
     }
 
     // Sealing done. Wake up the DetachThread so it can loop until the profiler code is
@@ -274,58 +289,58 @@ void ProfilingAPIDetach::ExecuteEvacuationLoop()
     }
     CONTRACTL_END;
 
-    // Wait until there's a profiler to detach (or until this thread should "wake up"
-    // for some other reason, such as exiting due to an unsuccessful startup-load of a
-    // profiler).
-    DWORD dwRet = s_eventDetachWorkAvailable.Wait(INFINITE, FALSE /* alertable */);
-    if (dwRet != WAIT_OBJECT_0)
+    while (true)
     {
-        // The wait ended due to a failure or a reason other than the event getting
-        // signaled (e.g., WAIT_ABANDONED)
-        DWORD dwErr;
-        if (dwRet == WAIT_FAILED)
+        // Wait until there's a profiler to detach (or until this thread should "wake up"
+        // for some other reason, such as exiting due to an unsuccessful startup-load of a
+        // profiler).
+        DWORD dwRet = s_eventDetachWorkAvailable.Wait(INFINITE, FALSE /* alertable */);
+        if (dwRet != WAIT_OBJECT_0)
         {
-            dwErr = GetLastError();
-            LOG((
-                LF_CORPROF,
-                LL_ERROR,
-                "**PROF: DetachThread wait for s_eventDetachWorkAvailable failed with GetLastError = %d.\n",
-                dwErr));
+            // The wait ended due to a failure or a reason other than the event getting
+            // signaled (e.g., WAIT_ABANDONED)
+            DWORD dwErr;
+            if (dwRet == WAIT_FAILED)
+            {
+                dwErr = GetLastError();
+                LOG((
+                    LF_CORPROF,
+                    LL_ERROR,
+                    "**PROF: DetachThread wait for s_eventDetachWorkAvailable failed with GetLastError = %d.\n",
+                    dwErr));
+            }
+            else
+            {
+                dwErr = dwRet;      // No extra error info available beyond the return code
+                LOG((
+                    LF_CORPROF,
+                    LL_ERROR,
+                    "**PROF: DetachThread wait for s_eventDetachWorkAvailable terminated with %d.\n",
+                    dwErr));
+            }
+
+            ProfilingAPIUtility::LogProfError(IDS_PROF_DETACH_THREAD_ERROR, dwErr);
+            return;
         }
-        else
+
         {
-            dwErr = dwRet;      // No extra error info available beyond the return code
-            LOG((
-                LF_CORPROF,
-                LL_ERROR,
-                "**PROF: DetachThread wait for s_eventDetachWorkAvailable terminated with %d.\n",
-                dwErr));
-        }
+            CRITSEC_Holder csh(ProfilingAPIUtility::GetStatusCrst());
 
-        ProfilingAPIUtility::LogProfError(IDS_PROF_DETACH_THREAD_ERROR, dwErr);
-        return;
-    }
+            for (SIZE_T pos = 0; pos < s_profilerDetachInfos.Size(); ++pos)
+            {
+                ProfilerDetachInfo current = s_profilerDetachInfos.Pop();
 
-    // Peek to make sure there's actually a profiler to detach
-    {
-        CRITSEC_Holder csh(ProfilingAPIUtility::GetStatusCrst());
+                do
+                {
+                    // Give profiler a chance to return from its procs
+                    SleepWhileProfilerEvacuates(&current);
+                }
+                while (!ProfilingAPIUtility::IsProfilerEvacuated(current.m_pProfilerInfo));
 
-        if (s_profilerDetachInfo.m_pEEToProf == NULL)
-        {
-            // Nothing to detach.  This can happen if the DetachThread (i.e., current
-            // thread) was created but then the profiler failed to load.
-            return;
+                UnloadProfiler(&current);
+            }
         }
     }
-
-    do
-    {
-        // Give profiler a chance to return from its procs
-        SleepWhileProfilerEvacuates();
-    }
-    while (!ProfilingAPIUtility::IsProfilerEvacuated());
-
-    UnloadProfiler();
 }
 
 //---------------------------------------------------------------------------------------
@@ -335,7 +350,7 @@ void ProfilingAPIDetach::ExecuteEvacuationLoop()
 //
 
 // static
-void ProfilingAPIDetach::SleepWhileProfilerEvacuates()
+void ProfilingAPIDetach::SleepWhileProfilerEvacuates(ProfilerDetachInfo *pDetachInfo)
 {
     CONTRACTL
     {
@@ -398,9 +413,9 @@ void ProfilingAPIDetach::SleepWhileProfilerEvacuates()
     {
         CRITSEC_Holder csh(ProfilingAPIUtility::GetStatusCrst());
 
-        _ASSERTE(s_profilerDetachInfo.m_pEEToProf != NULL);
-        ui64ExpectedCompletionMilliseconds = s_profilerDetachInfo.m_dwExpectedCompletionMilliseconds;
-        ui64DetachStartTime = s_profilerDetachInfo.m_ui64DetachStartTime;
+        _ASSERTE(pDetachInfo->m_pProfilerInfo != NULL);
+        ui64ExpectedCompletionMilliseconds = pDetachInfo->m_dwExpectedCompletionMilliseconds;
+        ui64DetachStartTime = pDetachInfo->m_ui64DetachStartTime;
     }
 
     // ui64SleepMilliseconds is calculated to ensure that CLR checks evacuation status roughly:
@@ -456,7 +471,7 @@ void ProfilingAPIDetach::SleepWhileProfilerEvacuates()
 //
 
 // static
-void ProfilingAPIDetach::UnloadProfiler()
+void ProfilingAPIDetach::UnloadProfiler(ProfilerDetachInfo *pDetachInfo)
 {
     CONTRACTL
     {
@@ -467,27 +482,39 @@ void ProfilingAPIDetach::UnloadProfiler()
     }
     CONTRACTL_END;
 
-    _ASSERTE(g_profControlBlock.curProfStatus.Get() == kProfStatusDetaching);
+    _ASSERTE(pDetachInfo->m_pProfilerInfo->curProfStatus.Get() == kProfStatusDetaching);
 
     {
         CRITSEC_Holder csh(ProfilingAPIUtility::GetStatusCrst());
 
         // Notify profiler it's about to be unloaded
-        _ASSERTE(s_profilerDetachInfo.m_pEEToProf != NULL);
-        s_profilerDetachInfo.m_pEEToProf->ProfilerDetachSucceeded();
-
-        // Reset detach state.
-        s_profilerDetachInfo.Init();
+        _ASSERTE(pDetachInfo->m_pProfilerInfo != NULL);
+        
+        {
+            // This EvacuationCounterHolder is just to make asserts in EEToProfInterfaceImpl happy.
+            // Using it like this without the dirty read/evac counter increment/clean read pattern
+            // is not safe generally, but in this specific case we can skip all that since we are in
+            // a critical section and are the only ones with access to the ProfilerInfo *
+            EvacuationCounterHolder evacuationCounter(pDetachInfo->m_pProfilerInfo);
+            pDetachInfo->m_pProfilerInfo->pProfInterface->ProfilerDetachSucceeded();
+        }
+        
+        EEToProfInterfaceImpl *pProfInterface = pDetachInfo->m_pProfilerInfo->pProfInterface.Load();
+        pDetachInfo->m_pProfilerInfo->pProfInterface.Store(NULL);
+        delete pProfInterface;
 
         // This deletes the EEToProfInterfaceImpl object managing the detaching profiler,
         // releases the profiler's callback interfaces, unloads the profiler DLL, sets
         // the status to kProfStatusNone, and resets g_profControlBlock for use next time
         // a profiler tries to attach.
         //
-        // Note that s_profilerDetachInfo.Init() has already NULL'd out
-        // s_profilerDetachInfo.m_pEEToProf, so we won't have a dangling pointer to the
+        // Note that we've already NULL'd out
+        // pDetachInfo->m_pProfilerInfo->pProfInterface, so we won't have a dangling pointer to the
         // EEToProfInterfaceImpl that's about to be destroyed.
-        ProfilingAPIUtility::TerminateProfiling();
+        ProfilingAPIUtility::TerminateProfiling(pDetachInfo->m_pProfilerInfo);
+
+        // Reset detach state.
+        pDetachInfo->Init();
     }
 
     ProfilingAPIUtility::LogProfInfo(IDS_PROF_DETACH_COMPLETE);
@@ -570,56 +597,69 @@ HRESULT ProfilingAPIDetach::CreateDetachThread()
         NOTHROW;
         GC_NOTRIGGER;
         MODE_ANY;
-        CANNOT_TAKE_LOCK;
+        CAN_TAKE_LOCK;
     }
     CONTRACTL_END;
 
-    // FUTURE: When reattach with neutered profilers is implemented, this
-    // function should check if a DetachThread already exists (use synchronization
-    // to prevent race), and just return if so.
-
-    HandleHolder hDetachThread;
-
-    // The DetachThread is intentionally not an EE Thread-object thread (it won't
-    // execute managed code).
-    hDetachThread = ::CreateThread(
-        NULL,       // lpThreadAttributes; don't want child processes inheriting this handle
-        0,          // dwStackSize (0 = use default)
-        ProfilingAPIDetachThreadStart,
-        NULL,       // lpParameter (none to pass)
-        0,          // dwCreationFlags (0 = use default flags, start thread immediately)
-        NULL        // lpThreadId (don't need therad ID)
-        );
-    if (hDetachThread == NULL)
+    if (s_profilerDetachThreadCreated)
+    {
+        return S_OK;
+    }
+
     {
-        DWORD dwErr = GetLastError();
+        CRITSEC_Holder csh(ProfilingAPIUtility::GetStatusCrst());
+
+        if (!s_profilerDetachThreadCreated)
+        {
+            HandleHolder hDetachThread;
+
+            // The DetachThread is intentionally not an EE Thread-object thread (it won't
+            // execute managed code).
+            hDetachThread = ::CreateThread(
+                NULL,       // lpThreadAttributes; don't want child processes inheriting this handle
+                0,          // dwStackSize (0 = use default)
+                ProfilingAPIDetachThreadStart,
+                NULL,       // lpParameter (none to pass)
+                0,          // dwCreationFlags (0 = use default flags, start thread immediately)
+                NULL        // lpThreadId (don't need therad ID)
+                );
+            if (hDetachThread == NULL)
+            {
+                DWORD dwErr = GetLastError();
 
-        LOG((
-            LF_CORPROF,
-            LL_ERROR,
-            "**PROF: Failed to create DetachThread.  GetLastError=%d.\n",
-            dwErr));
+                LOG((
+                    LF_CORPROF,
+                    LL_ERROR,
+                    "**PROF: Failed to create DetachThread.  GetLastError=%d.\n",
+                    dwErr));
 
-        return HRESULT_FROM_WIN32(dwErr);
+                return HRESULT_FROM_WIN32(dwErr);
+            }
+
+            s_profilerDetachThreadCreated = TRUE;
+        }
     }
 
     return S_OK;
 }
 
-//---------------------------------------------------------------------------------------
-//
-// Accessor for ProfilingAPIDetach::s_profilerDetachInfo.m_pEEToProf, which is the
-// profiler being detached (or NULL if no profiler is being detached).
-//
-// Return Value:
-//      EEToProfInterfaceImpl * for the profiler being detached.
-//
-
 // static
-EEToProfInterfaceImpl * ProfilingAPIDetach::GetEEToProfPtr()
+BOOL ProfilingAPIDetach::IsEEToProfPtrRegisteredForDetach(EEToProfInterfaceImpl *pEEToProf)
 {
     LIMITED_METHOD_CONTRACT;
-    return s_profilerDetachInfo.m_pEEToProf;
+
+    CRITSEC_Holder csh(ProfilingAPIUtility::GetStatusCrst());
+
+    for (SIZE_T pos = 0; pos < s_profilerDetachInfos.Size(); ++pos)
+    {
+        ProfilerDetachInfo &current = s_profilerDetachInfos[pos];
+        if (current.m_pProfilerInfo->pProfInterface == pEEToProf)
+        {
+            return TRUE;
+        }
+    }
+
+    return FALSE;
 }
 
 #endif // FEATURE_PROFAPI_ATTACH_DETACH
index 7b85cb6..5f97e4e 100644 (file)
@@ -24,13 +24,8 @@ struct ProfilerDetachInfo
     ProfilerDetachInfo();
     void Init();
 
-    // NULL if we're not trying to detach a profiler.  Otherwise, this is the
-    // EEToProfInterfaceImpl instance we're detaching.
-    //
-    // FUTURE: Although m_pEEToProf, when non-NULL, is always the same as
-    // g_profControlBlock.pProfInterface, that will no longer be the case once we allow
-    // re-attach with neutered profilers.
-    EEToProfInterfaceImpl * m_pEEToProf;
+    // This is the profiler instance we're detaching.
+    ProfilerInfo           *m_pProfilerInfo;
 
     // Time when profiler originally called RequestProfilerDetach()
     ULONGLONG               m_ui64DetachStartTime;
@@ -48,23 +43,25 @@ class ProfilingAPIDetach
 public:
     static HRESULT Initialize();
 
-    static HRESULT RequestProfilerDetach(DWORD dwExpectedCompletionMilliseconds);
+    static HRESULT RequestProfilerDetach(ProfilerInfo *profilerInfo, DWORD dwExpectedCompletionMilliseconds);
 
     static HRESULT CreateDetachThread();
     static DWORD WINAPI ProfilingAPIDetachThreadStart(LPVOID lpParameter);
     static void ExecuteEvacuationLoop();
 
-    static EEToProfInterfaceImpl * GetEEToProfPtr();
+    static BOOL IsEEToProfPtrRegisteredForDetach(EEToProfInterfaceImpl *pEEToProf);
 
 private:
-    static ProfilerDetachInfo s_profilerDetachInfo;
+    static CQuickArrayList<ProfilerDetachInfo> s_profilerDetachInfos;
 
     // Signaled by RequestProfilerDetach() when there is detach work ready to be
     // done by the DetachThread
     static CLREvent           s_eventDetachWorkAvailable;
 
-    static void SleepWhileProfilerEvacuates();
-    static void UnloadProfiler();
+    static Volatile<BOOL>     s_profilerDetachThreadCreated;
+
+    static void SleepWhileProfilerEvacuates(ProfilerDetachInfo *pDetachInfo);
+    static void UnloadProfiler(ProfilerDetachInfo *pDetachInfo);
 
     // Prevent instantiation of ProfilingAPIDetach objects (should be static-only)
     ProfilingAPIDetach();
index ea1738f..ac2ea14 100644 (file)
@@ -52,9 +52,9 @@
 // issue a profiler callback. Readers are scattered throughout the runtime, and have the
 // following format:
 //    {
-//        BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+//        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
 //        g_profControlBlock.pProfInterface->AppDomainCreationStarted(MyAppDomainID);
-//        END_PIN_PROFILER();
+//        END_PROFILER_CALLBACK();
 //    }
 // The BEGIN / END macros do the following:
 // * Evaluate the expression argument (e.g., CORProfilerTrackAppDomainLoads()). This is a
 // first, which the writer will be sure to see in (c).  For more details about how the
 // evacuation counters work, see code:ProfilingAPIUtility::IsProfilerEvacuated.
 //
-// WHEN ARE BEGIN/END_PIN_PROFILER REQUIRED?
-//
-// In general, any time you access g_profControlBlock.pProfInterface, you must be inside
-// a BEGIN/END_PIN_PROFILER block. This is pretty much always true throughout the EE, but
-// there are some exceptions inside the profiling API code itself, where the BEGIN / END
-// macros are unnecessary:
-//     * If you are inside a public ICorProfilerInfo function's implementation, the
-//         profiler is already pinned. This is because the profiler called the Info
-//         function from either:
-//         * a callback implemented inside of g_profControlBlock.pProfInterface, in which
-//             case the BEGIN/END macros are already in place around the call to that
-//             callback, OR
-//         * a hijacked thread or a thread of the profiler's own creation. In either
-//             case, it's the profiler's responsibility to end hijacking and end its own
-//             threads before requesting a detach. So the profiler DLL is guaranteed not
-//             to disappear while hijacking or profiler-created threads are in action.
-//    * If you're executing while code:ProfilingAPIUtility::s_csStatus is held, then
-//        you're explicitly serialized against all code that might unload the profiler's
-//        DLL and delete g_profControlBlock.pProfInterface. So the profiler is therefore
-//        still guaranteed not to disappear.
-//    * If slow ELT helpers, fast ELT hooks, or profiler-instrumented code is on the
-//        stack, then the profiler cannot be detached yet anyway. Today, we outright
-//        refuse a detach request from a profiler that instrumented code or enabled ELT.
-//        Once rejit / revert is implemented, the evacuation checks will ensure all
-//        instrumented code (including ELT) are reverted and off all stacks before
-//        attempting to unload the profielr.
-
 
 #include "common.h"
 
 #include "securitywrapper.h"
 #endif // !TARGET_UNIX
 
-//---------------------------------------------------------------------------------------
-// Normally, this would go in profilepriv.inl, but it's not easily inlineable because of
-// the use of BEGIN/END_PIN_PROFILER
-//
-// Return Value:
-//      TRUE iff security transparency checks in full trust assemblies should be disabled
-//      due to the profiler.
-//
-BOOL CORProfilerBypassSecurityChecks()
-{
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        CANNOT_TAKE_LOCK;
-    }
-    CONTRACTL_END;
-
-    {
-        BEGIN_PIN_PROFILER(CORProfilerPresent());
-
-        // V2 profiler binaries, for compatibility purposes, should bypass transparency
-        // checks in full trust assemblies.
-        if (!(&g_profControlBlock)->pProfInterface->IsCallback3Supported())
-            return TRUE;
-
-        // V4 profiler binaries must opt in to bypassing transparency checks in full trust
-        // assemblies.
-        if (((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST) != 0)
-            return TRUE;
-
-        END_PIN_PROFILER();
-    }
-
-    // All other cases, including no profiler loaded at all: Don't bypass
-    return FALSE;
-}
-
 // ----------------------------------------------------------------------------
 // CurrentProfilerStatus methods
 
@@ -379,6 +314,9 @@ void ProfilingAPIUtility::LogProfEventVA(
 
     AppendSupplementaryInformation(iStringResourceID, &messageToLog);
 
+    // Write to ETW and EventPipe with the message
+    FireEtwProfilerMessage(GetClrInstanceId(), messageToLog.GetUnicode());
+
     // Ouput debug strings for diagnostic messages.
     WszOutputDebugString(messageToLog);
 }
@@ -498,6 +436,9 @@ HRESULT ProfilingAPIUtility::InitializeProfiling()
     }
 
     AttemptLoadProfilerForStartup();
+    AttemptLoadDelayedStartupProfilers();
+    AttemptLoadProfilerList();
+
     // For now, the return value from AttemptLoadProfilerForStartup is of no use to us.
     // Any event has been logged already by AttemptLoadProfilerForStartup, and
     // regardless of whether a profiler got loaded, we still need to continue.
@@ -687,108 +628,85 @@ HRESULT ProfilingAPIUtility::AttemptLoadProfilerForStartup()
     fProfEnabled = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_ENABLE_PROFILING);
 
     NewArrayHolder<WCHAR> wszClsid(NULL);
-    NewArrayHolder<const WCHAR> cwszProfilerDLL(NULL);
+    NewArrayHolder<WCHAR> wszProfilerDLL(NULL);
     CLSID *pClsid;
     CLSID clsid;
 
-    if (fProfEnabled != 0)
+    if (fProfEnabled == 0)
     {
-        LOG((LF_CORPROF, LL_INFO10, "**PROF: Initializing Profiling Services.\n"));
+        LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiling not enabled.\n"));
+        return S_FALSE;
+    }
 
-        NewArrayHolder<WCHAR> wszProfilerDLL(NULL);
+    LOG((LF_CORPROF, LL_INFO10, "**PROF: Initializing Profiling Services.\n"));
 
-        IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER, &wszClsid));
+    IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER, &wszClsid));
 
-    #if defined(TARGET_ARM64)
-        IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_ARM64, &wszProfilerDLL));
-    #elif defined(TARGET_ARM)
-        IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_ARM32, &wszProfilerDLL));
-    #endif
+#if defined(TARGET_ARM64)
+    IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_ARM64, &wszProfilerDLL));
+#elif defined(TARGET_ARM)
+    IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_ARM32, &wszProfilerDLL));
+#endif
+    if(wszProfilerDLL == NULL)
+    {
+#ifdef TARGET_64BIT
+        IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_64, &wszProfilerDLL));
+#else
+        IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_32, &wszProfilerDLL));
+#endif
         if(wszProfilerDLL == NULL)
         {
-    #ifdef TARGET_64BIT
-            IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_64, &wszProfilerDLL));
-    #else
-            IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH_32, &wszProfilerDLL));
-    #endif
-            if(wszProfilerDLL == NULL)
-            {
-                IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH, &wszProfilerDLL));
-            }
+            IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_PROFILER_PATH, &wszProfilerDLL));
         }
+    }
 
-        // If the environment variable doesn't exist, profiling is not enabled.
-        if (wszClsid == NULL)
-        {
-            LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiling flag set, but required "
-                 "environment variable does not exist.\n"));
-
-            LogProfError(IDS_E_PROF_NO_CLSID);
-
-            return S_FALSE;
-        }
+    // If the environment variable doesn't exist, profiling is not enabled.
+    if (wszClsid == NULL)
+    {
+        LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiling flag set, but required "
+             "environment variable does not exist.\n"));
 
-        if ((wszProfilerDLL != NULL) && (wcslen(wszProfilerDLL) >= MAX_LONGPATH))
-        {
-            LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiling flag set, but COR_PROFILER_PATH was not set properly.\n"));
+        LogProfError(IDS_E_PROF_NO_CLSID);
 
-            LogProfError(IDS_E_PROF_BAD_PATH);
+        return S_FALSE;
+    }
 
-            return S_FALSE;
-        }
+    if ((wszProfilerDLL != NULL) && (wcslen(wszProfilerDLL) >= MAX_LONGPATH))
+    {
+        LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiling flag set, but COR_PROFILER_PATH was not set properly.\n"));
 
-    #ifdef TARGET_UNIX
-        // If the environment variable doesn't exist, profiling is not enabled.
-        if (wszProfilerDLL == NULL)
-        {
-            LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiling flag set, but required "
-                 "environment variable does not exist.\n"));
+        LogProfError(IDS_E_PROF_BAD_PATH);
 
-            LogProfError(IDS_E_PROF_BAD_PATH);
+        return S_FALSE;
+    }
 
-            return S_FALSE;
-        }
-    #endif // TARGET_UNIX
+#ifdef TARGET_UNIX
+    // If the environment variable doesn't exist, profiling is not enabled.
+    if (wszProfilerDLL == NULL)
+    {
+        LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiling flag set, but required "
+             "environment variable does not exist.\n"));
 
-        hr = ProfilingAPIUtility::ProfilerCLSIDFromString(wszClsid, &clsid);
-        if (FAILED(hr))
-        {
-            // ProfilerCLSIDFromString already logged an event if there was a failure
-            return hr;
-        }
+        LogProfError(IDS_E_PROF_BAD_PATH);
 
-        pClsid = &clsid;
-        cwszProfilerDLL.Assign(wszProfilerDLL.GetValue());
-        wszProfilerDLL.SuppressRelease();
-    }
-    else if (g_profControlBlock.fIsStoredProfilerRegistered)
-    {
-        LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiler loading from GUID/Path stored from the IPC channel."));
-        pClsid = &(g_profControlBlock.clsStoredProfilerGuid);
-        
-        // Convert to string for logging
-        constexpr size_t guidStringSize = 128;
-        wszClsid.Assign(new (nothrow) WCHAR[guidStringSize]);
-        if (wszClsid != NULL)
-        {
-            StringFromGUID2(*pClsid, wszClsid, guidStringSize);
-        }
-        
-        // Assign, but don't take ownership of, the stored profiler path. This relies on 
-        // g_profControlBlock.sStoredProfilerPath not mutating, which would invalidate the pointer.
-        cwszProfilerDLL.Assign(g_profControlBlock.sStoredProfilerPath.GetUnicode(), FALSE);
+        return S_FALSE;
     }
-    else
+#endif // TARGET_UNIX
+
+    hr = ProfilingAPIUtility::ProfilerCLSIDFromString(wszClsid, &clsid);
+    if (FAILED(hr))
     {
-        LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiling not enabled.\n"));
-        return S_FALSE;
+        // ProfilerCLSIDFromString already logged an event if there was a failure
+        return hr;
     }
 
+    pClsid = &clsid;
+
     hr = LoadProfiler(
         kStartupLoad,
         pClsid,
         wszClsid,
-        cwszProfilerDLL,
+        wszProfilerDLL,
         NULL,               // No client data for startup load
         0);                 // No client data for startup load
     if (FAILED(hr))
@@ -801,6 +719,121 @@ HRESULT ProfilingAPIUtility::AttemptLoadProfilerForStartup()
     return S_OK;
 }
 
+//static
+HRESULT ProfilingAPIUtility::AttemptLoadDelayedStartupProfilers()
+{
+    if (g_profControlBlock.storedProfilers.IsEmpty())
+    {
+        return S_OK;
+    }
+
+    HRESULT storedHr = S_OK;
+    STOREDPROFILERLIST *profilers = &g_profControlBlock.storedProfilers;
+    for (StoredProfilerNode* item = profilers->GetHead(); item != NULL; item = STOREDPROFILERLIST::GetNext(item))
+    {
+        LOG((LF_CORPROF, LL_INFO10, "**PROF: Profiler loading from GUID/Path stored from the IPC channel."));
+        CLSID *pClsid = &(item->guid);
+
+        // Convert to string for logging
+        constexpr size_t guidStringSize = 39;
+        NewArrayHolder<WCHAR> wszClsid(new (nothrow) WCHAR[guidStringSize]);
+        // GUIDs should always be the same number of characters...
+        _ASSERTE(wszClsid != NULL);
+        if (wszClsid != NULL)
+        {
+            StringFromGUID2(*pClsid, wszClsid, guidStringSize);
+        }
+
+        HRESULT hr = LoadProfiler(
+            kStartupLoad,
+            pClsid,
+            wszClsid,
+            item->path.GetUnicode(),
+            NULL,               // No client data for startup load
+            0);                 // No client data for startup load
+        if (FAILED(hr))
+        {
+            // LoadProfiler logs if there is an error
+            storedHr = hr;
+        }
+    }
+
+    return storedHr;
+}
+
+// static
+HRESULT ProfilingAPIUtility::AttemptLoadProfilerList()
+{
+    HRESULT hr = S_OK;
+    DWORD dwEnabled = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_ENABLE_NOTIFICATION_PROFILERS);
+    if (dwEnabled == 0)
+    {
+        // Profiler list explicitly disabled, bail
+        LogProfInfo(IDS_E_PROF_NOTIFICATION_DISABLED);
+        return S_OK;
+    }
+
+    NewArrayHolder<WCHAR> wszProfilerList(NULL);
+#ifdef TARGET_64BIT
+    CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_64, &wszProfilerList);
+#else // TARGET_64BIT
+    CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_32, &wszProfilerList);
+#endif // TARGET_64BIT
+    if (wszProfilerList == NULL)
+    {
+        CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_CORECLR_NOTIFICATION_PROFILERS, &wszProfilerList);
+        if (wszProfilerList == NULL)
+        {
+            // No profiler list specified, bail
+            return S_OK;
+        }
+    }
+
+    WCHAR *pOuter = NULL;
+    WCHAR *pInner = NULL;
+    WCHAR *currentSection = NULL;
+    WCHAR *currentPath = NULL;
+    WCHAR *currentGuid = NULL;
+
+    HRESULT storedHr = S_OK;
+    // Get each semicolon delimited config
+    currentSection = wcstok_s(wszProfilerList, W(";"), &pOuter);
+    while (currentSection != NULL)
+    {
+        // Parse this config "path={guid}"
+        currentPath = wcstok_s(currentSection, W("="), &pInner);
+        currentGuid = wcstok_s(NULL, W("="), &pInner);
+
+        CLSID clsid;
+        hr = ProfilingAPIUtility::ProfilerCLSIDFromString(currentGuid, &clsid);
+        if (FAILED(hr))
+        {
+            // ProfilerCLSIDFromString already logged an event if there was a failure
+            storedHr = hr;
+            goto NextSection;
+        }
+
+        hr = LoadProfiler(
+            kStartupLoad,
+            &clsid,
+            currentGuid,
+            currentPath,
+            NULL,               // No client data for startup load
+            0);                 // No client data for startup load
+        if (FAILED(hr))
+        {
+            // LoadProfiler already logged if there was an error
+            storedHr = hr;
+            goto NextSection;
+        }
+
+NextSection:
+        // Get next config
+        currentSection = wcstok_s(NULL, W(";"), &pOuter);
+    }
+
+    return storedHr;
+}
 
 //---------------------------------------------------------------------------------------
 //
@@ -1060,6 +1093,12 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
     // Client data is currently only specified on attach
     _ASSERTE((pvClientData == NULL) || (loadType == kAttachLoad));
 
+    ProfilerInfo profilerInfo;
+    // RAII type that will deregister if we bail at any point
+    ProfilerInfoHolder profilerInfoHolder(&profilerInfo);
+    profilerInfo.Init();
+    profilerInfo.inUse = TRUE;
+
     HRESULT hr = PerformDeferredInit();
     if (FAILED(hr))
     {
@@ -1073,19 +1112,10 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
     }
 
     {
-        // To prevent race conditions we need to signal that a load is already happening.
-        // The diagnostics server is single threaded, but it can potentially be
-        // racing with the startup path, or theoretically in the future it could be
-        // racing with another attach request if the diagnostic server becomes
-        // multithreaded.
-        CRITSEC_Holder csh(s_csStatus);
-
-        if (g_profControlBlock.curProfStatus.Get() != kProfStatusNone)
-        {
-            return CORPROF_E_PROFILER_ALREADY_ACTIVE;
-        }
-
-        g_profControlBlock.curProfStatus.Set(kProfStatusPreInitialize);
+        // Usually we need to take the lock when modifying profiler status, but at this
+        // point no one else could have a pointer to this ProfilerInfo so we don't
+        // need to synchronize. Once we store it in g_profControlBlock we need to.
+        profilerInfo.curProfStatus.Set(kProfStatusPreInitialize);
     }
 
     NewHolder<EEToProfInterfaceImpl> pEEProf(new (nothrow) EEToProfInterfaceImpl());
@@ -1100,17 +1130,13 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
     hr = DoPreInitialization(pEEProf, pClsid, wszClsid, wszProfilerDLL, loadType, dwConcurrentGCWaitTimeoutInMs);
     if (FAILED(hr))
     {
-        CRITSEC_Holder csh(s_csStatus);
-        g_profControlBlock.curProfStatus.Set(kProfStatusNone);
         return hr;
     }
 
     {
-        // All modification of the profiler's status and
-        // g_profControlBlock.pProfInterface need to be serialized against each other,
-        // in particular, this code should be serialized against detach and unloading
-        // code.
-        CRITSEC_Holder csh(s_csStatus);
+        // Usually we need to take the lock when modifying profiler status, but at this
+        // point no one else could have a pointer to this ProfilerInfo so we don't
+        // need to synchronize. Once we store it in g_profControlBlock we need to.
 
         // We've successfully allocated and initialized the callback wrapper object and the
         // Info interface implementation objects.  The profiler DLL is therefore also
@@ -1122,18 +1148,64 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
         // callback (which we do immediately below), and have it successfully call
         // back into us via the Info interface (ProfToEEInterfaceImpl) to perform its
         // initialization.
-        g_profControlBlock.pProfInterface = pEEProf.GetValue();
+        profilerInfo.pProfInterface = pEEProf.GetValue();
         pEEProf.SuppressRelease();
         pEEProf = NULL;
 
         // Set global status to reflect the proper type of Init we're doing (attach vs
         // startup)
-        g_profControlBlock.curProfStatus.Set(
+        profilerInfo.curProfStatus.Set(
             (loadType == kStartupLoad) ?
                 kProfStatusInitializingForStartupLoad :
                 kProfStatusInitializingForAttachLoad);
     }
 
+    ProfilerInfo *pProfilerInfo = NULL;
+    {
+        // Now we register the profiler, from this point on we need to worry about
+        // synchronization
+        CRITSEC_Holder csh(s_csStatus);
+
+        // Check if this profiler is notification only and load as appropriate
+        BOOL notificationOnly = FALSE;
+        {
+            EvacuationCounterHolder holder(&profilerInfo);
+            HRESULT callHr = profilerInfo.pProfInterface->LoadAsNotficationOnly(&notificationOnly);
+            if (FAILED(callHr))
+            {
+                notificationOnly = FALSE;
+            }
+        }
+
+        if (notificationOnly)
+        {
+            pProfilerInfo = g_profControlBlock.FindNextFreeProfilerInfoSlot();
+            if (pProfilerInfo == NULL)
+            {
+                LogProfError(IDS_E_PROF_NOTIFICATION_LIMIT_EXCEEDED);
+                return CORPROF_E_PROFILER_ALREADY_ACTIVE;
+            }
+            
+            *pProfilerInfo = profilerInfo;
+        }
+        else
+        {
+            // "main" profiler, there can only be one
+            if (g_profControlBlock.mainProfilerInfo.curProfStatus.Get() != kProfStatusNone)
+            {
+                LogProfError(IDS_PROF_ALREADY_LOADED);
+                return CORPROF_E_PROFILER_ALREADY_ACTIVE;
+            }
+
+            // This profiler cannot be a notification only profiler, copy it over to the 
+            // main slot and the ProfilerInfoHolder above will clear out the notification slot
+            g_profControlBlock.mainProfilerInfo = profilerInfo;
+            pProfilerInfo = &(g_profControlBlock.mainProfilerInfo);
+        }
+
+        pProfilerInfo->pProfInterface->SetProfilerInfo(pProfilerInfo);
+    }
+
     // Now that the profiler is officially loaded and in Init status, call into the
     // profiler's appropriate Initialize() callback. Note that if the profiler fails this
     // call, we should abort the rest of the profiler loading, and reset our state so we
@@ -1141,13 +1213,25 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
 
     if (loadType == kStartupLoad)
     {
-        hr = g_profControlBlock.pProfInterface->Initialize();
+        // This EvacuationCounterHolder is just to make asserts in EEToProfInterfaceImpl happy.
+        // Using it like this without the dirty read/evac counter increment/clean read pattern
+        // is not safe generally, but in this specific case we can skip all that since we haven't
+        // published it yet, so we are the only thread that can access it.
+        EvacuationCounterHolder holder(pProfilerInfo);
+        hr = pProfilerInfo->pProfInterface->Initialize();
     }
     else
     {
+        // This EvacuationCounterHolder is just to make asserts in EEToProfInterfaceImpl happy.
+        // Using it like this without the dirty read/evac counter increment/clean read pattern
+        // is not safe generally, but in this specific case we can skip all that since we haven't
+        // published it yet, so we are the only thread that can access it.
+        EvacuationCounterHolder holder(pProfilerInfo);
+
         _ASSERTE(loadType == kAttachLoad);
-        _ASSERTE(g_profControlBlock.pProfInterface->IsCallback3Supported());
-        hr = g_profControlBlock.pProfInterface->InitializeForAttach(pvClientData, cbClientData);
+        _ASSERTE(pProfilerInfo->pProfInterface->IsCallback3Supported());
+
+        hr = pProfilerInfo->pProfInterface->InitializeForAttach(pvClientData, cbClientData);
     }
 
     if (FAILED(hr))
@@ -1162,7 +1246,7 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
         // the reason InitializeForAttach callback failed even though we cannot be sure and we cannot
         // cannot assume hr is going to be CORPROF_E_TIMEOUT_WAITING_FOR_CONCURRENT_GC.
         // The best we can do in this case is to report this failure anyway.
-        if (g_profControlBlock.pProfInterface->HasTimedOutWaitingForConcurrentGC())
+        if (pProfilerInfo->pProfInterface->HasTimedOutWaitingForConcurrentGC())
         {
             ProfilingAPIUtility::LogProfError(IDS_E_PROF_TIMEOUT_WAITING_FOR_CONCURRENT_GC, dwConcurrentGCWaitTimeoutInMs, wszClsid);
         }
@@ -1171,7 +1255,7 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
         if ((loadType == kAttachLoad) &&
             ((hr == CORPROF_E_PROFILER_NOT_ATTACHABLE) || (hr == E_NOTIMPL)))
         {
-            _ASSERTE(g_profControlBlock.pProfInterface->IsCallback3Supported());
+            _ASSERTE(pProfilerInfo->pProfInterface->IsCallback3Supported());
 
             // Profiler supports ICorProfilerCallback3, but explicitly doesn't support
             // Attach loading.  So log specialized event
@@ -1196,14 +1280,14 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
 
         // Profiler failed; reset everything. This will automatically reset
         // g_profControlBlock and will unload the profiler's DLL.
-        TerminateProfiling();
+        TerminateProfiling(pProfilerInfo);
         return hr;
     }
 
 #ifdef FEATURE_MULTICOREJIT
 
     // Disable multicore JIT when profiling is enabled
-    if (g_profControlBlock.dwEventMask & COR_PRF_MONITOR_JIT_COMPILATION)
+    if (pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION))
     {
         MulticoreJitManager::DisableMulticoreJit();
     }
@@ -1213,7 +1297,7 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
     // Indicate that profiling is properly initialized.  On an attach-load, this will
     // force a FlushStoreBuffers(), which is important for catch-up synchronization (see
     // code:#ProfCatchUpSynchronization)
-    g_profControlBlock.curProfStatus.Set(kProfStatusActive);
+    pProfilerInfo->curProfStatus.Set(kProfStatusActive);
 
     LOG((
         LF_CORPROF,
@@ -1229,7 +1313,7 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
         // For startup profilers only: If the profiler is interested in tracking GC
         // events, then we must disable concurrent GC since concurrent GC can allocate
         // and kill objects without relocating and thus not doing a heap walk.
-        if (CORProfilerTrackGC())
+        if (pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_GC))
         {
             LOG((LF_CORPROF, LL_INFO10, "**PROF: Turning off concurrent GC at startup.\n"));
             // Previously we would use SetGCConcurrent(0) to indicate to the GC that it shouldn't even
@@ -1303,11 +1387,17 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
         // code:ProfilerFunctionEnum::Init#ProfilerEnumGeneral
 
         {
-            BEGIN_PIN_PROFILER(CORProfilerPresent());
-            g_profControlBlock.pProfInterface->ProfilerAttachComplete();
-            END_PIN_PROFILER();
+            // This EvacuationCounterHolder is just to make asserts in EEToProfInterfaceImpl happy.
+            // Using it like this without the dirty read/evac counter increment/clean read pattern
+            // is not safe generally, but in this specific case we can skip all that since we haven't
+            // published it yet, so we are the only thread that can access it.
+            EvacuationCounterHolder holder(pProfilerInfo);
+            pProfilerInfo->pProfInterface->ProfilerAttachComplete();
         }
     }
+
+    // Yay, the profiler is started up. Don't deregister it if we get to this point
+    profilerInfoHolder.SuppressRelease();
     return S_OK;
 }
 
@@ -1323,7 +1413,7 @@ HRESULT ProfilingAPIUtility::LoadProfiler(
 //
 
 // static
-BOOL ProfilingAPIUtility::IsProfilerEvacuated()
+BOOL ProfilingAPIUtility::IsProfilerEvacuated(ProfilerInfo *pProfilerInfo)
 {
     CONTRACTL
     {
@@ -1334,64 +1424,36 @@ BOOL ProfilingAPIUtility::IsProfilerEvacuated()
     }
     CONTRACTL_END;
 
-    _ASSERTE(g_profControlBlock.curProfStatus.Get() == kProfStatusDetaching);
-
-    // Check evacuation counters on all the threads (see
+    _ASSERTE(pProfilerInfo->curProfStatus.Get() == kProfStatusDetaching);
+
+    // Note that threads are still in motion as we check its evacuation counter.
+    // This is ok, because we've already changed the profiler status to
+    // kProfStatusDetaching and flushed CPU buffers. So at this point the counter
+    // will typically only go down to 0 (and not increment anymore), with one
+    // small exception (below). So if we get a read of 0 below, the counter will
+    // typically stay there. Specifically:
+    //     * Profiler is most likely not about to increment its evacuation counter
+    //         from 0 to 1 because pThread sees that the status is
+    //         kProfStatusDetaching.
+    //     * Note that there is a small race where pThread might actually
+    //         increment its evac counter from 0 to 1 (if it dirty-read the
+    //         profiler status a tad too early), but that implies that when
+    //         pThread rechecks the profiler status (clean read) then pThread
+    //         will immediately decrement the evac counter back to 0 and avoid
+    //         calling into the EEToProfInterfaceImpl pointer.
+    //
+    // (see
     // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization
-    // for details). Doing this under the thread store lock not only ensures we can
-    // iterate through the Thread objects safely, but also forces us to serialize with
-    // the GC. The latter is important, as server GC enters the profiler on non-EE
-    // Threads, and so no evacuation counters might be incremented during server GC even
-    // though control could be entering the profiler.
+    // for details)
+    DWORD dwEvacCounter = pProfilerInfo->dwProfilerEvacuationCounter;
+    if (dwEvacCounter != 0)
     {
-        ThreadStoreLockHolder TSLockHolder;
-
-        Thread * pThread = ThreadStore::GetAllThreadList(
-            NULL,   // cursor thread; always NULL to begin with
-            0,      // mask to AND with Thread::m_State to filter returned threads
-            0);     // bits to match the result of the above AND.  (m_State & 0 == 0,
-                    // so we won't filter out any threads)
-
-        // Note that, by not filtering out any of the threads, we're intentionally including
-        // stuff like TS_Dead or TS_Unstarted.  But that keeps us on the safe
-        // side.  If an EE Thread object exists, we want to check its counters to be
-        // absolutely certain it isn't executing in a profiler.
-
-        while (pThread != NULL)
-        {
-            // Note that pThread is still in motion as we check its evacuation counter.
-            // This is ok, because we've already changed the profiler status to
-            // kProfStatusDetaching and flushed CPU buffers. So at this point the counter
-            // will typically only go down to 0 (and not increment anymore), with one
-            // small exception (below). So if we get a read of 0 below, the counter will
-            // typically stay there. Specifically:
-            //     * pThread is most likely not about to increment its evacuation counter
-            //         from 0 to 1 because pThread sees that the status is
-            //         kProfStatusDetaching.
-            //     * Note that there is a small race where pThread might actually
-            //         increment its evac counter from 0 to 1 (if it dirty-read the
-            //         profiler status a tad too early), but that implies that when
-            //         pThread rechecks the profiler status (clean read) then pThread
-            //         will immediately decrement the evac counter back to 0 and avoid
-            //         calling into the EEToProfInterfaceImpl pointer.
-            //
-            // (see
-            // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization
-            // for details)
-            DWORD dwEvacCounter = pThread->GetProfilerEvacuationCounter();
-            if (dwEvacCounter != 0)
-            {
-                LOG((
-                    LF_CORPROF,
-                    LL_INFO100,
-                    "**PROF: Profiler not yet evacuated because OS Thread ID 0x%x has evac counter of %d (decimal).\n",
-                    pThread->GetOSThreadId(),
-                    dwEvacCounter));
-                return FALSE;
-            }
-
-            pThread = ThreadStore::GetAllThreadList(pThread, 0, 0);
-        }
+        LOG((
+            LF_CORPROF,
+            LL_INFO100,
+            "**PROF: Profiler not yet evacuated because it has evac counter of %d (decimal).\n",
+            dwEvacCounter));
+        return FALSE;
     }
 
     // FUTURE: When rejit feature crew complete, add code to verify all rejitted
@@ -1412,7 +1474,7 @@ BOOL ProfilingAPIUtility::IsProfilerEvacuated()
 //
 
 // static
-void ProfilingAPIUtility::TerminateProfiling()
+void ProfilingAPIUtility::TerminateProfiling(ProfilerInfo *pProfilerInfo)
 {
     CONTRACTL
     {
@@ -1439,7 +1501,7 @@ void ProfilingAPIUtility::TerminateProfiling()
 
 
 #ifdef FEATURE_PROFAPI_ATTACH_DETACH
-        if (ProfilingAPIDetach::GetEEToProfPtr() != NULL)
+        if (pProfilerInfo->curProfStatus.Get() == kProfStatusDetaching && pProfilerInfo->pProfInterface.Load() != NULL)
         {
             // The profiler is still being referenced by
             // ProfilingAPIDetach::s_profilerDetachInfo, so don't try to release and
@@ -1461,9 +1523,9 @@ void ProfilingAPIUtility::TerminateProfiling()
         }
 #endif // FEATURE_PROFAPI_ATTACH_DETACH
 
-        if (g_profControlBlock.curProfStatus.Get() == kProfStatusActive)
+        if (pProfilerInfo->curProfStatus.Get() == kProfStatusActive)
         {
-            g_profControlBlock.curProfStatus.Set(kProfStatusDetaching);
+            pProfilerInfo->curProfStatus.Set(kProfStatusDetaching);
 
             // Profiler was active when TerminateProfiling() was called, so we're unloading
             // it due to shutdown. But other threads may still be trying to enter profiler
@@ -1471,7 +1533,7 @@ void ProfilingAPIUtility::TerminateProfiling()
             // that the status has been changed to kProfStatusDetaching, no new threads will
             // attempt to enter the profiler. But use the detach evacuation counters to see
             // if other threads already began to enter the profiler.
-            if (!ProfilingAPIUtility::IsProfilerEvacuated())
+            if (!ProfilingAPIUtility::IsProfilerEvacuated(pProfilerInfo))
             {
                 // Other threads might be entering the profiler, so just skip cleanup
                 return;
@@ -1482,34 +1544,40 @@ void ProfilingAPIUtility::TerminateProfiling()
         // If we have a profiler callback wrapper and / or info implementation
         // active, then terminate them.
 
-        if (g_profControlBlock.pProfInterface.Load() != NULL)
+        if (pProfilerInfo->pProfInterface.Load() != NULL)
         {
             // This destructor takes care of releasing the profiler's ICorProfilerCallback*
             // interface, and unloading the DLL when we're not in process teardown.
-            delete g_profControlBlock.pProfInterface;
-            g_profControlBlock.pProfInterface.Store(NULL);
+            delete pProfilerInfo->pProfInterface;
+            pProfilerInfo->pProfInterface.Store(NULL);
         }
 
         // NOTE: Intentionally not destroying / NULLing s_csStatus. If
         // s_csStatus is already initialized, we can reuse it each time we do another
         // attach / detach, so no need to destroy it.
 
+        // Attach/Load/Detach are all synchronized with the Status Crst, don't need to worry about races
         // If we disabled concurrent GC and somehow failed later during the initialization
-        if (g_profControlBlock.fConcurrentGCDisabledForAttach)
+        if (g_profControlBlock.fConcurrentGCDisabledForAttach.Load() && g_profControlBlock.IsMainProfiler(pProfilerInfo->pProfInterface))
         {
+            g_profControlBlock.fConcurrentGCDisabledForAttach = FALSE;
+
             // We know for sure GC has been fully initialized as we've turned off concurrent GC before
             _ASSERTE(IsGarbageCollectorFullyInitialized());
             GCHeapUtilities::GetGCHeap()->TemporaryEnableConcurrentGC();
-            g_profControlBlock.fConcurrentGCDisabledForAttach = FALSE;
         }
 
         // #ProfileResetSessionStatus Reset all the status variables that are for the current
         // profiling attach session.
         // When you are adding new status in g_profControlBlock, you need to think about whether
         // your new status is per-session, or consistent across sessions
-        g_profControlBlock.ResetPerSessionStatus();
+        pProfilerInfo->ResetPerSessionStatus();
 
-        g_profControlBlock.curProfStatus.Set(kProfStatusNone);
+        pProfilerInfo->curProfStatus.Set(kProfStatusNone);
+        
+        g_profControlBlock.DeRegisterProfilerInfo(pProfilerInfo);
+        
+        g_profControlBlock.UpdateGlobalEventMask();
     }
 }
 
index 4c8ed1d..1cf7ea4 100644 (file)
@@ -64,52 +64,13 @@ public:
         UINT cbClientData,
         DWORD dwConcurrentGCWaitTimeoutInMs);
 
-    static BOOL IsProfilerEvacuated();
-    static void TerminateProfiling();
+    static BOOL IsProfilerEvacuated(ProfilerInfo *pDetachInfo);
+    static void TerminateProfiling(ProfilerInfo *pProfilerInfo);
     static void LogProfError(int iStringResourceID, ...);
     static void LogProfInfo(int iStringResourceID, ...);
     static void LogNoInterfaceError(REFIID iidRequested, LPCWSTR wszClsid);
     INDEBUG(static BOOL ShouldInjectProfAPIFault(ProfAPIFaultFlags faultFlag);)
 
-#ifdef FEATURE_PROFAPI_ATTACH_DETACH
-    // ----------------------------------------------------------------------------
-    // ProfilingAPIUtility::IncEvacuationCounter
-    //
-    // Description:
-    //    Simple helper to increase the evacuation counter inside an EE thread by one
-    //
-    // Arguments:
-    //    * pThread - pointer to an EE Thread
-    //
-    template<typename ThreadType>
-    static FORCEINLINE void IncEvacuationCounter(ThreadType * pThread)
-    {
-        LIMITED_METHOD_CONTRACT;
-
-        if (pThread)
-            pThread->IncProfilerEvacuationCounter();
-    }
-
-    // ----------------------------------------------------------------------------
-    // ProfilingAPIUtility::DecEvacuationCounter
-    //
-    // Description:
-    //    Simple helper to decrease the evacuation counter inside an EE thread by one
-    //
-    // Arguments:
-    //    * pThread - pointer to an EE Thread
-    //
-    template<typename ThreadType>
-    static FORCEINLINE void DecEvacuationCounter(ThreadType * pThread)
-    {
-        LIMITED_METHOD_CONTRACT;
-
-        if (pThread)
-            pThread->DecProfilerEvacuationCounter();
-    }
-
-#endif // FEATURE_PROFAPI_ATTACH_DETACH
-
     // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization
     static CRITSEC_COOKIE GetStatusCrst();
 
@@ -147,6 +108,8 @@ private:
         DWORD dwConcurrentGCWaitTimeoutInMs = INFINITE);
     static HRESULT ProfilerCLSIDFromString(__inout_z LPWSTR wszClsid, CLSID * pClsid);
     static HRESULT AttemptLoadProfilerForStartup();
+    static HRESULT AttemptLoadDelayedStartupProfilers();
+    static HRESULT AttemptLoadProfilerList();
 
     static void AppendSupplementaryInformation(int iStringResource, SString * pString);
 
@@ -173,4 +136,11 @@ private:
     DWORD      m_dwOriginalFullState;
 };
 
+FORCEINLINE void DeregisterProfilerIfNotificationOnly(ProfilerInfo *pProfilerInfo) 
+{
+    g_profControlBlock.DeRegisterProfilerInfo(pProfilerInfo);
+}
+
+typedef Wrapper<ProfilerInfo *, DoNothing, DeregisterProfilerIfNotificationOnly> ProfilerInfoHolder;
+
 #endif //__PROFILING_HELPER_H__
index 9416137..c1e9833 100644 (file)
@@ -177,7 +177,7 @@ enum ProfToClrEntrypointFlags
     do                                                                                     \
     {                                                                                      \
         if ((((p2eeFlags) & kP2EEAllowableAfterAttach) == 0) &&                            \
-            (g_profControlBlock.pProfInterface->IsLoadedViaAttach()))                      \
+            (m_pProfilerInfo->pProfInterface->IsLoadedViaAttach()))                      \
         {                                                                                  \
             LOG((LF_CORPROF,                                                               \
                  LL_ERROR,                                                                 \
@@ -214,10 +214,10 @@ enum ProfToClrEntrypointFlags
     do                                                                                      \
     {                                                                                       \
         INCONTRACT(AssertTriggersContract(((p2eeFlags) & kP2EETriggers)));                  \
-        _ASSERTE(g_profControlBlock.curProfStatus.Get() != kProfStatusNone);                \
+        _ASSERTE(m_pProfilerInfo->curProfStatus.Get() != kProfStatusNone);                \
         LOG(logParams);                                                                     \
         /* If profiler was neutered, disallow call */                                       \
-        if (g_profControlBlock.curProfStatus.Get() == kProfStatusDetaching)                 \
+        if (m_pProfilerInfo->curProfStatus.Get() == kProfStatusDetaching)                 \
         {                                                                                   \
             LOG((LF_CORPROF,                                                                \
                  LL_ERROR,                                                                  \
@@ -256,8 +256,8 @@ enum ProfToClrEntrypointFlags
     do                                                                                          \
     {                                                                                           \
         PROFILER_TO_CLR_ENTRYPOINT_ASYNC(logParams);                                            \
-        if (g_profControlBlock.curProfStatus.Get() != kProfStatusInitializingForStartupLoad &&  \
-            g_profControlBlock.curProfStatus.Get() != kProfStatusInitializingForAttachLoad)     \
+        if (m_pProfilerInfo->curProfStatus.Get() != kProfStatusInitializingForStartupLoad &&  \
+            m_pProfilerInfo->curProfStatus.Get() != kProfStatusInitializingForAttachLoad)     \
         {                                                                                       \
             return CORPROF_E_CALL_ONLY_FROM_INIT;                                               \
         }                                                                                       \
@@ -622,13 +622,13 @@ void __stdcall ProfilerObjectAllocatedCallback(OBJECTREF objref, ClassID classId
     // Notify the profiler of the allocation
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAllocations() || CORProfilerTrackLargeAllocations());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAllocations() || CORProfilerTrackLargeAllocations());
         // Note that for generic code we always return uninstantiated ClassIDs and FunctionIDs.
         // Thus we strip any instantiations of the ClassID (which is really a type handle) here.
-        g_profControlBlock.pProfInterface->ObjectAllocated(
+        g_profControlBlock.ObjectAllocated(
                 (ObjectID) OBJECTREFToObject(objref),
                 classId);
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 }
@@ -661,18 +661,18 @@ void __stdcall GarbageCollectionStartedCallback(int generation, BOOL induced)
 
     // Notify the profiler of start of the collection
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackGC() || CORProfilerTrackBasicGC());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC() || CORProfilerTrackBasicGC());
         BOOL generationCollected[COR_PRF_GC_PINNED_OBJECT_HEAP+1];
         if (generation == COR_PRF_GC_GEN_2)
             generation = COR_PRF_GC_PINNED_OBJECT_HEAP;
         for (int gen = 0; gen <= COR_PRF_GC_PINNED_OBJECT_HEAP; gen++)
             generationCollected[gen] = gen <= generation;
 
-        g_profControlBlock.pProfInterface->GarbageCollectionStarted(
+        g_profControlBlock.GarbageCollectionStarted(
             COR_PRF_GC_PINNED_OBJECT_HEAP+1,
             generationCollected,
             induced ? COR_PRF_GC_INDUCED : COR_PRF_GC_OTHER);
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 }
@@ -695,9 +695,9 @@ void __stdcall GarbageCollectionFinishedCallback()
 #ifdef PROFILING_SUPPORTED
     // Notify the profiler of end of the collection
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackGC() || CORProfilerTrackBasicGC());
-        g_profControlBlock.pProfInterface->GarbageCollectionFinished();
-        END_PIN_PROFILER();
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC() || CORProfilerTrackBasicGC());
+        g_profControlBlock.GarbageCollectionFinished();
+        END_PROFILER_CALLBACK();
     }
 
     // Mark that GC is finished.
@@ -1131,7 +1131,7 @@ bool HeapWalkHelper(Object * pBO, void * pvContext)
         // It is not safe and could be overflowed to downcast size_t to ULONG on WIN64.
         // However, we have to do this dangerous downcast here to comply with the existing Profiling COM interface.
         // We are currently evaluating ways to fix this potential overflow issue.
-        hr = g_profControlBlock.pProfInterface->ObjectReference(
+        hr = g_profControlBlock.ObjectReference(
             (ObjectID) pBO,
             SafeGetClassIDFromObject(pBO),
             (ULONG) cNumRefs,
@@ -1210,13 +1210,13 @@ bool AllocByClassHelper(Object * pBO, void * pv)
     _ASSERTE(pv != NULL);
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerPresent());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackAllocations());
         // Pass along the call
-        g_profControlBlock.pProfInterface->AllocByClass(
+        g_profControlBlock.AllocByClass(
             (ObjectID) pBO,
             SafeGetClassIDFromObject(pBO),
             pv);
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 
     return TRUE;
@@ -1286,8 +1286,7 @@ void ScanRootsHelper(Object* pObj, Object ** ppRoot, ScanContext *pSC, uint32_t
     if (pPSC->fProfilerPinned)
     {
         // Let the profiling code know about this root reference
-        g_profControlBlock.pProfInterface->
-            RootReference2((BYTE *)pObj, pPSC->dwEtwRootKind, (EtwGCRootFlags)dwEtwRootFlags, (BYTE *)rootID, &((pPSC)->pHeapId));
+        g_profControlBlock.RootReference2((BYTE *)pObj, pPSC->dwEtwRootKind, (EtwGCRootFlags)dwEtwRootFlags, (BYTE *)rootID, &((pPSC)->pHeapId));
     }
 #endif
 
@@ -1451,7 +1450,7 @@ HRESULT ProfToEEInterfaceImpl::SetEventMask(DWORD dwEventMask)
 
     _ASSERTE(CORProfilerPresentOrInitializing());
 
-    return g_profControlBlock.pProfInterface->SetEventMask(dwEventMask, 0 /* No high bits */);
+    return m_pProfilerInfo->pProfInterface->SetEventMask(dwEventMask, 0 /* No high bits */);
 }
 
 HRESULT ProfToEEInterfaceImpl::SetEventMask2(DWORD dwEventsLow, DWORD dwEventsHigh)
@@ -1483,7 +1482,7 @@ HRESULT ProfToEEInterfaceImpl::SetEventMask2(DWORD dwEventsLow, DWORD dwEventsHi
 
     _ASSERTE(CORProfilerPresentOrInitializing());
 
-    return g_profControlBlock.pProfInterface->SetEventMask(dwEventsLow, dwEventsHigh);
+    return m_pProfilerInfo->pProfInterface->SetEventMask(dwEventsLow, dwEventsHigh);
 }
 
 
@@ -2571,7 +2570,7 @@ HRESULT ProfToEEInterfaceImpl::GetEventMask(DWORD * pdwEvents)
         return E_INVALIDARG;
     }
 
-    *pdwEvents = g_profControlBlock.dwEventMask;
+    *pdwEvents = m_pProfilerInfo->eventMask.GetEventMask();
     return S_OK;
 }
 
@@ -2608,8 +2607,8 @@ HRESULT ProfToEEInterfaceImpl::GetEventMask2(DWORD *pdwEventsLow, DWORD *pdwEven
         return E_INVALIDARG;
     }
 
-    *pdwEventsLow = g_profControlBlock.dwEventMask;
-    *pdwEventsHigh = g_profControlBlock.dwEventMaskHigh;
+    *pdwEventsLow = m_pProfilerInfo->eventMask.GetEventMask();
+    *pdwEventsHigh = m_pProfilerInfo->eventMask.GetEventMaskHigh();
     return S_OK;
 }
 
@@ -4462,6 +4461,11 @@ HRESULT ProfToEEInterfaceImpl::SetILFunctionBody(ModuleID    moduleId,
         return E_INVALIDARG;
     }
 
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
     Module      *pModule;               // Working pointer for real class.
     HRESULT     hr = S_OK;
 
@@ -4478,7 +4482,7 @@ HRESULT ProfToEEInterfaceImpl::SetILFunctionBody(ModuleID    moduleId,
     }
 
     // Remember the profiler is doing this, as that means we must never detach it!
-    g_profControlBlock.pProfInterface->SetUnrevertiblyModifiedILFlag();
+    g_profControlBlock.mainProfilerInfo.pProfInterface->SetUnrevertiblyModifiedILFlag();
 
     // This action is not temporary!
     // If the profiler want to be able to revert, they need to use
@@ -5751,7 +5755,12 @@ HRESULT ProfToEEInterfaceImpl::SetEnterLeaveFunctionHooks(FunctionEnter * pFuncE
                                         pFuncLeave,
                                         pFuncTailcall));
 
-    return g_profControlBlock.pProfInterface->SetEnterLeaveFunctionHooks(pFuncEnter, pFuncLeave, pFuncTailcall);
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
+    return g_profControlBlock.mainProfilerInfo.pProfInterface->SetEnterLeaveFunctionHooks(pFuncEnter, pFuncLeave, pFuncTailcall);
 }
 
 
@@ -5787,8 +5796,13 @@ HRESULT ProfToEEInterfaceImpl::SetEnterLeaveFunctionHooks2(FunctionEnter2 * pFun
                                         pFuncLeave,
                                         pFuncTailcall));
 
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
     return
-        g_profControlBlock.pProfInterface->SetEnterLeaveFunctionHooks2(pFuncEnter, pFuncLeave, pFuncTailcall);
+        g_profControlBlock.mainProfilerInfo.pProfInterface->SetEnterLeaveFunctionHooks2(pFuncEnter, pFuncLeave, pFuncTailcall);
 }
 
 
@@ -5824,8 +5838,13 @@ HRESULT ProfToEEInterfaceImpl::SetEnterLeaveFunctionHooks3(FunctionEnter3 * pFun
                                         pFuncLeave3,
                                         pFuncTailcall3));
 
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
     return
-        g_profControlBlock.pProfInterface->SetEnterLeaveFunctionHooks3(pFuncEnter3,
+        g_profControlBlock.mainProfilerInfo.pProfInterface->SetEnterLeaveFunctionHooks3(pFuncEnter3,
                                                                        pFuncLeave3,
                                                                        pFuncTailcall3);
 }
@@ -5864,8 +5883,13 @@ HRESULT ProfToEEInterfaceImpl::SetEnterLeaveFunctionHooks3WithInfo(FunctionEnter
                                         pFuncLeave3WithInfo,
                                         pFuncTailcall3WithInfo));
 
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
     return
-        g_profControlBlock.pProfInterface->SetEnterLeaveFunctionHooks3WithInfo(pFuncEnter3WithInfo,
+        g_profControlBlock.mainProfilerInfo.pProfInterface->SetEnterLeaveFunctionHooks3WithInfo(pFuncEnter3WithInfo,
                                                                                pFuncLeave3WithInfo,
                                                                                pFuncTailcall3WithInfo);
 }
@@ -5898,7 +5922,12 @@ HRESULT ProfToEEInterfaceImpl::SetFunctionIDMapper(FunctionIDMapper *pFunc)
                                       "**PROF: SetFunctionIDMapper 0x%p.\n",
                                       pFunc));
 
-    g_profControlBlock.pProfInterface->SetFunctionIDMapper(pFunc);
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
+    g_profControlBlock.mainProfilerInfo.pProfInterface->SetFunctionIDMapper(pFunc);
 
     return (S_OK);
 }
@@ -5931,7 +5960,12 @@ HRESULT ProfToEEInterfaceImpl::SetFunctionIDMapper2(FunctionIDMapper2 *pFunc, vo
                                       pFunc,
                                       clientData));
 
-    g_profControlBlock.pProfInterface->SetFunctionIDMapper2(pFunc, clientData);
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
+    g_profControlBlock.mainProfilerInfo.pProfInterface->SetFunctionIDMapper2(pFunc, clientData);
 
     return (S_OK);
 }
@@ -6709,7 +6743,12 @@ HRESULT ProfToEEInterfaceImpl::RequestReJITWithInliners(
          LL_INFO1000,
          "**PROF: RequestReJITWithInliners.\n"));
 
-    if (!g_profControlBlock.pProfInterface->IsCallback4Supported())
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
+    if (!m_pProfilerInfo->pProfInterface->IsCallback4Supported())
     {
         return CORPROF_E_CALLBACK4_REQUIRED;
     }
@@ -6737,7 +6776,7 @@ HRESULT ProfToEEInterfaceImpl::RequestReJITWithInliners(
     }
 
     // Remember the profiler is doing this, as that means we must never detach it!
-    g_profControlBlock.pProfInterface->SetUnrevertiblyModifiedILFlag();
+    g_profControlBlock.mainProfilerInfo.pProfInterface->SetUnrevertiblyModifiedILFlag();
 
     HRESULT hr = SetupThreadForReJIT();
     if (FAILED(hr))
@@ -7067,7 +7106,8 @@ HRESULT ProfToEEInterfaceImpl::EventPipeStartSession(
                                              EP_SERIALIZATION_FORMAT_NETTRACE_V4,
                                              requestRundown,
                                              NULL,
-                                             reinterpret_cast<EventPipeSessionSynchronousCallback>(&ProfToEEInterfaceImpl::EventPipeCallbackHelper));
+                                             reinterpret_cast<EventPipeSessionSynchronousCallback>(&ProfToEEInterfaceImpl::EventPipeCallbackHelper),
+                                             reinterpret_cast<void *>(m_pProfilerInfo));
         if (sessionID != 0)
         {
             EventPipeAdapter::StartStreaming(sessionID);
@@ -7378,28 +7418,33 @@ void ProfToEEInterfaceImpl::EventPipeCallbackHelper(EventPipeProvider *provider,
                                                     LPCGUID pRelatedActivityId,
                                                     Thread *pEventThread,
                                                     ULONG numStackFrames,
-                                                    UINT_PTR stackFrames[])
-{
-    // If we got here we know a profiler has started an EventPipe session
-    BEGIN_PIN_PROFILER(true);
-    // But, a profiler could always register for a session and then detach without
-    // closing the session. So check if we have an interface before proceeding.
-    if (g_profControlBlock.pProfInterface != nullptr)
-    {
-        g_profControlBlock.pProfInterface->EventPipeEventDelivered(provider,
-                                                                   eventId,
-                                                                   eventVersion,
-                                                                   cbMetadataBlob,
-                                                                   metadataBlob,
-                                                                   cbEventData,
-                                                                   eventData,
-                                                                   pActivityId,
-                                                                   pRelatedActivityId,
-                                                                   pEventThread,
-                                                                   numStackFrames,
-                                                                   stackFrames);
-    }
-    END_PIN_PROFILER();
+                                                    UINT_PTR stackFrames[],
+                                                    void *additionalData)
+{
+    _ASSERTE(additionalData != NULL);
+    ProfilerInfo *pProfilerInfo = reinterpret_cast<ProfilerInfo *>(additionalData);
+
+    _ASSERTE(pProfilerInfo->pProfInterface.Load() != NULL);
+    {
+        EvacuationCounterHolder holder(pProfilerInfo);
+        // But, a profiler could always register for a session and then detach without
+        // closing the session. So check if we have an interface before proceeding.
+        if (pProfilerInfo->pProfInterface.Load() != NULL)
+        {
+            pProfilerInfo->pProfInterface->EventPipeEventDelivered(provider,
+                                                                       eventId,
+                                                                       eventVersion,
+                                                                       cbMetadataBlob,
+                                                                       metadataBlob,
+                                                                       cbEventData,
+                                                                       eventData,
+                                                                       pActivityId,
+                                                                       pRelatedActivityId,
+                                                                       pEventThread,
+                                                                       numStackFrames,
+                                                                       stackFrames);
+        }
+    }
 };
 
 
@@ -9116,7 +9161,12 @@ HRESULT ProfToEEInterfaceImpl::RequestReJIT(ULONG       cFunctions,   // in
          LL_INFO1000,
          "**PROF: RequestReJIT.\n"));
 
-    if (!g_profControlBlock.pProfInterface->IsCallback4Supported())
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
+    if (!m_pProfilerInfo->pProfInterface->IsCallback4Supported())
     {
         return CORPROF_E_CALLBACK4_REQUIRED;
     }
@@ -9133,7 +9183,7 @@ HRESULT ProfToEEInterfaceImpl::RequestReJIT(ULONG       cFunctions,   // in
     }
 
     // Remember the profiler is doing this, as that means we must never detach it!
-    g_profControlBlock.pProfInterface->SetUnrevertiblyModifiedILFlag();
+    g_profControlBlock.mainProfilerInfo.pProfInterface->SetUnrevertiblyModifiedILFlag();
 
     HRESULT hr = SetupThreadForReJIT();
     if (FAILED(hr))
@@ -9178,6 +9228,11 @@ HRESULT ProfToEEInterfaceImpl::RequestRevert(ULONG       cFunctions,  // in
          LL_INFO1000,
          "**PROF: RequestRevert.\n"));
 
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
     if (!CORProfilerEnableRejit())
     {
         return CORPROF_E_REJIT_NOT_ENABLED;
@@ -9190,7 +9245,7 @@ HRESULT ProfToEEInterfaceImpl::RequestRevert(ULONG       cFunctions,  // in
     }
 
     // Remember the profiler is doing this, as that means we must never detach it!
-    g_profControlBlock.pProfInterface->SetUnrevertiblyModifiedILFlag();
+    g_profControlBlock.mainProfilerInfo.pProfInterface->SetUnrevertiblyModifiedILFlag();
 
     // Initialize the status array
     if (rgHrStatuses != NULL)
@@ -9497,7 +9552,7 @@ HRESULT ProfToEEInterfaceImpl::RequestProfilerDetach(DWORD dwExpectedCompletionM
         "**PROF: RequestProfilerDetach.\n"));
 
 #ifdef FEATURE_PROFAPI_ATTACH_DETACH
-    return ProfilingAPIDetach::RequestProfilerDetach(dwExpectedCompletionMilliseconds);
+    return ProfilingAPIDetach::RequestProfilerDetach(g_profControlBlock.GetProfilerInfo(this), dwExpectedCompletionMilliseconds);
 #else // FEATURE_PROFAPI_ATTACH_DETACH
     return E_NOTIMPL;
 #endif // FEATURE_PROFAPI_ATTACH_DETACH
@@ -9710,7 +9765,12 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionEnter3Info(FunctionID functionId,
                                     LL_INFO1000,
                                     "**PROF: GetFunctionEnter3Info.\n"));
 
-    _ASSERTE(g_profControlBlock.pProfInterface->GetEnter3WithInfoHook() != NULL);
+    _ASSERTE(g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter3WithInfoHook() != NULL);
+
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
 
     if (!CORProfilerELT3SlowPathEnterEnabled())
     {
@@ -9868,7 +9928,12 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionLeave3Info(FunctionID functionId,
                                     LL_INFO1000,
                                     "**PROF: GetFunctionLeave3Info.\n"));
 
-    _ASSERTE(g_profControlBlock.pProfInterface->GetLeave3WithInfoHook() != NULL);
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
+
+    _ASSERTE(g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave3WithInfoHook() != NULL);
 
     if (!CORProfilerELT3SlowPathLeaveEnabled())
     {
@@ -10000,7 +10065,12 @@ HRESULT ProfToEEInterfaceImpl::GetFunctionTailcall3Info(FunctionID functionId,
                                     LL_INFO1000,
                                     "**PROF: GetFunctionTailcall3Info.\n"));
 
-    _ASSERTE(g_profControlBlock.pProfInterface->GetTailcall3WithInfoHook() != NULL);
+    _ASSERTE(g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall3WithInfoHook() != NULL);
+
+    if (!g_profControlBlock.IsMainProfiler(this))
+    {
+        return E_INVALIDARG;
+    }
 
     if (!CORProfilerELT3SlowPathTailcallEnabled())
     {
@@ -10409,10 +10479,9 @@ void __stdcall ProfilerManagedToUnmanagedTransitionMD(MethodDesc *pMD,
     // Do not notify the profiler about QCalls
     if (pMD == NULL || !pMD->IsQCall())
     {
-        BEGIN_PIN_PROFILER(CORProfilerPresent());
-        g_profControlBlock.pProfInterface->ManagedToUnmanagedTransition(MethodDescToFunctionID(pMD),
-                                                                        reason);
-        END_PIN_PROFILER();
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackTransitions());
+        g_profControlBlock.ManagedToUnmanagedTransition(MethodDescToFunctionID(pMD), reason);
+        END_PROFILER_CALLBACK();
     }
 }
 
@@ -10444,10 +10513,9 @@ void __stdcall ProfilerUnmanagedToManagedTransitionMD(MethodDesc *pMD,
     // Do not notify the profiler about QCalls
     if (pMD == NULL || !pMD->IsQCall())
     {
-        BEGIN_PIN_PROFILER(CORProfilerPresent());
-        g_profControlBlock.pProfInterface->UnmanagedToManagedTransition(MethodDescToFunctionID(pMD),
-                                                                        reason);
-        END_PIN_PROFILER();
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackTransitions());
+        g_profControlBlock.UnmanagedToManagedTransition(MethodDescToFunctionID(pMD), reason);
+        END_PROFILER_CALLBACK();
     }
 }
 
@@ -10472,12 +10540,12 @@ HCIMPL2(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecifi
     // code:ProfControlBlock#TestOnlyELT
     if (g_profControlBlock.fTestOnlyForceEnterLeave)
     {
-        if ((g_profControlBlock.pProfInterface.Load() == NULL) ||
+        if ((g_profControlBlock.mainProfilerInfo.pProfInterface.Load() == NULL) ||
             (
-                (g_profControlBlock.pProfInterface->GetEnterHook()          == NULL) &&
-                (g_profControlBlock.pProfInterface->GetEnter2Hook()         == NULL) &&
-                (g_profControlBlock.pProfInterface->GetEnter3Hook()         == NULL) &&
-                (g_profControlBlock.pProfInterface->GetEnter3WithInfoHook() == NULL)
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnterHook()          == NULL) &&
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter2Hook()         == NULL) &&
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter3Hook()         == NULL) &&
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter3WithInfoHook() == NULL)
             )
            )
         {
@@ -10487,7 +10555,7 @@ HCIMPL2(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecifi
 #endif // PROF_TEST_ONLY_FORCE_ELT
 
     // ELT3 Fast-Path hooks should be NULL when ELT intermediary is used.
-    _ASSERTE(g_profControlBlock.pProfInterface->GetEnter3Hook() == NULL);
+    _ASSERTE(g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter3Hook() == NULL);
     _ASSERTE(GetThread()->PreemptiveGCDisabled());
     _ASSERTE(platformSpecificHandle != NULL);
 
@@ -10505,21 +10573,21 @@ HCIMPL2(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecifi
     //
     // CLR v4 Slow-Path ELT
     //
-    if (g_profControlBlock.pProfInterface->GetEnter3WithInfoHook() != NULL)
+    if (g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter3WithInfoHook() != NULL)
     {
         FunctionIDOrClientID functionIDOrClientID;
         functionIDOrClientID.clientID = clientData;
-        g_profControlBlock.pProfInterface->GetEnter3WithInfoHook()(
+        g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter3WithInfoHook()(
             functionIDOrClientID,
             (COR_PRF_ELT_INFO)&eltInfo);
         goto LExit;
     }
 
-    if (g_profControlBlock.pProfInterface->GetEnter2Hook() != NULL)
+    if (g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter2Hook() != NULL)
     {
         // We have run out of heap memory, so the content of the mapping table becomes stale.
         // All Whidbey ETL hooks must be turned off.
-        if (!g_profControlBlock.pProfInterface->IsClientIDToFunctionIDMappingEnabled())
+        if (!g_profControlBlock.mainProfilerInfo.pProfInterface->IsClientIDToFunctionIDMappingEnabled())
         {
             goto LExit;
         }
@@ -10531,14 +10599,14 @@ HCIMPL2(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecifi
         // key to retrieve the corresponding clientID from the internal FunctionID hash table.
         FunctionID functionId = clientData;
         _ASSERTE(functionId != NULL);
-        clientData = g_profControlBlock.pProfInterface->LookupClientIDFromCache(functionId);
+        clientData = g_profControlBlock.mainProfilerInfo.pProfInterface->LookupClientIDFromCache(functionId);
 
         //
         // Whidbey Fast-Path ELT
         //
         if (CORProfilerELT2FastPathEnterEnabled())
         {
-            g_profControlBlock.pProfInterface->GetEnter2Hook()(
+            g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter2Hook()(
                 functionId,
                 clientData,
                 NULL,
@@ -10594,7 +10662,7 @@ HCIMPL2(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecifi
         HRESULT hr = ProfilingGetFunctionEnter3Info(functionId, (COR_PRF_ELT_INFO)&eltInfo, &frameInfo, &ulArgInfoSize, pArgumentInfo);
 
         _ASSERTE(hr == S_OK);
-        g_profControlBlock.pProfInterface->GetEnter2Hook()(functionId, clientData, frameInfo, pArgumentInfo);
+        g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnter2Hook()(functionId, clientData, frameInfo, pArgumentInfo);
 
         goto LExit;
     }
@@ -10606,7 +10674,7 @@ HCIMPL2(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecifi
     // in the first place.  (Note that SetEnterLeaveFunctionHooks* will return
     // an error unless it's called in the profiler's Initialize(), so a profiler can't change
     // its mind about where the hooks are.)
-    _ASSERTE(g_profControlBlock.pProfInterface->GetEnterHook() != NULL);
+    _ASSERTE(g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnterHook() != NULL);
 
     // Note that we cannot assert CORProfilerTrackEnterLeave() (i.e., profiler flag
     // COR_PRF_MONITOR_ENTERLEAVE), because the profiler may decide whether
@@ -10618,7 +10686,7 @@ HCIMPL2(EXTERN_C void, ProfileEnter, UINT_PTR clientData, void * platformSpecifi
     // Everett ELT
     //
     {
-        g_profControlBlock.pProfInterface->GetEnterHook()((FunctionID)clientData);
+        g_profControlBlock.mainProfilerInfo.pProfInterface->GetEnterHook()((FunctionID)clientData);
     }
 
 LExit:
@@ -10644,12 +10712,12 @@ HCIMPL2(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecifi
     // code:ProfControlBlock#TestOnlyELT
     if (g_profControlBlock.fTestOnlyForceEnterLeave)
     {
-        if ((g_profControlBlock.pProfInterface.Load() == NULL) ||
+        if ((g_profControlBlock.mainProfilerInfo.pProfInterface.Load() == NULL) ||
             (
-                (g_profControlBlock.pProfInterface->GetLeaveHook()          == NULL) &&
-                (g_profControlBlock.pProfInterface->GetLeave2Hook()         == NULL) &&
-                (g_profControlBlock.pProfInterface->GetLeave3Hook()         == NULL) &&
-                (g_profControlBlock.pProfInterface->GetLeave3WithInfoHook() == NULL)
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeaveHook()          == NULL) &&
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave2Hook()         == NULL) &&
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave3Hook()         == NULL) &&
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave3WithInfoHook() == NULL)
             )
            )
         {
@@ -10659,7 +10727,7 @@ HCIMPL2(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecifi
 #endif // PROF_TEST_ONLY_FORCE_ELT
 
     // ELT3 Fast-Path hooks should be NULL when ELT intermediary is used.
-    _ASSERTE(g_profControlBlock.pProfInterface->GetLeave3Hook() == NULL);
+    _ASSERTE(g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave3Hook() == NULL);
     _ASSERTE(GetThread()->PreemptiveGCDisabled());
     _ASSERTE(platformSpecificHandle != NULL);
 
@@ -10677,21 +10745,21 @@ HCIMPL2(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecifi
     //
     // CLR v4 Slow-Path ELT
     //
-    if (g_profControlBlock.pProfInterface->GetLeave3WithInfoHook() != NULL)
+    if (g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave3WithInfoHook() != NULL)
     {
         FunctionIDOrClientID functionIDOrClientID;
         functionIDOrClientID.clientID = clientData;
-        g_profControlBlock.pProfInterface->GetLeave3WithInfoHook()(
+        g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave3WithInfoHook()(
             functionIDOrClientID,
             (COR_PRF_ELT_INFO)&eltInfo);
         goto LExit;
     }
 
-    if (g_profControlBlock.pProfInterface->GetLeave2Hook() != NULL)
+    if (g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave2Hook() != NULL)
     {
         // We have run out of heap memory, so the content of the mapping table becomes stale.
         // All Whidbey ETL hooks must be turned off.
-        if (!g_profControlBlock.pProfInterface->IsClientIDToFunctionIDMappingEnabled())
+        if (!g_profControlBlock.mainProfilerInfo.pProfInterface->IsClientIDToFunctionIDMappingEnabled())
         {
             goto LExit;
         }
@@ -10703,14 +10771,14 @@ HCIMPL2(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecifi
         // key to retrieve the corresponding clientID from the internal FunctionID hash table.
         FunctionID functionId = clientData;
         _ASSERTE(functionId != NULL);
-        clientData = g_profControlBlock.pProfInterface->LookupClientIDFromCache(functionId);
+        clientData = g_profControlBlock.mainProfilerInfo.pProfInterface->LookupClientIDFromCache(functionId);
 
         //
         // Whidbey Fast-Path ELT
         //
         if (CORProfilerELT2FastPathLeaveEnabled())
         {
-            g_profControlBlock.pProfInterface->GetLeave2Hook()(
+            g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave2Hook()(
                 functionId,
                 clientData,
                 NULL,
@@ -10727,7 +10795,7 @@ HCIMPL2(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecifi
         HRESULT hr = ProfilingGetFunctionLeave3Info(functionId, (COR_PRF_ELT_INFO)&eltInfo, &frameInfo, &argumentRange);
         _ASSERTE(hr == S_OK);
 
-        g_profControlBlock.pProfInterface->GetLeave2Hook()(functionId, clientData, frameInfo, &argumentRange);
+        g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeave2Hook()(functionId, clientData, frameInfo, &argumentRange);
         goto LExit;
     }
 
@@ -10737,7 +10805,7 @@ HCIMPL2(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecifi
     // in the first place.  (Note that SetEnterLeaveFunctionHooks* will return
     // an error unless it's called in the profiler's Initialize(), so a profiler can't change
     // its mind about where the hooks are.)
-    _ASSERTE(g_profControlBlock.pProfInterface->GetLeaveHook() != NULL);
+    _ASSERTE(g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeaveHook() != NULL);
 
     // Note that we cannot assert CORProfilerTrackEnterLeave() (i.e., profiler flag
     // COR_PRF_MONITOR_ENTERLEAVE), because the profiler may decide whether
@@ -10749,7 +10817,7 @@ HCIMPL2(EXTERN_C void, ProfileLeave, UINT_PTR clientData, void * platformSpecifi
     // Everett ELT
     //
     {
-        g_profControlBlock.pProfInterface->GetLeaveHook()((FunctionID)clientData);
+        g_profControlBlock.mainProfilerInfo.pProfInterface->GetLeaveHook()((FunctionID)clientData);
     }
 
 LExit:
@@ -10776,12 +10844,12 @@ HCIMPL2(EXTERN_C void, ProfileTailcall, UINT_PTR clientData, void * platformSpec
     // code:ProfControlBlock#TestOnlyELT
     if (g_profControlBlock.fTestOnlyForceEnterLeave)
     {
-        if ((g_profControlBlock.pProfInterface.Load() == NULL) ||
+        if ((g_profControlBlock.mainProfilerInfo.pProfInterface.Load() == NULL) ||
             (
-                (g_profControlBlock.pProfInterface->GetTailcallHook()          == NULL) &&
-                (g_profControlBlock.pProfInterface->GetTailcall2Hook()         == NULL) &&
-                (g_profControlBlock.pProfInterface->GetTailcall3Hook()         == NULL) &&
-                (g_profControlBlock.pProfInterface->GetTailcall3WithInfoHook() == NULL)
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcallHook()          == NULL) &&
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall2Hook()         == NULL) &&
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall3Hook()         == NULL) &&
+                (g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall3WithInfoHook() == NULL)
             )
            )
         {
@@ -10791,7 +10859,7 @@ HCIMPL2(EXTERN_C void, ProfileTailcall, UINT_PTR clientData, void * platformSpec
 #endif // PROF_TEST_ONLY_FORCE_ELT
 
     // ELT3 fast-path hooks should be NULL when ELT intermediary is used.
-    _ASSERTE(g_profControlBlock.pProfInterface->GetTailcall3Hook() == NULL);
+    _ASSERTE(g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall3Hook() == NULL);
     _ASSERTE(GetThread()->PreemptiveGCDisabled());
     _ASSERTE(platformSpecificHandle != NULL);
 
@@ -10809,21 +10877,21 @@ HCIMPL2(EXTERN_C void, ProfileTailcall, UINT_PTR clientData, void * platformSpec
     //
     // CLR v4 Slow-Path ELT
     //
-    if (g_profControlBlock.pProfInterface->GetTailcall3WithInfoHook() != NULL)
+    if (g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall3WithInfoHook() != NULL)
     {
         FunctionIDOrClientID functionIDOrClientID;
         functionIDOrClientID.clientID = clientData;
-        g_profControlBlock.pProfInterface->GetTailcall3WithInfoHook()(
+        g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall3WithInfoHook()(
             functionIDOrClientID,
             (COR_PRF_ELT_INFO)&eltInfo);
         goto LExit;
     }
 
-    if (g_profControlBlock.pProfInterface->GetTailcall2Hook() != NULL)
+    if (g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall2Hook() != NULL)
     {
         // We have run out of heap memory, so the content of the mapping table becomes stale.
         // All Whidbey ETL hooks must be turned off.
-        if (!g_profControlBlock.pProfInterface->IsClientIDToFunctionIDMappingEnabled())
+        if (!g_profControlBlock.mainProfilerInfo.pProfInterface->IsClientIDToFunctionIDMappingEnabled())
         {
             goto LExit;
         }
@@ -10835,14 +10903,14 @@ HCIMPL2(EXTERN_C void, ProfileTailcall, UINT_PTR clientData, void * platformSpec
         // key to retrieve the corresponding clientID from the internal FunctionID hash table.
         FunctionID functionId = clientData;
         _ASSERTE(functionId != NULL);
-        clientData = g_profControlBlock.pProfInterface->LookupClientIDFromCache(functionId);
+        clientData = g_profControlBlock.mainProfilerInfo.pProfInterface->LookupClientIDFromCache(functionId);
 
         //
         // Whidbey Fast-Path ELT
         //
         if (CORProfilerELT2FastPathTailcallEnabled())
         {
-            g_profControlBlock.pProfInterface->GetTailcall2Hook()(
+            g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall2Hook()(
                 functionId,
                 clientData,
                 NULL);
@@ -10857,7 +10925,7 @@ HCIMPL2(EXTERN_C void, ProfileTailcall, UINT_PTR clientData, void * platformSpec
         HRESULT hr = ProfilingGetFunctionTailcall3Info(functionId, (COR_PRF_ELT_INFO)&eltInfo, &frameInfo);
         _ASSERTE(hr == S_OK);
 
-        g_profControlBlock.pProfInterface->GetTailcall2Hook()(functionId, clientData, frameInfo);
+        g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcall2Hook()(functionId, clientData, frameInfo);
         goto LExit;
     }
 
@@ -10867,7 +10935,7 @@ HCIMPL2(EXTERN_C void, ProfileTailcall, UINT_PTR clientData, void * platformSpec
     // in the first place.  (Note that SetEnterLeaveFunctionHooks* will return
     // an error unless it's called in the profiler's Initialize(), so a profiler can't change
     // its mind about where the hooks are.)
-    _ASSERTE(g_profControlBlock.pProfInterface->GetTailcallHook() != NULL);
+    _ASSERTE(g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcallHook() != NULL);
 
     // Note that we cannot assert CORProfilerTrackEnterLeave() (i.e., profiler flag
     // COR_PRF_MONITOR_ENTERLEAVE), because the profiler may decide whether
@@ -10878,7 +10946,7 @@ HCIMPL2(EXTERN_C void, ProfileTailcall, UINT_PTR clientData, void * platformSpec
     //
     // Everett ELT
     //
-    g_profControlBlock.pProfInterface->GetTailcallHook()((FunctionID)clientData);
+    g_profControlBlock.mainProfilerInfo.pProfInterface->GetTailcallHook()((FunctionID)clientData);
 
 LExit:
 
index de5b75a..1cb3407 100644 (file)
@@ -145,6 +145,9 @@ typedef struct _PROFILER_STACK_WALK_DATA PROFILER_STACK_WALK_DATA;
 
 class ProfToEEInterfaceImpl : public ICorProfilerInfo12
 {
+private:
+    ProfilerInfo *m_pProfilerInfo;
+
 public:
 
     // Internal Housekeeping
@@ -156,6 +159,12 @@ public:
     virtual ~ProfToEEInterfaceImpl();
     HRESULT Init();
 
+    void SetProfilerInfo(ProfilerInfo *pProfilerInfo)
+    {
+        LIMITED_METHOD_CONTRACT;
+        m_pProfilerInfo = pProfilerInfo;
+    }
+
     // IUnknown
     ULONG STDMETHODCALLTYPE AddRef();
     ULONG STDMETHODCALLTYPE Release();
@@ -694,7 +703,6 @@ public:
 protected:
 
     // Internal Helper Functions
-
     static void EventPipeCallbackHelper(EventPipeProvider *provider,
                                         DWORD eventId,
                                         DWORD eventVersion,
@@ -706,7 +714,8 @@ protected:
                                         LPCGUID pRelatedActivityId,
                                         Thread *pEventThread,
                                         ULONG numStackFrames,
-                                        UINT_PTR stackFrames[]);
+                                        UINT_PTR stackFrames[],
+                                        void *additionalData);
 
     HRESULT GetCodeInfoHelper(FunctionID functionId,
                                ReJITID  reJitId,
index a7a7e03..cf2803d 100644 (file)
@@ -946,10 +946,10 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig
 #ifndef CROSSGEN_COMPILE
 #ifdef PROFILING_SUPPORTED
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackCacheSearches());
-            g_profControlBlock.pProfInterface->
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackCacheSearches());
+            (&g_profControlBlock)->
                 JITCachedFunctionSearchStarted((FunctionID)pMD, &fShouldSearchCache);
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
         if (!fShouldSearchCache)
         {
@@ -1001,10 +1001,10 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig
 #ifndef CROSSGEN_COMPILE
 #ifdef PROFILING_SUPPORTED
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackCacheSearches());
-            g_profControlBlock.pProfInterface->
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackCacheSearches());
+            (&g_profControlBlock)->
                 JITCachedFunctionSearchFinished((FunctionID)pMD, COR_PRF_CACHED_FUNCTION_FOUND);
-            END_PIN_PROFILER();
+            END_PROFILER_CALLBACK();
         }
 #endif // PROFILING_SUPPORTED
 #endif // CROSSGEN_COMPILE
index ff180ce..d66c999 100644 (file)
@@ -1079,12 +1079,12 @@ HRESULT ReJitManager::ConfigureILCodeVersion(ILCodeVersion ilCodeVersion)
             }
             else
             {
-                BEGIN_PIN_PROFILER(CORProfilerPresent());
-                hr = g_profControlBlock.pProfInterface->GetReJITParameters(
+                BEGIN_PROFILER_CALLBACK(CORProfilerPresent());
+                hr = (&g_profControlBlock)->GetReJITParameters(
                     (ModuleID)pModule,
                     methodDef,
                     pFuncControl);
-                END_PIN_PROFILER();
+                END_PROFILER_CALLBACK();
             }
         }
 
index b69b63d..f59c536 100644 (file)
@@ -68,17 +68,17 @@ inline void ReJitManager::ReportReJITError(Module* pModule, mdMethodDef methodDe
     CONTRACTL_END;
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerPresent());
+        BEGIN_PROFILER_CALLBACK(CORProfilerEnableRejit());
         _ASSERTE(CORProfilerEnableRejit());
         {
             GCX_PREEMP();
-            g_profControlBlock.pProfInterface->ReJITError(
+            (&g_profControlBlock)->mainProfilerInfo.pProfInterface->ReJITError(
                 reinterpret_cast< ModuleID > (pModule),
                 methodDef,
                 reinterpret_cast< FunctionID > (pMD),
                 hrStatus);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 }
index 401be0a..a8851f3 100644 (file)
@@ -2304,9 +2304,9 @@ void QCALLTYPE RuntimeMethodHandle::Destroy(MethodDesc * pMethod)
     // Fire Unload Dynamic Method Event here
     ETW::MethodLog::DynamicMethodDestroyed(pMethod);
 
-    BEGIN_PIN_PROFILER(CORProfilerIsMonitoringDynamicFunctionUnloads());
-    g_profControlBlock.pProfInterface->DynamicMethodUnloaded((FunctionID)pMethod);
-    END_PIN_PROFILER();
+    BEGIN_PROFILER_CALLBACK(CORProfilerTrackDynamicFunctionUnloads());
+    (&g_profControlBlock)->DynamicMethodUnloaded((FunctionID)pMethod);
+    END_PROFILER_CALLBACK();
 
     pDynamicMethodDesc->Destroy();
 
index ee66f3e..4dfa4a2 100644 (file)
@@ -762,17 +762,17 @@ Thread* SetupThread()
     // thread has been created.
     if (!IsGCSpecialThread())
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackThreads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackThreads());
         {
             GCX_PREEMP();
-            g_profControlBlock.pProfInterface->ThreadCreated(
+            (&g_profControlBlock)->ThreadCreated(
                 (ThreadID)pThread);
         }
 
         DWORD osThreadId = ::GetCurrentThreadId();
-        g_profControlBlock.pProfInterface->ThreadAssignedToOSThread(
+        (&g_profControlBlock)->ThreadAssignedToOSThread(
             (ThreadID)pThread, osThreadId);
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -1429,9 +1429,6 @@ Thread::Thread()
     m_debuggerFilterContext = NULL;
     m_fInteropDebuggingHijacked = FALSE;
     m_profilerCallbackState = 0;
-#if defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA)
-    m_dwProfilerEvacuationCounter = 0;
-#endif // defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA)
 
     m_pProfilerFilterContext = NULL;
 
@@ -1871,20 +1868,20 @@ BOOL Thread::HasStarted()
     // information
     if (!IsGCSpecial())
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackThreads());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackThreads());
         BOOL gcOnTransition = GC_ON_TRANSITIONS(FALSE);     // disable GCStress 2 to avoid the profiler receiving a RuntimeThreadSuspended notification even before the ThreadCreated notification
-
+        
         {
             GCX_PREEMP();
-            g_profControlBlock.pProfInterface->ThreadCreated((ThreadID) this);
+            (&g_profControlBlock)->ThreadCreated((ThreadID) this);
         }
 
         GC_ON_TRANSITIONS(gcOnTransition);
 
         DWORD osThreadId = ::GetCurrentThreadId();
-        g_profControlBlock.pProfInterface->ThreadAssignedToOSThread(
+        (&g_profControlBlock)->ThreadAssignedToOSThread(
             (ThreadID) this, osThreadId);
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -3009,10 +3006,10 @@ void Thread::OnThreadTerminate(BOOL holdingLock)
 #ifdef PROFILING_SUPPORTED
         // If a profiler is present, then notify the profiler of thread destroy
         {
-            BEGIN_PIN_PROFILER(CORProfilerTrackThreads());
+            BEGIN_PROFILER_CALLBACK(CORProfilerTrackThreads());
             GCX_PREEMP();
-            g_profControlBlock.pProfInterface->ThreadDestroyed((ThreadID) this);
-            END_PIN_PROFILER();
+            (&g_profControlBlock)->ThreadDestroyed((ThreadID) this);
+            END_PROFILER_CALLBACK();
         }
 #endif // PROFILING_SUPPORTED
 
index 5fe312d..0aadbf4 100644 (file)
@@ -3623,16 +3623,6 @@ private:
     //---------------------------------------------------------------
     DWORD m_profilerCallbackState;
 
-#if defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA)
-    //---------------------------------------------------------------
-    // m_dwProfilerEvacuationCounter keeps track of how many profiler
-    // callback calls remain on the stack
-    //---------------------------------------------------------------
-    // Why volatile?
-    // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization.
-    Volatile<DWORD> m_dwProfilerEvacuationCounter;
-#endif // defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA)
-
 private:
     UINT32 m_workerThreadPoolCompletionCount;
     static UINT64 s_workerThreadPoolCompletionCountOverflow;
@@ -3802,30 +3792,6 @@ public:
         return m_pProfilerFilterContext;
     }
 
-#ifdef PROFILING_SUPPORTED
-
-    FORCEINLINE DWORD GetProfilerEvacuationCounter(void)
-    {
-        LIMITED_METHOD_CONTRACT;
-        return m_dwProfilerEvacuationCounter;
-    }
-
-    FORCEINLINE void IncProfilerEvacuationCounter(void)
-    {
-        LIMITED_METHOD_CONTRACT;
-        m_dwProfilerEvacuationCounter++;
-        _ASSERTE(m_dwProfilerEvacuationCounter != 0U);
-    }
-
-    FORCEINLINE void DecProfilerEvacuationCounter(void)
-    {
-        LIMITED_METHOD_CONTRACT;
-        _ASSERTE(m_dwProfilerEvacuationCounter != 0U);
-        m_dwProfilerEvacuationCounter--;
-    }
-
-#endif // PROFILING_SUPPORTED
-
     //-------------------------------------------------------------------------
     // The hijack lock enforces that a thread on which a profiler is currently
     // performing a stack walk cannot be hijacked.
index d9d2c9b..cf09d50 100644 (file)
@@ -401,12 +401,12 @@ retry:
 
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends());
         if (str == STR_Success)
         {
-            g_profControlBlock.pProfInterface->RuntimeThreadSuspended((ThreadID)this);
+            (&g_profControlBlock)->RuntimeThreadSuspended((ThreadID)this);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -456,12 +456,12 @@ DWORD Thread::ResumeThread()
     }
 #ifdef PROFILING_SUPPORTED
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends());
         if ((res != 0) && (res != (DWORD)-1))
         {
-            g_profControlBlock.pProfInterface->RuntimeThreadResumed((ThreadID)this);
+            (&g_profControlBlock)->RuntimeThreadResumed((ThreadID)this);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif
     return res;
@@ -2142,12 +2142,12 @@ void Thread::RareDisablePreemptiveGC()
                 // If profiler desires GC events, notify it that this thread is waiting until the GC is over
                 // Do not send suspend notifications for debugger suspensions
                 {
-                    BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
+                    BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends());
                     if (!(m_State & TS_DebugSuspendPending))
                     {
-                        g_profControlBlock.pProfInterface->RuntimeThreadSuspended((ThreadID)this);
+                        (&g_profControlBlock)->RuntimeThreadSuspended((ThreadID)this);
                     }
-                    END_PIN_PROFILER();
+                    END_PROFILER_CALLBACK();
                 }
 #endif // PROFILING_SUPPORTED
 
@@ -2168,9 +2168,9 @@ void Thread::RareDisablePreemptiveGC()
 #ifdef PROFILING_SUPPORTED
                 // Let the profiler know that this thread is resuming
                 {
-                    BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
-                    g_profControlBlock.pProfInterface->RuntimeThreadResumed((ThreadID)this);
-                    END_PIN_PROFILER();
+                    BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends());
+                    (&g_profControlBlock)->RuntimeThreadResumed((ThreadID)this);
+                    END_PROFILER_CALLBACK();
                 }
 #endif // PROFILING_SUPPORTED
             }
@@ -3226,12 +3226,12 @@ void ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason)
     // If the profiler desires information about GCs, then let it know that one
     // is starting.
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends());
         _ASSERTE(reason != ThreadSuspend::SUSPEND_FOR_DEBUGGER);
         _ASSERTE(reason != ThreadSuspend::SUSPEND_FOR_DEBUGGER_SWEEP);
 
         {
-            g_profControlBlock.pProfInterface->RuntimeSuspendStarted(
+            (&g_profControlBlock)->RuntimeSuspendStarted(
                 GCSuspendReasonToProfSuspendReason(reason));
         }
         if (pCurThread)
@@ -3239,9 +3239,9 @@ void ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason)
             // Notify the profiler that the thread that is actually doing the GC is 'suspended',
             // meaning that it is doing stuff other than run the managed code it was before the
             // GC started.
-            g_profControlBlock.pProfInterface->RuntimeThreadSuspended((ThreadID)pCurThread);
+            (&g_profControlBlock)->RuntimeThreadSuspended((ThreadID)pCurThread);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -3588,9 +3588,9 @@ void ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason)
 #ifdef PROFILING_SUPPORTED
     // If a profiler is keeping track of GC events, notify it
     {
-    BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
-    g_profControlBlock.pProfInterface->RuntimeSuspendFinished();
-    END_PIN_PROFILER();
+    BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends());
+    (&g_profControlBlock)->RuntimeSuspendFinished();
+    END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -3711,12 +3711,12 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded)
 #ifdef PROFILING_SUPPORTED
     // Need to give resume event for the GC thread
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends());
         if (pCurThread)
         {
-            g_profControlBlock.pProfInterface->RuntimeThreadResumed((ThreadID)pCurThread);
+            (&g_profControlBlock)->RuntimeThreadResumed((ThreadID)pCurThread);
         }
-        END_PIN_PROFILER();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -3739,10 +3739,10 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded)
     // This thread is logically "resuming" from a GC now.  Tell the profiler.
     //
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends());
         GCX_PREEMP();
-        g_profControlBlock.pProfInterface->RuntimeResumeFinished();
-        END_PIN_PROFILER();
+        (&g_profControlBlock)->RuntimeResumeFinished();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
@@ -5481,9 +5481,9 @@ void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceded)
     // corresponding call to RuntimeSuspendStarted is done at a lower architectural layer,
     // in ThreadSuspend::SuspendRuntime.
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
-        g_profControlBlock.pProfInterface->RuntimeResumeStarted();
-        END_PIN_PROFILER();
+        BEGIN_PROFILER_CALLBACK(CORProfilerTrackSuspends());
+        (&g_profControlBlock)->RuntimeResumeStarted();
+        END_PROFILER_CALLBACK();
     }
 #endif // PROFILING_SUPPORTED
 
index f3472be..6ed6171 100644 (file)
@@ -156,7 +156,8 @@ event_pipe_enable (
                format,
                rundown_requested,
                stream,
-               sync_callback);
+               sync_callback,
+        NULL);
 
        if (config_providers) {
                for (int i = 0; i < providers_len; ++i) {
index b8f27a8..6405e42 100644 (file)
@@ -426,6 +426,7 @@ eventpipe_protocol_helper_collect_tracing (
                payload->serialization_format,
                true,
                ds_ipc_stream_get_stream_ref (stream),
+               NULL,
                NULL);
 
        if (session_id == 0) {
@@ -475,6 +476,7 @@ eventpipe_protocol_helper_collect_tracing_2 (
                payload->serialization_format,
                payload->rundown_requested,
                ds_ipc_stream_get_stream_ref (stream),
+               NULL,
                NULL);
 
        if (session_id == 0) {
index 973b203..60a5fe0 100644 (file)
@@ -132,7 +132,8 @@ ep_session_alloc (
        uint32_t circular_buffer_size_in_mb,
        const EventPipeProviderConfiguration *providers,
        uint32_t providers_len,
-       EventPipeSessionSynchronousCallback sync_callback)
+       EventPipeSessionSynchronousCallback sync_callback,
+       void *callback_additional_data)
 {
        EP_ASSERT (index < EP_MAX_NUMBER_OF_SESSIONS);
        EP_ASSERT (format < EP_SERIALIZATION_FORMAT_COUNT);
@@ -159,6 +160,7 @@ ep_session_alloc (
        instance->format = format;
        instance->rundown_requested = rundown_requested;
        instance->synchronous_callback = sync_callback;
+       instance->callback_additional_data = callback_additional_data;
 
        // Hard coded 10MB for now, we'll probably want to make
        // this configurable later.
@@ -473,7 +475,8 @@ ep_session_write_event (
                                related_activity_id,
                                event_thread,
                                stack == NULL ? 0 : ep_stack_contents_get_size (stack),
-                               stack == NULL ? NULL : (uintptr_t *)ep_stack_contents_get_pointer (stack));
+                               stack == NULL ? NULL : (uintptr_t *)ep_stack_contents_get_pointer (stack),
+                               session->callback_additional_data);
                        result = true;
                } else {
                        EP_ASSERT (session->buffer_manager != NULL);
index 48087ed..a38adc4 100644 (file)
@@ -35,6 +35,8 @@ struct _EventPipeSession_Internal {
        EventPipeFile *file;
        // For synchoronous sessions.
        EventPipeSessionSynchronousCallback synchronous_callback;
+       // Additional data to pass to the callback
+       void *callback_additional_data;
        // Start date and time in UTC.
        ep_system_timestamp_t session_start_time;
        // Start timestamp.
@@ -85,7 +87,8 @@ ep_session_alloc (
        uint32_t circular_buffer_size_in_mb,
        const EventPipeProviderConfiguration *providers,
        uint32_t providers_len,
-       EventPipeSessionSynchronousCallback sync_callback);
+       EventPipeSessionSynchronousCallback sync_callback,
+       void *callback_additional_data);
 
 void
 ep_session_free (EventPipeSession *session);
index 6b5a70b..a40ab0c 100644 (file)
@@ -201,7 +201,8 @@ typedef void (*EventPipeSessionSynchronousCallback)(
        const uint8_t *related_activity_id,
        /*ep_rt_thread_handle_t*/ void *event_thread,
        uint32_t stack_frames_len,
-       uintptr_t *stack_frames);
+       uintptr_t *stack_frames,
+    void *additional_data);
 
 typedef bool (*EventPipeIpcStreamFactorySuspendedPortsCallback)(void);
 
index 28bdb70..38c1e1a 100644 (file)
@@ -56,7 +56,8 @@ enable (
        bool rundown_requested,
        IpcStream *stream,
        EventPipeProviderCallbackDataQueue *provider_callback_data_queue,
-       EventPipeSessionSynchronousCallback sync_callback);
+       EventPipeSessionSynchronousCallback sync_callback,
+       void *callback_additional_data);
 
 static
 void
@@ -423,7 +424,8 @@ enable (
        bool rundown_requested,
        IpcStream *stream,
        EventPipeProviderCallbackDataQueue *provider_callback_data_queue,
-       EventPipeSessionSynchronousCallback sync_callback)
+       EventPipeSessionSynchronousCallback sync_callback,
+       void *callback_additional_data)
 {
        EP_ASSERT (format < EP_SERIALIZATION_FORMAT_COUNT);
        EP_ASSERT (session_type == EP_SESSION_TYPE_SYNCHRONOUS || circular_buffer_size_in_mb > 0);
@@ -450,7 +452,8 @@ enable (
                circular_buffer_size_in_mb,
                providers,
                providers_len,
-               sync_callback);
+               sync_callback,
+               callback_additional_data);
 
        ep_raise_error_if_nok (session != NULL && ep_session_is_valid (session));
 
@@ -854,6 +857,7 @@ enable_default_session_via_env_variables (void)
                        EP_SERIALIZATION_FORMAT_NETTRACE_V4,
                        true,
                        NULL,
+                       NULL,
                        NULL);
 
                if (session_id)
@@ -904,7 +908,8 @@ ep_enable (
        EventPipeSerializationFormat format,
        bool rundown_requested,
        IpcStream *stream,
-       EventPipeSessionSynchronousCallback sync_callback)
+       EventPipeSessionSynchronousCallback sync_callback,
+       void *callback_additional_data)
 {
        ep_return_zero_if_nok (format < EP_SERIALIZATION_FORMAT_COUNT);
        ep_return_zero_if_nok (session_type == EP_SESSION_TYPE_SYNCHRONOUS || circular_buffer_size_in_mb > 0);
@@ -934,7 +939,8 @@ ep_enable (
                        rundown_requested,
                        stream,
                        provider_callback_data_queue,
-                       sync_callback);
+                       sync_callback,
+                       callback_additional_data);
        EP_LOCK_EXIT (section1)
 
        while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) {
@@ -961,7 +967,8 @@ ep_enable_2 (
        EventPipeSerializationFormat format,
        bool rundown_requested,
        IpcStream *stream,
-       EventPipeSessionSynchronousCallback sync_callback)
+       EventPipeSessionSynchronousCallback sync_callback,
+       void *callback_additional_data)
 {
        const ep_char8_t *providers_config_to_parse = providers_config;
        int32_t providers_len = 0;
@@ -1038,7 +1045,8 @@ ep_enable_2 (
                format,
                rundown_requested,
                stream,
-               sync_callback);
+               sync_callback,
+               callback_additional_data);
 
 ep_on_exit:
 
index eb0e6a7..f70abd4 100644 (file)
@@ -181,7 +181,8 @@ ep_enable (
        EventPipeSerializationFormat format,
        bool rundown_requested,
        IpcStream *stream,
-       EventPipeSessionSynchronousCallback sync_callback);
+       EventPipeSessionSynchronousCallback sync_callback,
+       void *callback_additional_data);
 
 EventPipeSessionID
 ep_enable_2 (
@@ -192,7 +193,8 @@ ep_enable_2 (
        EventPipeSerializationFormat format,
        bool rundown_requested,
        IpcStream *stream,
-       EventPipeSessionSynchronousCallback sync_callback);
+       EventPipeSessionSynchronousCallback sync_callback,
+       void *callback_additional_data);
 
 void
 ep_disable (EventPipeSessionID id);