summaryrefslogtreecommitdiff
path: root/src/gc/handletable.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gc/handletable.h')
-rw-r--r--src/gc/handletable.h254
1 files changed, 254 insertions, 0 deletions
diff --git a/src/gc/handletable.h b/src/gc/handletable.h
new file mode 100644
index 0000000000..bbb8b1db22
--- /dev/null
+++ b/src/gc/handletable.h
@@ -0,0 +1,254 @@
+// 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
+
+
+/****************************************************************************
+ *
+ * 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);
+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);
+
+/*
+ * bulk handle allocation and deallocation
+ */
+uint32_t HndCreateHandles(HHANDLETABLE hTable, uint32_t uType, OBJECTHANDLE *pHandles, uint32_t uCount);
+void HndDestroyHandles(HHANDLETABLE hTable, uint32_t uType, const OBJECTHANDLE *pHandles, uint32_t uCount);
+
+/*
+ * 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
+
+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);
+
+ /*
+ * Scanning callback.
+ */
+typedef void (CALLBACK *HANDLESCANPROC)(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *pExtraInfo, uintptr_t param1, uintptr_t param2);
+
+/*
+ * NON-GC handle enumeration
+ */
+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
+
+
+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);
+
+/*--------------------------------------------------------------------------*/
+
+
+#if defined(USE_CHECKED_OBJECTREFS) && !defined(_NOVM)
+#define OBJECTREF_TO_UNCHECKED_OBJECTREF(objref) (*((_UNCHECKED_OBJECTREF*)&(objref)))
+#define UNCHECKED_OBJECTREF_TO_OBJECTREF(obj) (OBJECTREF(obj))
+#else
+#define OBJECTREF_TO_UNCHECKED_OBJECTREF(objref) (objref)
+#define UNCHECKED_OBJECTREF_TO_OBJECTREF(obj) (obj)
+#endif
+
+#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
+ */
+
+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;
+}
+
+
+
+/*
+ * inline handle checking
+ */
+FORCEINLINE BOOL HndCheckForNullUnchecked(OBJECTHANDLE handle)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ return (handle == NULL || (*(_UNCHECKED_OBJECTREF *)handle) == NULL);
+}
+
+
+/*
+ *
+ * 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
+