diff options
Diffstat (limited to 'src/vm/threads.h')
-rw-r--r-- | src/vm/threads.h | 477 |
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. |