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 | /* |
6 | * Generational GC handle manager. Entrypoint Header. |
7 | * |
8 | * Implements generic support for external handles into a GC heap. |
9 | * |
10 | |
11 | * |
12 | */ |
13 | |
14 | #ifndef _HANDLETABLE_H |
15 | #define _HANDLETABLE_H |
16 | |
17 | #include "gcinterface.h" |
18 | |
19 | /**************************************************************************** |
20 | * |
21 | * FLAGS, CONSTANTS AND DATA TYPES |
22 | * |
23 | ****************************************************************************/ |
24 | |
25 | #ifdef _DEBUG |
26 | #define DEBUG_DestroyedHandleValue ((_UNCHECKED_OBJECTREF)0x7) |
27 | #endif |
28 | |
29 | /* |
30 | * handle flags used by HndCreateHandleTable |
31 | */ |
32 | #define HNDF_NORMAL (0x00) |
33 | #define (0x01) |
34 | |
35 | /* |
36 | * handle to handle table |
37 | */ |
38 | typedef DPTR(struct HandleTable) PTR_HandleTable; |
39 | typedef DPTR(PTR_HandleTable) PTR_PTR_HandleTable; |
40 | typedef PTR_HandleTable HHANDLETABLE; |
41 | typedef PTR_PTR_HandleTable PTR_HHANDLETABLE; |
42 | |
43 | /*--------------------------------------------------------------------------*/ |
44 | |
45 | |
46 | |
47 | /**************************************************************************** |
48 | * |
49 | * PUBLIC ROUTINES AND MACROS |
50 | * |
51 | ****************************************************************************/ |
52 | #ifndef DACCESS_COMPILE |
53 | /* |
54 | * handle manager init and shutdown routines |
55 | */ |
56 | HHANDLETABLE HndCreateHandleTable(const uint32_t *pTypeFlags, uint32_t uTypeCount, ADIndex uADIndex); |
57 | void HndDestroyHandleTable(HHANDLETABLE hTable); |
58 | #endif // !DACCESS_COMPILE |
59 | |
60 | /* |
61 | * retrieve index stored in table at creation |
62 | */ |
63 | void HndSetHandleTableIndex(HHANDLETABLE hTable, uint32_t uTableIndex); |
64 | uint32_t HndGetHandleTableIndex(HHANDLETABLE hTable); |
65 | ADIndex HndGetHandleTableADIndex(HHANDLETABLE hTable); |
66 | |
67 | GC_DAC_VISIBLE |
68 | ADIndex HndGetHandleADIndex(OBJECTHANDLE handle); |
69 | |
70 | #ifndef DACCESS_COMPILE |
71 | /* |
72 | * individual handle allocation and deallocation |
73 | */ |
74 | OBJECTHANDLE HndCreateHandle(HHANDLETABLE hTable, uint32_t uType, OBJECTREF object, uintptr_t = 0); |
75 | void HndDestroyHandle(HHANDLETABLE hTable, uint32_t uType, OBJECTHANDLE handle); |
76 | |
77 | void HndDestroyHandleOfUnknownType(HHANDLETABLE hTable, OBJECTHANDLE handle); |
78 | |
79 | /* |
80 | * owner data associated with handles |
81 | */ |
82 | void HndSetHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintptr_t ); |
83 | uintptr_t HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintptr_t , uintptr_t ); |
84 | #endif // !DACCESS_COMPILE |
85 | |
86 | GC_DAC_VISIBLE |
87 | uintptr_t HndGetHandleExtraInfo(OBJECTHANDLE handle); |
88 | |
89 | /* |
90 | * get parent table of handle |
91 | */ |
92 | HHANDLETABLE HndGetHandleTable(OBJECTHANDLE handle); |
93 | |
94 | /* |
95 | * write barrier |
96 | */ |
97 | void HndWriteBarrier(OBJECTHANDLE handle, OBJECTREF value); |
98 | |
99 | /* |
100 | * logging an ETW event (for inlined methods) |
101 | */ |
102 | void HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value); |
103 | |
104 | /* |
105 | * NON-GC handle enumeration |
106 | */ |
107 | GC_DAC_VISIBLE_NO_MANGLE |
108 | void HndEnumHandles(HHANDLETABLE hTable, const uint32_t *puType, uint32_t uTypeCount, |
109 | HANDLESCANPROC pfnEnum, uintptr_t lParam1, uintptr_t lParam2, bool fAsync); |
110 | |
111 | /* |
112 | * GC-time handle scanning |
113 | */ |
114 | #define HNDGCF_NORMAL (0x00000000) // normal scan |
115 | #define HNDGCF_AGE (0x00000001) // age handles while scanning |
116 | #define HNDGCF_ASYNC (0x00000002) // drop the table lock while scanning |
117 | #define (0x00000004) // iterate per-handle data while scanning |
118 | |
119 | GC_DAC_VISIBLE_NO_MANGLE |
120 | void HndScanHandlesForGC(HHANDLETABLE hTable, |
121 | HANDLESCANPROC scanProc, |
122 | uintptr_t param1, |
123 | uintptr_t param2, |
124 | const uint32_t *types, |
125 | uint32_t typeCount, |
126 | uint32_t condemned, |
127 | uint32_t maxgen, |
128 | uint32_t flags); |
129 | |
130 | void HndResetAgeMap(HHANDLETABLE hTable, const uint32_t *types, uint32_t typeCount, uint32_t condemned, uint32_t maxgen, uint32_t flags); |
131 | void HndVerifyTable(HHANDLETABLE hTable, const uint32_t *types, uint32_t typeCount, uint32_t condemned, uint32_t maxgen, uint32_t flags); |
132 | |
133 | void HndNotifyGcCycleComplete(HHANDLETABLE hTable, uint32_t condemned, uint32_t maxgen); |
134 | |
135 | /* |
136 | * Handle counting |
137 | */ |
138 | |
139 | uint32_t HndCountHandles(HHANDLETABLE hTable); |
140 | uint32_t HndCountAllHandles(BOOL fUseLocks); |
141 | |
142 | /*--------------------------------------------------------------------------*/ |
143 | |
144 | |
145 | #ifdef _DEBUG_IMPL |
146 | void ValidateAssignObjrefForHandle(OBJECTREF, ADIndex appDomainIndex); |
147 | void ValidateFetchObjrefForHandle(OBJECTREF, ADIndex appDomainIndex); |
148 | void ValidateAppDomainForHandle(OBJECTHANDLE handle); |
149 | #endif |
150 | |
151 | /* |
152 | * handle assignment |
153 | */ |
154 | void HndAssignHandle(OBJECTHANDLE handle, OBJECTREF objref); |
155 | |
156 | /* |
157 | * interlocked-exchange assignment |
158 | */ |
159 | void* HndInterlockedCompareExchangeHandle(OBJECTHANDLE handle, OBJECTREF objref, OBJECTREF oldObjref); |
160 | |
161 | /* |
162 | * Note that HndFirstAssignHandle is similar to HndAssignHandle, except that it only |
163 | * succeeds if transitioning from NULL to non-NULL. In other words, if this handle |
164 | * is being initialized for the first time. |
165 | */ |
166 | BOOL HndFirstAssignHandle(OBJECTHANDLE handle, OBJECTREF objref); |
167 | |
168 | /* |
169 | * inline handle dereferencing |
170 | * |
171 | * NOTE: Changes to this implementation should be kept in sync with ObjectFromHandle |
172 | * on the VM side. |
173 | * |
174 | */ |
175 | GC_DAC_VISIBLE |
176 | FORCEINLINE |
177 | OBJECTREF HndFetchHandle(OBJECTHANDLE handle) |
178 | { |
179 | WRAPPER_NO_CONTRACT; |
180 | |
181 | // sanity |
182 | _ASSERTE(handle); |
183 | |
184 | #ifdef _DEBUG_IMPL |
185 | _ASSERTE("Attempt to access destroyed handle." && *(_UNCHECKED_OBJECTREF *)handle != DEBUG_DestroyedHandleValue); |
186 | |
187 | // Make sure the objref for handle is valid |
188 | ValidateFetchObjrefForHandle(ObjectToOBJECTREF(*(Object **)handle), |
189 | HndGetHandleTableADIndex(HndGetHandleTable(handle))); |
190 | #endif // _DEBUG_IMPL |
191 | |
192 | // wrap the raw objectref and return it |
193 | return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle)); |
194 | } |
195 | |
196 | |
197 | /* |
198 | * inline null testing (needed in certain cases where we're in the wrong GC mod) |
199 | */ |
200 | FORCEINLINE BOOL HndIsNull(OBJECTHANDLE handle) |
201 | { |
202 | LIMITED_METHOD_CONTRACT; |
203 | |
204 | // sanity |
205 | _ASSERTE(handle); |
206 | |
207 | return NULL == *(Object **)handle; |
208 | } |
209 | |
210 | |
211 | /* |
212 | * |
213 | * Checks handle value for null or special value used for free handles in cache. |
214 | * |
215 | */ |
216 | FORCEINLINE BOOL HndIsNullOrDestroyedHandle(_UNCHECKED_OBJECTREF value) |
217 | { |
218 | LIMITED_METHOD_CONTRACT; |
219 | |
220 | #ifdef DEBUG_DestroyedHandleValue |
221 | if (value == DEBUG_DestroyedHandleValue) |
222 | return TRUE; |
223 | #endif |
224 | |
225 | return (value == NULL); |
226 | } |
227 | |
228 | /*--------------------------------------------------------------------------*/ |
229 | |
230 | #include "handletable.inl" |
231 | |
232 | #endif //_HANDLETABLE_H |
233 | |
234 | |