#define FEATURE_REDHAWK 1
#define FEATURE_CONSERVATIVE_GC 1
+#define GCENV_INCLUDED
+
#ifndef _MSC_VER
#define __stdcall
#define __forceinline inline
#define CALLER_LIMITS_SPINNING 0
bool __SwitchToThread (uint32_t dwSleepMSec, uint32_t dwSwitchCount);
-//-------------------------------------------------------------------------------------------------
-//
-// Low-level types describing GC object layouts.
-//
-
-// Bits stolen from the sync block index that the GC/HandleTable knows about (currently these are at the same
-// positions as the mainline runtime but we can change this below when it becomes apparent how Redhawk will
-// handle sync blocks).
-#define BIT_SBLK_GC_RESERVE 0x20000000
-#define BIT_SBLK_FINALIZER_RUN 0x40000000
-
-// The sync block index header (small structure that immediately precedes every object in the GC heap). Only
-// the GC uses this so far, and only to store a couple of bits of information.
-class ObjHeader
-{
-private:
-#if defined(_WIN64)
- uint32_t m_uAlignpad;
-#endif // _WIN64
- uint32_t m_uSyncBlockValue;
-
-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 SetGCBit() { m_uSyncBlockValue |= BIT_SBLK_GC_RESERVE; }
- void ClrGCBit() { m_uSyncBlockValue &= ~BIT_SBLK_GC_RESERVE; }
-};
-
-#define MTFlag_ContainsPointers 1
-#define MTFlag_HasFinalizer 2
-
-class MethodTable
-{
-public:
- uint32_t m_baseSize;
- uint16_t m_componentSize;
- uint16_t m_flags;
-
-public:
- void InitializeFreeObject()
- {
- m_baseSize = 3 * sizeof(void *);
- m_componentSize = 1;
- m_flags = 0;
- }
-
- uint32_t GetBaseSize()
- {
- return m_baseSize;
- }
-
- uint16_t RawGetComponentSize()
- {
- return m_componentSize;
- }
-
- bool ContainsPointers()
- {
- return (m_flags & MTFlag_ContainsPointers) != 0;
- }
-
- bool ContainsPointersOrCollectible()
- {
- return ContainsPointers();
- }
-
- bool HasComponentSize()
- {
- return m_componentSize != 0;
- }
-
- bool HasFinalizer()
- {
- return (m_flags & MTFlag_HasFinalizer) != 0;
- }
-
- bool HasCriticalFinalizer()
- {
- return false;
- }
-
- bool SanityCheck()
- {
- return true;
- }
-};
-#define EEType MethodTable
-
-class Object
-{
- MethodTable * m_pMethTab;
-
-public:
- ObjHeader * GetHeader()
- {
- return ((ObjHeader *)this) - 1;
- }
-
- MethodTable * RawGetMethodTable() const
- {
- return m_pMethTab;
- }
-
- void RawSetMethodTable(MethodTable * pMT)
- {
- m_pMethTab = pMT;
- }
-
- void SetMethodTable(MethodTable * pMT)
- {
- m_pMethTab = pMT;
- }
-};
-#define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader))
-
-class ArrayBase : public Object
-{
- DWORD m_dwLength;
-
-public:
- DWORD GetNumComponents()
- {
- return m_dwLength;
- }
-
- static SIZE_T GetOffsetOfNumComponents()
- {
- return offsetof(ArrayBase, m_dwLength);
- }
-};
+class ObjHeader;
+class MethodTable;
+class Object;
+class ArrayBase;
// Various types used to refer to object references or handles. This will get more complex if we decide
// Redhawk wants to wrap object references in the debug build.
//
struct alloc_context;
-
-class Thread
-{
- uint32_t m_fPreemptiveGCDisabled;
- uintptr_t m_alloc_context[16]; // Reserve enough space to fix allocation context
-
- friend class ThreadStore;
- Thread * m_pNext;
-
-public:
- Thread()
- {
- }
-
- bool PreemptiveGCDisabled()
- {
- return !!m_fPreemptiveGCDisabled;
- }
-
- void EnablePreemptiveGC()
- {
- m_fPreemptiveGCDisabled = false;
- }
-
- void DisablePreemptiveGC()
- {
- m_fPreemptiveGCDisabled = true;
- }
-
- alloc_context* GetAllocContext()
- {
- return (alloc_context *)&m_alloc_context;
- }
-
- void SetGCSpecial(bool fGCSpecial)
- {
- }
-
- bool CatchAtSafePoint()
- {
- // This is only called by the GC on a background GC worker thread that's explicitly interested in letting
- // a foreground GC proceed at that point. So it's always safe to return true.
- return true;
- }
-};
+class Thread;
Thread * GetThread();
-class ThreadStore
-{
-public:
- static Thread * GetThreadList(Thread * pThread);
-
- static void AttachCurrentThread(bool fAcquireThreadStoreLock);
-};
-
struct ScanContext;
typedef void promote_func(PTR_PTR_Object, ScanContext*, unsigned);
// 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, LPARAM lp1, LPARAM 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);
+
+ // ThreadStore functions
+ static void AttachCurrentThread(); // does not acquire thread store lock
+ static Thread * GetThreadList(Thread * pThread);
};
class FinalizerThread
{
public:
+ static bool Initialize();
static void EnableFinalization();
- static bool HaveExtraWorkForFinalizer()
- {
- return false;
- }
+ static bool HaveExtraWorkForFinalizer();
+
+ static bool IsCurrentThreadFinalizer();
+ static void Wait(DWORD timeout, bool allowReentrantWait = false);
+ static bool WatchDog();
+ static void SignalFinalizationDone(bool fFinalizer);
+ static void SetFinalizerThread(Thread * pThread);
};
typedef uint32_t (__stdcall *BackgroundCallback)(void* pCallbackContext);
{
}
-// -----------------------------------------------------------------------------------------------------------
-// Config file enumulation
-//
-
-class EEConfig
-{
-public:
- enum HeapVerifyFlags {
- HEAPVERIFY_NONE = 0,
- HEAPVERIFY_GC = 1, // Verify the heap at beginning and end of GC
- HEAPVERIFY_BARRIERCHECK = 2, // Verify the brick table
- HEAPVERIFY_SYNCBLK = 4, // Verify sync block scanning
-
- // the following options can be used to mitigate some of the overhead introduced
- // by heap verification. some options might cause heap verifiction to be less
- // effective depending on the scenario.
-
- HEAPVERIFY_NO_RANGE_CHECKS = 0x10, // Excludes checking if an OBJECTREF is within the bounds of the managed heap
- HEAPVERIFY_NO_MEM_FILL = 0x20, // Excludes filling unused segment portions with fill pattern
- HEAPVERIFY_POST_GC_ONLY = 0x40, // Performs heap verification post-GCs only (instead of before and after each GC)
- HEAPVERIFY_DEEP_ON_COMPACT = 0x80 // Performs deep object verfication only on compacting GCs.
- };
-
- enum GCStressFlags {
- GCSTRESS_NONE = 0,
- GCSTRESS_ALLOC = 1, // GC on all allocs and 'easy' places
- GCSTRESS_TRANSITION = 2, // GC on transitions to preemtive GC
- GCSTRESS_INSTR_JIT = 4, // GC on every allowable JITed instr
- GCSTRESS_INSTR_NGEN = 8, // GC on every allowable NGEN instr
- GCSTRESS_UNIQUE = 16, // GC only on a unique stack trace
- };
-
- int GetHeapVerifyLevel() { return 0; }
- bool IsHeapVerifyEnabled() { return GetHeapVerifyLevel() != 0; }
-
- GCStressFlags GetGCStressLevel() const { return GCSTRESS_NONE; }
- bool IsGCStressMix() const { return false; }
-
- int GetGCtraceStart() const { return 0; }
- int GetGCtraceEnd () const { return 0; }//1000000000; }
- int GetGCtraceFac () const { return 0; }
- int GetGCprnLvl () const { return 0; }
- bool IsGCBreakOnOOMEnabled() const { return false; }
- int GetGCgen0size () const { return 0; }
- int GetSegmentSize () const { return 0; }
- int GetGCconcurrent() const { return 1; }
- int GetGCLatencyMode() const { return 1; }
- int GetGCForceCompact() const { return 0; }
- int GetGCRetainVM () const { return 0; }
- int GetGCTrimCommit() const { return 0; }
- int GetGCLOHCompactionMode() const { return 0; }
-
- bool GetGCAllowVeryLargeObjects () const { return false; }
-
- bool GetGCConservative() const { return true; }
-};
-
-extern EEConfig * g_pConfig;
-
class CLRConfig
{
public:
}
};
-
-// -----------------------------------------------------------------------------------------------------------
-//
-// Helper classes expected by the GC
-//
-
-class EEThreadId
-{
-public:
- EEThreadId(UINT32 uiId) : m_uiId(uiId) {}
- bool IsSameThread()
- {
- return m_uiId == GetCurrentThreadId();
- }
-
-private:
- UINT32 m_uiId;
-};
-
-#define CRST_REENTRANCY 0
-#define CRST_UNSAFE_SAMELEVEL 0
-#define CRST_UNSAFE_ANYMODE 0
-#define CRST_DEBUGGER_THREAD 0
-#define CRST_DEFAULT 0
-
-#define CrstHandleTable 0
-
-typedef int CrstFlags;
-typedef int CrstType;
-
-class CrstStatic
-{
- CRITICAL_SECTION m_cs;
-#ifdef _DEBUG
- UINT32 m_holderThreadId;
-#endif
-
-public:
- bool InitNoThrow(CrstType eType, CrstFlags eFlags = CRST_DEFAULT)
- {
- UnsafeInitializeCriticalSection(&m_cs);
- return true;
- }
-
- void Destroy()
- {
- UnsafeDeleteCriticalSection(&m_cs);
- }
-
- void Enter()
- {
- UnsafeEEEnterCriticalSection(&m_cs);
-#ifdef _DEBUG
- m_holderThreadId = GetCurrentThreadId();
-#endif
- }
-
- void Leave()
- {
-#ifdef _DEBUG
- m_holderThreadId = 0;
-#endif
- UnsafeEELeaveCriticalSection(&m_cs);
- }
-
-#ifdef _DEBUG
- EEThreadId GetHolderThreadId()
- {
- return m_holderThreadId;
- }
-
- bool OwnedByCurrentThread()
- {
- return GetHolderThreadId().IsSameThread();
- }
-#endif
-};
-
-class CLREventStatic
-{
-public:
- void CreateManualEvent(bool bInitialState);
- void CreateAutoEvent(bool bInitialState);
- void CreateOSManualEvent(bool bInitialState);
- void CreateOSAutoEvent(bool bInitialState);
- void CloseEvent();
- bool IsValid() const;
- bool Set();
- bool Reset();
- uint32_t Wait(uint32_t dwMilliseconds, bool bAlertable);
-
-private:
- HANDLE m_hEvent;
- bool m_fInitialized;
-};
-
-class CrstHolder
-{
- CrstStatic * m_pLock;
-
-public:
- CrstHolder(CrstStatic * pLock)
- : m_pLock(pLock)
- {
- m_pLock->Enter();
- }
-
- ~CrstHolder()
- {
- m_pLock->Leave();
- }
-};
-
-class CrstHolderWithState
-{
- CrstStatic * m_pLock;
- bool m_fAcquired;
-
-public:
- CrstHolderWithState(CrstStatic * pLock, bool fAcquire = true)
- : m_pLock(pLock), m_fAcquired(fAcquire)
- {
- if (fAcquire)
- m_pLock->Enter();
- }
-
- ~CrstHolderWithState()
- {
- if (m_fAcquired)
- m_pLock->Leave();
- }
-
- void Acquire()
- {
- if (!m_fAcquired)
- {
- m_pLock->Enter();
- m_fAcquired = true;
- }
- }
-
- void Release()
- {
- if (m_fAcquired)
- {
- m_pLock->Leave();
- m_fAcquired = false;
- }
- }
-
- CrstStatic * GetValue()
- {
- return m_pLock;
- }
-};
-
-
template <typename TYPE>
class NewHolder
{
AppDomain *DefaultDomain() { return NULL; }
DWORD GetTotalNumSizedRefHandles() { return 0; }
};
+
+#ifdef STRESS_HEAP
+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); }
+}
+
+enum gcs_trigger_points
+{
+ cfg_any,
+};
+
+template <enum gcs_trigger_points tp>
+class GCStress
+{
+public:
+ static inline bool IsEnabled()
+ {
+ return g_pConfig->GetGCStressLevel() != 0;
+ }
+};
+#endif // STRESS_HEAP
+
--- /dev/null
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//-------------------------------------------------------------------------------------------------
+//
+// Low-level types describing GC object layouts.
+//
+
+// Bits stolen from the sync block index that the GC/HandleTable knows about (currently these are at the same
+// positions as the mainline runtime but we can change this below when it becomes apparent how Redhawk will
+// handle sync blocks).
+#define BIT_SBLK_GC_RESERVE 0x20000000
+#define BIT_SBLK_FINALIZER_RUN 0x40000000
+
+// The sync block index header (small structure that immediately precedes every object in the GC heap). Only
+// the GC uses this so far, and only to store a couple of bits of information.
+class ObjHeader
+{
+private:
+#if defined(_WIN64)
+ uint32_t m_uAlignpad;
+#endif // _WIN64
+ uint32_t m_uSyncBlockValue;
+
+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 SetGCBit() { m_uSyncBlockValue |= BIT_SBLK_GC_RESERVE; }
+ void ClrGCBit() { m_uSyncBlockValue &= ~BIT_SBLK_GC_RESERVE; }
+};
+
+#define MTFlag_ContainsPointers 1
+#define MTFlag_HasFinalizer 2
+#define MTFlag_IsArray 4
+
+class MethodTable
+{
+public:
+ uint16_t m_componentSize;
+ uint16_t m_flags;
+ uint32_t m_baseSize;
+
+ MethodTable * m_pRelatedType;
+
+public:
+ void InitializeFreeObject()
+ {
+ m_baseSize = 3 * sizeof(void *);
+ m_componentSize = 1;
+ m_flags = 0;
+ }
+
+ uint32_t GetBaseSize()
+ {
+ return m_baseSize;
+ }
+
+ uint16_t RawGetComponentSize()
+ {
+ return m_componentSize;
+ }
+
+ bool ContainsPointers()
+ {
+ return (m_flags & MTFlag_ContainsPointers) != 0;
+ }
+
+ bool ContainsPointersOrCollectible()
+ {
+ return ContainsPointers();
+ }
+
+ bool HasComponentSize()
+ {
+ return m_componentSize != 0;
+ }
+
+ bool HasFinalizer()
+ {
+ return (m_flags & MTFlag_HasFinalizer) != 0;
+ }
+
+ bool HasCriticalFinalizer()
+ {
+ return false;
+ }
+
+ bool IsArray()
+ {
+ return (m_flags & MTFlag_IsArray) != 0;
+ }
+
+ MethodTable * GetParent()
+ {
+ _ASSERTE(!IsArray());
+ return m_pRelatedType;
+ }
+
+ bool SanityCheck()
+ {
+ return true;
+ }
+};
+
+class Object
+{
+ MethodTable * m_pMethTab;
+
+public:
+ ObjHeader * GetHeader()
+ {
+ return ((ObjHeader *)this) - 1;
+ }
+
+ MethodTable * RawGetMethodTable() const
+ {
+ return m_pMethTab;
+ }
+
+ void RawSetMethodTable(MethodTable * pMT)
+ {
+ m_pMethTab = pMT;
+ }
+
+ void SetMethodTable(MethodTable * pMT)
+ {
+ m_pMethTab = pMT;
+ }
+};
+#define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader))
+
+class ArrayBase : public Object
+{
+ DWORD m_dwLength;
+
+public:
+ DWORD GetNumComponents()
+ {
+ return m_dwLength;
+ }
+
+ static SIZE_T GetOffsetOfNumComponents()
+ {
+ return offsetof(ArrayBase, m_dwLength);
+ }
+};
--- /dev/null
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+// -----------------------------------------------------------------------------------------------------------
+//
+// Helper classes expected by the GC
+//
+class EEThreadId
+{
+public:
+ EEThreadId(UINT32 uiId) : m_uiId(uiId) {}
+ bool IsSameThread()
+ {
+ return m_uiId == GetCurrentThreadId();
+ }
+
+private:
+ UINT32 m_uiId;
+};
+
+#define CRST_REENTRANCY 0
+#define CRST_UNSAFE_SAMELEVEL 0
+#define CRST_UNSAFE_ANYMODE 0
+#define CRST_DEBUGGER_THREAD 0
+#define CRST_DEFAULT 0
+
+#define CrstHandleTable 0
+
+typedef int CrstFlags;
+typedef int CrstType;
+
+class CrstStatic
+{
+ CRITICAL_SECTION m_cs;
+#ifdef _DEBUG
+ UINT32 m_holderThreadId;
+#endif
+
+public:
+ bool InitNoThrow(CrstType eType, CrstFlags eFlags = CRST_DEFAULT)
+ {
+ UnsafeInitializeCriticalSection(&m_cs);
+ return true;
+ }
+
+ void Destroy()
+ {
+ UnsafeDeleteCriticalSection(&m_cs);
+ }
+
+ void Enter()
+ {
+ UnsafeEEEnterCriticalSection(&m_cs);
+#ifdef _DEBUG
+ m_holderThreadId = GetCurrentThreadId();
+#endif
+ }
+
+ void Leave()
+ {
+#ifdef _DEBUG
+ m_holderThreadId = 0;
+#endif
+ UnsafeEELeaveCriticalSection(&m_cs);
+ }
+
+#ifdef _DEBUG
+ EEThreadId GetHolderThreadId()
+ {
+ return m_holderThreadId;
+ }
+
+ bool OwnedByCurrentThread()
+ {
+ return GetHolderThreadId().IsSameThread();
+ }
+#endif
+};
+
+class CrstHolder
+{
+ CrstStatic * m_pLock;
+
+public:
+ CrstHolder(CrstStatic * pLock)
+ : m_pLock(pLock)
+ {
+ m_pLock->Enter();
+ }
+
+ ~CrstHolder()
+ {
+ m_pLock->Leave();
+ }
+};
+
+class CrstHolderWithState
+{
+ CrstStatic * m_pLock;
+ bool m_fAcquired;
+
+public:
+ CrstHolderWithState(CrstStatic * pLock, bool fAcquire = true)
+ : m_pLock(pLock), m_fAcquired(fAcquire)
+ {
+ if (fAcquire)
+ m_pLock->Enter();
+ }
+
+ ~CrstHolderWithState()
+ {
+ if (m_fAcquired)
+ m_pLock->Leave();
+ }
+
+ void Acquire()
+ {
+ if (!m_fAcquired)
+ {
+ m_pLock->Enter();
+ m_fAcquired = true;
+ }
+ }
+
+ void Release()
+ {
+ if (m_fAcquired)
+ {
+ m_pLock->Leave();
+ m_fAcquired = false;
+ }
+ }
+
+ CrstStatic * GetValue()
+ {
+ return m_pLock;
+ }
+};
+
+class CLREventStatic
+{
+public:
+ void CreateManualEvent(bool bInitialState);
+ void CreateAutoEvent(bool bInitialState);
+ void CreateOSManualEvent(bool bInitialState);
+ void CreateOSAutoEvent(bool bInitialState);
+ void CloseEvent();
+ bool IsValid() const;
+ bool Set();
+ bool Reset();
+ uint32_t Wait(uint32_t dwMilliseconds, bool bAlertable);
+
+private:
+ HANDLE m_hEvent;
+ bool m_fInitialized;
+};
}
}
-void CLREventStatic::CreateManualEvent(bool bInitialState)
-{
+void CLREventStatic::CreateManualEvent(bool bInitialState)
+{
// TODO: Implement
m_fInitialized = true;
}
-void CLREventStatic::CreateAutoEvent(bool bInitialState)
-{
+void CLREventStatic::CreateAutoEvent(bool bInitialState)
+{
// TODO: Implement
m_fInitialized = true;
}
-void CLREventStatic::CreateOSManualEvent(bool bInitialState)
-{
+void CLREventStatic::CreateOSManualEvent(bool bInitialState)
+{
CreateManualEvent(bInitialState);
}
-void CLREventStatic::CreateOSAutoEvent (bool bInitialState)
-{
+void CLREventStatic::CreateOSAutoEvent (bool bInitialState)
+{
CreateAutoEvent(bInitialState);
}
-void CLREventStatic::CloseEvent()
-{
+void CLREventStatic::CloseEvent()
+{
if (m_fInitialized)
- {
+ {
// TODO: Implement
m_fInitialized = false;
}
}
-bool CLREventStatic::IsValid() const
-{
+bool CLREventStatic::IsValid() const
+{
return m_fInitialized;
}
-bool CLREventStatic::Set()
-{
+bool CLREventStatic::Set()
+{
if (!m_fInitialized)
return false;
// TODO: Implement
return true;
}
-bool CLREventStatic::Reset()
-{
+bool CLREventStatic::Reset()
+{
if (!m_fInitialized)
return false;
// TODO: Implement
MethodTable * g_pFreeObjectMethodTable;
-EEConfig * g_pConfig;
-
GCSystemInfo g_SystemInfo;
void InitializeSystemInfo()
// TODO: Implement
}
-void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason)
-{
- GCHeap::GetGCHeap()->SetGCInProgress(TRUE);
-
- // TODO: Implement
-}
-
-void GCToEEInterface::RestartEE(bool bFinishedGC)
-{
- // TODO: Implement
-
- GCHeap::GetGCHeap()->SetGCInProgress(FALSE);
-}
-
-void GCToEEInterface::ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc)
-{
- // TODO: Implement - Scan stack roots on given thread
-}
-
-void GCToEEInterface::ScanStaticGCRefsOpportunistically(promote_func* fn, ScanContext* sc)
-{
-}
-
-void GCToEEInterface::GcStartWork(int condemned, int max_gen)
-{
-}
-
-void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc)
-{
-}
-
-void GCToEEInterface::GcBeforeBGCSweepWork()
-{
-}
-
-void GCToEEInterface::GcDone(int condemned)
-{
-}
-
void FinalizerThread::EnableFinalization()
{
// Signal to finalizer thread that there are objects to finalize
// TODO: Implement for finalization
}
-bool PalStartBackgroundGCThread(BackgroundCallback callback, void* pCallbackContext)
-{
- // TODO: Implement for background GC
- return false;
-}
-
-bool IsGCSpecialThread()
-{
- // TODO: Implement for background GC
- return false;
-}
-
bool PalHasCapability(PalCapability capability)
{
// TODO: Implement for background GC
}
}
-void CLREventStatic::CreateManualEvent(bool bInitialState)
-{
- m_hEvent = CreateEventW(NULL, TRUE, bInitialState, NULL);
+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);
+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);
+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);
+void CLREventStatic::CreateOSAutoEvent(bool bInitialState)
+{
+ m_hEvent = CreateEventW(NULL, FALSE, bInitialState, NULL);
m_fInitialized = true;
}
-void CLREventStatic::CloseEvent()
-{
+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::IsValid() const
+{
+ return m_fInitialized && m_hEvent != INVALID_HANDLE_VALUE;
}
-bool CLREventStatic::Set()
-{
+bool CLREventStatic::Set()
+{
if (!m_fInitialized)
return false;
- return !!SetEvent(m_hEvent);
+ return !!SetEvent(m_hEvent);
}
-bool CLREventStatic::Reset()
-{
+bool CLREventStatic::Reset()
+{
if (!m_fInitialized)
return false;
- return !!ResetEvent(m_hEvent);
+ return !!ResetEvent(m_hEvent);
}
uint32_t CLREventStatic::Wait(uint32_t dwMilliseconds, bool bAlertable)
if (m_fInitialized)
{
bool disablePreemptive = false;
- Thread * pCurThread = GetThread();
+ Thread * pCurThread = GetThread();
if (NULL != pCurThread)
{
}
}
- result = WaitForSingleObjectEx(m_hEvent, dwMilliseconds, bAlertable);
+ result = WaitForSingleObjectEx(m_hEvent, dwMilliseconds, bAlertable);
if (disablePreemptive)
{
MethodTable * g_pFreeObjectMethodTable;
-EEConfig * g_pConfig;
-
GCSystemInfo g_SystemInfo;
void InitializeSystemInfo()
bool g_fFinalizerRunOnShutDown;
-__declspec(thread) 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 GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason)
-{
- GCHeap::GetGCHeap()->SetGCInProgress(TRUE);
-
- // TODO: Implement
-}
-
-void GCToEEInterface::RestartEE(bool bFinishedGC)
-{
- // TODO: Implement
-
- GCHeap::GetGCHeap()->SetGCInProgress(FALSE);
-}
-
-void GCToEEInterface::ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc)
-{
- // TODO: Implement - Scan stack roots on given thread
-}
-
-void GCToEEInterface::ScanStaticGCRefsOpportunistically(promote_func* fn, ScanContext* sc)
-{
-}
-
-void GCToEEInterface::GcStartWork(int condemned, int max_gen)
-{
-}
-
-void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc)
-{
-}
-
-void GCToEEInterface::GcBeforeBGCSweepWork()
-{
-}
-
-void GCToEEInterface::GcDone(int condemned)
-{
-}
-
-void FinalizerThread::EnableFinalization()
-{
- // Signal to finalizer thread that there are objects to finalize
- // TODO: Implement for finalization
-}
-
-bool PalStartBackgroundGCThread(BackgroundCallback callback, void* pCallbackContext)
-{
- // TODO: Implement for background GC
- return false;
-}
-
-bool IsGCSpecialThread()
-{
- // TODO: Implement for background GC
- return false;
-}
-
bool PalHasCapability(PalCapability capability)
{
// TODO: Implement for background GC
return false;
}
+
{
// every 8th attempt:
Thread *pCurThread = GetThread();
- BOOL bToggleGC = FALSE;
+ bool bToggleGC = false;
if (pCurThread)
{
- bToggleGC = pCurThread->PreemptiveGCDisabled();
+ bToggleGC = GCToEEInterface::IsPreemptiveGCDisabled(pCurThread);
if (bToggleGC)
- pCurThread->EnablePreemptiveGC();
+ GCToEEInterface::EnablePreemptiveGC(pCurThread);
}
// if we're waiting for gc to finish, we should block immediately
{
if (bToggleGC || g_TrapReturningThreads)
{
- pCurThread->DisablePreemptiveGC();
+ GCToEEInterface::DisablePreemptiveGC(pCurThread);
if (!bToggleGC)
{
- pCurThread->EnablePreemptiveGC();
+ GCToEEInterface::EnablePreemptiveGC(pCurThread);
}
}
}
// every 8th attempt:
Thread *pCurThread = GetThread();
- BOOL bToggleGC = FALSE;
+ bool bToggleGC = false;
if (pCurThread)
{
- bToggleGC = pCurThread->PreemptiveGCDisabled();
+ bToggleGC = GCToEEInterface::IsPreemptiveGCDisabled(pCurThread);
if (bToggleGC)
{
- pCurThread->EnablePreemptiveGC();
+ GCToEEInterface::EnablePreemptiveGC(pCurThread);
}
else
{
#ifdef SYNCHRONIZATION_STATS
(spin_lock->num_disable_preemptive_w)++;
#endif //SYNCHRONIZATION_STATS
- pCurThread->DisablePreemptiveGC();
+ GCToEEInterface::DisablePreemptiveGC(pCurThread);
}
}
}
BOOL gc_heap::enable_preemptive (Thread* current_thread)
{
- BOOL cooperative_mode = FALSE;
+ bool cooperative_mode = false;
if (current_thread)
{
- cooperative_mode = current_thread->PreemptiveGCDisabled();
+ cooperative_mode = GCToEEInterface::IsPreemptiveGCDisabled(current_thread);
if (cooperative_mode)
{
- current_thread->EnablePreemptiveGC();
+ GCToEEInterface::EnablePreemptiveGC(current_thread);
}
}
{
if (restore_cooperative)
{
- current_thread->DisablePreemptiveGC();
+ GCToEEInterface::DisablePreemptiveGC(current_thread);
}
}
}
// since now GC threads can be managed threads.
ClrFlsSetThreadType (ThreadType_GC);
assert (heap->bgc_thread != NULL);
- heap->bgc_thread->SetGCSpecial(true);
+ GCToEEInterface::SetGCSpecial(heap->bgc_thread);
STRESS_LOG_RESERVE_MEM (GC_STRESSLOG_MULTIPLY);
// We commit the thread's entire stack to ensure we're robust in low memory conditions.
{
assert (bgc_thread == GetThread());
- if (bgc_thread->PreemptiveGCDisabled() && bgc_thread->CatchAtSafePoint())
+ if (GCToEEInterface::IsPreemptiveGCDisabled(bgc_thread) && GCToEEInterface::CatchAtSafePoint(bgc_thread))
{
- bgc_thread->EnablePreemptiveGC();
- bgc_thread->DisablePreemptiveGC();
+ GCToEEInterface::EnablePreemptiveGC(bgc_thread);
+ GCToEEInterface::DisablePreemptiveGC(bgc_thread);
}
}
STRESS_LOG_ROOT_RELOCATE(ppObject, object, pheader, ((!(flags & GC_CALL_INTERIOR)) ? ((Object*)object)->GetGCSafeMethodTable() : 0));
}
-/*static*/ BOOL GCHeap::IsLargeObject(MethodTable *mt)
-{
- return mt->GetBaseSize() >= LARGE_OBJECT_SIZE;
-}
-
/*static*/ BOOL GCHeap::IsObjectInFixedHeap(Object *pObj)
{
// For now we simply look at the size of the object to determine if it in the
{
#ifdef BACKGROUND_GC
full_gc_counts[gc_type_background]++;
-#ifdef STRESS_HEAP
+#if defined(STRESS_HEAP) && !defined(FEATURE_REDHAWK)
GCHeap::gc_stress_fgcs_in_bgc = 0;
-#endif // STRESS_HEAP
+#endif // STRESS_HEAP && !FEATURE_REDHAWK
#endif // BACKGROUND_GC
}
else
{
_ASSERTE(dbgOnly_IsSpecialEEThread() ||
GetThread() == 0 ||
- GetThread()->PreemptiveGCDisabled());
+ GCToEEInterface::IsPreemptiveGCDisabled(GetThread()));
retry:
if (FastInterlockExchange (&lock, 0) >= 0)
{
_ASSERTE(dbgOnly_IsSpecialEEThread() ||
GetThread() == 0 ||
- GetThread()->PreemptiveGCDisabled());
+ GCToEEInterface::IsPreemptiveGCDisabled(GetThread()));
#ifdef _DEBUG
lockowner_threadid = (DWORD) -1;
// static if since restricting for all heaps is fine
virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0;
-
- static BOOL IsLargeObject(MethodTable *mt) {
- WRAPPER_NO_CONTRACT;
-
- return mt->GetBaseSize() >= LARGE_OBJECT_SIZE;
- }
-
static unsigned GetMaxGeneration() {
LIMITED_METHOD_DAC_CONTRACT;
return max_generation;
#ifdef FEATURE_BASICFREEZE
// frozen segment management functions
virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo) = 0;
+ virtual void UnregisterFrozenSegment(segment_handle seg) = 0;
#endif //FEATURE_BASICFREEZE
// debug support
DWORD gc_heap::user_thread_wait (CLREvent *event, BOOL no_mode_change, int time_out_ms)
{
Thread* pCurThread = NULL;
- BOOL mode = FALSE;
+ bool mode = false;
DWORD dwWaitResult = NOERROR;
if (!no_mode_change)
{
pCurThread = GetThread();
- mode = pCurThread ? pCurThread->PreemptiveGCDisabled() : FALSE;
+ mode = pCurThread ? GCToEEInterface::IsPreemptiveGCDisabled(pCurThread) : false;
if (mode)
{
- pCurThread->EnablePreemptiveGC();
+ GCToEEInterface::EnablePreemptiveGC(pCurThread);
}
}
if (!no_mode_change && mode)
{
- pCurThread->DisablePreemptiveGC();
+ GCToEEInterface::DisablePreemptiveGC(pCurThread);
}
return dwWaitResult;
// should not be acquired as part of this operation. This is necessary because this thread is created in
// the context of a garbage collection and the lock is already held by the GC.
ASSERT(GCHeap::GetGCHeap()->IsGCInProgress());
- ThreadStore::AttachCurrentThread(false);
+ GCToEEInterface::AttachCurrentThread();
// Inform the GC which Thread* we are.
pStartContext->m_pRealContext->bgc_thread = GetThread();
#endif // BACKGROUND_GC && FEATURE_REDHAWK
+#ifdef FEATURE_BASICFREEZE
+segment_handle GCHeap::RegisterFrozenSegment(segment_info *pseginfo)
+{
+ heap_segment * seg = new (nothrow) heap_segment;
+ if (!seg)
+ {
+ return NULL;
+ }
+
+ BYTE* base_mem = (BYTE*)pseginfo->pvMem;
+ heap_segment_mem(seg) = base_mem + pseginfo->ibFirstObject;
+ heap_segment_allocated(seg) = base_mem + pseginfo->ibAllocated;
+ heap_segment_committed(seg) = base_mem + pseginfo->ibCommit;
+ heap_segment_reserved(seg) = base_mem + pseginfo->ibReserved;
+ heap_segment_next(seg) = 0;
+ heap_segment_used(seg) = heap_segment_allocated(seg);
+ heap_segment_plan_allocated(seg) = 0;
+ seg->flags = heap_segment_flags_readonly;
+
+#if defined (MULTIPLE_HEAPS) && !defined (ISOLATED_HEAPS)
+ gc_heap* heap = gc_heap::g_heaps[0];
+ heap_segment_heap(seg) = heap;
+#else
+ gc_heap* heap = pGenGCHeap;
+#endif //MULTIPLE_HEAPS && !ISOLATED_HEAPS
+
+ if (heap->insert_ro_segment(seg) == FALSE)
+ {
+ delete seg;
+ return NULL;
+ }
+
+ return reinterpret_cast< segment_handle >(seg);
+}
+
+void GCHeap::UnregisterFrozenSegment(segment_handle seg)
+{
+#if defined (MULTIPLE_HEAPS) && !defined (ISOLATED_HEAPS)
+ gc_heap* heap = gc_heap::g_heaps[0];
+#else
+ gc_heap* heap = pGenGCHeap;
+#endif //MULTIPLE_HEAPS && !ISOLATED_HEAPS
+
+ heap->remove_ro_segment(reinterpret_cast<heap_segment*>(seg));
+}
+#endif // FEATURE_BASICFREEZE
+
+
#endif // !DACCESS_COMPILE
+
+
int GetHomeHeapNumber ();
bool IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number);
int GetNumberOfHeaps ();
- void HideAllocContext(alloc_context*);
- void RevealAllocContext(alloc_context*);
-
- static BOOL IsLargeObject(MethodTable *mt);
+ void HideAllocContext(alloc_context*);
+ void RevealAllocContext(alloc_context*);
BOOL IsObjectInFixedHeap(Object *pObj);
DWORD flags=0);
// Find the relocation address for an object
- PER_HEAP_ISOLATED void Relocate (Object** object,
+ PER_HEAP_ISOLATED void Relocate (Object** object,
ScanContext* sc,
DWORD flags=0);
BOOL IsHeapPointer (void* object, BOOL small_heap_only = FALSE);
#ifdef VERIFY_HEAP
- void ValidateObjectMember (Object *obj);
+ void ValidateObjectMember (Object *obj);
#endif //_DEBUG
PER_HEAP size_t ApproxTotalBytesInUse(BOOL small_heap_only = FALSE);
BOOL FinalizeAppDomain(AppDomain *pDomain, BOOL fRunFinalizers);
BOOL ShouldRestartFinalizerWatchDog();
- void SetCardsAfterBulkCopy( Object**, size_t);
+ void SetCardsAfterBulkCopy( Object**, size_t);
#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
void WalkObject (Object* obj, walk_fn fn, void* context);
#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
#ifdef FEATURE_BASICFREEZE
// frozen segment management functions
virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo);
+ virtual void UnregisterFrozenSegment(segment_handle seg);
#endif // FEATURE_BASICFREEZE
void WaitUntilConcurrentGCComplete (); // Use in managd threads
void TemporaryEnableConcurrentGC();
void TemporaryDisableConcurrentGC();
BOOL IsConcurrentGCEnabled();
-
+
PER_HEAP_ISOLATED CLREvent *WaitForGCEvent; // used for syncing w/GC
PER_HEAP_ISOLATED CFinalize* m_Finalize;
}
Thread* pThread = NULL;
- while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
+ while ((pThread = GCToEEInterface::GetThreadList(pThread)) != NULL)
{
STRESS_LOG2(LF_GC|LF_GCROOTS, LL_INFO100, "{ Starting scan of Thread %p ID = %x\n", pThread, pThread->GetThreadId());
- if (GCHeap::GetGCHeap()->IsThreadUsingAllocationContextHeap(pThread->GetAllocContext(), sc->thread_number))
+ if (GCHeap::GetGCHeap()->IsThreadUsingAllocationContextHeap(
+ GCToEEInterface::GetAllocContext(pThread), sc->thread_number))
{
sc->thread_under_crawl = pThread;
#ifdef FEATURE_EVENT_TRACE
if (GCHeap::UseAllocationContexts())
{
Thread *thread = NULL;
- while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
+ while ((thread = GCToEEInterface::GetThreadList(thread)) != NULL)
{
- GCHeap::GetGCHeap()->FixAllocContext(thread->GetAllocContext(), FALSE, arg, heap);
+ GCHeap::GetGCHeap()->FixAllocContext(GCToEEInterface::GetAllocContext(thread), FALSE, arg, heap);
}
}
}
if (GCHeap::UseAllocationContexts())
{
Thread *thread = NULL;
- while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
+ while ((thread = GCToEEInterface::GetThreadList(thread)) != NULL)
{
- (*fn) (thread->GetAllocContext());
+ (*fn) (GCToEEInterface::GetAllocContext(thread));
}
}
}
*pUserData = lExtraInfo;
}
}
+
+/*
+* HndCompareExchangeHandleExtraInfo
+*
+* Stores owner data with handle.
+*
+*/
+LPARAM HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, UINT uType, LPARAM lOldExtraInfo, LPARAM lNewExtraInfo)
+{
+ WRAPPER_NO_CONTRACT;
+
+ // fetch the user data slot for this handle if we have the right type
+ LPARAM *pUserData = HandleValidateAndFetchUserDataPointer(handle, uType);
+
+ // is there a slot?
+ if (pUserData)
+ {
+ // yes - attempt to store the info
+ return (LPARAM)FastInterlockCompareExchangePointer((PVOID*)pUserData, (PVOID)lNewExtraInfo, (PVOID)lOldExtraInfo);
+ }
+
+ _ASSERTE(!"Shouldn't be trying to call HndCompareExchangeHandleExtraInfo on handle types without extra info");
+ return NULL;
+}
#endif // !DACCESS_COMPILE
/*
* owner data associated with handles
*/
void HndSetHandleExtraInfo(OBJECTHANDLE handle, UINT uType, LPARAM lExtraInfo);
+LPARAM HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, UINT uType, LPARAM lOldExtraInfo, LPARAM lNewExtraInfo);
#endif // !DACCESS_COMPILE
LPARAM HndGetHandleExtraInfo(OBJECTHANDLE handle);
{
LPARAM lEnableMask; // mask of types to trace
HANDLESCANPROC pfnTrace; // tracing function to use
- LPARAM lp2; // second parameter
+ LPARAM lp2; // second parameter
};
}
}
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
/*
* Scan callback for tracing ref-counted handles.
*
if (!HndIsNullOrDestroyedHandle(pObj) && !GCHeap::GetGCHeap()->IsPromoted(pObj))
{
- //<REVISIT_TODO>@todo optimize the access to the ref-count
- ComCallWrapper* pWrap = ComCallWrapper::GetWrapperForObject((OBJECTREF)pObj);
- _ASSERTE(pWrap != NULL);
-
- BOOL fIsActive = pWrap->IsWrapperActive();
- if (fIsActive)
+ if (GCToEEInterface::RefCountedHandleCallbacks(pObj))
{
_ASSERTE(lp2);
promote_func* callback = (promote_func*) lp2;
// Assert this object wasn't relocated since we are passing a temporary object's address.
_ASSERTE(pOldObj == pObj);
}
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
void CALLBACK TraceDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, LPARAM *pExtraInfo, LPARAM lp1, LPARAM lp2)
{
break;
case HNDTYPE_VARIABLE:
-#if 0 // this feature appears to be unused for now
- rootFlags |= COR_PRF_GC_ROOT_VARIABLE;
+#ifdef FEATURE_REDHAWK
+ {
+ // Set the appropriate ETW flags for the current strength of this variable handle
+ UINT nVarHandleType = GetVariableHandleType(handle);
+ if (((nVarHandleType & VHT_WEAK_SHORT) != 0) ||
+ ((nVarHandleType & VHT_WEAK_LONG) != 0))
+ {
+ rootFlags |= kEtwGCRootFlagsWeakRef;
+ }
+ if ((nVarHandleType & VHT_PINNED) != 0)
+ {
+ rootFlags |= kEtwGCRootFlagsPinning;
+ }
+
+ // No special ETW flag for strong handles (VHT_STRONG)
+ }
#else
_ASSERTE(!"Variable handle encountered");
#endif
break;
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_REDHAWK)
case HNDTYPE_REFCOUNTED:
rootFlags |= kEtwGCRootFlagsRefCounted;
if (*pRef != NULL)
rootFlags |= kEtwGCRootFlagsWeakRef;
}
break;
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
}
_UNCHECKED_OBJECTREF pSec = NULL;
return HndCreateHandle(hTable, HNDTYPE_VARIABLE, object, (LPARAM)type);
}
+/*
+* GetVariableHandleType.
+*
+* Retrieves the dynamic type of a variable-strength handle.
+*/
+UINT GetVariableHandleType(OBJECTHANDLE handle)
+{
+ WRAPPER_NO_CONTRACT;
+
+ return (UINT)HndGetHandleExtraInfo(handle);
+}
/*
* UpdateVariableHandleType.
HndSetHandleExtraInfo(handle, HNDTYPE_VARIABLE, (LPARAM)type);
}
+/*
+* CompareExchangeVariableHandleType.
+*
+* Changes the dynamic type of a variable-strength handle. Unlike UpdateVariableHandleType we assume that the
+* types have already been validated.
+*/
+UINT CompareExchangeVariableHandleType(OBJECTHANDLE handle, UINT oldType, UINT newType)
+{
+ WRAPPER_NO_CONTRACT;
+
+ // verify that we are being asked to get/set valid types
+ _ASSERTE(IS_VALID_VHT_VALUE(oldType) && IS_VALID_VHT_VALUE(newType));
+
+ // attempt to store the type in the handle's extra info
+ return (UINT)HndCompareExchangeHandleExtraInfo(handle, HNDTYPE_VARIABLE, (LPARAM)oldType, (LPARAM)newType);
+}
+
/*
* TraceVariableHandles.
// promote objects pointed to by variable handles whose dynamic type is VHT_STRONG
TraceVariableHandles(PromoteObject, LPARAM(sc), LPARAM(fn), VHT_STRONG, condemned, maxgen, flags);
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
// don't scan ref-counted handles during concurrent phase as the clean-up of CCWs can race with AD unload and cause AV's
if (!sc->concurrent)
{
walk = walk->pNext;
}
}
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
}
#ifdef FEATURE_COMINTEROP
UINT types[] =
{
HNDTYPE_WEAK_LONG,
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
HNDTYPE_REFCOUNTED,
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
};
// check objects pointed to by short weak handles
HNDTYPE_WEAK_SHORT,
HNDTYPE_WEAK_LONG,
HNDTYPE_STRONG,
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
HNDTYPE_REFCOUNTED,
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
+#ifdef FEATURE_COMINTEROP
HNDTYPE_WEAK_WINRT,
#endif // FEATURE_COMINTEROP
HNDTYPE_SIZEDREF,
HandleTableMap *walk = &g_HandleTableMap;
while (walk) {
for (UINT i = 0; i < INITIAL_HANDLE_TABLE_ARRAY_SIZE; i ++)
- if (walk->pBuckets[i] != NULL)
- {
- HHANDLETABLE hTable = walk->pBuckets[i]->pTable[getSlotNumber(sc)];
- if (hTable)
- HndScanHandlesForGC(hTable, UpdatePointer, LPARAM(sc), LPARAM(fn), types, _countof(types), condemned, maxgen, flags);
- }
+ if (walk->pBuckets[i] != NULL)
+ {
+ HHANDLETABLE hTable = walk->pBuckets[i]->pTable[getSlotNumber(sc)];
+ if (hTable)
+ HndScanHandlesForGC(hTable, UpdatePointer, LPARAM(sc), LPARAM(fn), types, _countof(types), condemned, maxgen, flags);
+ }
walk = walk->pNext;
}
HNDTYPE_WEAK_SHORT,
HNDTYPE_WEAK_LONG,
HNDTYPE_STRONG,
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
HNDTYPE_REFCOUNTED,
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
+#ifdef FEATURE_COMINTEROP
HNDTYPE_WEAK_WINRT,
-#endif // FEATURE_COMINTEROP,
+#endif // FEATURE_COMINTEROP
HNDTYPE_PINNED,
// HNDTYPE_VARIABLE,
HNDTYPE_ASYNCPINNED,
HNDTYPE_PINNED,
HNDTYPE_VARIABLE,
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
HNDTYPE_REFCOUNTED,
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
+#ifdef FEATURE_COMINTEROP
HNDTYPE_WEAK_WINRT,
#endif // FEATURE_COMINTEROP
HNDTYPE_ASYNCPINNED,
HNDTYPE_PINNED,
HNDTYPE_VARIABLE,
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
HNDTYPE_REFCOUNTED,
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
+#ifdef FEATURE_COMINTEROP
HNDTYPE_WEAK_WINRT,
#endif // FEATURE_COMINTEROP
HNDTYPE_ASYNCPINNED,
HNDTYPE_PINNED,
HNDTYPE_VARIABLE,
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
HNDTYPE_REFCOUNTED,
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
+#ifdef FEATURE_COMINTEROP
HNDTYPE_WEAK_WINRT,
#endif // FEATURE_COMINTEROP
HNDTYPE_ASYNCPINNED,
{
WRAPPER_NO_CONTRACT;
- if (!GCHeap::IsGCHeapInitialized())
- return 0;
+ if (!GCHeap::IsGCHeapInitialized())
+ return 0;
return GCHeap::GetGCHeap()->GetHomeHeapNumber();
}
*/
#define HNDTYPE_VARIABLE (4)
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
/*
* REFCOUNTED HANDLES
*
*
*/
#define HNDTYPE_REFCOUNTED (5)
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
/*
*
*
*/
-#define HNDTYPE_DEPENDENT (6)
+#define HNDTYPE_DEPENDENT (6)
/*
* PINNED HANDLES for asynchronous operation
#ifndef DACCESS_COMPILE
OBJECTHANDLE CreateVariableHandle(HHANDLETABLE hTable, OBJECTREF object, UINT type);
+UINT GetVariableHandleType(OBJECTHANDLE handle);
void UpdateVariableHandleType(OBJECTHANDLE handle, UINT type);
+UINT CompareExchangeVariableHandleType(OBJECTHANDLE handle, UINT oldType, UINT newType);
inline void DestroyVariableHandle(OBJECTHANDLE handle)
{
//
// Initialize current thread
//
- ThreadStore::AttachCurrentThread(false);
+ ThreadStore::AttachCurrentThread();
//
// Create a Methodtable with GCDesc
<ClInclude Include="gcenv.h" />
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="gcenv.cpp" />
<ClCompile Include="GCSample.cpp" />
<ClCompile Include="..\gccommon.cpp" />
<ClCompile Include="..\gceewks.cpp" />
<ClCompile Include="..\handletablecore.cpp" />
<ClCompile Include="..\handletablescan.cpp" />
<ClCompile Include="..\objecthandle.cpp" />
- <ClCompile Include="..\env\gcenv.cpp" />
+ <ClCompile Include="..\env\gcenv.windows.cpp" />
<ClCompile Include="..\env\common.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClInclude>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="common.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="GCSample.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\gcscan.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="gcenv.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="..\gceewks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\gccommon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\env\gcenv.windows.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\env\common.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="gcenv.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
--- /dev/null
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "common.h"
+
+#include "windows.h"
+
+#include "gcenv.h"
+#include "gc.h"
+
+EEConfig * g_pConfig;
+
+#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()
+{
+ // TODO: Locks
+
+ Thread * pThread = new Thread();
+ pThread->GetAllocContext()->init();
+ pCurrentThread = pThread;
+
+ pThread->m_pNext = g_pThreadList;
+ g_pThreadList = pThread;
+}
+
+void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason)
+{
+ GCHeap::GetGCHeap()->SetGCInProgress(TRUE);
+
+ // TODO: Implement
+}
+
+void GCToEEInterface::RestartEE(bool bFinishedGC)
+{
+ // TODO: Implement
+
+ GCHeap::GetGCHeap()->SetGCInProgress(FALSE);
+}
+
+void GCToEEInterface::ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc)
+{
+ // TODO: Implement - Scan stack roots on given thread
+}
+
+void GCToEEInterface::ScanStaticGCRefsOpportunistically(promote_func* fn, ScanContext* sc)
+{
+}
+
+void GCToEEInterface::GcStartWork(int condemned, int max_gen)
+{
+}
+
+void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc)
+{
+}
+
+void GCToEEInterface::GcBeforeBGCSweepWork()
+{
+}
+
+void GCToEEInterface::GcDone(int condemned)
+{
+}
+
+bool GCToEEInterface::RefCountedHandleCallbacks(Object * pObject)
+{
+ return false;
+}
+
+bool GCToEEInterface::IsPreemptiveGCDisabled(Thread * pThread)
+{
+ return !!pThread->PreemptiveGCDisabled();
+}
+
+void GCToEEInterface::EnablePreemptiveGC(Thread * pThread)
+{
+ return pThread->EnablePreemptiveGC();
+}
+
+void GCToEEInterface::DisablePreemptiveGC(Thread * pThread)
+{
+ pThread->DisablePreemptiveGC();
+}
+
+void GCToEEInterface::SetGCSpecial(Thread * pThread)
+{
+ pThread->SetGCSpecial(true);
+}
+
+alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread)
+{
+ return pThread->GetAllocContext();
+}
+
+bool GCToEEInterface::CatchAtSafePoint(Thread * pThread)
+{
+ return pThread->CatchAtSafePoint();
+}
+
+// does not acquire thread store lock
+void GCToEEInterface::AttachCurrentThread()
+{
+ ThreadStore::AttachCurrentThread();
+}
+
+Thread * GCToEEInterface::GetThreadList(Thread * pThread)
+{
+ return ThreadStore::GetThreadList(pThread);
+}
+
+void FinalizerThread::EnableFinalization()
+{
+ // Signal to finalizer thread that there are objects to finalize
+ // TODO: Implement for finalization
+}
+
+bool FinalizerThread::HaveExtraWorkForFinalizer()
+{
+ return false;
+}
+
+bool PalStartBackgroundGCThread(BackgroundCallback callback, void* pCallbackContext)
+{
+ // TODO: Implement for background GC
+ return false;
+}
+
+bool IsGCSpecialThread()
+{
+ // TODO: Implement for background GC
+ return false;
+}
--- /dev/null
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "gcenv.base.h"
+#include "gcenv.object.h"
+#include "gcenv.sync.h"
+
+//
+// Thread
+//
+
+struct alloc_context;
+
+class Thread
+{
+ uint32_t m_fPreemptiveGCDisabled;
+ uintptr_t m_alloc_context[16]; // Reserve enough space to fix allocation context
+
+ friend class ThreadStore;
+ Thread * m_pNext;
+
+public:
+ Thread()
+ {
+ }
+
+ bool PreemptiveGCDisabled()
+ {
+ return !!m_fPreemptiveGCDisabled;
+ }
+
+ void EnablePreemptiveGC()
+ {
+ m_fPreemptiveGCDisabled = false;
+ }
+
+ void DisablePreemptiveGC()
+ {
+ m_fPreemptiveGCDisabled = true;
+ }
+
+ alloc_context* GetAllocContext()
+ {
+ return (alloc_context *)&m_alloc_context;
+ }
+
+ void SetGCSpecial(bool fGCSpecial)
+ {
+ }
+
+ bool CatchAtSafePoint()
+ {
+ // This is only called by the GC on a background GC worker thread that's explicitly interested in letting
+ // a foreground GC proceed at that point. So it's always safe to return true.
+ return true;
+ }
+};
+
+Thread * GetThread();
+
+class ThreadStore
+{
+public:
+ static Thread * GetThreadList(Thread * pThread);
+
+ static void AttachCurrentThread();
+};
+
+// -----------------------------------------------------------------------------------------------------------
+// Config file enumulation
+//
+
+class EEConfig
+{
+public:
+ enum HeapVerifyFlags {
+ HEAPVERIFY_NONE = 0,
+ HEAPVERIFY_GC = 1, // Verify the heap at beginning and end of GC
+ HEAPVERIFY_BARRIERCHECK = 2, // Verify the brick table
+ HEAPVERIFY_SYNCBLK = 4, // Verify sync block scanning
+
+ // the following options can be used to mitigate some of the overhead introduced
+ // by heap verification. some options might cause heap verifiction to be less
+ // effective depending on the scenario.
+
+ HEAPVERIFY_NO_RANGE_CHECKS = 0x10, // Excludes checking if an OBJECTREF is within the bounds of the managed heap
+ HEAPVERIFY_NO_MEM_FILL = 0x20, // Excludes filling unused segment portions with fill pattern
+ HEAPVERIFY_POST_GC_ONLY = 0x40, // Performs heap verification post-GCs only (instead of before and after each GC)
+ HEAPVERIFY_DEEP_ON_COMPACT = 0x80 // Performs deep object verfication only on compacting GCs.
+ };
+
+ enum GCStressFlags {
+ GCSTRESS_NONE = 0,
+ GCSTRESS_ALLOC = 1, // GC on all allocs and 'easy' places
+ GCSTRESS_TRANSITION = 2, // GC on transitions to preemtive GC
+ GCSTRESS_INSTR_JIT = 4, // GC on every allowable JITed instr
+ GCSTRESS_INSTR_NGEN = 8, // GC on every allowable NGEN instr
+ GCSTRESS_UNIQUE = 16, // GC only on a unique stack trace
+ };
+
+ int GetHeapVerifyLevel() { return 0; }
+ bool IsHeapVerifyEnabled() { return GetHeapVerifyLevel() != 0; }
+
+ GCStressFlags GetGCStressLevel() const { return GCSTRESS_NONE; }
+ bool IsGCStressMix() const { return false; }
+
+ int GetGCtraceStart() const { return 0; }
+ int GetGCtraceEnd() const { return 0; }//1000000000; }
+ int GetGCtraceFac() const { return 0; }
+ int GetGCprnLvl() const { return 0; }
+ bool IsGCBreakOnOOMEnabled() const { return false; }
+ int GetGCgen0size() const { return 0; }
+ int GetSegmentSize() const { return 0; }
+ int GetGCconcurrent() const { return 1; }
+ int GetGCLatencyMode() const { return 1; }
+ int GetGCForceCompact() const { return 0; }
+ int GetGCRetainVM() const { return 0; }
+ int GetGCTrimCommit() const { return 0; }
+ int GetGCLOHCompactionMode() const { return 0; }
+
+ bool GetGCAllowVeryLargeObjects() const { return false; }
+
+ bool GetGCConservative() const { return true; }
+};
+
+extern EEConfig * g_pConfig;
#ifdef FEATURE_COMINTEROP
#include "runtimecallablewrapper.h"
#include "rcwwalker.h"
+#include "comcallablewrapper.h"
#endif // FEATURE_COMINTEROP
void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
#endif // FEATURE_COMINTEROP
}
+bool GCToEEInterface::RefCountedHandleCallbacks(Object * pObject)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ }
+ CONTRACTL_END;
+
+#ifdef FEATURE_COMINTEROP
+ //<REVISIT_TODO>@todo optimize the access to the ref-count
+ ComCallWrapper* pWrap = ComCallWrapper::GetWrapperForObject((OBJECTREF)pObject);
+ _ASSERTE(pWrap != NULL);
+
+ return !!pWrap->IsWrapperActive();
+#else
+ return false;
+#endif
+}
+
void GCToEEInterface::GcBeforeBGCSweepWork()
{
CONTRACTL
SyncBlockCache::GetSyncBlockCache()->GCDone(FALSE, max_gen);
}
+
+void GCToEEInterface::SetGCSpecial(Thread * pThread)
+{
+ WRAPPER_NO_CONTRACT;
+ pThread->SetGCSpecial(true);
+}
+
+alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread)
+{
+ WRAPPER_NO_CONTRACT;
+ return pThread->GetAllocContext();
+}
+
+bool GCToEEInterface::CatchAtSafePoint(Thread * pThread)
+{
+ WRAPPER_NO_CONTRACT;
+ return !!pThread->CatchAtSafePoint();
+}
+
+Thread * GCToEEInterface::GetThreadList(Thread * pThread)
+{
+ WRAPPER_NO_CONTRACT;
+ return ThreadStore::GetThreadList(pThread);
+}
// 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, LPARAM lp1, LPARAM lp2);
static void SyncBlockCacheDemote(int max_gen);
static void SyncBlockCachePromotionsGranted(int max_gen);
+
+ // Thread functions
+ static bool IsPreemptiveGCDisabled(Thread * pThread)
+ {
+ WRAPPER_NO_CONTRACT;
+ return !!pThread->PreemptiveGCDisabled();
+ }
+
+ static void EnablePreemptiveGC(Thread * pThread)
+ {
+ WRAPPER_NO_CONTRACT;
+ pThread->EnablePreemptiveGC();
+ }
+
+ static void DisablePreemptiveGC(Thread * pThread)
+ {
+ WRAPPER_NO_CONTRACT;
+ pThread->DisablePreemptiveGC();
+ }
+
+ static void SetGCSpecial(Thread * pThread);
+ static alloc_context * GetAllocContext(Thread * pThread);
+ static bool CatchAtSafePoint(Thread * pThread);
+
+ static Thread * GetThreadList(Thread * pThread);
};
#endif // GCENV_H_
\ No newline at end of file
_ASSERTE(helper == CORINFO_HELP_NEWFAST);
}
else
- if (GCHeap::IsLargeObject(pMT) ||
+ if ((pMT->GetBaseSize() >= LARGE_OBJECT_SIZE) ||
pMT->HasFinalizer())
{
// Use slow helper