summaryrefslogtreecommitdiff
path: root/src/gc/env
diff options
context:
space:
mode:
Diffstat (limited to 'src/gc/env')
-rw-r--r--src/gc/env/common.h2
-rw-r--r--src/gc/env/gcenv.base.h380
-rw-r--r--src/gc/env/gcenv.ee.h85
-rw-r--r--src/gc/env/gcenv.interlocked.h102
-rw-r--r--src/gc/env/gcenv.interlocked.inl200
-rw-r--r--src/gc/env/gcenv.object.h4
-rw-r--r--src/gc/env/gcenv.os.h274
-rw-r--r--src/gc/env/gcenv.structs.h70
-rw-r--r--src/gc/env/gcenv.sync.h31
-rw-r--r--src/gc/env/gcenv.unix.cpp569
-rw-r--r--src/gc/env/gcenv.windows.cpp268
11 files changed, 806 insertions, 1179 deletions
diff --git a/src/gc/env/common.h b/src/gc/env/common.h
index 3e982f8f6c..39e97b3e7a 100644
--- a/src/gc/env/common.h
+++ b/src/gc/env/common.h
@@ -22,7 +22,7 @@
#include <new>
-#ifndef WIN32
+#ifdef PLATFORM_UNIX
#include <pthread.h>
#endif
diff --git a/src/gc/env/gcenv.base.h b/src/gc/env/gcenv.base.h
index 5b8f5f7dd3..628a90cc88 100644
--- a/src/gc/env/gcenv.base.h
+++ b/src/gc/env/gcenv.base.h
@@ -16,11 +16,17 @@
#define REDHAWK_PALIMPORT extern "C"
#define REDHAWK_PALAPI __stdcall
-
#ifndef _MSC_VER
#define __stdcall
+#ifdef __clang__
+#define __forceinline __attribute__((always_inline))
+#else // __clang__
#define __forceinline inline
-#endif
+#endif // __clang__
+#endif // !_MSC_VER
+
+#define SIZE_T_MAX ((size_t)-1)
+#define SSIZE_T_MAX ((ptrdiff_t)(SIZE_T_MAX / 2))
#ifndef _INC_WINDOWS
// -----------------------------------------------------------------------------------------------------------
@@ -44,17 +50,14 @@ typedef size_t SIZE_T;
typedef void * HANDLE;
-#define SIZE_T_MAX ((size_t)-1)
-#define SSIZE_T_MAX ((ptrdiff_t)(SIZE_T_MAX / 2))
-
// -----------------------------------------------------------------------------------------------------------
// HRESULT subset.
-#ifdef WIN32
+#ifdef PLATFORM_UNIX
+typedef int32_t HRESULT;
+#else
// this must exactly match the typedef used by windows.h
typedef long HRESULT;
-#else
-typedef int32_t HRESULT;
#endif
#define SUCCEEDED(_hr) ((HRESULT)(_hr) >= 0)
@@ -104,122 +107,20 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x)
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
-#ifndef WIN32
+#ifdef PLATFORM_UNIX
#define _vsnprintf vsnprintf
#define sprintf_s snprintf
+#define swprintf_s swprintf
#endif
-#define WINBASEAPI extern "C"
#define WINAPI __stdcall
typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter);
-WINBASEAPI
-void
-WINAPI
-DebugBreak();
-
-WINBASEAPI
-BOOL
-WINAPI
-VirtualUnlock(
- LPVOID lpAddress,
- SIZE_T dwSize
- );
-
-WINBASEAPI
-DWORD
-WINAPI
-GetLastError();
-
-WINBASEAPI
-UINT
-WINAPI
-GetWriteWatch(
- DWORD dwFlags,
- PVOID lpBaseAddress,
- SIZE_T dwRegionSize,
- PVOID *lpAddresses,
- ULONG_PTR * lpdwCount,
- DWORD * lpdwGranularity
-);
-
-WINBASEAPI
-UINT
-WINAPI
-ResetWriteWatch(
- LPVOID lpBaseAddress,
- SIZE_T dwRegionSize
-);
-
-WINBASEAPI
-VOID
-WINAPI
-FlushProcessWriteBuffers();
-
-WINBASEAPI
-DWORD
-WINAPI
-GetTickCount();
-
-WINBASEAPI
-BOOL
-WINAPI
-QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);
-
-WINBASEAPI
-BOOL
-WINAPI
-QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
-
-WINBASEAPI
-DWORD
-WINAPI
-GetCurrentThreadId(
- VOID);
-
-WINBASEAPI
-BOOL
-WINAPI
-CloseHandle(
- HANDLE hObject);
-
#define WAIT_OBJECT_0 0
#define WAIT_TIMEOUT 258
#define WAIT_FAILED 0xFFFFFFFF
-#define GENERIC_WRITE 0x40000000
-#define FILE_SHARE_READ 0x00000001
-#define CREATE_ALWAYS 2
-#define FILE_ATTRIBUTE_NORMAL 0x00000080
-
-WINBASEAPI
-BOOL
-WINAPI
-WriteFile(
- HANDLE hFile,
- LPCVOID lpBuffer,
- DWORD nNumberOfBytesToWrite,
- DWORD * lpNumberOfBytesWritten,
- PVOID lpOverlapped);
-
-#define FILE_BEGIN 0
-
-WINBASEAPI
-DWORD
-WINAPI
-SetFilePointer(
- HANDLE hFile,
- int32_t lDistanceToMove,
- int32_t * lpDistanceToMoveHigh,
- DWORD dwMoveMethod);
-
-WINBASEAPI
-BOOL
-WINAPI
-FlushFileBuffers(
- HANDLE hFile);
-
#if defined(_MSC_VER)
#if defined(_ARM_)
@@ -263,24 +164,8 @@ FlushFileBuffers(
#endif
#else // _MSC_VER
-WINBASEAPI
-VOID
-WINAPI
-YieldProcessor();
-
-WINBASEAPI
-VOID
-WINAPI
-MemoryBarrier();
-
#endif // _MSC_VER
-typedef struct _GUID {
- unsigned long Data1;
- unsigned short Data2;
- unsigned short Data3;
- unsigned char Data4[8];
-} GUID;
#endif // _INC_WINDOWS
// -----------------------------------------------------------------------------------------------------------
@@ -410,56 +295,6 @@ typedef DPTR(uint8_t) PTR_uint8_t;
#define UI64(_literal) _literal##ULL
-int32_t FastInterlockIncrement(int32_t volatile *lpAddend);
-int32_t FastInterlockDecrement(int32_t volatile *lpAddend);
-int32_t FastInterlockExchange(int32_t volatile *Target, int32_t Value);
-int32_t FastInterlockCompareExchange(int32_t volatile *Destination, int32_t Exchange, int32_t Comperand);
-int32_t FastInterlockExchangeAdd(int32_t volatile *Addend, int32_t Value);
-
-void * _FastInterlockExchangePointer(void * volatile *Target, void * Value);
-void * _FastInterlockCompareExchangePointer(void * volatile *Destination, void * Exchange, void * Comperand);
-
-template <typename T>
-inline T FastInterlockExchangePointer(
- T volatile * target,
- T value)
-{
- return (T)((TADDR)_FastInterlockExchangePointer((void **)target, value));
-}
-
-template <typename T>
-inline T FastInterlockExchangePointer(
- T volatile * target,
- nullptr_t value)
-{
- return (T)((TADDR)_FastInterlockExchangePointer((void **)target, value));
-}
-
-template <typename T>
-inline T FastInterlockCompareExchangePointer(
- T volatile * destination,
- T exchange,
- T comparand)
-{
- return (T)((TADDR)_FastInterlockCompareExchangePointer((void **)destination, exchange, comparand));
-}
-
-template <typename T>
-inline T FastInterlockCompareExchangePointer(
- T volatile * destination,
- T exchange,
- nullptr_t comparand)
-{
- return (T)((TADDR)_FastInterlockCompareExchangePointer((void **)destination, exchange, comparand));
-}
-
-
-void FastInterlockOr(uint32_t volatile *p, uint32_t msk);
-void FastInterlockAnd(uint32_t volatile *p, uint32_t msk);
-
-#define CALLER_LIMITS_SPINNING 0
-bool __SwitchToThread (uint32_t dwSleepMSec, uint32_t dwSwitchCount);
-
class ObjHeader;
class MethodTable;
class Object;
@@ -493,7 +328,51 @@ typedef TADDR OBJECTHANDLE;
#define VOLATILE(T) T volatile
+//
+// This code is extremely compiler- and CPU-specific, and will need to be altered to
+// support new compilers and/or CPUs. Here we enforce that we can only compile using
+// VC++, or Clang on x86, AMD64, ARM and ARM64.
+//
+#if !defined(_MSC_VER) && !defined(__clang__)
+#error The Volatile type is currently only defined for Visual C++ and Clang
+#endif
+
+#if defined(__clang__) && !defined(_X86_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_)
+#error The Volatile type is currently only defined for Clang when targeting x86, AMD64, ARM or ARM64 CPUs
+#endif
+
+#if defined(__clang__)
+#if defined(_ARM_) || defined(_ARM64_)
+// This is functionally equivalent to the MemoryBarrier() macro used on ARM on Windows.
+#define VOLATILE_MEMORY_BARRIER() asm volatile ("dmb sy" : : : "memory")
+#else
+//
+// For Clang, we prevent reordering by the compiler by inserting the following after a volatile
+// load (to prevent subsequent operations from moving before the read), and before a volatile
+// write (to prevent prior operations from moving past the write). We don't need to do anything
+// special to prevent CPU reorderings, because the x86 and AMD64 architectures are already
+// sufficiently constrained for our purposes. If we ever need to run on weaker CPU architectures
+// (such as PowerPC), then we will need to do more work.
+//
+// Please do not use this macro outside of this file. It is subject to change or removal without
+// notice.
+//
+#define VOLATILE_MEMORY_BARRIER() asm volatile ("" : : : "memory")
+#endif // !_ARM_
+#elif defined(_ARM_) && _ISO_VOLATILE
+// ARM has a very weak memory model and very few tools to control that model. We're forced to perform a full
+// memory barrier to preserve the volatile semantics. Technically this is only necessary on MP systems but we
+// currently don't have a cheap way to determine the number of CPUs from this header file. Revisit this if it
+// turns out to be a performance issue for the uni-proc case.
+#define VOLATILE_MEMORY_BARRIER() MemoryBarrier()
+#else
+//
+// On VC++, reorderings at the compiler and machine level are prevented by the use of the
+// "volatile" keyword in VolatileLoad and VolatileStore. This should work on any CPU architecture
+// targeted by VC++ with /iso_volatile-.
+//
#define VOLATILE_MEMORY_BARRIER()
+#endif
//
// VolatileLoad loads a T from a pointer to T. It is guaranteed that this load will not be optimized
@@ -539,11 +418,6 @@ void VolatileStore(T* pt, T val)
}
extern GCSystemInfo g_SystemInfo;
-void InitializeSystemInfo();
-
-void
-GetProcessMemoryLoad(
- GCMemoryStatus* lpBuffer);
extern MethodTable * g_pFreeObjectMethodTable;
@@ -552,43 +426,6 @@ extern int32_t g_TrapReturningThreads;
extern bool g_fFinalizerRunOnShutDown;
//
-// Memory allocation
-//
-#define MEM_COMMIT 0x1000
-#define MEM_RESERVE 0x2000
-#define MEM_DECOMMIT 0x4000
-#define MEM_RELEASE 0x8000
-#define MEM_RESET 0x80000
-
-#define PAGE_NOACCESS 0x01
-#define PAGE_READWRITE 0x04
-
-void * ClrVirtualAlloc(
- void * lpAddress,
- size_t dwSize,
- uint32_t flAllocationType,
- uint32_t flProtect);
-
-void * ClrVirtualAllocAligned(
- void * lpAddress,
- size_t dwSize,
- uint32_t flAllocationType,
- uint32_t flProtect,
- size_t dwAlignment);
-
-bool ClrVirtualFree(
- void * lpAddress,
- size_t dwSize,
- uint32_t dwFreeType);
-
-bool
-ClrVirtualProtect(
- void * lpAddress,
- size_t dwSize,
- uint32_t flNewProtect,
- uint32_t * lpflOldProtect);
-
-//
// Locks
//
@@ -597,71 +434,8 @@ class Thread;
Thread * GetThread();
-struct ScanContext;
-typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t);
-
typedef void (CALLBACK *HANDLESCANPROC)(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *pExtraInfo, uintptr_t param1, uintptr_t param2);
-typedef void enum_alloc_context_func(alloc_context*, void*);
-
-class GCToEEInterface
-{
-public:
- //
- // Suspend/Resume callbacks
- //
- typedef enum
- {
- SUSPEND_FOR_GC,
- SUSPEND_FOR_GC_PREP
- } SUSPEND_REASON;
-
- static void SuspendEE(SUSPEND_REASON reason);
- static void RestartEE(bool bFinishedGC); //resume threads.
-
- //
- // The stack roots enumeration callback
- //
- static void GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc);
-
- //
- // Callbacks issues during GC that the execution engine can do its own bookeeping
- //
-
- // start of GC call back - single threaded
- static void GcStartWork(int condemned, int max_gen);
-
- //EE can perform post stack scanning action, while the
- // user threads are still suspended
- static void AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc);
-
- // Called before BGC starts sweeping, the heap is walkable
- static void GcBeforeBGCSweepWork();
-
- // post-gc callback.
- static void GcDone(int condemned);
-
- // Promote refcounted handle callback
- static bool RefCountedHandleCallbacks(Object * pObject);
-
- // Sync block cache management
- static void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2);
- static void SyncBlockCacheDemote(int max_gen);
- static void SyncBlockCachePromotionsGranted(int max_gen);
-
- // Thread functions
- static bool IsPreemptiveGCDisabled(Thread * pThread);
- static void EnablePreemptiveGC(Thread * pThread);
- static void DisablePreemptiveGC(Thread * pThread);
- static void SetGCSpecial(Thread * pThread);
- static bool CatchAtSafePoint(Thread * pThread);
- static alloc_context * GetAllocContext(Thread * pThread);
-
- // ThreadStore functions
- static void AttachCurrentThread(); // does not acquire thread store lock
- static void GcEnumAllocContexts (enum_alloc_context_func* fn, void* param);
-};
-
class FinalizerThread
{
public:
@@ -678,9 +452,20 @@ public:
static HANDLE GetFinalizerEvent();
};
+#ifdef FEATURE_REDHAWK
typedef uint32_t (__stdcall *BackgroundCallback)(void* pCallbackContext);
REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartBackgroundGCThread(BackgroundCallback callback, void* pCallbackContext);
+enum PalCapability
+{
+ WriteWatchCapability = 0x00000001, // GetWriteWatch() and friends
+ LowMemoryNotificationCapability = 0x00000002, // CreateMemoryResourceNotification() and friends
+ GetCurrentProcessorNumberCapability = 0x00000004, // GetCurrentProcessorNumber()
+};
+
+REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalHasCapability(PalCapability capability);
+#endif // FEATURE_REDHAWK
+
void DestroyThread(Thread * pThread);
bool IsGCSpecialThread();
@@ -692,12 +477,6 @@ inline bool dbgOnly_IsSpecialEEThread()
#define ClrFlsSetThreadType(type)
-void UnsafeInitializeCriticalSection(CRITICAL_SECTION * lpCriticalSection);
-void UnsafeEEEnterCriticalSection(CRITICAL_SECTION *lpCriticalSection);
-void UnsafeEELeaveCriticalSection(CRITICAL_SECTION * lpCriticalSection);
-void UnsafeDeleteCriticalSection(CRITICAL_SECTION *lpCriticalSection);
-
-
//
// Performance logging
//
@@ -763,29 +542,10 @@ VOID LogSpewAlways(const char *fmt, ...);
#define STRESS_LOG_RESERVE_MEM(numChunks) do {} while (0)
#define STRESS_LOG_GC_STACK
-typedef void* CLR_MUTEX_ATTRIBUTES;
-typedef void* CLR_MUTEX_COOKIE;
-
-CLR_MUTEX_COOKIE ClrCreateMutex(CLR_MUTEX_ATTRIBUTES lpMutexAttributes, bool bInitialOwner, LPCWSTR lpName);
-void ClrCloseMutex(CLR_MUTEX_COOKIE mutex);
-bool ClrReleaseMutex(CLR_MUTEX_COOKIE mutex);
-uint32_t ClrWaitForMutex(CLR_MUTEX_COOKIE mutex, uint32_t dwMilliseconds, bool bAlertable);
-
-REDHAWK_PALIMPORT HANDLE REDHAWK_PALAPI PalCreateFileW(_In_z_ LPCWSTR pFileName, uint32_t desiredAccess, uint32_t shareMode, _In_opt_ void* pSecurityAttributes, uint32_t creationDisposition, uint32_t flagsAndAttributes, HANDLE hTemplateFile);
-
#define DEFAULT_GC_PRN_LVL 3
// -----------------------------------------------------------------------------------------------------------
-enum PalCapability
-{
- WriteWatchCapability = 0x00000001, // GetWriteWatch() and friends
- LowMemoryNotificationCapability = 0x00000002, // CreateMemoryResourceNotification() and friends
- GetCurrentProcessorNumberCapability = 0x00000004, // GetCurrentProcessorNumber()
-};
-
-REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalHasCapability(PalCapability capability);
-
void StompWriteBarrierEphemeral();
void StompWriteBarrierResize(bool bReqUpperBoundsCheck);
@@ -862,8 +622,8 @@ namespace GCStressPolicy
static volatile int32_t s_cGcStressDisables;
inline bool IsEnabled() { return s_cGcStressDisables == 0; }
- inline void GlobalDisable() { FastInterlockIncrement(&s_cGcStressDisables); }
- inline void GlobalEnable() { FastInterlockDecrement(&s_cGcStressDisables); }
+ inline void GlobalDisable() { Interlocked::Increment(&s_cGcStressDisables); }
+ inline void GlobalEnable() { Interlocked::Decrement(&s_cGcStressDisables); }
}
enum gcs_trigger_points
diff --git a/src/gc/env/gcenv.ee.h b/src/gc/env/gcenv.ee.h
new file mode 100644
index 0000000000..741337fbbf
--- /dev/null
+++ b/src/gc/env/gcenv.ee.h
@@ -0,0 +1,85 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+// Interface between the GC and EE
+//
+
+#ifndef __GCENV_EE_H__
+#define __GCENV_EE_H__
+
+struct ScanContext;
+class CrawlFrame;
+
+typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t);
+
+typedef void enum_alloc_context_func(alloc_context*, void*);
+
+typedef struct
+{
+ promote_func* f;
+ ScanContext* sc;
+ CrawlFrame * cf;
+} GCCONTEXT;
+
+
+class GCToEEInterface
+{
+public:
+ //
+ // Suspend/Resume callbacks
+ //
+ typedef enum
+ {
+ SUSPEND_FOR_GC = 1,
+ SUSPEND_FOR_GC_PREP = 6
+ } SUSPEND_REASON;
+
+ static void SuspendEE(SUSPEND_REASON reason);
+ static void RestartEE(bool bFinishedGC); //resume threads.
+
+ //
+ // The GC roots enumeration callback
+ //
+ static void GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc);
+
+ //
+ // Callbacks issues during GC that the execution engine can do its own bookeeping
+ //
+
+ // start of GC call back - single threaded
+ static void GcStartWork(int condemned, int max_gen);
+
+ //EE can perform post stack scanning action, while the
+ // user threads are still suspended
+ static void AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc);
+
+ // Called before BGC starts sweeping, the heap is walkable
+ static void GcBeforeBGCSweepWork();
+
+ // post-gc callback.
+ static void GcDone(int condemned);
+
+ // Promote refcounted handle callback
+ static bool RefCountedHandleCallbacks(Object * pObject);
+
+ // Sync block cache management
+ static void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2);
+ static void SyncBlockCacheDemote(int max_gen);
+ static void SyncBlockCachePromotionsGranted(int max_gen);
+
+ // Thread functions
+ static bool IsPreemptiveGCDisabled(Thread * pThread);
+ static void EnablePreemptiveGC(Thread * pThread);
+ static void DisablePreemptiveGC(Thread * pThread);
+
+ static void SetGCSpecial(Thread * pThread);
+ static alloc_context * GetAllocContext(Thread * pThread);
+ static bool CatchAtSafePoint(Thread * pThread);
+
+ static void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param);
+
+ static void AttachCurrentThread(); // does not acquire thread store lock
+};
+
+#endif // __GCENV_EE_H__
diff --git a/src/gc/env/gcenv.interlocked.h b/src/gc/env/gcenv.interlocked.h
new file mode 100644
index 0000000000..1d6cc8424f
--- /dev/null
+++ b/src/gc/env/gcenv.interlocked.h
@@ -0,0 +1,102 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+// Interlocked operations
+//
+
+#ifndef __GCENV_INTERLOCKED_H__
+#define __GCENV_INTERLOCKED_H__
+
+// Interlocked operations
+class Interlocked
+{
+public:
+
+ // Increment the value of the specified 32-bit variable as an atomic operation.
+ // Parameters:
+ // addend - variable to be incremented
+ // Return:
+ // The resulting incremented value
+ template<typename T>
+ static T Increment(T volatile *addend);
+
+ // Decrement the value of the specified 32-bit variable as an atomic operation.
+ // Parameters:
+ // addend - variable to be decremented
+ // Return:
+ // The resulting decremented value
+ template<typename T>
+ static T Decrement(T volatile *addend);
+
+ // Perform an atomic AND operation on the specified values values
+ // Parameters:
+ // destination - the first operand and the destination
+ // value - second operand
+ template<typename T>
+ static void And(T volatile *destination, T value);
+
+ // Perform an atomic OR operation on the specified values values
+ // Parameters:
+ // destination - the first operand and the destination
+ // value - second operand
+ template<typename T>
+ static void Or(T volatile *destination, T value);
+
+ // Set a 32-bit variable to the specified value as an atomic operation.
+ // Parameters:
+ // destination - value to be exchanged
+ // value - value to set the destination to
+ // Return:
+ // The previous value of the destination
+ template<typename T>
+ static T Exchange(T volatile *destination, T value);
+
+ // Set a pointer variable to the specified value as an atomic operation.
+ // Parameters:
+ // destination - value to be exchanged
+ // value - value to set the destination to
+ // Return:
+ // The previous value of the destination
+ template <typename T>
+ static T ExchangePointer(T volatile * destination, T value);
+
+ template <typename T>
+ static T ExchangePointer(T volatile * destination, std::nullptr_t value);
+
+ // Perform an atomic addition of two 32-bit values and return the original value of the addend.
+ // Parameters:
+ // addend - variable to be added to
+ // value - value to add
+ // Return:
+ // The previous value of the addend
+ template<typename T>
+ static T ExchangeAdd(T volatile *addend, T value);
+
+ // Performs an atomic compare-and-exchange operation on the specified values.
+ // Parameters:
+ // destination - value to be exchanged
+ // exchange - value to set the destination to
+ // comparand - value to compare the destination to before setting it to the exchange.
+ // The destination is set only if the destination is equal to the comparand.
+ // Return:
+ // The original value of the destination
+ template<typename T>
+ static T CompareExchange(T volatile *destination, T exchange, T comparand);
+
+ // Performs an atomic compare-and-exchange operation on the specified pointers.
+ // Parameters:
+ // destination - value to be exchanged
+ // exchange - value to set the destination to
+ // comparand - value to compare the destination to before setting it to the exchange.
+ // The destination is set only if the destination is equal to the comparand.
+ // Return:
+ // The original value of the destination
+ template <typename T>
+ static T CompareExchangePointer(T volatile *destination, T exchange, T comparand);
+
+ template <typename T>
+ static T CompareExchangePointer(T volatile *destination, T exchange, std::nullptr_t comparand);
+};
+
+#endif // __GCENV_INTERLOCKED_H__
diff --git a/src/gc/env/gcenv.interlocked.inl b/src/gc/env/gcenv.interlocked.inl
new file mode 100644
index 0000000000..62e171cadf
--- /dev/null
+++ b/src/gc/env/gcenv.interlocked.inl
@@ -0,0 +1,200 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+// __forceinline implementation of the Interlocked class methods
+//
+
+#ifndef __GCENV_INTERLOCKED_INL__
+#define __GCENV_INTERLOCKED_INL__
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif // _MSC_VER
+
+// Increment the value of the specified 32-bit variable as an atomic operation.
+// Parameters:
+// addend - variable to be incremented
+// Return:
+// The resulting incremented value
+template <typename T>
+__forceinline T Interlocked::Increment(T volatile *addend)
+{
+#ifdef _MSC_VER
+ static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
+ return _InterlockedIncrement((long*)addend);
+#else
+ return __sync_add_and_fetch(addend, 1);
+#endif
+}
+
+// Decrement the value of the specified 32-bit variable as an atomic operation.
+// Parameters:
+// addend - variable to be decremented
+// Return:
+// The resulting decremented value
+template <typename T>
+__forceinline T Interlocked::Decrement(T volatile *addend)
+{
+#ifdef _MSC_VER
+ static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
+ return _InterlockedDecrement((long*)addend);
+#else
+ return __sync_sub_and_fetch(addend, 1);
+#endif
+}
+
+// Set a 32-bit variable to the specified value as an atomic operation.
+// Parameters:
+// destination - value to be exchanged
+// value - value to set the destination to
+// Return:
+// The previous value of the destination
+template <typename T>
+__forceinline T Interlocked::Exchange(T volatile *destination, T value)
+{
+#ifdef _MSC_VER
+ static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
+ return _InterlockedExchange((long*)destination, value);
+#else
+ return __sync_swap(destination, value);
+#endif
+}
+
+// Performs an atomic compare-and-exchange operation on the specified values.
+// Parameters:
+// destination - value to be exchanged
+// exchange - value to set the destinaton to
+// comparand - value to compare the destination to before setting it to the exchange.
+// The destination is set only if the destination is equal to the comparand.
+// Return:
+// The original value of the destination
+template <typename T>
+__forceinline T Interlocked::CompareExchange(T volatile *destination, T exchange, T comparand)
+{
+#ifdef _MSC_VER
+ static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
+ return _InterlockedCompareExchange((long*)destination, exchange, comparand);
+#else
+ return __sync_val_compare_and_swap(destination, comparand, exchange);
+#endif
+}
+
+// Perform an atomic addition of two 32-bit values and return the original value of the addend.
+// Parameters:
+// addend - variable to be added to
+// value - value to add
+// Return:
+// The previous value of the addend
+template <typename T>
+__forceinline T Interlocked::ExchangeAdd(T volatile *addend, T value)
+{
+#ifdef _MSC_VER
+ static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
+ return _InterlockedExchangeAdd((long*)addend, value);
+#else
+ return __sync_fetch_and_add(addend, value);
+#endif
+}
+
+// Perform an atomic AND operation on the specified values values
+// Parameters:
+// destination - the first operand and the destination
+// value - second operand
+template <typename T>
+__forceinline void Interlocked::And(T volatile *destination, T value)
+{
+#ifdef _MSC_VER
+ static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
+ _InterlockedAnd((long*)destination, value);
+#else
+ __sync_and_and_fetch(destination, value);
+#endif
+}
+
+// Perform an atomic OR operation on the specified values values
+// Parameters:
+// destination - the first operand and the destination
+// value - second operand
+template <typename T>
+__forceinline void Interlocked::Or(T volatile *destination, T value)
+{
+#ifdef _MSC_VER
+ static_assert(sizeof(long) == sizeof(T), "Size of long must be the same as size of T");
+ _InterlockedOr((long*)destination, value);
+#else
+ __sync_or_and_fetch(destination, value);
+#endif
+}
+
+// Set a pointer variable to the specified value as an atomic operation.
+// Parameters:
+// destination - value to be exchanged
+// value - value to set the destination to
+// Return:
+// The previous value of the destination
+template <typename T>
+__forceinline T Interlocked::ExchangePointer(T volatile * destination, T value)
+{
+#ifdef _MSC_VER
+#ifdef BIT64
+ return (T)(TADDR)_InterlockedExchangePointer((void* volatile *)destination, value);
+#else
+ return (T)(TADDR)_InterlockedExchange((long volatile *)(void* volatile *)destination, (long)(void*)value);
+#endif
+#else
+ return (T)(TADDR)__sync_swap((void* volatile *)destination, value);
+#endif
+}
+
+template <typename T>
+__forceinline T Interlocked::ExchangePointer(T volatile * destination, std::nullptr_t value)
+{
+#ifdef _MSC_VER
+#ifdef BIT64
+ return (T)(TADDR)_InterlockedExchangePointer((void* volatile *)destination, value);
+#else
+ return (T)(TADDR)_InterlockedExchange((long volatile *)(void* volatile *)destination, (long)(void*)value);
+#endif
+#else
+ return (T)(TADDR)__sync_swap((void* volatile *)destination, value);
+#endif
+}
+
+// Performs an atomic compare-and-exchange operation on the specified pointers.
+// Parameters:
+// destination - value to be exchanged
+// exchange - value to set the destinaton to
+// comparand - value to compare the destination to before setting it to the exchange.
+// The destination is set only if the destination is equal to the comparand.
+// Return:
+// The original value of the destination
+template <typename T>
+__forceinline T Interlocked::CompareExchangePointer(T volatile *destination, T exchange, T comparand)
+{
+#ifdef _MSC_VER
+#ifdef BIT64
+ return (T)(TADDR)_InterlockedCompareExchangePointer((void* volatile *)destination, exchange, comparand);
+#else
+ return (T)(TADDR)_InterlockedCompareExchange((long volatile *)(void* volatile *)destination, (long)(void*)exchange, (long)(void*)comparand);
+#endif
+#else
+ return (T)(TADDR)__sync_val_compare_and_swap((void* volatile *)destination, comparand, exchange);
+#endif
+}
+
+template <typename T>
+__forceinline T Interlocked::CompareExchangePointer(T volatile *destination, T exchange, std::nullptr_t comparand)
+{
+#ifdef _MSC_VER
+#ifdef BIT64
+ return (T)(TADDR)_InterlockedCompareExchangePointer((void* volatile *)destination, exchange, comparand);
+#else
+ return (T)(TADDR)_InterlockedCompareExchange((long volatile *)(void* volatile *)destination, (long)(void*)exchange, (long)(void*)comparand);
+#endif
+#else
+ return (T)(TADDR)__sync_val_compare_and_swap((void* volatile *)destination, comparand, exchange);
+#endif
+}
+
+#endif // __GCENV_INTERLOCKED_INL__
diff --git a/src/gc/env/gcenv.object.h b/src/gc/env/gcenv.object.h
index 31dfe838dd..d3660173ce 100644
--- a/src/gc/env/gcenv.object.h
+++ b/src/gc/env/gcenv.object.h
@@ -26,8 +26,8 @@ private:
public:
uint32_t GetBits() { return m_uSyncBlockValue; }
- void SetBit(uint32_t uBit) { FastInterlockOr(&m_uSyncBlockValue, uBit); }
- void ClrBit(uint32_t uBit) { FastInterlockAnd(&m_uSyncBlockValue, ~uBit); }
+ void SetBit(uint32_t uBit) { Interlocked::Or(&m_uSyncBlockValue, uBit); }
+ void ClrBit(uint32_t uBit) { Interlocked::And(&m_uSyncBlockValue, ~uBit); }
void SetGCBit() { m_uSyncBlockValue |= BIT_SBLK_GC_RESERVE; }
void ClrGCBit() { m_uSyncBlockValue &= ~BIT_SBLK_GC_RESERVE; }
};
diff --git a/src/gc/env/gcenv.os.h b/src/gc/env/gcenv.os.h
new file mode 100644
index 0000000000..c1ae87a042
--- /dev/null
+++ b/src/gc/env/gcenv.os.h
@@ -0,0 +1,274 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+// Interface between GC and the OS specific functionality
+//
+
+#ifndef __GCENV_OS_H__
+#define __GCENV_OS_H__
+
+// Critical section used by the GC
+class CLRCriticalSection
+{
+ CRITICAL_SECTION m_cs;
+
+public:
+ // Initialize the critical section
+ void Initialize();
+
+ // Destroy the critical section
+ void Destroy();
+
+ // Enter the critical section. Blocks until the section can be entered.
+ void Enter();
+
+ // Leave the critical section
+ void Leave();
+};
+
+// Flags for the GCToOSInterface::VirtualReserve method
+struct VirtualReserveFlags
+{
+ enum
+ {
+ None = 0,
+ WriteWatch = 1,
+ };
+};
+
+// Affinity of a GC thread
+struct GCThreadAffinity
+{
+ static const int None = -1;
+
+ // Processor group index, None if no group is specified
+ int Group;
+ // Processor index, None if no affinity is specified
+ int Processor;
+};
+
+// GC thread function prototype
+typedef void (*GCThreadFunction)(void* param);
+
+// Interface that the GC uses to invoke OS specific functionality
+class GCToOSInterface
+{
+public:
+
+ //
+ // Initialization and shutdown of the interface
+ //
+
+ // Initialize the interface implementation
+ // Return:
+ // true if it has succeeded, false if it has failed
+ static bool Initialize();
+
+ // Shutdown the interface implementation
+ static void Shutdown();
+
+ //
+ // Virtual memory management
+ //
+
+ // Reserve virtual memory range.
+ // Parameters:
+ // address - starting virtual address, it can be NULL to let the function choose the starting address
+ // size - size of the virtual memory range
+ // alignment - requested memory alignment
+ // flags - flags to control special settings like write watching
+ // Return:
+ // Starting virtual address of the reserved range
+ static void* VirtualReserve(void *address, size_t size, size_t alignment, uint32_t flags);
+
+ // Release virtual memory range previously reserved using VirtualReserve
+ // Parameters:
+ // address - starting virtual address
+ // size - size of the virtual memory range
+ // Return:
+ // true if it has succeeded, false if it has failed
+ static bool VirtualRelease(void *address, size_t size);
+
+ // Commit virtual memory range. It must be part of a range reserved using VirtualReserve.
+ // Parameters:
+ // address - starting virtual address
+ // size - size of the virtual memory range
+ // Return:
+ // true if it has succeeded, false if it has failed
+ static bool VirtualCommit(void *address, size_t size);
+
+ // Decomit virtual memory range.
+ // Parameters:
+ // address - starting virtual address
+ // size - size of the virtual memory range
+ // Return:
+ // true if it has succeeded, false if it has failed
+ static bool VirtualDecommit(void *address, size_t size);
+
+ // Reset virtual memory range. Indicates that data in the memory range specified by address and size is no
+ // longer of interest, but it should not be decommitted.
+ // Parameters:
+ // address - starting virtual address
+ // size - size of the virtual memory range
+ // unlock - true if the memory range should also be unlocked
+ // Return:
+ // true if it has succeeded, false if it has failed
+ static bool VirtualReset(void *address, size_t size, bool unlock);
+
+ //
+ // Write watching
+ //
+
+ // Check if the OS supports write watching
+ static bool SupportsWriteWatch();
+
+ // Reset the write tracking state for the specified virtual memory range.
+ // Parameters:
+ // address - starting virtual address
+ // size - size of the virtual memory range
+ static void ResetWriteWatch(void *address, size_t size);
+
+ // Retrieve addresses of the pages that are written to in a region of virtual memory
+ // Parameters:
+ // resetState - true indicates to reset the write tracking state
+ // address - starting virtual address
+ // size - size of the virtual memory range
+ // pageAddresses - buffer that receives an array of page addresses in the memory region
+ // pageAddressesCount - on input, size of the lpAddresses array, in array elements
+ // on output, the number of page addresses that are returned in the array.
+ // Return:
+ // true if it has succeeded, false if it has failed
+ static bool GetWriteWatch(bool resetState, void* address, size_t size, void** pageAddresses, uintptr_t* pageAddressesCount);
+
+ //
+ // Thread and process
+ //
+
+ // Create a new thread
+ // Parameters:
+ // function - the function to be executed by the thread
+ // param - parameters of the thread
+ // affinity - processor affinity of the thread
+ // Return:
+ // true if it has succeeded, false if it has failed
+ static bool CreateThread(GCThreadFunction function, void* param, GCThreadAffinity* affinity);
+
+ // Causes the calling thread to sleep for the specified number of milliseconds
+ // Parameters:
+ // sleepMSec - time to sleep before switching to another thread
+ static void Sleep(uint32_t sleepMSec);
+
+ // Causes the calling thread to yield execution to another thread that is ready to run on the current processor.
+ // Parameters:
+ // switchCount - number of times the YieldThread was called in a loop
+ static void YieldThread(uint32_t switchCount);
+
+ // Get the number of the current processor
+ static uint32_t GetCurrentProcessorNumber();
+
+ // Check if the OS supports getting current processor number
+ static bool CanGetCurrentProcessorNumber();
+
+ // Set ideal processor for the current thread
+ // Parameters:
+ // processorIndex - index of the processor in the group
+ // affinity - ideal processor affinity for the thread
+ // Return:
+ // true if it has succeeded, false if it has failed
+ static bool SetCurrentThreadIdealAffinity(GCThreadAffinity* affinity);
+
+ // Get numeric id of the current thread if possible on the
+ // current platform. It is indended for logging purposes only.
+ // Return:
+ // Numeric id of the current thread or 0 if the
+ static uint32_t GetCurrentThreadIdForLogging();
+
+ // Get id of the current process
+ // Return:
+ // Id of the current process
+ static uint32_t GetCurrentProcessId();
+
+ //
+ // Processor topology
+ //
+
+ // Get number of logical processors
+ static uint32_t GetLogicalCpuCount();
+
+ // Get size of the largest cache on the processor die
+ // Parameters:
+ // trueSize - true to return true cache size, false to return scaled up size based on
+ // the processor architecture
+ // Return:
+ // Size of the cache
+ static size_t GetLargestOnDieCacheSize(bool trueSize = true);
+
+ // Get number of processors assigned to the current process
+ // Return:
+ // The number of processors
+ static uint32_t GetCurrentProcessCpuCount();
+
+ // Get affinity mask of the current process
+ // Parameters:
+ // processMask - affinity mask for the specified process
+ // systemMask - affinity mask for the system
+ // Return:
+ // true if it has succeeded, false if it has failed
+ // Remarks:
+ // A process affinity mask is a bit vector in which each bit represents the processors that
+ // a process is allowed to run on. A system affinity mask is a bit vector in which each bit
+ // represents the processors that are configured into a system.
+ // A process affinity mask is a subset of the system affinity mask. A process is only allowed
+ // to run on the processors configured into a system. Therefore, the process affinity mask cannot
+ // specify a 1 bit for a processor when the system affinity mask specifies a 0 bit for that processor.
+ static bool GetCurrentProcessAffinityMask(uintptr_t *processMask, uintptr_t *systemMask);
+
+ //
+ // Misc
+ //
+
+ // Get global memory status
+ // Parameters:
+ // ms - pointer to the structure that will be filled in with the memory status
+ static void GetMemoryStatus(GCMemoryStatus* ms);
+
+ // Flush write buffers of processors that are executing threads of the current process
+ static void FlushProcessWriteBuffers();
+
+ // Break into a debugger
+ static void DebugBreak();
+
+ //
+ // Time
+ //
+
+ // Get a high precision performance counter
+ // Return:
+ // The counter value
+ static int64_t QueryPerformanceCounter();
+
+ // Get a frequency of the high precision performance counter
+ // Return:
+ // The counter frequency
+ static int64_t QueryPerformanceFrequency();
+
+ // Get a time stamp with a low precision
+ // Return:
+ // Time stamp in milliseconds
+ static uint32_t GetLowPrecisionTimeStamp();
+
+ //
+ // File
+ //
+
+ // Open a file
+ // Parameters:
+ // filename - name of the file to open
+ // mode - mode to open the file in (like in the CRT fopen)
+ // Return:
+ // FILE* of the opened file
+ static FILE* OpenFile(const WCHAR* filename, const WCHAR* mode);
+};
+
+#endif // __GCENV_OS_H__
diff --git a/src/gc/env/gcenv.structs.h b/src/gc/env/gcenv.structs.h
index e3bfb17f56..7c576a5928 100644
--- a/src/gc/env/gcenv.structs.h
+++ b/src/gc/env/gcenv.structs.h
@@ -31,6 +31,62 @@ struct GCMemoryStatus
typedef void * HANDLE;
+#ifdef PLATFORM_UNIX
+
+class EEThreadId
+{
+ pthread_t m_id;
+ // Indicates whether the m_id is valid or not. pthread_t doesn't have any
+ // portable "invalid" value.
+ bool m_isValid;
+
+public:
+ bool IsCurrentThread()
+ {
+ return m_isValid && pthread_equal(m_id, pthread_self());
+ }
+
+ void SetToCurrentThread()
+ {
+ m_id = pthread_self();
+ m_isValid = true;
+ }
+
+ void Clear()
+ {
+ m_isValid = false;
+ }
+};
+
+#else // PLATFORM_UNIX
+
+#ifndef _INC_WINDOWS
+extern "C" uint32_t __stdcall GetCurrentThreadId();
+#endif
+
+class EEThreadId
+{
+ uint32_t m_uiId;
+public:
+
+ bool IsCurrentThread()
+ {
+ return m_uiId == ::GetCurrentThreadId();
+ }
+
+ void SetToCurrentThread()
+ {
+ m_uiId = ::GetCurrentThreadId();
+ }
+
+ void Clear()
+ {
+ m_uiId = 0;
+ }
+};
+
+#endif // PLATFORM_UNIX
+
#ifndef _INC_WINDOWS
typedef union _LARGE_INTEGER {
@@ -46,7 +102,13 @@ typedef union _LARGE_INTEGER {
int64_t QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
-#ifdef WIN32
+#ifdef PLATFORM_UNIX
+
+typedef struct _RTL_CRITICAL_SECTION {
+ pthread_mutex_t mutex;
+} CRITICAL_SECTION, RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
+
+#else
#pragma pack(push, 8)
@@ -67,12 +129,6 @@ typedef struct _RTL_CRITICAL_SECTION {
#pragma pack(pop)
-#else
-
-typedef struct _RTL_CRITICAL_SECTION {
- pthread_mutex_t mutex;
-} CRITICAL_SECTION, RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
-
#endif
#endif // _INC_WINDOWS
diff --git a/src/gc/env/gcenv.sync.h b/src/gc/env/gcenv.sync.h
index c3aea23fde..fe619cc696 100644
--- a/src/gc/env/gcenv.sync.h
+++ b/src/gc/env/gcenv.sync.h
@@ -7,19 +7,6 @@
//
// Helper classes expected by the GC
//
-class EEThreadId
-{
-public:
- EEThreadId(uint32_t uiId) : m_uiId(uiId) {}
- bool IsSameThread()
- {
- return m_uiId == GetCurrentThreadId();
- }
-
-private:
- uint32_t m_uiId;
-};
-
#define CRST_REENTRANCY 0
#define CRST_UNSAFE_SAMELEVEL 0
#define CRST_UNSAFE_ANYMODE 0
@@ -33,37 +20,37 @@ typedef int CrstType;
class CrstStatic
{
- CRITICAL_SECTION m_cs;
+ CLRCriticalSection m_cs;
#ifdef _DEBUG
- uint32_t m_holderThreadId;
+ EEThreadId m_holderThreadId;
#endif
public:
bool InitNoThrow(CrstType eType, CrstFlags eFlags = CRST_DEFAULT)
{
- UnsafeInitializeCriticalSection(&m_cs);
+ m_cs.Initialize();
return true;
}
void Destroy()
{
- UnsafeDeleteCriticalSection(&m_cs);
+ m_cs.Destroy();
}
void Enter()
{
- UnsafeEEEnterCriticalSection(&m_cs);
+ m_cs.Enter();
#ifdef _DEBUG
- m_holderThreadId = GetCurrentThreadId();
+ m_holderThreadId.SetToCurrentThread();
#endif
}
void Leave()
{
#ifdef _DEBUG
- m_holderThreadId = 0;
+ m_holderThreadId.Clear();
#endif
- UnsafeEELeaveCriticalSection(&m_cs);
+ m_cs.Leave();
}
#ifdef _DEBUG
@@ -74,7 +61,7 @@ public:
bool OwnedByCurrentThread()
{
- return GetHolderThreadId().IsSameThread();
+ return GetHolderThreadId().IsCurrentThread();
}
#endif
};
diff --git a/src/gc/env/gcenv.unix.cpp b/src/gc/env/gcenv.unix.cpp
deleted file mode 100644
index c9186d5d43..0000000000
--- a/src/gc/env/gcenv.unix.cpp
+++ /dev/null
@@ -1,569 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-//
-// Implementation of the GC environment
-//
-
-#include "common.h"
-
-#include "gcenv.h"
-#include "gc.h"
-
-#include <sys/mman.h>
-#include <sys/time.h>
-
-int32_t FastInterlockIncrement(int32_t volatile *lpAddend)
-{
- return __sync_add_and_fetch(lpAddend, 1);
-}
-
-int32_t FastInterlockDecrement(int32_t volatile *lpAddend)
-{
- return __sync_sub_and_fetch(lpAddend, 1);
-}
-
-int32_t FastInterlockExchange(int32_t volatile *Target, int32_t Value)
-{
- return __sync_swap(Target, Value);
-}
-
-int32_t FastInterlockCompareExchange(int32_t volatile *Destination, int32_t Exchange, int32_t Comperand)
-{
- return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
-}
-
-int32_t FastInterlockExchangeAdd(int32_t volatile *Addend, int32_t Value)
-{
- return __sync_fetch_and_add(Addend, Value);
-}
-
-void * _FastInterlockExchangePointer(void * volatile *Target, void * Value)
-{
- return __sync_swap(Target, Value);
-}
-
-void * _FastInterlockCompareExchangePointer(void * volatile *Destination, void * Exchange, void * Comperand)
-{
- return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
-}
-
-void FastInterlockOr(uint32_t volatile *p, uint32_t msk)
-{
- __sync_fetch_and_or(p, msk);
-}
-
-void FastInterlockAnd(uint32_t volatile *p, uint32_t msk)
-{
- __sync_fetch_and_and(p, msk);
-}
-
-
-void UnsafeInitializeCriticalSection(CRITICAL_SECTION * lpCriticalSection)
-{
- pthread_mutex_init(&lpCriticalSection->mutex, NULL);
-}
-
-void UnsafeEEEnterCriticalSection(CRITICAL_SECTION *lpCriticalSection)
-{
- pthread_mutex_lock(&lpCriticalSection->mutex);
-}
-
-void UnsafeEELeaveCriticalSection(CRITICAL_SECTION * lpCriticalSection)
-{
- pthread_mutex_unlock(&lpCriticalSection->mutex);
-}
-
-void UnsafeDeleteCriticalSection(CRITICAL_SECTION *lpCriticalSection)
-{
- pthread_mutex_destroy(&lpCriticalSection->mutex);
-}
-
-
-void GetProcessMemoryLoad(GCMemoryStatus* pGCMemStatus)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- pGCMemStatus->dwMemoryLoad = 0;
- pGCMemStatus->ullTotalPageFile = 0;
- pGCMemStatus->ullAvailPageFile = 0;
-
- // There is no API to get the total virtual address space size on
- // Unix, so we use a constant value representing 128TB, which is
- // the approximate size of total user virtual address space on
- // the currently supported Unix systems.
- static const uint64_t _128TB = (1ull << 47);
- pGCMemStatus->ullTotalVirtual = _128TB;
- pGCMemStatus->ullAvailVirtual = _128TB;
-
- // TODO: Implement
- pGCMemStatus->ullTotalPhys = _128TB;
- pGCMemStatus->ullAvailPhys = _128TB;
-
- // If the machine has more RAM than virtual address limit, let us cap it.
- // Our GC can never use more than virtual address limit.
- if (pGCMemStatus->ullAvailPhys > pGCMemStatus->ullTotalVirtual)
- {
- pGCMemStatus->ullAvailPhys = pGCMemStatus->ullAvailVirtual;
- }
-}
-
-void CLREventStatic::CreateManualEvent(bool bInitialState)
-{
- // TODO: Implement
- m_fInitialized = true;
-}
-
-void CLREventStatic::CreateAutoEvent(bool bInitialState)
-{
- // TODO: Implement
- m_fInitialized = true;
-}
-
-void CLREventStatic::CreateOSManualEvent(bool bInitialState)
-{
- CreateManualEvent(bInitialState);
-}
-
-void CLREventStatic::CreateOSAutoEvent (bool bInitialState)
-{
- CreateAutoEvent(bInitialState);
-}
-
-void CLREventStatic::CloseEvent()
-{
- if (m_fInitialized)
- {
- // TODO: Implement
- m_fInitialized = false;
- }
-}
-
-bool CLREventStatic::IsValid() const
-{
- return m_fInitialized;
-}
-
-bool CLREventStatic::Set()
-{
- if (!m_fInitialized)
- return false;
- // TODO: Implement
- return true;
-}
-
-bool CLREventStatic::Reset()
-{
- if (!m_fInitialized)
- return false;
- // TODO: Implement
- return true;
-}
-
-uint32_t CLREventStatic::Wait(uint32_t dwMilliseconds, bool bAlertable)
-{
- DWORD result = WAIT_FAILED;
-
- if (m_fInitialized)
- {
- bool disablePreemptive = false;
- Thread * pCurThread = GetThread();
-
- if (NULL != pCurThread)
- {
- if (pCurThread->PreemptiveGCDisabled())
- {
- pCurThread->EnablePreemptiveGC();
- disablePreemptive = true;
- }
- }
-
- // TODO: Implement
- result = WAIT_OBJECT_0;
-
- if (disablePreemptive)
- {
- pCurThread->DisablePreemptiveGC();
- }
- }
-
- return result;
-}
-
-bool __SwitchToThread(uint32_t dwSleepMSec, uint32_t dwSwitchCount)
-{
- return sched_yield() == 0;
-}
-
-void * ClrVirtualAlloc(
- void * lpAddress,
- size_t dwSize,
- uint32_t flAllocationType,
- uint32_t flProtect)
-{
- return ClrVirtualAllocAligned(lpAddress, dwSize, flAllocationType, flProtect, OS_PAGE_SIZE);
-}
-
-static int W32toUnixAccessControl(uint32_t flProtect)
-{
- int prot = 0;
-
- switch (flProtect & 0xff)
- {
- case PAGE_NOACCESS:
- prot = PROT_NONE;
- break;
- case PAGE_READWRITE:
- prot = PROT_READ | PROT_WRITE;
- break;
- default:
- _ASSERTE(false);
- break;
- }
- return prot;
-}
-
-void * ClrVirtualAllocAligned(
- void * lpAddress,
- size_t dwSize,
- uint32_t flAllocationType,
- uint32_t flProtect,
- size_t dwAlignment)
-{
- if ((flAllocationType & ~(MEM_RESERVE | MEM_COMMIT)) != 0)
- {
- // TODO: Implement
- return NULL;
- }
-
- _ASSERTE(((size_t)lpAddress & (OS_PAGE_SIZE - 1)) == 0);
-
- // Align size to whole pages
- dwSize = (dwSize + (OS_PAGE_SIZE - 1)) & ~(OS_PAGE_SIZE - 1);
-
- if (flAllocationType & MEM_RESERVE)
- {
- size_t alignedSize = dwSize;
-
- if (dwAlignment > OS_PAGE_SIZE)
- alignedSize += (dwAlignment - OS_PAGE_SIZE);
-
- void * pRetVal = mmap(lpAddress, alignedSize, W32toUnixAccessControl(flProtect),
- MAP_ANON | MAP_PRIVATE, -1, 0);
-
- if (dwAlignment > OS_PAGE_SIZE && pRetVal != NULL)
- {
- void * pAlignedRetVal = (void *)(((size_t)pRetVal + (dwAlignment - 1)) & ~(dwAlignment - 1));
-
- size_t startPadding = (size_t)pAlignedRetVal - (size_t)pRetVal;
- if (startPadding != 0)
- {
- int ret = munmap(pRetVal, startPadding);
- _ASSERTE(ret == 0);
- }
-
- size_t endPadding = alignedSize - (startPadding + dwSize);
- if (endPadding != 0)
- {
- int ret = munmap((void *)((size_t)pAlignedRetVal + dwSize), endPadding);
- _ASSERTE(ret == 0);
- }
-
- pRetVal = pAlignedRetVal;
- }
-
- return pRetVal;
- }
-
- if (flAllocationType & MEM_COMMIT)
- {
- int ret = mprotect(lpAddress, dwSize, W32toUnixAccessControl(flProtect));
- return (ret == 0) ? lpAddress : NULL;
- }
-
- return NULL;
-}
-
-bool ClrVirtualFree(
- void * lpAddress,
- size_t dwSize,
- uint32_t dwFreeType)
-{
- // TODO: Implement
- return false;
-}
-
-bool
-ClrVirtualProtect(
- void * lpAddress,
- size_t dwSize,
- uint32_t flNewProtect,
- uint32_t * lpflOldProtect)
-{
- // TODO: Implement, not currently used
- return false;
-}
-
-MethodTable * g_pFreeObjectMethodTable;
-
-GCSystemInfo g_SystemInfo;
-
-void InitializeSystemInfo()
-{
- // TODO: Implement
- g_SystemInfo.dwNumberOfProcessors = 4;
-
- g_SystemInfo.dwPageSize = OS_PAGE_SIZE;
- g_SystemInfo.dwAllocationGranularity = OS_PAGE_SIZE;
-}
-
-int32_t g_TrapReturningThreads;
-
-bool g_fFinalizerRunOnShutDown;
-
-#ifdef _MSC_VER
-__declspec(thread)
-#else
-__thread
-#endif
-Thread * pCurrentThread;
-
-Thread * GetThread()
-{
- return pCurrentThread;
-}
-
-Thread * g_pThreadList = NULL;
-
-Thread * ThreadStore::GetThreadList(Thread * pThread)
-{
- if (pThread == NULL)
- return g_pThreadList;
-
- return pThread->m_pNext;
-}
-
-void ThreadStore::AttachCurrentThread(bool fAcquireThreadStoreLock)
-{
- // TODO: Locks
-
- Thread * pThread = new Thread();
- pThread->GetAllocContext()->init();
- pCurrentThread = pThread;
-
- pThread->m_pNext = g_pThreadList;
- g_pThreadList = pThread;
-}
-
-void DestroyThread(Thread * pThread)
-{
- // TODO: Implement
-}
-
-void FinalizerThread::EnableFinalization()
-{
- // Signal to finalizer thread that there are objects to finalize
- // TODO: Implement for finalization
-}
-
-bool PalHasCapability(PalCapability capability)
-{
- // TODO: Implement for background GC
- return false;
-}
-
-WINBASEAPI
-UINT
-WINAPI
-GetWriteWatch(
- DWORD dwFlags,
- PVOID lpBaseAddress,
- SIZE_T dwRegionSize,
- PVOID *lpAddresses,
- uintptr_t * lpdwCount,
- uint32_t * lpdwGranularity
- )
-{
- // TODO: Implement for background GC
- *lpAddresses = NULL;
- *lpdwCount = 0;
- // Until it is implemented, return non-zero value as an indicator of failure
- return 1;
-}
-
-WINBASEAPI
-UINT
-WINAPI
-ResetWriteWatch(
- LPVOID lpBaseAddress,
- SIZE_T dwRegionSize
- )
-{
- // TODO: Implement for background GC
- // Until it is implemented, return non-zero value as an indicator of failure
- return 1;
-}
-
-WINBASEAPI
-BOOL
-WINAPI
-VirtualUnlock(
- LPVOID lpAddress,
- SIZE_T dwSize
- )
-{
- // TODO: Implement
- return false;
-}
-
-
-WINBASEAPI
-VOID
-WINAPI
-FlushProcessWriteBuffers()
-{
- // TODO: Implement
-}
-
-const int tccSecondsToMillieSeconds = 1000;
-const int tccSecondsToMicroSeconds = 1000000;
-const int tccMillieSecondsToMicroSeconds = 1000; // 10^3
-
-WINBASEAPI
-DWORD
-WINAPI
-GetTickCount()
-{
- // TODO: More efficient, platform-specific implementation
- struct timeval tv;
- if (gettimeofday(&tv, NULL) == -1)
- {
- _ASSERTE(!"gettimeofday() failed");
- return 0;
- }
- return (tv.tv_sec * tccSecondsToMillieSeconds) + (tv.tv_usec / tccMillieSecondsToMicroSeconds);
-}
-
-WINBASEAPI
-BOOL
-WINAPI
-QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)
-{
- // TODO: More efficient, platform-specific implementation
- struct timeval tv;
- if (gettimeofday(&tv, NULL) == -1)
- {
- _ASSERTE(!"gettimeofday() failed");
- return FALSE;
- }
- lpPerformanceCount->QuadPart =
- (int64_t) tv.tv_sec * (int64_t) tccSecondsToMicroSeconds + (int64_t) tv.tv_usec;
- return TRUE;
-}
-
-WINBASEAPI
-BOOL
-WINAPI
-QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)
-{
- lpFrequency->QuadPart = (int64_t) tccSecondsToMicroSeconds;
- return TRUE;
-}
-
-WINBASEAPI
-DWORD
-WINAPI
-GetCurrentThreadId(
- VOID)
-{
- // TODO: Implement
- return 1;
-}
-
-WINBASEAPI
-VOID
-WINAPI
-YieldProcessor()
-{
- // TODO: Implement
-}
-
-WINBASEAPI
-void
-WINAPI
-DebugBreak()
-{
- // TODO: Implement
-}
-
-WINBASEAPI
-VOID
-WINAPI
-MemoryBarrier()
-{
- // TODO: Implement
-}
-
-// File I/O - Used for tracking only
-
-WINBASEAPI
-DWORD
-WINAPI
-SetFilePointer(
- HANDLE hFile,
- int32_t lDistanceToMove,
- int32_t * lpDistanceToMoveHigh,
- DWORD dwMoveMethod)
-{
- // TODO: Reimplement callers using CRT
- return 0;
-}
-
-WINBASEAPI
-BOOL
-WINAPI
-FlushFileBuffers(
- HANDLE hFile)
-{
- // TODO: Reimplement callers using CRT
- return FALSE;
-}
-
-WINBASEAPI
-BOOL
-WINAPI
-WriteFile(
- HANDLE hFile,
- LPCVOID lpBuffer,
- DWORD nNumberOfBytesToWrite,
- DWORD * lpNumberOfBytesWritten,
- PVOID lpOverlapped)
-{
- // TODO: Reimplement callers using CRT
- return FALSE;
-}
-
-WINBASEAPI
-BOOL
-WINAPI
-CloseHandle(
- HANDLE hObject)
-{
- // TODO: Reimplement callers using CRT
- return FALSE;
-}
-
-WINBASEAPI
-DWORD
-WINAPI
-GetLastError()
-{
- return 1;
-}
diff --git a/src/gc/env/gcenv.windows.cpp b/src/gc/env/gcenv.windows.cpp
deleted file mode 100644
index 1059e5e6a2..0000000000
--- a/src/gc/env/gcenv.windows.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-//
-// Implementation of the GC environment
-//
-
-#include "common.h"
-
-#include "windows.h"
-
-#include "gcenv.h"
-#include "gc.h"
-
-int32_t FastInterlockIncrement(int32_t volatile *lpAddend)
-{
- return InterlockedIncrement((LONG *)lpAddend);
-}
-
-int32_t FastInterlockDecrement(int32_t volatile *lpAddend)
-{
- return InterlockedDecrement((LONG *)lpAddend);
-}
-
-int32_t FastInterlockExchange(int32_t volatile *Target, int32_t Value)
-{
- return InterlockedExchange((LONG *)Target, Value);
-}
-
-int32_t FastInterlockCompareExchange(int32_t volatile *Destination, int32_t Exchange, int32_t Comperand)
-{
- return InterlockedCompareExchange((LONG *)Destination, Exchange, Comperand);
-}
-
-int32_t FastInterlockExchangeAdd(int32_t volatile *Addend, int32_t Value)
-{
- return InterlockedExchangeAdd((LONG *)Addend, Value);
-}
-
-void * _FastInterlockExchangePointer(void * volatile *Target, void * Value)
-{
- return InterlockedExchangePointer(Target, Value);
-}
-
-void * _FastInterlockCompareExchangePointer(void * volatile *Destination, void * Exchange, void * Comperand)
-{
- return InterlockedCompareExchangePointer(Destination, Exchange, Comperand);
-}
-
-void FastInterlockOr(uint32_t volatile *p, uint32_t msk)
-{
- InterlockedOr((LONG volatile *)p, msk);
-}
-
-void FastInterlockAnd(uint32_t volatile *p, uint32_t msk)
-{
- InterlockedAnd((LONG volatile *)p, msk);
-}
-
-
-void UnsafeInitializeCriticalSection(CRITICAL_SECTION * lpCriticalSection)
-{
- InitializeCriticalSection(lpCriticalSection);
-}
-
-void UnsafeEEEnterCriticalSection(CRITICAL_SECTION *lpCriticalSection)
-{
- EnterCriticalSection(lpCriticalSection);
-}
-
-void UnsafeEELeaveCriticalSection(CRITICAL_SECTION * lpCriticalSection)
-{
- LeaveCriticalSection(lpCriticalSection);
-}
-
-void UnsafeDeleteCriticalSection(CRITICAL_SECTION *lpCriticalSection)
-{
- DeleteCriticalSection(lpCriticalSection);
-}
-
-
-void GetProcessMemoryLoad(GCMemoryStatus* pGCMemStatus)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- MEMORYSTATUSEX memStatus;
-
- memStatus.dwLength = sizeof(MEMORYSTATUSEX);
- BOOL fRet = GlobalMemoryStatusEx(&memStatus);
- _ASSERTE (fRet);
-
- // If the machine has more RAM than virtual address limit, let us cap it.
- // Our GC can never use more than virtual address limit.
- if (memStatus.ullAvailPhys > memStatus.ullTotalVirtual)
- {
- memStatus.ullAvailPhys = memStatus.ullAvailVirtual;
- }
-
- // Convert Windows struct to abstract struct
- pGCMemStatus->dwMemoryLoad = memStatus.dwMemoryLoad ;
- pGCMemStatus->ullTotalPhys = memStatus.ullTotalPhys ;
- pGCMemStatus->ullAvailPhys = memStatus.ullAvailPhys ;
- pGCMemStatus->ullTotalPageFile = memStatus.ullTotalPageFile ;
- pGCMemStatus->ullAvailPageFile = memStatus.ullAvailPageFile ;
- pGCMemStatus->ullTotalVirtual = memStatus.ullTotalVirtual ;
- pGCMemStatus->ullAvailVirtual = memStatus.ullAvailVirtual ;
-}
-
-void CLREventStatic::CreateManualEvent(bool bInitialState)
-{
- m_hEvent = CreateEventW(NULL, TRUE, bInitialState, NULL);
- m_fInitialized = true;
-}
-
-void CLREventStatic::CreateAutoEvent(bool bInitialState)
-{
- m_hEvent = CreateEventW(NULL, FALSE, bInitialState, NULL);
- m_fInitialized = true;
-}
-
-void CLREventStatic::CreateOSManualEvent(bool bInitialState)
-{
- m_hEvent = CreateEventW(NULL, TRUE, bInitialState, NULL);
- m_fInitialized = true;
-}
-
-void CLREventStatic::CreateOSAutoEvent(bool bInitialState)
-{
- m_hEvent = CreateEventW(NULL, FALSE, bInitialState, NULL);
- m_fInitialized = true;
-}
-
-void CLREventStatic::CloseEvent()
-{
- if (m_fInitialized && m_hEvent != INVALID_HANDLE_VALUE)
- {
- CloseHandle(m_hEvent);
- m_hEvent = INVALID_HANDLE_VALUE;
- }
-}
-
-bool CLREventStatic::IsValid() const
-{
- return m_fInitialized && m_hEvent != INVALID_HANDLE_VALUE;
-}
-
-bool CLREventStatic::Set()
-{
- if (!m_fInitialized)
- return false;
- return !!SetEvent(m_hEvent);
-}
-
-bool CLREventStatic::Reset()
-{
- if (!m_fInitialized)
- return false;
- return !!ResetEvent(m_hEvent);
-}
-
-uint32_t CLREventStatic::Wait(uint32_t dwMilliseconds, bool bAlertable)
-{
- DWORD result = WAIT_FAILED;
-
- if (m_fInitialized)
- {
- bool disablePreemptive = false;
- Thread * pCurThread = GetThread();
-
- if (NULL != pCurThread)
- {
- if (pCurThread->PreemptiveGCDisabled())
- {
- pCurThread->EnablePreemptiveGC();
- disablePreemptive = true;
- }
- }
-
- result = WaitForSingleObjectEx(m_hEvent, dwMilliseconds, bAlertable);
-
- if (disablePreemptive)
- {
- pCurThread->DisablePreemptiveGC();
- }
- }
-
- return result;
-}
-
-bool __SwitchToThread(uint32_t dwSleepMSec, uint32_t dwSwitchCount)
-{
- SwitchToThread();
- return true;
-}
-
-void * ClrVirtualAlloc(
- void * lpAddress,
- size_t dwSize,
- uint32_t flAllocationType,
- uint32_t flProtect)
-{
- return VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
-}
-
-void * ClrVirtualAllocAligned(
- void * lpAddress,
- size_t dwSize,
- uint32_t flAllocationType,
- uint32_t flProtect,
- size_t dwAlignment)
-{
- return VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
-}
-
-bool ClrVirtualFree(
- void * lpAddress,
- size_t dwSize,
- uint32_t dwFreeType)
-{
- return !!VirtualFree(lpAddress, dwSize, dwFreeType);
-}
-
-bool
-ClrVirtualProtect(
- void * lpAddress,
- size_t dwSize,
- uint32_t flNewProtect,
- uint32_t * lpflOldProtect)
-{
- return !!VirtualProtect(lpAddress, dwSize, flNewProtect, (DWORD *)lpflOldProtect);
-}
-
-MethodTable * g_pFreeObjectMethodTable;
-
-GCSystemInfo g_SystemInfo;
-
-void InitializeSystemInfo()
-{
- SYSTEM_INFO systemInfo;
- GetSystemInfo(&systemInfo);
-
- g_SystemInfo.dwNumberOfProcessors = systemInfo.dwNumberOfProcessors;
- g_SystemInfo.dwPageSize = systemInfo.dwPageSize;
- g_SystemInfo.dwAllocationGranularity = systemInfo.dwAllocationGranularity;
-}
-
-int32_t g_TrapReturningThreads;
-
-bool g_fFinalizerRunOnShutDown;
-
-void DestroyThread(Thread * pThread)
-{
- // TODO: Implement
-}
-
-bool PalHasCapability(PalCapability capability)
-{
- // TODO: Implement for background GC
- return false;
-}
-