summaryrefslogtreecommitdiff
path: root/src/vm/threads.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/threads.h')
-rw-r--r--src/vm/threads.h477
1 files changed, 59 insertions, 418 deletions
diff --git a/src/vm/threads.h b/src/vm/threads.h
index 51116e1ad6..a055f2e9e0 100644
--- a/src/vm/threads.h
+++ b/src/vm/threads.h
@@ -143,6 +143,7 @@
#include "mscoree.h"
#include "appdomainstack.h"
#include "gcheaputilities.h"
+#include "gchandletableutilities.h"
#include "gcinfotypes.h"
#include <clrhost.h>
@@ -244,12 +245,6 @@ public:
static void ObjectRefProtected(const OBJECTREF* ref) { }
static void ObjectRefNew(const OBJECTREF* ref) { }
- static void ReverseLeaveRuntime();
- static void __stdcall EnterRuntime();
-
- static void BeginThreadAffinity() { }
- static void EndThreadAffinity() { }
-
void EnablePreemptiveGC() { }
void DisablePreemptiveGC() { }
@@ -419,32 +414,6 @@ public:
}
};
-class LeaveRuntimeHolder
-{
-public:
- template <typename T>
- LeaveRuntimeHolder(T target)
- {
- STATIC_CONTRACT_LIMITED_METHOD;
- }
-};
-
-class LeaveRuntimeHolderNoThrow
-{
-public:
- template <typename T>
- LeaveRuntimeHolderNoThrow(T target)
- {
- STATIC_CONTRACT_LIMITED_METHOD;
- }
-
- HRESULT GetHR() const
- {
- STATIC_CONTRACT_LIMITED_METHOD;
- return S_OK;
- }
-};
-
inline BOOL dbgOnly_IsSpecialEEThread() { return FALSE; }
#define INCTHREADLOCKCOUNT() { }
@@ -584,14 +553,6 @@ inline Thread* GetThreadNULLOk()
#define GetThreadNULLOk() GetThread()
#endif
-//***************************************************************************
-#if defined(_DEBUG) && defined(_TARGET_X86_) && !defined(FEATURE_CORECLR)
- #define HAS_TRACK_CXX_EXCEPTION_CODE_HACK 1
- #define TRACK_CXX_EXCEPTION_CODE_HACK
-#else
- #define HAS_TRACK_CXX_EXCEPTION_CODE_HACK 0
-#endif
-
// manifest constant for waiting in the exposed classlibs
const INT32 INFINITE_TIMEOUT = -1;
@@ -675,7 +636,7 @@ DWORD GetAppDomainTLSIndex();
DWORD GetRuntimeId();
-EXTERN_C Thread* __stdcall CreateThreadBlockThrow();
+EXTERN_C Thread* WINAPI CreateThreadBlockThrow();
//---------------------------------------------------------------------------
// One-time initialization. Called during Dll initialization.
@@ -688,9 +649,9 @@ void InitThreadManager();
#ifdef FEATURE_HIJACK
-EXTERN_C void __stdcall OnHijackTripThread();
+EXTERN_C void WINAPI OnHijackTripThread();
#ifdef _TARGET_X86_
-EXTERN_C void __stdcall OnHijackFPTripThread(); // hijacked JIT code is returning an FP value
+EXTERN_C void WINAPI OnHijackFPTripThread(); // hijacked JIT code is returning an FP value
#endif // _TARGET_X86_
#endif // FEATURE_HIJACK
@@ -1036,14 +997,10 @@ class BaseStackGuard;
//
// A code:Thread contains all the per-thread information needed by the runtime. You can get at this
// structure throught the and OS TLS slot see code:#RuntimeThreadLocals for more
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
-class Thread: public ICLRTask2
-#else // !FEATURE_INCLUDE_ALL_INTERFACES
// Implementing IUnknown would prevent the field (e.g. m_Context) layout from being rearranged (which will need to be fixed in
// "asmconstants.h" for the respective architecture). As it is, ICLRTask derives from IUnknown and would have got IUnknown implemented
// here - so doing this explicitly and maintaining layout sanity should be just fine.
class Thread: public IUnknown
-#endif // FEATURE_INCLUDE_ALL_INTERFACES
{
friend struct ThreadQueue; // used to enqueue & dequeue threads onto SyncBlocks
friend class ThreadStore;
@@ -1274,9 +1231,7 @@ public:
// effort.
//
// Once we are completely independent of the OS UEF, we could remove this.
-#ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
TSNC_InsideSyncContextWait = 0x02000000, // Whether we are inside DoSyncContextWait
-#endif // FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
TSNC_DebuggerSleepWaitJoin = 0x04000000, // Indicates to the debugger that this thread is in a sleep wait or join state
// This almost mirrors the TS_Interruptible state however that flag can change
// during GC-preemptive mode whereas this one cannot.
@@ -1309,10 +1264,6 @@ public:
DAC_EMPTY_RET(E_FAIL);
STDMETHODIMP Reset (BOOL fFull)
DAC_EMPTY_RET(E_FAIL);
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
- STDMETHODIMP GetMemStats(COR_GC_THREAD_STATS *memUsage)
- DAC_EMPTY_RET(E_FAIL);
-#endif //FEATURE_INCLUDE_ALL_INTERFACES
STDMETHODIMP ExitTask()
DAC_EMPTY_RET(E_FAIL);
STDMETHODIMP Abort()
@@ -1500,6 +1451,24 @@ public:
}
#endif //FEATURE_COMINTEROP
+#ifndef DACCESS_COMPILE
+ bool HasDeadThreadBeenConsideredForGCTrigger()
+ {
+ LIMITED_METHOD_CONTRACT;
+ _ASSERTE(IsDead());
+
+ return m_fHasDeadThreadBeenConsideredForGCTrigger;
+ }
+
+ void SetHasDeadThreadBeenConsideredForGCTrigger()
+ {
+ LIMITED_METHOD_CONTRACT;
+ _ASSERTE(IsDead());
+
+ m_fHasDeadThreadBeenConsideredForGCTrigger = true;
+ }
+#endif // !DACCESS_COMPILE
+
// returns if there is some extra work for the finalizer thread.
BOOL HaveExtraWorkForFinalizer();
@@ -1641,13 +1610,6 @@ public:
// in the object header to store it.
DWORD m_ThreadId;
- #if HAS_TRACK_CXX_EXCEPTION_CODE_HACK // do we have C++ exception code tracking?
- // It's very hard to deal with SEH properly using C++ catch handlers. The
- // following field is updated with the correct SEH exception whenever a C++
- // __CxxFrameHandler3 call is made on this thread. If you grab it at the
- // top of a C++ catch(...), it's likely to be correct.
- DWORD m_LastCxxSEHExceptionCode;
- #endif // HAS_TRACK_CXX_EXCEPTION_CODE_HACK
// RWLock state
LockEntry *m_pHead;
@@ -1790,12 +1752,6 @@ public:
private:
DWORD m_dwBeginLockCount; // lock count when the thread enters current domain
-#ifndef FEATURE_CORECLR
- DWORD m_dwBeginCriticalRegionCount; // lock count when the thread enters current domain
- DWORD m_dwCriticalRegionCount;
-
- DWORD m_dwThreadAffinityCount;
-#endif // !FEATURE_CORECLR
#ifdef _DEBUG
DWORD dbg_m_cSuspendedThreads;
@@ -1888,68 +1844,19 @@ public:
LIMITED_METHOD_CONTRACT;
_ASSERTE(m_dwLockCount >= m_dwBeginLockCount);
-#ifndef FEATURE_CORECLR
- _ASSERTE(m_dwCriticalRegionCount >= m_dwBeginCriticalRegionCount);
-#endif // !FEATURE_CORECLR
// Equivalent to (m_dwLockCount != m_dwBeginLockCount ||
// m_dwCriticalRegionCount ! m_dwBeginCriticalRegionCount),
// but without branching instructions
BOOL fHasLock = (m_dwLockCount ^ m_dwBeginLockCount);
-#ifndef FEATURE_CORECLR
- fHasLock |= (m_dwCriticalRegionCount ^ m_dwBeginCriticalRegionCount);
-#endif // !FEATURE_CORECLR
return fHasLock;
}
-#ifndef FEATURE_CORECLR
- inline void BeginCriticalRegion()
- {
- LIMITED_METHOD_CONTRACT;
- _ASSERTE (GetThread() == this);
- if (CLRHosted())
- {
- m_dwCriticalRegionCount ++;
- _ASSERTE (m_dwCriticalRegionCount != 0);
- }
- }
-
- inline void EndCriticalRegion()
- {
- LIMITED_METHOD_CONTRACT;
- _ASSERTE (GetThread() == this);
- if (CLRHosted())
- {
- _ASSERTE (m_dwCriticalRegionCount > 0);
- m_dwCriticalRegionCount --;
- }
- }
-
- inline void BeginCriticalRegion_NoCheck()
- {
- LIMITED_METHOD_CONTRACT;
- _ASSERTE (GetThread() == this);
- m_dwCriticalRegionCount ++;
- _ASSERTE (m_dwCriticalRegionCount != 0);
- }
-
- inline void EndCriticalRegion_NoCheck()
- {
- LIMITED_METHOD_CONTRACT;
- _ASSERTE (GetThread() == this);
- _ASSERTE (m_dwCriticalRegionCount > 0);
- m_dwCriticalRegionCount --;
- }
-#endif // !FEATURE_CORECLR
inline BOOL HasCriticalRegion()
{
LIMITED_METHOD_CONTRACT;
-#ifndef FEATURE_CORECLR
- return m_dwCriticalRegionCount != 0;
-#else
return FALSE;
-#endif
}
inline DWORD GetNewHashCode()
@@ -1982,63 +1889,11 @@ public:
#endif
public:
- static void __stdcall LeaveRuntime(size_t target);
- static HRESULT LeaveRuntimeNoThrow(size_t target);
- static void __stdcall LeaveRuntimeThrowComplus(size_t target);
- static void __stdcall EnterRuntime();
- static HRESULT EnterRuntimeNoThrow();
- static HRESULT EnterRuntimeNoThrowWorker();
-
- // Reverse PInvoke hook for host
- static void ReverseEnterRuntime();
- static HRESULT ReverseEnterRuntimeNoThrow();
- static void ReverseEnterRuntimeThrowComplusHelper(HRESULT hr);
- static void ReverseEnterRuntimeThrowComplus();
- static void ReverseLeaveRuntime();
-
- // Hook for OS Critical Section, Mutex, and others that require thread affinity
- static void BeginThreadAffinity();
- static void EndThreadAffinity();
-
-#ifndef FEATURE_CORECLR
- inline void IncThreadAffinityCount()
- {
- LIMITED_METHOD_CONTRACT;
- _ASSERTE (GetThread() == this);
- m_dwThreadAffinityCount++;
- _ASSERTE (m_dwThreadAffinityCount > 0);
- }
- inline void DecThreadAffinityCount()
- {
- LIMITED_METHOD_CONTRACT;
- _ASSERTE (GetThread() == this);
- _ASSERTE (m_dwThreadAffinityCount > 0);
- m_dwThreadAffinityCount --;
- }
-
- static void BeginThreadAffinityAndCriticalRegion()
- {
- LIMITED_METHOD_CONTRACT;
- BeginThreadAffinity();
- GetThread()->BeginCriticalRegion();
- }
-
- static void EndThreadAffinityAndCriticalRegion()
- {
- LIMITED_METHOD_CONTRACT;
- GetThread()->EndCriticalRegion();
- EndThreadAffinity();
- }
-#endif // !FEATURE_CORECLR
BOOL HasThreadAffinity()
{
LIMITED_METHOD_CONTRACT;
-#ifndef FEATURE_CORECLR
- return m_dwThreadAffinityCount > 0;
-#else
return FALSE;
-#endif
}
private:
@@ -2603,9 +2458,6 @@ public:
return m_Context;
}
-#ifdef FEATURE_REMOTING
- void SetExposedContext(Context *c);
-#endif
// This callback is used when we are executing in the EE and discover that we need
// to switch appdomains.
@@ -2636,11 +2488,7 @@ private:
//
// In Telesto, we don't support true appdomain marshaling so the "orBlob" is in fact an
// agile wrapper object whose ToString() echoes the original exception's ToString().
-#ifdef FEATURE_CORECLR
typedef OBJECTREF ORBLOBREF;
-#else
- typedef U1ARRAYREF ORBLOBREF;
-#endif
RaiseCrossContextResult TryRaiseCrossContextException(Exception **ppExOrig,
Exception *pException,
@@ -2797,7 +2645,6 @@ public:
return (ObjectFromHandle(m_ExposedObject) != NULL) ;
}
-#ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
void GetSynchronizationContext(OBJECTREF *pSyncContextObj)
{
CONTRACTL
@@ -2815,24 +2662,7 @@ public:
if (ExposedThreadObj != NULL)
*pSyncContextObj = ExposedThreadObj->GetSynchronizationContext();
}
-#endif // FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
-#ifdef FEATURE_COMPRESSEDSTACK
- OBJECTREF GetCompressedStack()
- {
- CONTRACTL
- {
- MODE_COOPERATIVE;
- GC_NOTRIGGER;
- NOTHROW;
- }
- CONTRACTL_END;
- THREADBASEREF ExposedThreadObj = (THREADBASEREF)GetExposedObjectRaw();
- if (ExposedThreadObj != NULL)
- return (OBJECTREF)(ExposedThreadObj->GetCompressedStack());
- return NULL;
- }
-#endif // #ifdef FEATURE_COMPRESSEDSTACK
// When we create a managed thread, the thread is suspended. We call StartThread to get
// the thread start.
@@ -2909,9 +2739,6 @@ public:
)
{
WRAPPER_NO_CONTRACT;
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
- _ASSERTE (m_pHostTask == NULL || GetThreadHandle() != SWITCHOUT_HANDLE_VALUE);
-#endif // FEATURE_INCLUDE_ALL_INTERFACES
return ::GetThreadContext (GetThreadHandle(), lpContext);
}
@@ -2921,9 +2748,6 @@ public:
)
{
WRAPPER_NO_CONTRACT;
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
- _ASSERTE (m_pHostTask == NULL || GetThreadHandle() != SWITCHOUT_HANDLE_VALUE);
-#endif // FEATURE_INCLUDE_ALL_INTERFACES
return ::SetThreadContext (GetThreadHandle(), lpContext);
}
#endif
@@ -2931,12 +2755,7 @@ public:
BOOL HasValidThreadHandle ()
{
WRAPPER_NO_CONTRACT;
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
- return m_pHostTask != NULL ||
- GetThreadHandle() != INVALID_HANDLE_VALUE;
-#else // !FEATURE_INCLUDE_ALL_INTERFACES
return GetThreadHandle() != INVALID_HANDLE_VALUE;
-#endif // FEATURE_INCLUDE_ALL_INTERFACES
}
DWORD GetThreadId()
@@ -2978,17 +2797,6 @@ public:
return m_dwConnectionId;
}
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
- IHostTask* GetHostTask() const
- {
- LIMITED_METHOD_CONTRACT;
- return m_pHostTask;
- }
-
- IHostTask* GetHostTaskWithAddRef();
-
- void ReleaseHostTask();
-#endif // FEATURE_INCLUDE_ALL_INTERFACES
void SetConnectionId(CONNID dwConnectionId)
{
@@ -3007,10 +2815,6 @@ public:
static bool SysStartSuspendForDebug(AppDomain *pAppDomain);
static bool SysSweepThreadsForDebug(bool forceSync);
static void SysResumeFromDebug(AppDomain *pAppDomain);
-#ifndef FEATURE_CORECLR
- void UserSuspendThread();
- BOOL UserResumeThread();
-#endif // FEATURE_CORECLR
void UserSleep(INT32 time);
@@ -3515,9 +3319,7 @@ private:
DWORD DoSignalAndWaitWorker(HANDLE* pHandles, DWORD millis,BOOL alertable);
#endif // !FEATURE_PAL
DWORD DoAppropriateAptStateWait(int numWaiters, HANDLE* pHandles, BOOL bWaitAll, DWORD timeout, WaitMode mode);
-#ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
DWORD DoSyncContextWait(OBJECTREF *pSyncCtxObj, int countHandles, HANDLE *handles, BOOL waitAll, DWORD millis);
-#endif // #ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
public:
//************************************************************************
@@ -3615,10 +3417,12 @@ public:
static PCODE VirtualUnwindCallFrame(T_CONTEXT* pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers = NULL,
EECodeInfo * pCodeInfo = NULL);
static UINT_PTR VirtualUnwindCallFrame(PREGDISPLAY pRD, EECodeInfo * pCodeInfo = NULL);
+#ifndef DACCESS_COMPILE
static PCODE VirtualUnwindLeafCallFrame(T_CONTEXT* pContext);
static PCODE VirtualUnwindNonLeafCallFrame(T_CONTEXT* pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers = NULL,
PT_RUNTIME_FUNCTION pFunctionEntry = NULL, UINT_PTR uImageBase = NULL);
static UINT_PTR VirtualUnwindToFirstManagedCallFrame(T_CONTEXT* pContext);
+#endif // DACCESS_COMPILE
#endif // WIN64EXCEPTIONS
// During a <clinit>, this thread must not be asynchronously
@@ -3702,9 +3506,6 @@ public:
OBJECTREF GetCulture(BOOL bUICulture);
// Release user cultures that can't survive appdomain unload
-#ifdef FEATURE_LEAK_CULTURE_INFO
- void ResetCultureForDomain(ADID id);
-#endif // FEATURE_LEAK_CULTURE_INFO
// Functions to set the culture on the thread.
void SetCultureId(LCID lcid, BOOL bUICulture);
@@ -3930,9 +3731,11 @@ private:
void SetupForSuspension(ULONG bit)
{
WRAPPER_NO_CONTRACT;
- if (bit & TS_UserSuspendPending) {
- m_UserSuspendEvent.Reset();
- }
+
+ // CoreCLR does not support user-requested thread suspension
+ _ASSERTE(!(bit & TS_UserSuspendPending));
+
+
if (bit & TS_DebugSuspendPending) {
m_DebugSuspendEvent.Reset();
}
@@ -3949,8 +3752,14 @@ private:
//
ThreadState oldState = m_State;
+ // CoreCLR does not support user-requested thread suspension
+ _ASSERTE(!(oldState & TS_UserSuspendPending));
+
while ((oldState & (TS_UserSuspendPending | TS_DebugSuspendPending)) == 0)
{
+ // CoreCLR does not support user-requested thread suspension
+ _ASSERTE(!(oldState & TS_UserSuspendPending));
+
//
// Construct the destination state we desire - all suspension bits turned off.
//
@@ -3969,9 +3778,8 @@ private:
oldState = m_State;
}
- if (bit & TS_UserSuspendPending) {
- m_UserSuspendEvent.Set();
- }
+ // CoreCLR does not support user-requested thread suspension
+ _ASSERTE(!(bit & TS_UserSuspendPending));
if (bit & TS_DebugSuspendPending) {
m_DebugSuspendEvent.Set();
@@ -3979,13 +3787,6 @@ private:
}
- // For getting a thread to a safe point. A client waits on the event, which is
- // set by the thread when it reaches a safe spot.
-#ifndef FEATURE_CORECLR
- void FinishSuspendingThread();
-#endif // FEATURE_CORECLR
- void SetSafeEvent();
-
public:
FORCEINLINE void UnhijackThreadNoAlloc()
{
@@ -4070,7 +3871,7 @@ private:
void HandleThreadInterrupt(BOOL fWaitForADUnload);
public:
- static void __stdcall UserInterruptAPC(ULONG_PTR ignore);
+ static void WINAPI UserInterruptAPC(ULONG_PTR ignore);
#if defined(_DEBUG) && defined(TRACK_SYNC)
@@ -4106,8 +3907,6 @@ public:
private:
// For suspends:
- CLREvent m_SafeEvent;
- CLREvent m_UserSuspendEvent;
CLREvent m_DebugSuspendEvent;
// For Object::Wait, Notify and NotifyAll, we use an Event inside the
@@ -4177,7 +3976,6 @@ private:
DWORD m_OSThreadId;
BOOL CreateNewOSThread(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, void *args);
- BOOL CreateNewHostTask(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, void *args);
OBJECTHANDLE m_ExposedObject;
OBJECTHANDLE m_StrongHndToExposedObject;
@@ -4649,11 +4447,9 @@ public:
public:
typedef Holder<Thread *, DoNothing, Thread::LoadingFileRelease> LoadingFileHolder;
-#ifndef FEATURE_LEAK_CULTURE_INFO
void InitCultureAccessors();
FieldDesc *managedThreadCurrentCulture;
FieldDesc *managedThreadCurrentUICulture;
-#endif
private:
// Don't allow a thread to be asynchronously stopped or interrupted (e.g. because
// it is performing a <clinit>)
@@ -4903,16 +4699,6 @@ public:
size_t *m_pCleanedStackBase;
#endif
-#ifdef STRESS_THREAD
-public:
- LONG m_stressThreadCount;
-#endif
-
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
-public:
- IHostTask *m_pHostTask;
-#endif
-
private:
PVOID m_pFiberData;
@@ -4985,7 +4771,7 @@ public:
private:
// used to pad stack on thread creation to avoid aliasing penalty in P4 HyperThread scenarios
- static DWORD __stdcall intermediateThreadProc(PVOID arg);
+ static DWORD WINAPI intermediateThreadProc(PVOID arg);
static int m_offset_counter;
static const int offset_multiplier = 128;
@@ -5247,10 +5033,6 @@ public:
static BOOL GetProcessDefaultStackSize(SIZE_T* reserveSize, SIZE_T* commitSize);
private:
- // YieldTask, ThreadAbort, GC all change thread context. ThreadAbort and GC uses ThreadStore lock to synchronize. But YieldTask can
- // not block. We use a counter to allow one thread to change thread context.
-
- Volatile<PVOID> m_WorkingOnThreadContext;
// Although this is a pointer, it is used as a flag to indicate the current context is unsafe
// to inspect. When NULL the context is safe to use, otherwise it points to the active patch skipper
@@ -5291,37 +5073,16 @@ private:
{
return FALSE;
}
- if (CLRTaskHosted())
- {
- PVOID myID = ClrTeb::GetFiberPtrId();
- PVOID id = FastInterlockCompareExchangePointer(pThread->m_WorkingOnThreadContext.GetPointer(), myID, NULL);
- return id == NULL || id == myID;
- }
- else
- {
- return TRUE;
- }
+ return TRUE;
}
static void LeaveWorkingOnThreadContext(Thread *pThread)
{
LIMITED_METHOD_CONTRACT;
-
- if (pThread->m_WorkingOnThreadContext == ClrTeb::GetFiberPtrId())
- {
- pThread->m_WorkingOnThreadContext = NULL;
- }
}
typedef ConditionalStateHolder<Thread *, Thread::EnterWorkingOnThreadContext, Thread::LeaveWorkingOnThreadContext> WorkingOnThreadContextHolder;
- BOOL WorkingOnThreadContext()
- {
- LIMITED_METHOD_CONTRACT;
-
- return !CLRTaskHosted() || m_WorkingOnThreadContext == ClrTeb::GetFiberPtrId();
- }
-
public:
void PrepareThreadForSOWork()
{
@@ -5489,6 +5250,9 @@ private:
// Disables pumping and thread join in RCW creation
bool m_fDisableComObjectEagerCleanup;
+ // See ThreadStore::TriggerGCForDeadThreadsIfNecessary()
+ bool m_fHasDeadThreadBeenConsideredForGCTrigger;
+
private:
CLRRandom m_random;
@@ -5603,16 +5367,9 @@ public:
LCID GetThreadCultureIdNoThrow(Thread *pThread, BOOL bUICulture);
-#ifndef FEATURE_CORECLR
-// Request/Remove Thread Affinity for the current thread
-typedef StateHolder<Thread::BeginThreadAffinityAndCriticalRegion, Thread::EndThreadAffinityAndCriticalRegion> ThreadAffinityAndCriticalRegionHolder;
-#endif // !FEATURE_CORECLR
-typedef StateHolder<Thread::BeginThreadAffinity, Thread::EndThreadAffinity> ThreadAffinityHolder;
-
typedef Thread::ForbidSuspendThreadHolder ForbidSuspendThreadHolder;
typedef Thread::ThreadPreventAsyncHolder ThreadPreventAsyncHolder;
typedef Thread::ThreadPreventAbortHolder ThreadPreventAbortHolder;
-typedef StateHolder<Thread::ReverseEnterRuntime, Thread::ReverseLeaveRuntime> ReverseEnterRuntimeHolder;
// Combines ForBindSuspendThreadHolder and CrstHolder into one.
class ForbidSuspendThreadCrstHolder
@@ -5629,97 +5386,13 @@ private:
CrstHolder m_lock_holder;
};
-// Non-throwing flavor of ReverseEnterRuntimeHolder that requires explicit call to AcquireNoThrow to acquire
-class ReverseEnterRuntimeHolderNoThrow : StateHolder<DoNothing, Thread::ReverseLeaveRuntime>
-{
-public:
- ReverseEnterRuntimeHolderNoThrow()
- : StateHolder<DoNothing, Thread::ReverseLeaveRuntime>(FALSE)
- {
- }
-
- HRESULT AcquireNoThrow()
- {
- WRAPPER_NO_CONTRACT;
-
- HRESULT hr = Thread::ReverseEnterRuntimeNoThrow();
- if (SUCCEEDED(hr))
- Acquire();
- return hr;
- }
-};
-
ETaskType GetCurrentTaskType();
-class LeaveRuntimeHolder
-{
-public:
- template <typename T>
- LeaveRuntimeHolder(T target)
- {
- STATIC_CONTRACT_WRAPPER;
- if (!CLRTaskHosted())
- return;
-
- Thread::LeaveRuntime((size_t)target);
- }
-
- ~LeaveRuntimeHolder()
- {
- STATIC_CONTRACT_WRAPPER;
- if (!CLRTaskHosted())
- return;
-
- Thread::EnterRuntime();
- }
-};
-
-class LeaveRuntimeHolderNoThrow
-{
-public:
- template <typename T>
- LeaveRuntimeHolderNoThrow(T target)
- {
- STATIC_CONTRACT_WRAPPER;
- if (!CLRTaskHosted())
- {
- hr = S_OK;
- return;
- }
-
- hr = Thread::LeaveRuntimeNoThrow((size_t)target);
- }
-
- ~LeaveRuntimeHolderNoThrow()
- {
- STATIC_CONTRACT_WRAPPER;
- if (!CLRTaskHosted())
- {
- hr = S_OK;
- return;
- }
-
- hr = Thread::EnterRuntimeNoThrow();
- }
-
- HRESULT GetHR() const
- {
- LIMITED_METHOD_CONTRACT;
- return hr;
- }
-
-private:
- HRESULT hr;
-};
-
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
-IHostTask *GetCurrentHostTask();
-#endif // FEATURE_INCLUDE_ALL_INTERFACES
typedef Thread::AVInRuntimeImplOkayHolder AVInRuntimeImplOkayHolder;
-BOOL RevertIfImpersonated(BOOL *bReverted, HANDLE *phToken, ThreadAffinityHolder *pTAHolder);
+BOOL RevertIfImpersonated(BOOL *bReverted, HANDLE *phToken);
void UndoRevert(BOOL bReverted, HANDLE hToken);
// ---------------------------------------------------------------------------
@@ -5866,6 +5539,8 @@ private:
LONG m_PendingThreadCount;
LONG m_DeadThreadCount;
+ LONG m_DeadThreadCountForGCTrigger;
+ bool m_TriggerGCForDeadThreads;
private:
// Space for the lazily-created GUID.
@@ -5878,6 +5553,11 @@ private:
Thread *m_HoldingThread;
EEThreadId m_holderthreadid; // current holder (or NULL)
+private:
+ static LONG s_DeadThreadCountThresholdForGCTrigger;
+ static DWORD s_DeadThreadGCTriggerPeriodMilliseconds;
+ static SIZE_T *s_DeadThreadGenerationCounts;
+
public:
static BOOL HoldingThreadStore()
@@ -5951,6 +5631,14 @@ public:
LIMITED_METHOD_CONTRACT;
s_pWaitForStackCrawlEvent->Reset();
}
+
+private:
+ void IncrementDeadThreadCountForGCTrigger();
+ void DecrementDeadThreadCountForGCTrigger();
+public:
+ void OnMaxGenerationGCStarted();
+ bool ShouldTriggerGCForDeadThreads();
+ void TriggerGCForDeadThreadsIfNecessary();
};
struct TSSuspendHelper {
@@ -6201,59 +5889,12 @@ struct PendingSync
void Restore(BOOL bRemoveFromSB);
};
-#ifdef FEATURE_INCLUDE_ALL_INTERFACES
-
-//
-// Tracking of unmanaged locks has very low value. It is only
-// exposed via SQL hosting interfaces. The hosts cannot really
-// do anything interesting with it because of the unmanaged locks
-// are always taken with holders in the VM, and hosts can keep
-// track of the unmanaged locks taken via hosting API. We should
-// consider getting rid of it in the next SxS version.
-//
-
-#define INCTHREADLOCKCOUNT() \
-{ \
- /* IncLockCount() asserts GetThread() == this */ \
- BEGIN_GETTHREAD_ALLOWED_IN_NO_THROW_REGION; \
- Thread *thread = GetThread(); \
- if (thread) \
- thread->IncLockCount(); \
- END_GETTHREAD_ALLOWED_IN_NO_THROW_REGION; \
-}
-
-#define INCTHREADLOCKCOUNTTHREAD(thread) \
-{ \
- /* IncLockCount() asserts GetThread() == this */ \
- if (thread) \
- (thread)->IncLockCount(); \
-}
-
-#define DECTHREADLOCKCOUNT( ) \
-{ \
- /* IncLockCount() asserts GetThread() == this */ \
- BEGIN_GETTHREAD_ALLOWED_IN_NO_THROW_REGION; \
- Thread *thread = GetThread(); \
- if (thread) \
- thread->DecLockCount(); \
- END_GETTHREAD_ALLOWED_IN_NO_THROW_REGION; \
-}
-
-#define DECTHREADLOCKCOUNTTHREAD(thread) \
-{ \
- /* IncLockCount() asserts GetThread() == this */ \
- if (thread) \
- (thread)->DecLockCount(); \
-}
-
-#else
#define INCTHREADLOCKCOUNT() { }
#define DECTHREADLOCKCOUNT() { }
#define INCTHREADLOCKCOUNTTHREAD(thread) { }
#define DECTHREADLOCKCOUNTTHREAD(thread) { }
-#endif
// --------------------------------------------------------------------------------
// GCHolder is used to implement the normal GCX_ macros.