diff options
Diffstat (limited to 'src/gc/env/gcenv.base.h')
-rw-r--r-- | src/gc/env/gcenv.base.h | 336 |
1 files changed, 195 insertions, 141 deletions
diff --git a/src/gc/env/gcenv.base.h b/src/gc/env/gcenv.base.h index 1e9406c296..98a4235301 100644 --- a/src/gc/env/gcenv.base.h +++ b/src/gc/env/gcenv.base.h @@ -7,10 +7,11 @@ // Sets up basic environment for CLR GC // -#define FEATURE_REDHAWK 1 -#define FEATURE_CONSERVATIVE_GC 1 +#ifdef _MSC_VER +#include <intrin.h> +#endif // _MSC_VER -#define GCENV_INCLUDED +#define FEATURE_REDHAWK 1 #define REDHAWK_PALIMPORT extern "C" #define REDHAWK_PALAPI __stdcall @@ -22,7 +23,11 @@ #else // __clang__ #define __forceinline inline #endif // __clang__ -#endif // !_MSC_VER +// [LOCALGC TODO] is there a better place for this? +#define NOINLINE __attribute__((noinline)) +#else // !_MSC_VER +#define NOINLINE __declspec(noinline) +#endif // _MSC_VER #ifndef SIZE_T_MAX #define SIZE_T_MAX ((size_t)-1) @@ -39,6 +44,7 @@ typedef int BOOL; typedef uint32_t DWORD; +typedef uint64_t DWORD64; // ----------------------------------------------------------------------------------------------------------- // HRESULT subset. @@ -59,12 +65,8 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x) } #define S_OK 0x0 -#define S_FALSE 0x1 #define E_FAIL 0x80004005 #define E_OUTOFMEMORY 0x8007000E -#define E_UNEXPECTED 0x8000FFFF -#define E_NOTIMPL 0x80004001 -#define E_INVALIDARG 0x80070057 #define COR_E_EXECUTIONENGINE 0x80131506 #define NOERROR 0x0 @@ -100,6 +102,8 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x) #define _vsnprintf_s(string, sizeInBytes, count, format, args) vsnprintf(string, sizeInBytes, format, args) #define sprintf_s snprintf #define swprintf_s swprintf +#define _snprintf_s(string, sizeInBytes, count, format, ...) \ + snprintf(string, sizeInBytes, format, ## __VA_ARGS__) #endif #ifdef UNICODE @@ -161,8 +165,8 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter); #elif defined(_X86_) #define YieldProcessor() __asm { rep nop } - - __forceinline void MemoryBarrier() + #define MemoryBarrier() MemoryBarrierImpl() + __forceinline void MemoryBarrierImpl() { int32_t Barrier; __asm { @@ -175,7 +179,145 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter); #endif #else // _MSC_VER +// Only clang defines __has_builtin, so we first test for a GCC define +// before using __has_builtin. + +#if defined(__i386__) || defined(__x86_64__) + +#if (__GNUC__ > 4 && __GNUC_MINOR > 7) || __has_builtin(__builtin_ia32_pause) + // clang added this intrinsic in 3.8 + // gcc added this intrinsic by 4.7.1 + #define YieldProcessor __builtin_ia32_pause +#endif // __has_builtin(__builtin_ia32_pause) + +#if defined(__GNUC__) || __has_builtin(__builtin_ia32_mfence) + // clang has had this intrinsic since at least 3.0 + // gcc has had this intrinsic since forever + #define MemoryBarrier __builtin_ia32_mfence +#endif // __has_builtin(__builtin_ia32_mfence) + +// If we don't have intrinsics, we can do some inline asm instead. +#ifndef YieldProcessor + #define YieldProcessor() asm volatile ("pause") +#endif // YieldProcessor + +#ifndef MemoryBarrier + #define MemoryBarrier() asm volatile ("mfence") +#endif // MemoryBarrier + +#endif // defined(__i386__) || defined(__x86_64__) + +#endif // _MSC_VER + +#ifndef YieldProcessor + #error "Don't know how to YieldProcessor on this architecture" +#endif + +#ifndef MemoryBarrier + #error "Don't know how to MemoryBarrier on this architecture" +#endif + +#ifdef _MSC_VER +#pragma intrinsic(_BitScanForward) +#if WIN64 + #pragma intrinsic(_BitScanForward64) +#endif +#endif // _MSC_VER + +// Cross-platform wrapper for the _BitScanForward compiler intrinsic. +inline uint8_t BitScanForward(uint32_t *bitIndex, uint32_t mask) +{ +#ifdef _MSC_VER + return _BitScanForward((unsigned long*)bitIndex, mask); +#else // _MSC_VER + unsigned char ret = FALSE; + int iIndex = __builtin_ffsl(mask); + if (iIndex != 0) + { + *bitIndex = (uint32_t)(iIndex - 1); + ret = TRUE; + } + + return ret; #endif // _MSC_VER +} + +// Cross-platform wrapper for the _BitScanForward64 compiler intrinsic. +inline uint8_t BitScanForward64(uint32_t *bitIndex, uint64_t mask) +{ +#ifdef _MSC_VER + #if _WIN32 + // MSVC targeting a 32-bit target does not support this intrinsic. + // We can fake it using two successive invocations of _BitScanForward. + uint32_t hi = (mask >> 32) & 0xFFFFFFFF; + uint32_t lo = mask & 0xFFFFFFFF; + uint32_t fakeBitIndex = 0; + if (BitScanForward(&fakeBitIndex, hi)) + { + *bitIndex = fakeBitIndex + 32; + } + + return BitScanForward(bitIndex, lo); + #else + return _BitScanForward64((unsigned long*)bitIndex, mask); + #endif // _WIN32 +#else + unsigned char ret = FALSE; + int iIndex = __builtin_ffsll(mask); + if (iIndex != 0) + { + *bitIndex = (uint32_t)(iIndex - 1); + ret = TRUE; + } + + return ret; +#endif // _MSC_VER +} + +// Aligns a size_t to the specified alignment. Alignment must be a power +// of two. +inline size_t ALIGN_UP(size_t val, size_t alignment) +{ + // alignment factor must be power of two + assert((alignment & (alignment - 1)) == 0); + size_t result = (val + (alignment - 1)) & ~(alignment - 1); + assert(result >= val); + return result; +} + +// Aligns a pointer to the specified alignment. Alignment must be a power +// of two. +inline uint8_t* ALIGN_UP(uint8_t* ptr, size_t alignment) +{ + size_t as_size_t = reinterpret_cast<size_t>(ptr); + return reinterpret_cast<uint8_t*>(ALIGN_UP(as_size_t, alignment)); +} + +// Aligns a size_t to the specified alignment by rounding down. Alignment must +// be a power of two. +inline size_t ALIGN_DOWN(size_t val, size_t alignment) +{ + // alignment factor must be power of two. + assert((alignment & (alignment - 1)) == 0); + size_t result = val & ~(alignment - 1); + return result; +} + +// Aligns a pointer to the specified alignment by rounding down. Alignment +// must be a power of two. +inline uint8_t* ALIGN_DOWN(uint8_t* ptr, size_t alignment) +{ + size_t as_size_t = reinterpret_cast<size_t>(ptr); + return reinterpret_cast<uint8_t*>(ALIGN_DOWN(as_size_t, alignment)); +} + +// Aligns a void pointer to the specified alignment by rounding down. Alignment +// must be a power of two. +inline void* ALIGN_DOWN(void* ptr, size_t alignment) +{ + size_t as_size_t = reinterpret_cast<size_t>(ptr); + return reinterpret_cast<void*>(ALIGN_DOWN(as_size_t, alignment)); +} typedef struct _PROCESSOR_NUMBER { uint16_t Group; @@ -241,75 +383,25 @@ typedef struct _PROCESSOR_NUMBER { // // Data access macros // -#ifdef DACCESS_COMPILE -#include "daccess.h" -#else // DACCESS_COMPILE typedef uintptr_t TADDR; - #define PTR_TO_TADDR(ptr) ((TADDR)(ptr)) #define DPTR(type) type* #define SPTR(type) type* - -#define GVAL_DECL(type, var) \ - extern type var -#define GVAL_IMPL(type, var) \ - type var -#define GVAL_IMPL_INIT(type, var, init) \ - type var = init - -#define GPTR_DECL(type, var) \ - extern type* var -#define GPTR_IMPL(type, var) \ - type* var -#define GPTR_IMPL_INIT(type, var, init) \ - type* var = init - -#define SPTR_DECL(type, var) \ - static type* var -#define SPTR_IMPL(type, cls, var) \ - type * cls::var -#define SPTR_IMPL_NS(type, ns, cls, var) \ - type * cls::var -#define SPTR_IMPL_NS_INIT(type, ns, cls, var, init) \ - type * cls::var = init - -#define SVAL_DECL(type, var) \ - static type var -#define SVAL_IMPL_NS(type, ns, cls, var) \ - type cls::var -#define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \ - type cls::var = init - -#define GARY_DECL(type, var, size) \ - extern type var[size] -#define GARY_IMPL(type, var, size) \ - type var[size] - -struct _DacGlobals; -#endif // DACCESS_COMPILE - typedef DPTR(size_t) PTR_size_t; typedef DPTR(uint8_t) PTR_uint8_t; // ----------------------------------------------------------------------------------------------------------- #define DATA_ALIGNMENT sizeof(uintptr_t) - #define RAW_KEYWORD(x) x - #define DECLSPEC_ALIGN(x) __declspec(align(x)) - #ifndef _ASSERTE #define _ASSERTE(_expr) ASSERT(_expr) #endif - #define CONSISTENCY_CHECK(_expr) ASSERT(_expr) - #define PREFIX_ASSUME(cond) ASSERT(cond) - #define EEPOLICY_HANDLE_FATAL_ERROR(error) ASSERT(!"EEPOLICY_HANDLE_FATAL_ERROR") - #define UI64(_literal) _literal##ULL class ObjHeader; @@ -331,7 +423,7 @@ typedef PTR_PTR_Object PTR_UNCHECKED_OBJECTREF; #define ObjectToOBJECTREF(_obj) (OBJECTREF)(_obj) #define OBJECTREFToObject(_obj) (Object*)(_obj) -#define VALIDATEOBJECTREF(_objref) _objref; +#define VALIDATEOBJECTREF(_objref) (void)_objref; #define VOLATILE(T) T volatile @@ -451,24 +543,13 @@ void VolatileStore(T* pt, T val) #endif } -extern GCSystemInfo g_SystemInfo; - -extern MethodTable * g_pFreeObjectMethodTable; - -extern int32_t g_TrapReturningThreads; - -// -// Locks -// - -struct gc_alloc_context; class Thread; -Thread * GetThread(); - -typedef void (CALLBACK *HANDLESCANPROC)(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *pExtraInfo, uintptr_t param1, uintptr_t param2); - -bool IsGCSpecialThread(); +inline bool IsGCSpecialThread() +{ + // [LOCALGC TODO] this is not correct + return false; +} inline bool dbgOnly_IsSpecialEEThread() { @@ -498,42 +579,11 @@ namespace ETW } GC_ROOT_KIND; }; -// -// Logging -// - -void LogSpewAlways(const char *fmt, ...); - -#define DEFAULT_GC_PRN_LVL 3 - -// ----------------------------------------------------------------------------------------------------------- - -bool IsGCThread(); - -class CLRConfig +inline bool IsGCThread() { -public: - enum CLRConfigTypes - { - UNSUPPORTED_GCLogEnabled, - UNSUPPORTED_GCLogFile, - UNSUPPORTED_GCLogFileSize, - UNSUPPORTED_GCConfigLogEnabled, - UNSUPPORTED_GCConfigLogFile, - UNSUPPORTED_BGCSpinCount, - UNSUPPORTED_BGCSpin, - EXTERNAL_GCStressStart, - INTERNAL_GCStressStartAtJit, - INTERNAL_DbgDACSkipVerifyDlls, - Config_COUNT - }; - - typedef CLRConfigTypes ConfigDWORDInfo; - typedef CLRConfigTypes ConfigStringInfo; - - static uint32_t GetConfigValue(ConfigDWORDInfo eType); - static HRESULT GetConfigValue(ConfigStringInfo /*eType*/, __out_z TCHAR * * outVal); -}; + // [LOCALGC TODO] this is not correct + return false; +} inline bool FitsInU1(uint64_t val) { @@ -577,46 +627,50 @@ public: DWORD GetTotalNumSizedRefHandles() { return 0; } }; -#ifdef STRESS_HEAP -namespace GCStressPolicy +class NumaNodeInfo { - static volatile int32_t s_cGcStressDisables; +public: + static bool CanEnableGCNumaAware() + { + // [LOCALGC TODO] enable NUMA node support + return false; + } - inline bool IsEnabled() { return s_cGcStressDisables == 0; } - inline void GlobalDisable() { Interlocked::Increment(&s_cGcStressDisables); } - inline void GlobalEnable() { Interlocked::Decrement(&s_cGcStressDisables); } -} + static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number) + { + // [LOCALGC TODO] enable NUMA node support + assert(!"should not be called"); + } -enum gcs_trigger_points -{ - cfg_any, + static bool GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, uint16_t * node_no) + { + // [LOCALGC TODO] enable NUMA node support + assert(!"should not be called"); + return false; + } }; -template <enum gcs_trigger_points tp> -class GCStress +class CPUGroupInfo { public: - static inline bool IsEnabled() + static bool CanEnableGCCPUGroups() { - return g_pConfig->GetGCStressLevel() != 0; + // [LOCALGC TODO] enable CPU group support + return false; } -}; -#endif // STRESS_HEAP -class NumaNodeInfo -{ -public: - static bool CanEnableGCNumaAware(); - static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number); - static bool GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, uint16_t * node_no); -}; + static uint32_t GetNumActiveProcessors() + { + // [LOCALGC TODO] enable CPU group support + assert(!"should not be called"); + return 0; + } -class CPUGroupInfo -{ -public: - static bool CanEnableGCCPUGroups(); - static uint32_t GetNumActiveProcessors(); - static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number); + static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number) + { + // [LOCALGC TODO] enable CPU group support + assert(!"should not be called"); + } }; |