Cleanup GC-EE Interface
authorJan Kotas <jkotas@microsoft.com>
Thu, 15 Oct 2015 14:14:05 +0000 (07:14 -0700)
committerJan Kotas <jkotas@microsoft.com>
Thu, 15 Oct 2015 15:37:24 +0000 (08:37 -0700)
- Add proper abstractions for threading methods to GCToEEInterface
- Split sample gcenv into multiple files to avoid redundant content
- Add handle table methods needed by .NET Native WinRT implementation

Part of dotnet/coreclr#1550

Commit migrated from https://github.com/dotnet/coreclr/commit/38034a26ff4e40e98d1af32abe5baef2c3eeea52

22 files changed:
src/coreclr/src/gc/env/gcenv.base.h [moved from src/coreclr/src/gc/env/gcenv.h with 71% similarity]
src/coreclr/src/gc/env/gcenv.object.h [new file with mode: 0644]
src/coreclr/src/gc/env/gcenv.sync.h [new file with mode: 0644]
src/coreclr/src/gc/env/gcenv.unix.cpp
src/coreclr/src/gc/env/gcenv.windows.cpp
src/coreclr/src/gc/gc.cpp
src/coreclr/src/gc/gc.h
src/coreclr/src/gc/gcee.cpp
src/coreclr/src/gc/gcimpl.h
src/coreclr/src/gc/gcscan.cpp
src/coreclr/src/gc/handletable.cpp
src/coreclr/src/gc/handletable.h
src/coreclr/src/gc/objecthandle.cpp
src/coreclr/src/gc/objecthandle.h
src/coreclr/src/gc/sample/GCSample.cpp
src/coreclr/src/gc/sample/GCSample.vcxproj
src/coreclr/src/gc/sample/GCSample.vcxproj.filters
src/coreclr/src/gc/sample/gcenv.cpp [new file with mode: 0644]
src/coreclr/src/gc/sample/gcenv.h [new file with mode: 0644]
src/coreclr/src/vm/gcenv.cpp
src/coreclr/src/vm/gcenv.h
src/coreclr/src/vm/jitinterface.cpp

similarity index 71%
rename from src/coreclr/src/gc/env/gcenv.h
rename to src/coreclr/src/gc/env/gcenv.base.h
index 6a9c421..74288a2 100644 (file)
@@ -10,6 +10,8 @@
 #define FEATURE_REDHAWK 1
 #define FEATURE_CONSERVATIVE_GC 1
 
+#define GCENV_INCLUDED
+
 #ifndef _MSC_VER
 #define __stdcall
 #define __forceinline inline
@@ -508,137 +510,10 @@ void FastInterlockAnd(uint32_t volatile *p, uint32_t msk);
 #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.
@@ -763,62 +638,10 @@ ClrVirtualProtect(
 //
 
 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);
 
@@ -864,21 +687,40 @@ public:
     // 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);
@@ -1014,65 +856,6 @@ inline void StompWriteBarrierResize(BOOL bReqUpperBoundsCheck)
 {
 }
 
-// -----------------------------------------------------------------------------------------------------------
-// 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:
@@ -1124,163 +907,6 @@ 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
 {
@@ -1355,3 +981,30 @@ public:
     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
+
diff --git a/src/coreclr/src/gc/env/gcenv.object.h b/src/coreclr/src/gc/env/gcenv.object.h
new file mode 100644 (file)
index 0000000..327f5e4
--- /dev/null
@@ -0,0 +1,149 @@
+//
+// 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);
+    }
+};
diff --git a/src/coreclr/src/gc/env/gcenv.sync.h b/src/coreclr/src/gc/env/gcenv.sync.h
new file mode 100644 (file)
index 0000000..e3abacb
--- /dev/null
@@ -0,0 +1,158 @@
+//
+// 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;
+};
index d0e6b91..0ababb5 100644 (file)
@@ -116,52 +116,52 @@ void GetProcessMemoryLoad(LPMEMORYSTATUSEX pMSEX)
     }
 }
 
-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
@@ -314,8 +314,6 @@ ClrVirtualProtect(
 
 MethodTable * g_pFreeObjectMethodTable;
 
-EEConfig * g_pConfig;
-
 GCSystemInfo g_SystemInfo;
 
 void InitializeSystemInfo()
@@ -370,63 +368,12 @@ 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
index 9d05fcb..aba1a82 100644 (file)
@@ -102,56 +102,56 @@ void GetProcessMemoryLoad(LPMEMORYSTATUSEX pMSEX)
     }
 }
 
-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)
@@ -161,7 +161,7 @@ uint32_t CLREventStatic::Wait(uint32_t dwMilliseconds, bool bAlertable)
     if (m_fInitialized)
     {
         bool        disablePreemptive = false;
-        Thread *    pCurThread  = GetThread();
+        Thread *    pCurThread = GetThread();
 
         if (NULL != pCurThread)
         {
@@ -172,7 +172,7 @@ uint32_t CLREventStatic::Wait(uint32_t dwMilliseconds, bool bAlertable)
             }
         }
 
-        result = WaitForSingleObjectEx(m_hEvent, dwMilliseconds, bAlertable); 
+        result = WaitForSingleObjectEx(m_hEvent, dwMilliseconds, bAlertable);
 
         if (disablePreemptive)
         {
@@ -228,8 +228,6 @@ ClrVirtualProtect(
 
 MethodTable * g_pFreeObjectMethodTable;
 
-EEConfig * g_pConfig;
-
 GCSystemInfo g_SystemInfo;
 
 void InitializeSystemInfo()
@@ -246,99 +244,14 @@ int32_t g_TrapReturningThreads;
 
 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;
 }
+
index f77f482..9dc6e13 100644 (file)
@@ -1442,12 +1442,12 @@ void WaitLongerNoInstru (int i)
 {
     // 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
@@ -1473,10 +1473,10 @@ void WaitLongerNoInstru (int i)
     {
         if (bToggleGC || g_TrapReturningThreads)
         {
-            pCurThread->DisablePreemptiveGC();
+            GCToEEInterface::DisablePreemptiveGC(pCurThread);
             if (!bToggleGC)
             {
-                pCurThread->EnablePreemptiveGC();
+                GCToEEInterface::EnablePreemptiveGC(pCurThread);
             }
         }
     }
@@ -1609,13 +1609,13 @@ void WaitLonger (int i
 
     // 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
         {
@@ -1657,7 +1657,7 @@ void WaitLonger (int i
 #ifdef SYNCHRONIZATION_STATS
             (spin_lock->num_disable_preemptive_w)++;
 #endif //SYNCHRONIZATION_STATS
-            pCurThread->DisablePreemptiveGC();
+            GCToEEInterface::DisablePreemptiveGC(pCurThread);
         }
     }
 }
@@ -1735,13 +1735,13 @@ static void leave_spin_lock (GCSpinLock * spin_lock)
 
 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);
         }
     }
 
@@ -1754,7 +1754,7 @@ void gc_heap::disable_preemptive (Thread* current_thread, BOOL restore_cooperati
     {
         if (restore_cooperative)
         {
-            current_thread->DisablePreemptiveGC(); 
+            GCToEEInterface::DisablePreemptiveGC(current_thread);
         }
     }
 }
@@ -24371,7 +24371,7 @@ DWORD __stdcall gc_heap::bgc_thread_stub (void* arg)
     // 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.
@@ -24607,10 +24607,10 @@ void gc_heap::allow_fgc()
 {
     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);
     }
 }
 
@@ -33419,11 +33419,6 @@ void GCHeap::Relocate (Object** ppObject, ScanContext* sc,
     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
@@ -34432,9 +34427,9 @@ void gc_heap::do_pre_gc()
     {
 #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
@@ -35397,7 +35392,7 @@ void CFinalize::EnterFinalizeLock()
 {
     _ASSERTE(dbgOnly_IsSpecialEEThread() ||
              GetThread() == 0 ||
-             GetThread()->PreemptiveGCDisabled());
+             GCToEEInterface::IsPreemptiveGCDisabled(GetThread()));
 
 retry:
     if (FastInterlockExchange (&lock, 0) >= 0)
@@ -35424,7 +35419,7 @@ void CFinalize::LeaveFinalizeLock()
 {
     _ASSERTE(dbgOnly_IsSpecialEEThread() ||
              GetThread() == 0 ||
-             GetThread()->PreemptiveGCDisabled());
+             GCToEEInterface::IsPreemptiveGCDisabled(GetThread()));
 
 #ifdef _DEBUG
     lockowner_threadid = (DWORD) -1;
index 7ccf5d5..f571cbc 100644 (file)
@@ -598,13 +598,6 @@ public:
     // 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;
@@ -622,6 +615,7 @@ public:
 #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 
index 169b217..196eb49 100644 (file)
@@ -675,16 +675,16 @@ void gc_heap::fire_etw_pin_object_event (BYTE* object, BYTE** ppObject)
 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);
         }
     }
 
@@ -692,7 +692,7 @@ DWORD gc_heap::user_thread_wait (CLREvent *event, BOOL no_mode_change, int time_
 
     if (!no_mode_change && mode)
     {
-        pCurThread->DisablePreemptiveGC();
+        GCToEEInterface::DisablePreemptiveGC(pCurThread);
     }
 
     return dwWaitResult;
@@ -787,7 +787,7 @@ DWORD WINAPI gc_heap::rh_bgc_thread_stub(void * pContext)
     // 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();
@@ -798,4 +798,54 @@ DWORD WINAPI gc_heap::rh_bgc_thread_stub(void * pContext)
 
 #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
+
+
index 86de9ca..53cf9c8 100644 (file)
@@ -135,10 +135,8 @@ public:
     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);
 
@@ -160,7 +158,7 @@ public:
                                           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);
 
@@ -180,7 +178,7 @@ public:
     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);
@@ -226,7 +224,7 @@ public:
     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)
@@ -255,6 +253,7 @@ public:     // FIX
 #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
@@ -267,7 +266,7 @@ public:     // FIX
     void TemporaryEnableConcurrentGC();
     void TemporaryDisableConcurrentGC();
     BOOL IsConcurrentGCEnabled();    
-  
+
     PER_HEAP_ISOLATED   CLREvent *WaitForGCEvent;     // used for syncing w/GC
 
     PER_HEAP_ISOLATED    CFinalize* m_Finalize;
index c5f4837..7729ffa 100644 (file)
@@ -178,11 +178,12 @@ VOID CNameSpace::GcScanRoots(promote_func* fn,  int condemned, int max_gen,
             }
 
             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
@@ -324,9 +325,9 @@ void CNameSpace::GcFixAllocContexts (void* arg, void *heap)
     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);
         }
     }
 }
@@ -338,9 +339,9 @@ void CNameSpace::GcEnumAllocContexts (enum_alloc_context_func* fn)
     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));
         }
     }
 }
index c3d566f..59aa60a 100644 (file)
@@ -669,6 +669,30 @@ void HndSetHandleExtraInfo(OBJECTHANDLE handle, UINT uType, LPARAM lExtraInfo)
         *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
 
 /*
index 10ca946..41ff462 100644 (file)
@@ -84,6 +84,7 @@ void            HndDestroyHandles(HHANDLETABLE hTable, UINT uType, const OBJECTH
  * 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);
index 8e07e9e..b62407a 100644 (file)
@@ -46,7 +46,7 @@ struct VARSCANINFO
 {
     LPARAM         lEnableMask; // mask of types to trace
     HANDLESCANPROC pfnTrace;    // tracing function to use
-       LPARAM             lp2;                 // second parameter
+    LPARAM         lp2;         // second parameter
 };
 
 
@@ -73,7 +73,7 @@ void CALLBACK VariableTraceDispatcher(_UNCHECKED_OBJECTREF *pObjRef, LPARAM *pEx
     }
 }
 
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK)
 /*
  * Scan callback for tracing ref-counted handles.
  *
@@ -97,12 +97,7 @@ void CALLBACK PromoteRefCounted(_UNCHECKED_OBJECTREF *pObjRef, LPARAM *pExtraInf
 
     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;
@@ -113,7 +108,7 @@ void CALLBACK PromoteRefCounted(_UNCHECKED_OBJECTREF *pObjRef, LPARAM *pExtraInf
     // 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)
 {
@@ -446,14 +441,28 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, LPARAM
         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)
@@ -463,7 +472,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, LPARAM
                 rootFlags |= kEtwGCRootFlagsWeakRef;
         }
         break;
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
     }
 
     _UNCHECKED_OBJECTREF pSec = NULL;
@@ -948,6 +957,17 @@ OBJECTHANDLE CreateVariableHandle(HHANDLETABLE hTable, OBJECTREF object, UINT ty
     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.
@@ -981,6 +1001,23 @@ void UpdateVariableHandleType(OBJECTHANDLE handle, UINT type)
     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.
@@ -1122,7 +1159,7 @@ void Ref_TraceNormalRoots(UINT condemned, UINT maxgen, ScanContext* sc, Ref_prom
     // 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)
     {
@@ -1141,7 +1178,7 @@ void Ref_TraceNormalRoots(UINT condemned, UINT maxgen, ScanContext* sc, Ref_prom
             walk = walk->pNext;
         }
     }
-#endif // FEATURE_COMINTEROP    
+#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
 }
 
 #ifdef FEATURE_COMINTEROP
@@ -1184,9 +1221,9 @@ void Ref_CheckReachable(UINT condemned, UINT maxgen, LPARAM lp1)
     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
@@ -1534,8 +1571,10 @@ void Ref_UpdatePointers(UINT condemned, UINT maxgen, ScanContext* sc, Ref_promot
         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,
@@ -1547,12 +1586,12 @@ void Ref_UpdatePointers(UINT condemned, UINT maxgen, ScanContext* sc, Ref_promot
     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;
     }
 
@@ -1578,10 +1617,12 @@ void Ref_ScanPointersForProfilerAndETW(UINT maxgen, LPARAM lp1)
         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,
@@ -1671,8 +1712,10 @@ void Ref_AgeHandles(UINT condemned, UINT maxgen, LPARAM lp1)
 
         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,
@@ -1712,8 +1755,10 @@ void Ref_RejuvenateHandles(UINT condemned, UINT maxgen, LPARAM lp1)
 
         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,
@@ -1752,8 +1797,10 @@ void Ref_VerifyHandleTable(UINT condemned, UINT maxgen, ScanContext* sc)
 
         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,
@@ -1781,8 +1828,8 @@ int GetCurrentThreadHomeHeapNumber()
 {
     WRAPPER_NO_CONTRACT;
 
-       if (!GCHeap::IsGCHeapInitialized())
-               return 0;
+    if (!GCHeap::IsGCHeapInitialized())
+        return 0;
     return GCHeap::GetGCHeap()->GetHomeHeapNumber();
 }
 
index 6371c7a..5267d7b 100644 (file)
  */
 #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
@@ -439,7 +439,9 @@ inline void DestroyDependentHandle(OBJECTHANDLE handle)
 #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)
 {
index 7c47fec..071a87f 100644 (file)
@@ -145,7 +145,7 @@ int main(int argc, char* argv[])
     //
     // Initialize current thread
     //
-    ThreadStore::AttachCurrentThread(false);
+    ThreadStore::AttachCurrentThread();
 
     //
     // Create a Methodtable with GCDesc
index 235d75d..a0a79c5 100644 (file)
@@ -83,6 +83,7 @@
     <ClInclude Include="gcenv.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="gcenv.cpp" />
     <ClCompile Include="GCSample.cpp" />
     <ClCompile Include="..\gccommon.cpp" />
     <ClCompile Include="..\gceewks.cpp" />
@@ -93,7 +94,7 @@
     <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>
index 07c46a7..1e9facd 100644 (file)
@@ -23,9 +23,6 @@
     </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
diff --git a/src/coreclr/src/gc/sample/gcenv.cpp b/src/coreclr/src/gc/sample/gcenv.cpp
new file mode 100644 (file)
index 0000000..45af9bc
--- /dev/null
@@ -0,0 +1,155 @@
+//
+// 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;
+}
diff --git a/src/coreclr/src/gc/sample/gcenv.h b/src/coreclr/src/gc/sample/gcenv.h
new file mode 100644 (file)
index 0000000..327aa36
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// 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;
index 963ca3a..7ed4328 100644 (file)
@@ -21,6 +21,7 @@
 #ifdef FEATURE_COMINTEROP
 #include "runtimecallablewrapper.h"
 #include "rcwwalker.h"
+#include "comcallablewrapper.h"
 #endif // FEATURE_COMINTEROP
 
 void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
@@ -611,6 +612,26 @@ void GCToEEInterface::GcDone(int condemned)
 #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
@@ -649,3 +670,27 @@ void GCToEEInterface::SyncBlockCachePromotionsGranted(int max_gen)
 
     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);
+}
index fc5ca6d..5816d02 100644 (file)
@@ -99,10 +99,38 @@ public:
     // 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
index ba0c8ba..ba6aebb 100644 (file)
@@ -6269,7 +6269,7 @@ CorInfoHelpFunc CEEInfo::getNewHelperStatic(MethodTable * pMT)
         _ASSERTE(helper == CORINFO_HELP_NEWFAST);
     }
     else
-    if (GCHeap::IsLargeObject(pMT) ||
+    if ((pMT->GetBaseSize() >= LARGE_OBJECT_SIZE) || 
         pMT->HasFinalizer())
     {
         // Use slow helper