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 |
19 | class EEToProfInterfaceImpl; |
20 | class Object; |
21 | struct 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 | |
36 | enum 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 | |
45 | class CurrentProfilerStatus |
46 | { |
47 | private: |
48 | // Why volatile? |
49 | // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization |
50 | Volatile<ProfilerStatus> m_profStatus; |
51 | |
52 | public: |
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. |
64 | struct 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 | |
124 | GVAL_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. |
151 | bool HeapWalkHelper(Object* pBO, void* pv); |
152 | void ScanRootsHelper(Object* pObj, Object** ppRoot, ScanContext *pSC, uint32_t dwUnused); |
153 | bool AllocByClassHelper(Object* pBO, void* pv); |
154 | |
155 | #endif // _ProfilePriv_h_ |
156 | |
157 | |