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 HNDF_EXTRAINFO (0x01)
34
35/*
36 * handle to handle table
37 */
38typedef DPTR(struct HandleTable) PTR_HandleTable;
39typedef DPTR(PTR_HandleTable) PTR_PTR_HandleTable;
40typedef PTR_HandleTable HHANDLETABLE;
41typedef 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 */
56HHANDLETABLE HndCreateHandleTable(const uint32_t *pTypeFlags, uint32_t uTypeCount, ADIndex uADIndex);
57void HndDestroyHandleTable(HHANDLETABLE hTable);
58#endif // !DACCESS_COMPILE
59
60/*
61 * retrieve index stored in table at creation
62 */
63void HndSetHandleTableIndex(HHANDLETABLE hTable, uint32_t uTableIndex);
64uint32_t HndGetHandleTableIndex(HHANDLETABLE hTable);
65ADIndex HndGetHandleTableADIndex(HHANDLETABLE hTable);
66
67GC_DAC_VISIBLE
68ADIndex HndGetHandleADIndex(OBJECTHANDLE handle);
69
70#ifndef DACCESS_COMPILE
71/*
72 * individual handle allocation and deallocation
73 */
74OBJECTHANDLE HndCreateHandle(HHANDLETABLE hTable, uint32_t uType, OBJECTREF object, uintptr_t lExtraInfo = 0);
75void HndDestroyHandle(HHANDLETABLE hTable, uint32_t uType, OBJECTHANDLE handle);
76
77void HndDestroyHandleOfUnknownType(HHANDLETABLE hTable, OBJECTHANDLE handle);
78
79/*
80 * owner data associated with handles
81 */
82void HndSetHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintptr_t lExtraInfo);
83uintptr_t HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintptr_t lOldExtraInfo, uintptr_t lNewExtraInfo);
84#endif // !DACCESS_COMPILE
85
86GC_DAC_VISIBLE
87uintptr_t HndGetHandleExtraInfo(OBJECTHANDLE handle);
88
89/*
90 * get parent table of handle
91 */
92HHANDLETABLE HndGetHandleTable(OBJECTHANDLE handle);
93
94/*
95 * write barrier
96 */
97void HndWriteBarrier(OBJECTHANDLE handle, OBJECTREF value);
98
99/*
100 * logging an ETW event (for inlined methods)
101 */
102void HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value);
103
104/*
105 * NON-GC handle enumeration
106 */
107GC_DAC_VISIBLE_NO_MANGLE
108void 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 HNDGCF_EXTRAINFO (0x00000004) // iterate per-handle data while scanning
118
119GC_DAC_VISIBLE_NO_MANGLE
120void 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
130void HndResetAgeMap(HHANDLETABLE hTable, const uint32_t *types, uint32_t typeCount, uint32_t condemned, uint32_t maxgen, uint32_t flags);
131void HndVerifyTable(HHANDLETABLE hTable, const uint32_t *types, uint32_t typeCount, uint32_t condemned, uint32_t maxgen, uint32_t flags);
132
133void HndNotifyGcCycleComplete(HHANDLETABLE hTable, uint32_t condemned, uint32_t maxgen);
134
135/*
136 * Handle counting
137 */
138
139uint32_t HndCountHandles(HHANDLETABLE hTable);
140uint32_t HndCountAllHandles(BOOL fUseLocks);
141
142/*--------------------------------------------------------------------------*/
143
144
145#ifdef _DEBUG_IMPL
146void ValidateAssignObjrefForHandle(OBJECTREF, ADIndex appDomainIndex);
147void ValidateFetchObjrefForHandle(OBJECTREF, ADIndex appDomainIndex);
148void ValidateAppDomainForHandle(OBJECTHANDLE handle);
149#endif
150
151/*
152 * handle assignment
153 */
154void HndAssignHandle(OBJECTHANDLE handle, OBJECTREF objref);
155
156/*
157 * interlocked-exchange assignment
158 */
159void* 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 */
166BOOL 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 */
175GC_DAC_VISIBLE
176FORCEINLINE
177OBJECTREF 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 */
200FORCEINLINE 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 */
216FORCEINLINE 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