summaryrefslogtreecommitdiff
path: root/src/gc/handletable.h
blob: 70959edf3b78a622ef31266b1f488dff91a1558b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

/*
 * Generational GC handle manager.  Entrypoint Header.
 *
 * Implements generic support for external handles into a GC heap.
 *

 *
 */

#ifndef _HANDLETABLE_H
#define _HANDLETABLE_H

#include "gcinterface.h"

/****************************************************************************
 *
 * FLAGS, CONSTANTS AND DATA TYPES
 *
 ****************************************************************************/

#ifdef _DEBUG
#define DEBUG_DestroyedHandleValue ((_UNCHECKED_OBJECTREF)0x7)
#endif

/*
 * handle flags used by HndCreateHandleTable
 */
#define HNDF_NORMAL         (0x00)
#define HNDF_EXTRAINFO      (0x01)

/*
 * handle to handle table
 */
typedef DPTR(struct HandleTable) PTR_HandleTable;
typedef DPTR(PTR_HandleTable) PTR_PTR_HandleTable;
typedef PTR_HandleTable HHANDLETABLE;
typedef PTR_PTR_HandleTable PTR_HHANDLETABLE;

/*--------------------------------------------------------------------------*/



/****************************************************************************
 *
 * PUBLIC ROUTINES AND MACROS
 *
 ****************************************************************************/
#ifndef DACCESS_COMPILE
/*
 * handle manager init and shutdown routines
 */
HHANDLETABLE    HndCreateHandleTable(const uint32_t *pTypeFlags, uint32_t uTypeCount, ADIndex uADIndex);
void            HndDestroyHandleTable(HHANDLETABLE hTable);
#endif // !DACCESS_COMPILE

/*
 * retrieve index stored in table at creation 
 */
void            HndSetHandleTableIndex(HHANDLETABLE hTable, uint32_t uTableIndex);
uint32_t        HndGetHandleTableIndex(HHANDLETABLE hTable);
ADIndex         HndGetHandleTableADIndex(HHANDLETABLE hTable);

GC_DAC_VISIBLE
ADIndex         HndGetHandleADIndex(OBJECTHANDLE handle);

#ifndef DACCESS_COMPILE
/*
 * individual handle allocation and deallocation
 */
OBJECTHANDLE    HndCreateHandle(HHANDLETABLE hTable, uint32_t uType, OBJECTREF object, uintptr_t lExtraInfo = 0);
void            HndDestroyHandle(HHANDLETABLE hTable, uint32_t uType, OBJECTHANDLE handle);

void            HndDestroyHandleOfUnknownType(HHANDLETABLE hTable, OBJECTHANDLE handle);

/*
 * owner data associated with handles
 */
void            HndSetHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintptr_t lExtraInfo);
uintptr_t          HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintptr_t lOldExtraInfo, uintptr_t lNewExtraInfo);
#endif // !DACCESS_COMPILE

GC_DAC_VISIBLE
uintptr_t          HndGetHandleExtraInfo(OBJECTHANDLE handle);

/*
 * get parent table of handle
 */
HHANDLETABLE    HndGetHandleTable(OBJECTHANDLE handle);

/*
 * write barrier
 */
void            HndWriteBarrier(OBJECTHANDLE handle, OBJECTREF value);

/* 
 * logging an ETW event (for inlined methods)
 */
void            HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value);

/*
 * NON-GC handle enumeration
 */
GC_DAC_VISIBLE_NO_MANGLE
void HndEnumHandles(HHANDLETABLE hTable, const uint32_t *puType, uint32_t uTypeCount,
                    HANDLESCANPROC pfnEnum, uintptr_t lParam1, uintptr_t lParam2, bool fAsync);

/*
 * GC-time handle scanning
 */
#define HNDGCF_NORMAL       (0x00000000)    // normal scan
#define HNDGCF_AGE          (0x00000001)    // age handles while scanning
#define HNDGCF_ASYNC        (0x00000002)    // drop the table lock while scanning
#define HNDGCF_EXTRAINFO    (0x00000004)    // iterate per-handle data while scanning

GC_DAC_VISIBLE_NO_MANGLE
void            HndScanHandlesForGC(HHANDLETABLE hTable,
                                    HANDLESCANPROC scanProc,
                                    uintptr_t param1,
                                    uintptr_t param2,
                                    const uint32_t *types,
                                    uint32_t typeCount,
                                    uint32_t condemned,
                                    uint32_t maxgen,
                                    uint32_t flags);

void            HndResetAgeMap(HHANDLETABLE hTable, const uint32_t *types, uint32_t typeCount, uint32_t condemned, uint32_t maxgen, uint32_t flags);
void            HndVerifyTable(HHANDLETABLE hTable, const uint32_t *types, uint32_t typeCount, uint32_t condemned, uint32_t maxgen, uint32_t flags);

void            HndNotifyGcCycleComplete(HHANDLETABLE hTable, uint32_t condemned, uint32_t maxgen);

/*
 * Handle counting
 */

uint32_t        HndCountHandles(HHANDLETABLE hTable);
uint32_t        HndCountAllHandles(BOOL fUseLocks);

/*--------------------------------------------------------------------------*/


#ifdef _DEBUG_IMPL
void ValidateAssignObjrefForHandle(OBJECTREF, ADIndex appDomainIndex);
void ValidateFetchObjrefForHandle(OBJECTREF, ADIndex appDomainIndex);
void ValidateAppDomainForHandle(OBJECTHANDLE handle);
#endif

/*
 * handle assignment
 */
void HndAssignHandle(OBJECTHANDLE handle, OBJECTREF objref);

/*
 * interlocked-exchange assignment
 */
void* HndInterlockedCompareExchangeHandle(OBJECTHANDLE handle, OBJECTREF objref, OBJECTREF oldObjref);

/*
 * Note that HndFirstAssignHandle is similar to HndAssignHandle, except that it only
 * succeeds if transitioning from NULL to non-NULL.  In other words, if this handle
 * is being initialized for the first time.
 */
BOOL HndFirstAssignHandle(OBJECTHANDLE handle, OBJECTREF objref);

/*
 * inline handle dereferencing
 *
 * NOTE: Changes to this implementation should be kept in sync with ObjectFromHandle
 *       on the VM side.
 *
 */
GC_DAC_VISIBLE
FORCEINLINE
OBJECTREF HndFetchHandle(OBJECTHANDLE handle)
{
    WRAPPER_NO_CONTRACT;

    // sanity
    _ASSERTE(handle);

#ifdef _DEBUG_IMPL
    _ASSERTE("Attempt to access destroyed handle." && *(_UNCHECKED_OBJECTREF *)handle != DEBUG_DestroyedHandleValue);

    // Make sure the objref for handle is valid
    ValidateFetchObjrefForHandle(ObjectToOBJECTREF(*(Object **)handle), 
                            HndGetHandleTableADIndex(HndGetHandleTable(handle)));
#endif // _DEBUG_IMPL

    // wrap the raw objectref and return it
    return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle));
}


/*
 * inline null testing (needed in certain cases where we're in the wrong GC mod)
 */
FORCEINLINE BOOL HndIsNull(OBJECTHANDLE handle)
{
    LIMITED_METHOD_CONTRACT;

    // sanity
    _ASSERTE(handle);

    return NULL == *(Object **)handle;
}


/*
 *
 * Checks handle value for null or special value used for free handles in cache.
 *
 */
FORCEINLINE BOOL HndIsNullOrDestroyedHandle(_UNCHECKED_OBJECTREF value)
{
    LIMITED_METHOD_CONTRACT;

#ifdef DEBUG_DestroyedHandleValue
    if (value == DEBUG_DestroyedHandleValue)
         return TRUE;
#endif

    return (value == NULL);
}

/*--------------------------------------------------------------------------*/

#include "handletable.inl"

#endif //_HANDLETABLE_H