1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5// ProfilePriv.h
6//
7
8//
9// Structures, etc. used by the Profiling API and throughout the EE
10//
11
12// ======================================================================================
13
14#ifndef _ProfilePriv_h_
15#define _ProfilePriv_h_
16
17
18// Forward declarations
19class EEToProfInterfaceImpl;
20class Object;
21struct ScanContext;
22
23#if defined (PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED)
24#ifndef PROFILING_SUPPORTED_DATA
25#define PROFILING_SUPPORTED_DATA 1
26#endif // PROFILING_SUPPORTED_DATA
27
28#include "corprof.h"
29
30//---------------------------------------------------------------------------------------
31// Enumerates the various init states of profiling.
32//
33// *** NOTE: The order is important here, as some of the status checks (e.g.,
34// CORProfilerPresentOrInitializing) use ">" with these enum values. ***
35
36enum ProfilerStatus
37{
38 kProfStatusNone = 0, // No profiler running.
39 kProfStatusDetaching = 1, // Prof was running, is now detaching, but still loaded
40 kProfStatusInitializingForStartupLoad = 2, // Prof ready for (or in) its Initialize callback
41 kProfStatusInitializingForAttachLoad = 3, // Prof ready for (or in) its InitializeForAttach callback
42 kProfStatusActive = 4, // Prof completed initialization and is actively running
43};
44
45class CurrentProfilerStatus
46{
47private:
48 // Why volatile?
49 // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization
50 Volatile<ProfilerStatus> m_profStatus;
51
52public:
53 void Init();
54 ProfilerStatus Get();
55 void Set(ProfilerStatus profStatus);
56};
57
58// ---------------------------------------------------------------------------------------
59// Global struct that lets the EE see the load status of the profiler, and provides a
60// pointer (pProfInterface) through which profiler calls can be made
61//
62// When you are adding new session, please refer to
63// code:ProfControlBlock::ResetPerSessionStatus#ProfileResetSessionStatus for more details.
64struct ProfControlBlock
65{
66 // **** IMPORTANT!! ****
67 // All uses of pProfInterface must be properly synchronized to avoid the profiler
68 // from detaching while the EE attempts to call into it. The recommended way to do
69 // this is to use the (lockless) BEGIN_PIN_PROFILER / END_PIN_PROFILER macros. See
70 // code:BEGIN_PIN_PROFILER for instructions. For full details on how the
71 // synchronization works, see
72 // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization
73 VolatilePtr<EEToProfInterfaceImpl> pProfInterface;
74 // **** IMPORTANT!! ****
75
76 DWORD dwEventMask; // Original low event mask bits
77 DWORD dwEventMaskHigh; // New high event mask bits
78 CurrentProfilerStatus curProfStatus;
79 BOOL fGCInProgress;
80 BOOL fBaseSystemClassesLoaded;
81
82#ifdef PROF_TEST_ONLY_FORCE_ELT_DATA
83 // #TestOnlyELT This implements a test-only (and debug-only) hook that allows a test
84 // profiler to ensure enter/leave/tailcall is enabled on startup even though no
85 // profiler is loaded on startup. This allows an attach profiler to use ELT to build
86 // shadow stacks for the sole purpose of verifying OTHER areas of the profiling API
87 // (e.g., stack walking). When this BOOL is TRUE, the JIT will insert calls to the
88 // slow-path profiling API enter/leave/tailcall hooks, which will forward the call to
89 // a profiler if one is loaded (and do nothing otherwise).
90 //
91 // See code:AreCallbackStateFlagsSet#P2CLRRestrictionsOverview for general information
92 // on how the test hooks lift restrictions normally in place for the Info functions.
93 BOOL fTestOnlyForceEnterLeave;
94#endif
95
96#ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED_DATA
97 // #TestOnlyObjectAllocated This implements a test-only (and debug-only) hook that allows
98 // a test profiler to ensure ObjectAllocated callback is enabled on startup even though no
99 // profiler is loaded on startup. This allows an attach profiler to use ObjectAllocated
100 // callback for the sole purpose of verifying OTHER GC areas of the profiling API
101 // (e.g., constructing a object graph). When this BOOL is TRUE, the JIT will use special
102 // version of new allocators that issue object allocation notifications, which will forward
103 // the notifications to a profiler if one is loaded (and do nothing otherwise).
104 //
105 // See code:AreCallbackStateFlagsSet#P2CLRRestrictionsOverview for general information
106 // on how the test hooks lift restrictions normally in place for the Info functions.
107 BOOL fTestOnlyForceObjectAllocated;
108#endif
109
110#ifdef _DEBUG
111 // Test-only, debug-only code to allow attaching profilers to call ICorProfilerInfo inteface,
112 // which would otherwise be disallowed for attaching profilers
113 BOOL fTestOnlyEnableICorProfilerInfo;
114#endif // _DEBUG
115
116 // Whether we've turned off concurrent GC during attach
117 BOOL fConcurrentGCDisabledForAttach;
118
119 void Init();
120 void ResetPerSessionStatus();
121};
122
123
124GVAL_DECL(ProfControlBlock, g_profControlBlock);
125
126// Provides definitions of the CORProfilerTrack* functions that test whether a profiler
127// is active and responding to various callbacks
128#include "profilepriv.inl"
129
130//---------------------------------------------------------------
131// Bit flags used to track profiler callback execution state, such as which
132// ICorProfilerCallback method we're currently executing. These help us enforce the
133// invariants of which calls a profiler is allowed to make at given times. These flags
134// are stored in Thread::m_profilerCallbackState.
135//
136// For now, we ensure:
137// * Only asynchronous-safe calls are made asynchronously (i.e., are made from
138// outside of profiler callbacks).
139// * GC_TRIGGERS info methods are not called from GC_NOTRIGGER callbacks
140//
141// Later, we may choose to enforce even more refined call trees and add more flags.
142#define COR_PRF_CALLBACKSTATE_INCALLBACK 0x1
143#define COR_PRF_CALLBACKSTATE_IN_TRIGGERS_SCOPE 0x2
144#define COR_PRF_CALLBACKSTATE_FORCEGC_WAS_CALLED 0x4
145//
146//---------------------------------------------------------------
147
148#endif // defined(PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED)
149
150// This is the helper callback that the gc uses when walking the heap.
151bool HeapWalkHelper(Object* pBO, void* pv);
152void ScanRootsHelper(Object* pObj, Object** ppRoot, ScanContext *pSC, uint32_t dwUnused);
153bool AllocByClassHelper(Object* pBO, void* pv);
154
155#endif // _ProfilePriv_h_
156
157