{
ifaceRet = static_cast<ISOSDacInterface11*>(this);
}
+ else if (IsEqualIID(interfaceId, __uuidof(ISOSDacInterface12)))
+ {
+ ifaceRet = static_cast<ISOSDacInterface12*>(this);
+ }
else
{
*iface = NULL;
if (threadStore != NULL)
{
int count = (int)threadStore->ThreadCountInEE();
- mAllocInfo = new (nothrow) AllocInfo[count];
+ mAllocInfo = new (nothrow) AllocInfo[count + 1];
if (mAllocInfo == NULL)
return E_OUTOFMEMORY;
j++;
}
}
+ if ((&g_global_alloc_context)->alloc_ptr != nullptr)
+ {
+ mAllocInfo[j].Ptr = (CORDB_ADDRESS)(&g_global_alloc_context)->alloc_ptr;
+ mAllocInfo[j].Limit = (CORDB_ADDRESS)(&g_global_alloc_context)->alloc_limit;
+ }
mThreadCount = j;
}
public ISOSDacInterface8,
public ISOSDacInterface9,
public ISOSDacInterface10,
- public ISOSDacInterface11
+ public ISOSDacInterface11,
+ public ISOSDacInterface12
{
public:
ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLegacyTarget=0);
CLRDATA_ADDRESS objAddr,
CLRDATA_ADDRESS *taggedMemory,
size_t *taggedMemorySizeInBytes);
+
+ // ISOSDacInterface12
+ virtual HRESULT STDMETHODCALLTYPE GetGlobalAllocationContext(
+ CLRDATA_ADDRESS *allocPtr,
+ CLRDATA_ADDRESS *allocLimit);
+
//
// ClrDataAccess.
//
SOSDacLeave();
return hr;
}
+
+HRESULT ClrDataAccess::GetGlobalAllocationContext(
+ CLRDATA_ADDRESS *allocPtr,
+ CLRDATA_ADDRESS *allocLimit)
+{
+ if (allocPtr == nullptr || allocLimit == nullptr)
+ {
+ return E_INVALIDARG;
+ }
+
+ SOSDacEnter();
+ *allocPtr = (CLRDATA_ADDRESS)((&g_global_alloc_context)->alloc_ptr);
+ *allocLimit = (CLRDATA_ADDRESS)((&g_global_alloc_context)->alloc_limit);
+ SOSDacLeave();
+ return hr;
+}
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCNumaAware, W("GCNumaAware"), 1, "Specifies if to enable GC NUMA aware")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCCpuGroup, W("GCCpuGroup"), 0, "Specifies if to enable GC to support CPU groups")
RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCName, W("GCName"), "")
+/**
+ * This flag allows us to force the runtime to use global allocation context on Windows x86/amd64 instead of thread allocation context just for testing purpose.
+ * The flag is unsafe for a subtle reason. Although the access to the g_global_alloc_context is protected under a lock. The implementation of
+ * that lock in the JIT helpers are not multi-core safe (in particular, it used and inc instruction without using the LOCK prefix). This is
+ * only useful for ad-hoc testing.
+ */
+CONFIG_DWORD_INFO(INTERNAL_GCUseGlobalAllocationContext, W("GCUseGlobalAllocationContext"), 0, "Force using the global allocation context for testing only")
///
/// JIT
DEFINE_DACVAR(ULONG, PTR_DWORD, dac__g_card_table, ::g_card_table)
DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_lowest_address, ::g_lowest_address)
DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_highest_address, ::g_highest_address)
+DEFINE_DACVAR(ULONG, gc_alloc_context, dac__g_global_alloc_context, ::g_global_alloc_context)
DEFINE_DACVAR(ULONG, IGCHeap, dac__g_pGCHeap, ::g_pGCHeap)
HRESULT IsTrackedType(CLRDATA_ADDRESS objAddr, BOOL* isTrackedType, BOOL* hasTaggedMemory);
HRESULT GetTaggedMemory(CLRDATA_ADDRESS objAddr, CLRDATA_ADDRESS* taggedMemory, size_t* taggedMemorySizeInBytes);
}
+
+[
+ object,
+ local,
+ uuid(1b93bacc-8ca4-432d-943a-3e6e7ec0b0a3)
+]
+interface ISOSDacInterface12 : IUnknown
+{
+ HRESULT GetGlobalAllocationContext(CLRDATA_ADDRESS* allocPtr, CLRDATA_ADDRESS* allocLimit);
+}
MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface11,0x96BA1DB9,0x14CD,0x4492,0x80,0x65,0x1C,0xAA,0xEC,0xF6,0xE5,0xCF);
+
+MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface12,0x1b93bacc,0x8ca4,0x432d,0x94,0x3a,0x3e,0x6e,0x7e,0xc0,0xb0,0xa3);
+
+
#undef MIDL_DEFINE_GUID
#ifdef __cplusplus
#endif /* C style interface */
+#endif /* __ISOSDacInterface11_INTERFACE_DEFINED__ */
+
+#ifndef __ISOSDacInterface12_INTERFACE_DEFINED__
+#define __ISOSDacInterface12_INTERFACE_DEFINED__
+/* interface ISOSDacInterface12 */
+/* [uuid][local][object] */
-#endif /* __ISOSDacInterface11_INTERFACE_DEFINED__ */
+EXTERN_C const IID IID_ISOSDacInterface12;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("1b93bacc-8ca4-432d-943a-3e6e7ec0b0a3")
+ ISOSDacInterface12 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetGlobalAllocationContext(
+ CLRDATA_ADDRESS *allocPtr,
+ CLRDATA_ADDRESS *allocLimit) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ISOSDacInterface12Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ISOSDacInterface12 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ISOSDacInterface12 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ISOSDacInterface12 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetGlobalAllocationContext )(
+ ISOSDacInterface12 * This,
+ CLRDATA_ADDRESS *allocPtr,
+ CLRDATA_ADDRESS *allocLimit);
+
+ END_INTERFACE
+ } ISOSDacInterface12Vtbl;
+
+ interface ISOSDacInterface12
+ {
+ CONST_VTBL struct ISOSDacInterface12Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ISOSDacInterface12_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ISOSDacInterface12_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ISOSDacInterface12_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ISOSDacInterface12_GetGlobalAllocationContext(This,allocPtr,allocLimit) \
+ ( (This)->lpVtbl -> GetGlobalAllocationContext(This,allocPtr,allocLimit) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ISOSDacInterface12_INTERFACE_DEFINED__ */
+
/* Additional Prototypes for ALL interfaces */
#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
-gc_alloc_context g_global_alloc_context = {};
+GVAL_IMPL_INIT(gc_alloc_context, g_global_alloc_context, {});
enum GC_LOAD_STATUS {
GC_LOAD_STATUS_BEFORE_START,
// The module that contains the GC.
PTR_VOID g_gc_module_base;
+bool GCHeapUtilities::s_useThreadAllocationContexts;
+
// GC entrypoints for the the linked-in GC. These symbols are invoked
// directly if we are not using a standalone GC.
extern "C" void GC_VersionInfo(/* Out */ VersionInfo* info);
{
LIMITED_METHOD_CONTRACT;
+ // When running on a single-proc Intel system, it's more efficient to use a single global
+ // allocation context for SOH allocations than to use one for every thread.
+#if (defined(TARGET_X86) || defined(TARGET_AMD64)) && !defined(TARGET_UNIX)
+#if DEBUG
+ bool useGlobalAllocationContext = (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCUseGlobalAllocationContext) != 0);
+#else
+ bool useGlobalAllocationContext = false;
+#endif
+ s_useThreadAllocationContexts = !useGlobalAllocationContext && (IsServerHeap() || ::g_SystemInfo.dwNumberOfProcessors != 1 || CPUGroupInfo::CanEnableGCCPUGroups());
+#else
+ s_useThreadAllocationContexts = true;
+#endif
+
// we should only call this once on startup. Attempting to load a GC
// twice is an error.
assert(g_pGCHeap == nullptr);
GPTR_DECL(uint8_t,g_highest_address);
GPTR_DECL(uint32_t,g_card_table);
GVAL_DECL(GCHeapType, g_heap_type);
-#ifndef DACCESS_COMPILE
-}
-#endif // !DACCESS_COMPILE
// For single-proc machines, the EE will use a single, shared alloc context
// for all allocations. In order to avoid extra indirections in assembly
// allocation helpers, the EE owns the global allocation context and the
// GC will update it when it needs to.
-extern "C" gc_alloc_context g_global_alloc_context;
+GVAL_DECL(gc_alloc_context, g_global_alloc_context);
+#ifndef DACCESS_COMPILE
+}
+#endif // !DACCESS_COMPILE
extern "C" uint32_t* g_card_bundle_table;
extern "C" uint8_t* g_ephemeral_low;
static bool UseThreadAllocationContexts()
{
- // When running on a single-proc Intel system, it's more efficient to use a single global
- // allocation context for SOH allocations than to use one for every thread.
-#if (defined(TARGET_X86) || defined(TARGET_AMD64)) && !defined(TARGET_UNIX)
- return IsServerHeap() || ::g_SystemInfo.dwNumberOfProcessors != 1 || CPUGroupInfo::CanEnableGCCPUGroups();
-#else
- return true;
-#endif
-
+ return s_useThreadAllocationContexts;
}
#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
private:
// This class should never be instantiated.
GCHeapUtilities() = delete;
+
+ static bool s_useThreadAllocationContexts;
};
#endif // _GCHEAPUTILITIES_H_