From dc11162e1c36624d3cabb6e0bf6583a94ab2e30c Mon Sep 17 00:00:00 2001 From: Steve MacLean Date: Tue, 5 Mar 2019 06:29:18 -0500 Subject: Remove dead AppDomain unload code (#23026) --- src/ToolBox/SOS/Strike/strike.cpp | 4 - src/debug/ee/debugger.cpp | 2 - src/vm/appdomain.cpp | 290 --------------------- src/vm/appdomain.hpp | 9 - src/vm/dllimportcallback.h | 2 - src/vm/eepolicy.cpp | 6 - src/vm/eepolicy.h | 3 - src/vm/excep.cpp | 6 - src/vm/finalizerthread.cpp | 47 +--- src/vm/syncblk.cpp | 31 --- src/vm/syncblk.h | 4 - src/vm/synch.h | 3 +- src/vm/threadpoolrequest.cpp | 108 +------- src/vm/threadpoolrequest.h | 58 +---- src/vm/threads.cpp | 18 +- src/vm/threads.h | 22 +- src/vm/threadsuspend.cpp | 217 +-------------- src/vm/win32threadpool.cpp | 25 +- src/vm/win32threadpool.h | 2 +- .../GC/Stress/Framework/ReliabilityFramework.cs | 30 --- 20 files changed, 48 insertions(+), 839 deletions(-) diff --git a/src/ToolBox/SOS/Strike/strike.cpp b/src/ToolBox/SOS/Strike/strike.cpp index 7d74458d46..f85957ee14 100644 --- a/src/ToolBox/SOS/Strike/strike.cpp +++ b/src/ToolBox/SOS/Strike/strike.cpp @@ -6562,10 +6562,6 @@ HRESULT PrintSpecialThreads() { type += "Finalizer "; } - if (ThreadType & ThreadType_ADUnloadHelper) - { - type += "ADUnloadHelper "; - } if (ThreadType & ThreadType_ShutdownHelper) { type += "ShutdownHelper "; diff --git a/src/debug/ee/debugger.cpp b/src/debug/ee/debugger.cpp index aea9020a67..86cd547501 100644 --- a/src/debug/ee/debugger.cpp +++ b/src/debug/ee/debugger.cpp @@ -10039,8 +10039,6 @@ LExit: // Called when this module is completely gone from ALL AppDomains, regardless of // whether a debugger is attached. -// Note that this doesn't get called until after the ADUnload is complete, which happens -// asyncronously in Whidbey (and won't happen at all if the process shuts down first). // This is normally not called only domain-neutral assemblies because they can't be unloaded. // However, it may be called if the loader fails to completely load a domain-neutral assembly. void Debugger::DestructModule(Module *pModule) diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 563de46075..6aff6ab60a 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -95,8 +95,6 @@ static const WCHAR OTHER_DOMAIN_FRIENDLY_NAME_PREFIX[] = W("Domain"); #define STATIC_OBJECT_TABLE_BUCKET_SIZE 1020 -//#define _DEBUG_ADUNLOAD 1 - // Statics SPTR_IMPL(AppDomain, AppDomain, m_pTheAppDomain); @@ -6634,225 +6632,12 @@ void AppDomain::ExceptionUnwind(Frame *pFrame) CONTRACTL_END; LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind for %8.8x\n", pFrame)); -#if _DEBUG_ADUNLOAD - printf("%x AppDomain::ExceptionUnwind for %8.8p\n", GetThread()->GetThreadId(), pFrame); -#endif Thread *pThread = GetThread(); _ASSERTE(pThread); LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind: not first transition or abort\n")); } -BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - Thread *pThread = NULL; - DWORD nThreadsNeedMoreWork=0; - if (retryCount != (unsigned int)-1 && retryCount < g_pConfig->AppDomainUnloadRetryCount()) - { - Thread *pCurThread = GetThread(); - if (pCurThread->CatchAtSafePoint()) - pCurThread->PulseGCMode(); - - m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork; - return !nThreadsNeedMoreWork; - } - - // For now piggyback on the GC's suspend EE mechanism - ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_APPDOMAIN_SHUTDOWN); -#ifdef _DEBUG - // @todo: what to do with any threads that didn't stop? - _ASSERTE(ThreadStore::s_pThreadStore->DbgBackgroundThreadCount() > 0); -#endif // _DEBUG - - int totalADCount = 0; - int finalizerADCount = 0; - pThread = NULL; - - RuntimeExceptionKind reKind = kLastException; - UINT resId = 0; - SmallStackSString ssThreadId; - - while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL) - { - // we already checked that we're not running in the unload domain - if (pThread == GetThread()) - { - continue; - } - -#ifdef _DEBUG - void PrintStackTraceWithADToLog(Thread *pThread); - if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) { - LOG((LF_APPDOMAIN, LL_INFO100, "\nStackTrace for %x\n", pThread->GetThreadId())); - PrintStackTraceWithADToLog(pThread); - } -#endif // _DEBUG - int count = 0; - Frame *pFrame = pThread->GetFirstTransitionInto(this, &count); - if (! pFrame) { - _ASSERTE(count == 0); - continue; - } - - if (pThread != FinalizerThread::GetFinalizerThread()) - { - totalADCount += count; - nThreadsNeedMoreWork++; - } - else - { - finalizerADCount = count; - } - - // don't setup the exception info for the unloading thread unless it's the last one in - if (retryCount != ((unsigned int) -1) && retryCount > g_pConfig->AppDomainUnloadRetryCount() && reKind == kLastException) - { -#ifdef AD_BREAK_ON_CANNOT_UNLOAD - static int breakOnCannotUnload = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADBreakOnCannotUnload); - if (breakOnCannotUnload) - _ASSERTE(!"Cannot unload AD"); -#endif // AD_BREAK_ON_CANNOT_UNLOAD - reKind = kCannotUnloadAppDomainException; - resId = IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD; - ssThreadId.Printf(W("%x"), pThread->GetThreadId()); - STRESS_LOG2(LF_APPDOMAIN, LL_INFO10, "AppDomain::UnwindThreads cannot stop thread %x with %d transitions\n", pThread->GetThreadId(), count); - // don't break out of this early or the assert totalADCount == (int)m_dwThreadEnterCount below will fire - // it's better to chew a little extra time here and make sure our counts are consistent - } - // only abort the thread requesting the unload if it's the last one in, that way it will get - // notification that the unload failed for some other thread not being aborted. And don't abort - // the finalizer thread - let it finish it's work as it's allowed to be in there. If it won't finish, - // then we will eventually get a CannotUnloadException on it. - - if (pThread != FinalizerThread::GetFinalizerThread()) - { - - STRESS_LOG2(LF_APPDOMAIN, LL_INFO100, "AppDomain::UnwindThreads stopping %x with %d transitions\n", pThread->GetThreadId(), count); - LOG((LF_APPDOMAIN, LL_INFO100, "AppDomain::UnwindThreads stopping %x with %d transitions\n", pThread->GetThreadId(), count)); -#if _DEBUG_ADUNLOAD - printf("AppDomain::UnwindThreads %x stopping %x with first frame %8.8p\n", GetThread()->GetThreadId(), pThread->GetThreadId(), pFrame); -#endif - pThread->SetAbortRequest(EEPolicy::TA_Safe); - } - TESTHOOKCALL(UnwindingThreads(GetId().m_dwId)) ; - } - _ASSERTE(totalADCount + finalizerADCount == (int)m_dwThreadEnterCount); - - //@TODO: This is intended to catch a stress bug. Remove when no longer needed. - if (totalADCount + finalizerADCount != (int)m_dwThreadEnterCount) - FreeBuildDebugBreak(); - - // if our count did get messed up, set it to whatever count we actually found in the domain to avoid looping - // or other problems related to incorrect count. This is very much a bug if this happens - a thread should always - // exit the domain gracefully. - // m_dwThreadEnterCount = totalADCount; - - // CommonTripThread will handle the abort for any threads that we've marked - ThreadSuspend::RestartEE(FALSE, TRUE); - if (reKind != kLastException) - COMPlusThrow(reKind, resId, ssThreadId.GetUnicode()); - - _ASSERTE((totalADCount==0 && nThreadsNeedMoreWork==0) ||(totalADCount!=0 && nThreadsNeedMoreWork!=0)); - - m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork; - return (totalADCount == 0); -} - -void AppDomain::UnwindThreads() -{ - // This function should guarantee appdomain - // consistency even if it fails. Everything that is going - // to make the appdomain impossible to reenter - // should be factored out - - // @todo: need real synchronization here!!! - CONTRACTL - { - MODE_COOPERATIVE; - THROWS; - GC_TRIGGERS; - } - CONTRACTL_END; - - int retryCount = -1; - m_dwThreadsStillInAppDomain=(ULONG)-1; - ULONGLONG startTime = CLRGetTickCount64(); - - // Force threads to go through slow path during AD unload. - TSSuspendHolder shTrap; - - BOOL fMarkUnloadRequestThread = TRUE; - - // now wait for all the threads running in our AD to get out - do - { - DWORD timeout = GetEEPolicy()->GetTimeout(OPR_AppDomainUnload); - EPolicyAction action = GetEEPolicy()->GetActionOnTimeout(OPR_AppDomainUnload, NULL); - if (timeout != INFINITE && action >= eExitProcess) { - // Escalation policy specified. - ULONGLONG curTime = CLRGetTickCount64(); - ULONGLONG elapseTime = curTime - startTime; - if (elapseTime > timeout) - { - // Escalate - switch (action) - { - case eExitProcess: - case eFastExitProcess: - case eRudeExitProcess: - case eDisableRuntime: - GetEEPolicy()->NotifyHostOnTimeout(OPR_AppDomainUnload, action); - EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_TIMEOUT); - _ASSERTE (!"Should not reach here"); - break; - default: - break; - } - } - } -#ifdef _DEBUG - if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) - DumpADThreadTrack(); -#endif // _DEBUG - if (StopEEAndUnwindThreads(retryCount, &fMarkUnloadRequestThread)) - break; - if (timeout != INFINITE) - { - // Turn off the timeout used by AD. - retryCount = 1; - } - else - { - // GCStress takes a long time to unwind, due to expensive creation of - // a threadabort exception. - if (!GCStress::IsEnabled()) - ++retryCount; - LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::UnwindThreads iteration %d waiting on thread count %d\n", retryCount, m_dwThreadEnterCount)); -#if _DEBUG_ADUNLOAD - printf("AppDomain::UnwindThreads iteration %d waiting on thread count %d\n", retryCount, m_dwThreadEnterCount); -#endif - } - - if (m_dwThreadEnterCount != 0) - { -#ifdef _DEBUG - GetThread()->UserSleep(20); -#else // !_DEBUG - GetThread()->UserSleep(10); -#endif // !_DEBUG - } - } - while (TRUE) ; -} - #ifdef _DEBUG void AppDomain::TrackADThreadEnter(Thread *pThread, Frame *pFrame) @@ -7506,81 +7291,6 @@ ULONGLONG g_ObjFinalizeStartTime = 0; Volatile g_FinalizerIsRunning = FALSE; Volatile g_FinalizerLoopCount = 0; -ULONGLONG GetObjFinalizeStartTime() -{ - LIMITED_METHOD_CONTRACT; - return g_ObjFinalizeStartTime; -} - -void FinalizerThreadAbortOnTimeout() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_MODE_COOPERATIVE; - STATIC_CONTRACT_GC_TRIGGERS; - - { - // If finalizer thread is blocked because scheduler is running another task, - // or it is waiting for another thread, we first see if we get finalizer thread - // running again. - Thread::ThreadAbortWatchDog(); - } - - EX_TRY - { - Thread *pFinalizerThread = FinalizerThread::GetFinalizerThread(); - EPolicyAction action = GetEEPolicy()->GetActionOnTimeout(OPR_FinalizerRun, pFinalizerThread); - switch (action) - { - case eAbortThread: - GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action); - pFinalizerThread->UserAbort(Thread::TAR_Thread, - EEPolicy::TA_Safe, - INFINITE, - Thread::UAC_FinalizerTimeout); - break; - case eRudeAbortThread: - GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action); - pFinalizerThread->UserAbort(Thread::TAR_Thread, - EEPolicy::TA_Rude, - INFINITE, - Thread::UAC_FinalizerTimeout); - break; - case eUnloadAppDomain: - { - AppDomain *pDomain = pFinalizerThread->GetDomain(); - pFinalizerThread->UserAbort(Thread::TAR_Thread, - EEPolicy::TA_Safe, - INFINITE, - Thread::UAC_FinalizerTimeout); - } - break; - case eRudeUnloadAppDomain: - { - AppDomain *pDomain = pFinalizerThread->GetDomain(); - pFinalizerThread->UserAbort(Thread::TAR_Thread, - EEPolicy::TA_Rude, - INFINITE, - Thread::UAC_FinalizerTimeout); - } - break; - case eExitProcess: - case eFastExitProcess: - case eRudeExitProcess: - case eDisableRuntime: - GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action); - EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_TIMEOUT); - _ASSERTE (!"Should not get here"); - break; - default: - break; - } - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions); -} - enum WorkType { WT_UnloadDomain = 0x1, diff --git a/src/vm/appdomain.hpp b/src/vm/appdomain.hpp index 7fdf912327..8cfd08cc02 100644 --- a/src/vm/appdomain.hpp +++ b/src/vm/appdomain.hpp @@ -2550,11 +2550,6 @@ public: LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadExit from [%d] (%8.8x) %S count %d\n", this, GetId().m_dwId, GetFriendlyNameForLogging(), GetThreadEnterCount())); -#if _DEBUG_ADUNLOAD - printf("AppDomain::ThreadExit %x from [%d] (%8.8x) %S count %d\n", - pThread->GetThreadId(), this, GetId().m_dwId, - GetFriendlyNameForLogging(), GetThreadEnterCount()); -#endif } } #endif // DACCESS_COMPILE @@ -2908,10 +2903,6 @@ private: while (lastStage !=stage) lastStage = (Stage)FastInterlockCompareExchange((LONG*)&m_Stage,stage,lastStage); }; - void UnwindThreads(); - // Return TRUE if EE is stopped - // Return FALSE if more work is needed - BOOL StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread); // List of unloaded LoaderAllocators, protected by code:GetLoaderAllocatorReferencesLock (for now) LoaderAllocator * m_pDelayedLoaderAllocatorUnloadList; diff --git a/src/vm/dllimportcallback.h b/src/vm/dllimportcallback.h index 555b737fa5..805e9c01bb 100644 --- a/src/vm/dllimportcallback.h +++ b/src/vm/dllimportcallback.h @@ -331,8 +331,6 @@ public: void Terminate(); - void OnADUnload(); - VOID RunTimeInit() { STANDARD_VM_CONTRACT; diff --git a/src/vm/eepolicy.cpp b/src/vm/eepolicy.cpp index 50ccac0350..22d196bca6 100644 --- a/src/vm/eepolicy.cpp +++ b/src/vm/eepolicy.cpp @@ -666,12 +666,6 @@ EPolicyAction EEPolicy::DetermineResourceConstraintAction(Thread *pThread) { action = eThrowException; } - // If the current thread is AD unload helper thread, it should not block itself. - else if (pThread->HasThreadStateNC(Thread::TSNC_ADUnloadHelper) && - action < eExitProcess) - { - action = eThrowException; - } return action; } diff --git a/src/vm/eepolicy.h b/src/vm/eepolicy.h index 5d6105fbc0..dc997db4d2 100644 --- a/src/vm/eepolicy.h +++ b/src/vm/eepolicy.h @@ -163,9 +163,6 @@ inline EEPolicy* GetEEPolicy() return (EEPolicy*)&g_EEPolicyInstance; } -extern void FinalizerThreadAbortOnTimeout(); -extern ULONGLONG GetObjFinalizeStartTime(); - // // Use EEPOLICY_HANDLE_FATAL_ERROR when you have a situtation where the Runtime's internal state would be // inconsistent if execution were allowed to continue. This will apply the proper host's policy for fatal diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index f2a02a04f5..2d5a1601b5 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -4798,12 +4798,6 @@ LONG InternalUnhandledExceptionFilter_Worker( } #endif -#ifdef _DEBUG_ADUNLOAD - printf("%x InternalUnhandledExceptionFilter_Worker: Called for %x\n", - ((pThread == NULL) ? NULL : pThread->GetThreadId()), pExceptionInfo->ExceptionRecord->ExceptionCode); - fflush(stdout); -#endif - // This shouldn't be possible, but MSVC re-installs us... for now, just bail if this happens. if (g_fNoExceptions) { diff --git a/src/vm/finalizerthread.cpp b/src/vm/finalizerthread.cpp index 2a44b455ca..4c152e8ec6 100644 --- a/src/vm/finalizerthread.cpp +++ b/src/vm/finalizerthread.cpp @@ -886,7 +886,6 @@ void FinalizerThread::FinalizerThreadWait(DWORD timeout) GCX_PREEMP(); Thread *pThread = GetThread(); - BOOL fADUnloadHelper = (pThread && pThread->HasThreadStateNC(Thread::TSNC_ADUnloadHelper)); ULONGLONG startTime = CLRGetTickCount64(); ULONGLONG endTime; @@ -907,55 +906,23 @@ void FinalizerThread::FinalizerThreadWait(DWORD timeout) //---------------------------------------------------- // Do appropriate wait and pump messages if necessary //---------------------------------------------------- - //WaitForSingleObject(hEventFinalizerDone, INFINITE); - - if (fADUnloadHelper) - { - timeout = GetEEPolicy()->GetTimeout(OPR_FinalizerRun); - } DWORD status = hEventFinalizerDone->Wait(timeout,TRUE); if (status != WAIT_TIMEOUT && !(g_FinalizerWaiterStatus & FWS_WaitInterrupt)) { return; } - if (!fADUnloadHelper) - { - // recalculate timeout - if (timeout != INFINITE) - { - ULONGLONG curTime = CLRGetTickCount64(); - if (curTime >= endTime) - { - return; - } - else - { - timeout = (DWORD)(endTime - curTime); - } - } - } - else + // recalculate timeout + if (timeout != INFINITE) { - if (status == WAIT_TIMEOUT) + ULONGLONG curTime = CLRGetTickCount64(); + if (curTime >= endTime) { - ULONGLONG finalizeStartTime = GetObjFinalizeStartTime(); - if (finalizeStartTime) - { - if (CLRGetTickCount64() >= finalizeStartTime+timeout) - { - GCX_COOP(); - FinalizerThreadAbortOnTimeout(); - } - } + return; } - if (endTime != MAXULONGLONG) + else { - ULONGLONG curTime = CLRGetTickCount64(); - if (curTime >= endTime) - { - return; - } + timeout = (DWORD)(endTime - curTime); } } } diff --git a/src/vm/syncblk.cpp b/src/vm/syncblk.cpp index 69defcf415..d5d801b999 100644 --- a/src/vm/syncblk.cpp +++ b/src/vm/syncblk.cpp @@ -56,18 +56,6 @@ SPTR_IMPL (SyncBlockCache, SyncBlockCache, s_pSyncBlockCache); -void SyncBlock::OnADUnload() -{ - WRAPPER_NO_CONTRACT; -#ifdef EnC_SUPPORTED - if (m_pEnCInfo) - { - m_pEnCInfo->Cleanup(); - m_pEnCInfo = NULL; - } -#endif -} - #ifndef FEATURE_PAL // static SLIST_HEADER InteropSyncBlockInfo::s_InteropInfoStandbyList; @@ -228,12 +216,6 @@ void InteropSyncBlockInfo::SetRawRCW(RCW* pRCW) } #endif // FEATURE_COMINTEROP -void UMEntryThunk::OnADUnload() -{ - LIMITED_METHOD_CONTRACT; - m_pObjectHandle = NULL; -} - #endif // !DACCESS_COMPILE PTR_SyncTableEntry SyncTableEntry::GetSyncTableEntry() @@ -729,12 +711,6 @@ VOID SyncBlockCache::CleanupSyncBlocksInAppDomain(AppDomain *pDomain) UMEntryThunk* umThunk=(UMEntryThunk*)pInteropInfo->GetUMEntryThunk(); - if (umThunk && umThunk->GetDomainId()==id) - { - umThunk->OnADUnload(); - STRESS_LOG1(LF_APPDOMAIN, LL_INFO100, "Thunk %x unloaded", umThunk); - } - #ifdef FEATURE_COMINTEROP { // we need to take RCWCache lock to avoid the race with another thread which is @@ -758,13 +734,6 @@ VOID SyncBlockCache::CleanupSyncBlocksInAppDomain(AppDomain *pDomain) } #endif // FEATURE_COMINTEROP } - - // NOTE: this will only notify the sync block if it is non-agile and living in the unloading domain. - // Agile objects that are still alive will not get notification! - if (pSyncBlock->GetAppDomainIndex() == index) - { - pSyncBlock->OnADUnload(); - } } STRESS_LOG1(LF_APPDOMAIN, LL_INFO100, "AD cleanup - %d sync blocks done", nb); // Make sure nobody decreased m_FreeSyncTableIndex behind our back (we would read diff --git a/src/vm/syncblk.h b/src/vm/syncblk.h index 58eb2869b5..6c58923d2b 100644 --- a/src/vm/syncblk.h +++ b/src/vm/syncblk.h @@ -764,8 +764,6 @@ public: void FreeUMEntryThunkOrInterceptStub(); - void OnADUnload(); - #endif // DACCESS_COMPILE void* GetUMEntryThunk() @@ -912,8 +910,6 @@ class SyncBlock return (m_Monitor.m_dwSyncIndex & SyncBlockPrecious) != 0; } - void OnADUnload(); - // True is the syncblock and its index are disposable. // If new members are added to the syncblock, this // method needs to be modified accordingly diff --git a/src/vm/synch.h b/src/vm/synch.h index 1da2107b8d..4869d3e940 100644 --- a/src/vm/synch.h +++ b/src/vm/synch.h @@ -14,8 +14,7 @@ enum WaitMode WaitMode_None =0x0, WaitMode_Alertable = 0x1, // Can be waken by APC. May pumping message. WaitMode_IgnoreSyncCtx = 0x2, // Dispatch to synchronization context if existed. - WaitMode_ADUnload = 0x4, // The block is to wait for AD unload start. If it is interrupted by AD Unload, we can start aborting. - WaitMode_InDeadlock = 0x8, // The wait can be terminated by host's deadlock detection + WaitMode_InDeadlock = 0x4, // The wait can be terminated by host's deadlock detection }; diff --git a/src/vm/threadpoolrequest.cpp b/src/vm/threadpoolrequest.cpp index f9576b7e62..5dda5347d4 100644 --- a/src/vm/threadpoolrequest.cpp +++ b/src/vm/threadpoolrequest.cpp @@ -173,45 +173,6 @@ void PerAppDomainTPCountList::ResetAppDomainIndex(TPIndex index) pAdCount->SetTPIndexUnused(); } -//--------------------------------------------------------------------------- -//ResetAppDomainTPCounts: Resets the per-appdomain thread pool counts for a -// given AppDomain. Don't clear the ADID until we can -// safely recycle the TPIndex -// -//Arguments: -//index - The index into the s_appDomainIndexList for the AppDomain we're -// trying to clear -// -//Assumptions: -//This function needs to be called from the AD unload thread after we make sure -//that no more code is running in unmanaged code. ClearAppDomainRequestsActive -//can be called from this function because no managed code is running (If -//managed code is running, this function needs to be called under a managed -//per-appdomain lock). -// -void PerAppDomainTPCountList::ResetAppDomainTPCounts(TPIndex index) -{ - CONTRACTL - { - NOTHROW; - MODE_ANY; - GC_TRIGGERS; - } - CONTRACTL_END; - - IPerAppDomainTPCount * pAdCount = dac_cast(s_appDomainIndexList.Get(index.m_dwIndex-1)); - _ASSERTE(pAdCount); - - STRESS_LOG2(LF_THREADPOOL, LL_INFO1000, "ResetAppDomainTPCounts: index %d pAdCount %p\n", index.m_dwIndex, pAdCount); - //Correct the thread pool counts, in case the appdomain was unloaded rudely. - if(pAdCount->IsRequestPending()) - { - ThreadpoolMgr::ClearAppDomainRequestsActive(FALSE, TRUE, (LONG)index.m_dwIndex); - } - - pAdCount->ClearAppDomainRequestsActive(TRUE); -} - //--------------------------------------------------------------------------- //AreRequestsPendingInAnyAppDomains checks to see if there any requests pending //in other appdomains. It also checks for pending unmanaged work requests. @@ -599,7 +560,7 @@ void ManagedPerAppDomainTPCount::SetAppDomainRequestsActive() #ifndef DACCESS_COMPILE LONG count = VolatileLoad(&m_numRequestsPending); - while (count != ADUnloading) + while (true) { LONG prev = FastInterlockCompareExchange(&m_numRequestsPending, count+1, count); if (prev == count) @@ -613,7 +574,7 @@ void ManagedPerAppDomainTPCount::SetAppDomainRequestsActive() #endif } -void ManagedPerAppDomainTPCount::ClearAppDomainRequestsActive(BOOL bADU) +void ManagedPerAppDomainTPCount::ClearAppDomainRequestsActive() { LIMITED_METHOD_CONTRACT; //This function should either be called by managed code or during AD unload, but before @@ -622,23 +583,13 @@ void ManagedPerAppDomainTPCount::ClearAppDomainRequestsActive(BOOL bADU) _ASSERTE(m_index.m_dwIndex != UNUSED_THREADPOOL_INDEX); _ASSERTE(m_id.m_dwId != 0); - if (bADU) - { - VolatileStore(&m_numRequestsPending, ADUnloading); - } - else + LONG count = VolatileLoad(&m_numRequestsPending); + while (count > 0) { - LONG count = VolatileLoad(&m_numRequestsPending); - // Test is: count > 0 && count != ADUnloading - // Since: const ADUnloading == -1 - // Both are tested: (count > 0) means following also true (count != ADUnloading) - while (count > 0) - { - LONG prev = FastInterlockCompareExchange(&m_numRequestsPending, 0, count); - if (prev == count) - break; - count = prev; - } + LONG prev = FastInterlockCompareExchange(&m_numRequestsPending, 0, count); + if (prev == count) + break; + count = prev; } } @@ -646,9 +597,6 @@ bool ManagedPerAppDomainTPCount::TakeActiveRequest() { LIMITED_METHOD_CONTRACT; LONG count = VolatileLoad(&m_numRequestsPending); - // Test is: count > 0 && count != ADUnloading - // Since: const ADUnloading == -1 - // Both are tested: (count > 0) means following also true (count != ADUnloading) while (count > 0) { LONG prev = FastInterlockCompareExchange(&m_numRequestsPending, count-1, count); @@ -659,37 +607,6 @@ bool ManagedPerAppDomainTPCount::TakeActiveRequest() return false; } -void ManagedPerAppDomainTPCount::ClearAppDomainUnloading() -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - -#ifndef DACCESS_COMPILE - // - // While the AD was trying to unload, we may have queued some work. We would not - // have added that work to this count, because the AD was unloading. So we assume - // here that we have work to do. - // - // We set this to NumberOfProcessors because that's the maximum count that the AD - // might have tried to add. It's OK for this count to be larger than the AD thinks - // it should be, but if it's smaller then we will be permanently out of sync with the - // AD. - // - VolatileStore(&m_numRequestsPending, (LONG)ThreadpoolMgr::NumberOfProcessors); - if (ThreadpoolMgr::IsInitialized()) - { - ThreadpoolMgr::MaybeAddWorkingWorker(); - ThreadpoolMgr::EnsureGateThreadRunning(); - } -#endif -} - - #ifndef DACCESS_COMPILE //--------------------------------------------------------------------------- @@ -714,10 +631,6 @@ void ManagedPerAppDomainTPCount::DispatchWorkItem(bool* foundWork, bool* wasNotR } } - //We are in a state where AppDomain Unload has begun, but not all threads have been - //forced out of the unloading domain. This check below will prevent us from getting - //unmanaged AD unloaded exceptions while trying to enter an unloaded appdomain. - if (!IsAppDomainUnloading()) { CONTRACTL { @@ -774,11 +687,6 @@ void ManagedPerAppDomainTPCount::DispatchWorkItem(bool* foundWork, bool* wasNotR *foundWork = true; } - else - { - __SwitchToThread(0, CALLER_LIMITS_SPINNING); - return; - } } #endif // !DACCESS_COMPILE diff --git a/src/vm/threadpoolrequest.h b/src/vm/threadpoolrequest.h index 3d2dc3da82..17df7a790f 100644 --- a/src/vm/threadpoolrequest.h +++ b/src/vm/threadpoolrequest.h @@ -50,7 +50,7 @@ public: virtual void SetAppDomainRequestsActive() = 0; //This functions marks the end of requests queued for this domain. - virtual void ClearAppDomainRequestsActive(BOOL bADU = FALSE) = 0; + virtual void ClearAppDomainRequestsActive() = 0; //Clears the "active" flag if it was set, and returns whether it was set. virtual bool TakeActiveRequest() = 0; @@ -61,14 +61,10 @@ public: virtual void SetTPIndexUnused() = 0; virtual BOOL IsTPIndexUnused() = 0; virtual void SetTPIndex(TPIndex index) = 0; - virtual void SetAppDomainUnloading() = 0; - virtual void ClearAppDomainUnloading() = 0; }; typedef DPTR(IPerAppDomainTPCount) PTR_IPerAppDomainTPCount; -static const LONG ADUnloading = -1; - #ifdef _MSC_VER // Disable this warning - we intentionally want __declspec(align()) to insert padding for us #pragma warning(disable: 4324) // structure was padded due to __declspec(align()) @@ -101,11 +97,11 @@ public: LIMITED_METHOD_CONTRACT; LONG count = VolatileLoad(&m_numRequestsPending); - return count != ADUnloading && count > 0; + return count > 0; } void SetAppDomainRequestsActive(); - void ClearAppDomainRequestsActive(BOOL bADU); + void ClearAppDomainRequestsActive(); bool TakeActiveRequest(); inline void SetAppDomainId(ADID id) @@ -115,7 +111,6 @@ public: //has started running yet. That implies, no requests should be pending //or dispatched to this structure yet. - _ASSERTE(VolatileLoad(&m_numRequestsPending) != ADUnloading); _ASSERTE(m_id.m_dwId == 0); m_id = id; @@ -128,7 +123,6 @@ public: //has started running yet. That implies, no requests should be pending //or dispatched to this structure yet. - _ASSERTE(VolatileLoad(&m_numRequestsPending) != ADUnloading); _ASSERTE(m_id.m_dwId == 0); _ASSERTE(m_index.m_dwIndex == UNUSED_THREADPOOL_INDEX); @@ -144,7 +138,6 @@ public: //added removed at this time. So, make sure that the per-appdomain structures that //have been cleared(reclaimed) don't have any pending requests to them. - _ASSERTE(VolatileLoad(&m_numRequestsPending) != ADUnloading); _ASSERTE(m_id.m_dwId == 0); return TRUE; @@ -165,19 +158,6 @@ public: m_index.m_dwIndex = UNUSED_THREADPOOL_INDEX; } - inline void SetAppDomainUnloading() - { - LIMITED_METHOD_CONTRACT; - VolatileStore(&m_numRequestsPending, ADUnloading); - } - - inline void ClearAppDomainUnloading(); - - inline BOOL IsAppDomainUnloading() - { - return VolatileLoad(&m_numRequestsPending) == ADUnloading; - } - void DispatchWorkItem(bool* foundWork, bool* wasNotRecalled); private: @@ -237,7 +217,7 @@ public: void SetAppDomainRequestsActive(); - inline void ClearAppDomainRequestsActive(BOOL bADU) + inline void ClearAppDomainRequestsActive() { LIMITED_METHOD_CONTRACT; VolatileStore(&m_outstandingThreadRequestCount, (LONG)0); @@ -273,18 +253,6 @@ public: _ASSERT(FALSE); } - inline void SetAppDomainUnloading() - { - WRAPPER_NO_CONTRACT; - _ASSERT(FALSE); - } - - inline void ClearAppDomainUnloading() - { - WRAPPER_NO_CONTRACT; - _ASSERT(FALSE); - } - private: SpinLock m_lock; ULONG m_NumRequests; @@ -317,29 +285,11 @@ class PerAppDomainTPCountList{ public: static void InitAppDomainIndexList(); static void ResetAppDomainIndex(TPIndex index); - static void ResetAppDomainTPCounts(TPIndex index); static bool AreRequestsPendingInAnyAppDomains(); static LONG GetAppDomainIndexForThreadpoolDispatch(); static void SetAppDomainId(TPIndex index, ADID id); static TPIndex AddNewTPIndex(); - static void SetAppDomainUnloading(TPIndex index) - { - WRAPPER_NO_CONTRACT; - IPerAppDomainTPCount * pAdCount = dac_cast (s_appDomainIndexList.Get(index.m_dwIndex-1)); - _ASSERTE(pAdCount); - pAdCount->SetAppDomainUnloading(); - } - - static void ClearAppDomainUnloading(TPIndex index) - { - WRAPPER_NO_CONTRACT; - IPerAppDomainTPCount * pAdCount = dac_cast (s_appDomainIndexList.Get(index.m_dwIndex-1)); - _ASSERTE(pAdCount); - pAdCount->ClearAppDomainUnloading(); - } - typedef Holder AppDomainUnloadingHolder; - inline static IPerAppDomainTPCount* GetPerAppdomainCount(TPIndex index) { return dac_cast(s_appDomainIndexList.Get(index.m_dwIndex-1)); diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index 53d87a7b61..53707759a4 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -3363,7 +3363,7 @@ void Thread::DoAppropriateWaitWorkerAlertableHelper(WaitMode mode) } else { - HandleThreadInterrupt((mode & WaitMode_ADUnload) != 0); + HandleThreadInterrupt(); // Safe to clear the interrupted state, no APC could have fired since we // reset m_UserInterrupt (which inhibits our APC callback from doing @@ -3476,7 +3476,7 @@ retry: if (m_State & TS_Interrupted) { - HandleThreadInterrupt(mode & WaitMode_ADUnload); + HandleThreadInterrupt(); } // We could be woken by some spurious APC or an EE APC queued to // interrupt us. In the latter case the TS_Interrupted bit will be set @@ -3685,7 +3685,7 @@ retry: if ((m_State & TS_Interrupted)) { - HandleThreadInterrupt(mode & WaitMode_ADUnload); + HandleThreadInterrupt(); } if (millis != INFINITE) { @@ -3799,7 +3799,7 @@ retry: // in the thread state bits. Otherwise we just go back to sleep again. if ((m_State & TS_Interrupted)) { - HandleThreadInterrupt(FALSE); + HandleThreadInterrupt(); } if (INFINITE != millis) { @@ -4192,7 +4192,7 @@ void Thread::UserSleep(INT32 time) // If someone has interrupted us, we should not enter the wait. if (IsUserInterrupted()) { - HandleThreadInterrupt(FALSE); + HandleThreadInterrupt(); } ThreadStateHolder tsh(TRUE, TS_Interruptible | TS_Interrupted); @@ -4213,7 +4213,7 @@ retry: // in the thread state bits. Otherwise we just go back to sleep again. if ((m_State & TS_Interrupted)) { - HandleThreadInterrupt(FALSE); + HandleThreadInterrupt(); } if (dwTime == INFINITE) @@ -5962,7 +5962,7 @@ Retry: #endif // _DEBUG -void Thread::HandleThreadInterrupt (BOOL fWaitForADUnload) +void Thread::HandleThreadInterrupt () { STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; @@ -5973,9 +5973,7 @@ void Thread::HandleThreadInterrupt (BOOL fWaitForADUnload) if ((m_UserInterrupt & TI_Abort) != 0) { - // If the thread is waiting for AD unload to finish, and the thread is interrupted, - // we can start aborting. - HandleThreadAbort(fWaitForADUnload); + HandleThreadAbort(); } if ((m_UserInterrupt & TI_Interrupt) != 0) { diff --git a/src/vm/threads.h b/src/vm/threads.h index 959ae490dd..3a0d00e6da 100644 --- a/src/vm/threads.h +++ b/src/vm/threads.h @@ -1239,7 +1239,7 @@ public: TSNC_OwnsSpinLock = 0x00000400, // The thread owns a spinlock. TSNC_PreparingAbort = 0x00000800, // Preparing abort. This avoids recursive HandleThreadAbort call. TSNC_OSAlertableWait = 0x00001000, // Preparing abort. This avoids recursive HandleThreadAbort call. - TSNC_ADUnloadHelper = 0x00002000, // This thread is AD Unload helper. + // unused = 0x00002000, TSNC_CreatingTypeInitException = 0x00004000, // Thread is trying to create a TypeInitException // unused = 0x00008000, // unused = 0x00010000, @@ -2079,11 +2079,7 @@ public: NOINLINE void RareDisablePreemptiveGC(); - void HandleThreadAbort() - { - HandleThreadAbort(FALSE); - } - void HandleThreadAbort(BOOL fForce); // fForce=TRUE only for a thread waiting to start AD unload + void HandleThreadAbort(); void PreWorkForThreadAbort(); @@ -2725,8 +2721,6 @@ public: { UAC_Normal, UAC_Host, // Called by host through IClrTask::Abort - UAC_WatchDog, // Called by ADUnload helper thread - UAC_FinalizerTimeout, }; HRESULT UserAbort(ThreadAbortRequester requester, @@ -2776,7 +2770,6 @@ private: public: void UserInterrupt(ThreadInterruptMode mode); - void SetAbortRequest(EEPolicy::ThreadAbortTypes abortType); // Should only be called by ADUnload BOOL ReadyForAbort() { return ReadyForAsyncException(); @@ -2874,16 +2867,9 @@ private: void RemoveAbortRequestBit(); public: - void MarkThreadForAbort(ThreadAbortRequester requester, EEPolicy::ThreadAbortTypes abortType, BOOL fTentative = FALSE); + void MarkThreadForAbort(ThreadAbortRequester requester, EEPolicy::ThreadAbortTypes abortType); void UnmarkThreadForAbort(ThreadAbortRequester requester, BOOL fForce = TRUE); -private: - static void ThreadAbortWatchDogAbort(Thread *pThread); - static void ThreadAbortWatchDogEscalate(Thread *pThread); - -public: - static void ThreadAbortWatchDog(); - static ULONGLONG GetNextSelfAbortEndTime() { LIMITED_METHOD_CONTRACT; @@ -3634,7 +3620,7 @@ private: FastInterlockExchange(&m_UserInterrupt, 0); } - void HandleThreadInterrupt(BOOL fWaitForADUnload); + void HandleThreadInterrupt(); public: static void WINAPI UserInterruptAPC(ULONG_PTR ignore); diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp index 330eb98c90..df6152e3bd 100644 --- a/src/vm/threadsuspend.cpp +++ b/src/vm/threadsuspend.cpp @@ -1395,10 +1395,7 @@ Thread::UserAbort(ThreadAbortRequester requester, SetAbortEndTime(newEndTime, abortType == EEPolicy::TA_Rude); } - // If the abort comes from the thread abort watchdog, proceed with the abort only - // if the abort is still requested. This handles race between watchdog and UnmarkThreadForAbort. - BOOL fTentative = (requester == Thread::TAR_Thread) && (client == UAC_WatchDog); - MarkThreadForAbort(requester, abortType, fTentative); + MarkThreadForAbort(requester, abortType); Thread *pCurThread = GetThread(); @@ -1456,26 +1453,13 @@ Thread::UserAbort(ThreadAbortRequester requester, BOOL fAlreadyAssert = FALSE; #endif - BOOL fOneTryOnly = (client == UAC_WatchDog) || (client == UAC_FinalizerTimeout); - BOOL fFirstRun = TRUE; - BOOL fNeedEscalation; - #if !defined(DISABLE_THREADSUSPEND) DWORD dwSwitchCount = 0; #endif // !defined(DISABLE_THREADSUSPEND) LRetry: - fNeedEscalation = FALSE; for (;;) { - if (fOneTryOnly) - { - if (!fFirstRun) - { - return S_OK; - } - fFirstRun = FALSE; - } // Lock the thread store LOG((LF_SYNC, INFO3, "UserAbort obtain lock\n")); @@ -1514,8 +1498,6 @@ LRetry: } if (timeout1 != INFINITE) { - // There is an escalation policy. - fNeedEscalation = TRUE; break; } } @@ -1892,11 +1874,6 @@ LPrepareRetry: checkForAbort.Release(); - if (fOneTryOnly) - { - break; - } - // Don't do a Sleep. It's possible that the thread we are trying to abort is // stuck in unmanaged code trying to get into the apartment that we are supposed // to be pumping! Instead, ping the current thread's handle. Obviously this @@ -1922,11 +1899,6 @@ LPrepareRetry: } // for(;;) - if (fOneTryOnly && !fNeedEscalation) - { - return S_OK; - } - if ((GetAbortEndTime() != MAXULONGLONG) && IsAbortRequested()) { while (TRUE) @@ -2056,155 +2028,6 @@ void Thread::SetRudeAbortEndTimeFromEEPolicy() ULONGLONG Thread::s_NextSelfAbortEndTime = MAXULONGLONG; -void Thread::ThreadAbortWatchDogAbort(Thread *pThread) -{ - CONTRACTL - { - NOTHROW; - if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);} - } - CONTRACTL_END; - - EEPolicy::ThreadAbortTypes abortType = EEPolicy::TA_Safe; - if (pThread->m_AbortInfo & TAI_ThreadRudeAbort) - { - abortType = EEPolicy::TA_Rude; - } - else if (pThread->m_AbortInfo & TAI_ThreadAbort) - { - abortType = EEPolicy::TA_Safe; - } - else - { - return; - } - - EX_TRY - { - pThread->UserAbort(Thread::TAR_Thread, abortType, INFINITE, Thread::UAC_WatchDog); - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions); -} - -void Thread::ThreadAbortWatchDogEscalate(Thread *pThread) -{ - CONTRACTL - { - NOTHROW; - if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);} - } - CONTRACTL_END; - - EPolicyAction action = eNoAction; - EClrOperation operation = OPR_ThreadRudeAbortInNonCriticalRegion; - if (!pThread->IsRudeAbort()) - { - operation = OPR_ThreadAbort; - } - else if (pThread->HasLockInCurrentDomain()) - { - operation = OPR_ThreadRudeAbortInCriticalRegion; - } - else - { - operation = OPR_ThreadRudeAbortInNonCriticalRegion; - } - action = GetEEPolicy()->GetActionOnTimeout(operation, pThread); - // We only support escalation to rude abort - - EX_TRY { - switch (action) - { - case eRudeAbortThread: - GetEEPolicy()->NotifyHostOnTimeout(operation,action); - pThread->UserAbort(Thread::TAR_Thread, EEPolicy::TA_Rude, INFINITE, Thread::UAC_WatchDog); - break; - case eExitProcess: - case eFastExitProcess: - case eRudeExitProcess: - case eDisableRuntime: - // HandleExitProcessFromEscalation will try to grab ThreadStore again. - _ASSERTE (ThreadStore::HoldingThreadStore()); - ThreadStore::UnlockThreadStore(); - GetEEPolicy()->NotifyHostOnTimeout(operation,action); - EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_THREADABORT); - _ASSERTE (!"Should not reach here"); - break; - case eNoAction: - break; - default: - _ASSERTE (!"unknown policy for thread abort"); - } - } - EX_CATCH { - } - EX_END_CATCH(SwallowAllExceptions); -} - -// If a thread is self-aborted and has a timeout, we need to watch the thread -void Thread::ThreadAbortWatchDog() -{ - CONTRACTL - { - NOTHROW; - if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);} - } - CONTRACTL_END; - - if (CLRHosted()) - { - ThreadStoreLockHolder tsLock; - - ULONGLONG curTime = CLRGetTickCount64(); - - s_NextSelfAbortEndTime = MAXULONGLONG; - - Thread *thread = NULL; - while ((thread = ThreadStore::GetThreadList(thread)) != NULL) - { - if (!thread->IsAbortRequested()) - { - continue; - } - - if (thread == FinalizerThread::GetFinalizerThread() && !g_FinalizerIsRunning) - { - // if finalizer method is not running, don't try to abort the finalizer thread - continue; - } - - BOOL fNeedsToInitiateAbort = !thread->IsAbortInitiated() || thread->IsRudeAbort(); - ULONGLONG endTime = thread->GetAbortEndTime(); - if (fNeedsToInitiateAbort) - { - s_NextSelfAbortEndTime = 0; - } - else if (endTime < s_NextSelfAbortEndTime) - { - s_NextSelfAbortEndTime = endTime; - } - - if (thread->m_AbortController == 0) - { - STRESS_LOG3(LF_ALWAYS, LL_ALWAYS, "ThreadAbortWatchDog for Thread %p Thread Id = %x with timeout %x\n", - thread, thread->GetThreadId(), endTime); - - if (endTime != MAXULONGLONG && curTime >= endTime) - { - ThreadAbortWatchDogEscalate(thread); - } - else if (fNeedsToInitiateAbort) - { - ThreadAbortWatchDogAbort(thread); - } - } - } - } -} - void Thread::LockAbortRequest(Thread* pThread) { WRAPPER_NO_CONTRACT; @@ -2233,7 +2056,7 @@ void Thread::UnlockAbortRequest(Thread *pThread) FastInterlockExchange(&pThread->m_AbortRequestLock, 0); } -void Thread::MarkThreadForAbort(ThreadAbortRequester requester, EEPolicy::ThreadAbortTypes abortType, BOOL fTentative /*=FALSE*/) +void Thread::MarkThreadForAbort(ThreadAbortRequester requester, EEPolicy::ThreadAbortTypes abortType) { CONTRACTL { @@ -2244,15 +2067,6 @@ void Thread::MarkThreadForAbort(ThreadAbortRequester requester, EEPolicy::Thread AbortRequestLockHolder lh(this); - if (fTentative) - { - if (!IsAbortRequested()) - { - STRESS_LOG0(LF_SYNC, LL_INFO1000, "Tentative thread abort abandoned\n"); - return; - } - } - #ifdef _DEBUG if (abortType == EEPolicy::TA_Rude) { @@ -2489,25 +2303,6 @@ void Thread::InternalResetAbort(ThreadAbortRequester requester, BOOL fResetRudeA } -// Throw a thread abort request when a suspended thread is resumed. Make sure you know what you -// are doing when you call this routine. -void Thread::SetAbortRequest(EEPolicy::ThreadAbortTypes abortType) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - MarkThreadForAbort(TAR_Thread, abortType); - - if (m_State & TS_Interruptible) - { - UserInterrupt(TI_Abort); - } -} - - void ThreadSuspend::LockThreadStore(ThreadSuspend::SUSPEND_REASON reason) { CONTRACTL { @@ -2961,7 +2756,7 @@ void Thread::HandleThreadAbortTimeout() EX_END_CATCH(SwallowAllExceptions); } -void Thread::HandleThreadAbort (BOOL fForce) +void Thread::HandleThreadAbort () { BEGIN_PRESERVE_LAST_ERROR; @@ -2986,7 +2781,7 @@ void Thread::HandleThreadAbort (BOOL fForce) // That's okay since COMPlusThrow will eventually erect SEH around the RaiseException. It prevents // us from stating CONTRACT here. - if (fForce || ReadyForAbort()) + if (ReadyForAbort()) { ResetThreadState ((ThreadState)(TS_Interrupted | TS_Interruptible)); // We are going to abort. Abort satisfies Thread.Interrupt requirement. @@ -4928,7 +4723,7 @@ ThrowControlForThread( } #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX) -// This function is called by UserAbort and StopEEAndUnwindThreads. +// This function is called by UserAbort. // It forces a thread to abort if allowed and the thread is running managed code. BOOL Thread::HandleJITCaseForAbort() { @@ -7344,7 +7139,7 @@ void SuspendStatistics::DisplayAndUpdate() cntWaitTimeouts - g_LastSuspendStatistics.cntWaitTimeouts, cntWaitTimeouts, cntHijackTrap - g_LastSuspendStatistics.cntHijackTrap, cntHijackTrap); - fprintf(logFile, "Redirected EIP Failures %d (%d), Collided GC/Debugger/ADUnload %d (%d)\n", + fprintf(logFile, "Redirected EIP Failures %d (%d), Collided GC/Debugger %d (%d)\n", cntFailedRedirections - g_LastSuspendStatistics.cntFailedRedirections, cntFailedRedirections, cntCollideRetry - g_LastSuspendStatistics.cntCollideRetry, cntCollideRetry); diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp index 6c78e48e36..def1374f20 100644 --- a/src/vm/win32threadpool.cpp +++ b/src/vm/win32threadpool.cpp @@ -1593,7 +1593,7 @@ BOOL ThreadpoolMgr::SetAppDomainRequestsActive(BOOL UnmanagedTP) return fShouldSignalEvent; } -void ThreadpoolMgr::ClearAppDomainRequestsActive(BOOL UnmanagedTP, BOOL AdUnloading, LONG id) +void ThreadpoolMgr::ClearAppDomainRequestsActive(BOOL UnmanagedTP, LONG id) //-------------------------------------------------------------------------- //This function informs the thread scheduler that the kast request has been //dequeued on an appdomain, or it's the last unmanaged TP request. @@ -1625,22 +1625,15 @@ void ThreadpoolMgr::ClearAppDomainRequestsActive(BOOL UnmanagedTP, BOOL AdUnload } else { - if (AdUnloading) - { - pAdCount = PerAppDomainTPCountList::GetPerAppdomainCount(TPIndex(id)); - } - else - { - Thread* pCurThread = GetThread(); - _ASSERTE( pCurThread); - - AppDomain* pAppDomain = pCurThread->GetDomain(); - _ASSERTE(pAppDomain); - - TPIndex tpindex = pAppDomain->GetTPIndex(); + Thread* pCurThread = GetThread(); + _ASSERTE( pCurThread); + + AppDomain* pAppDomain = pCurThread->GetDomain(); + _ASSERTE(pAppDomain); + + TPIndex tpindex = pAppDomain->GetTPIndex(); - pAdCount = PerAppDomainTPCountList::GetPerAppdomainCount(tpindex); - } + pAdCount = PerAppDomainTPCountList::GetPerAppdomainCount(tpindex); _ASSERTE(pAdCount); } diff --git a/src/vm/win32threadpool.h b/src/vm/win32threadpool.h index 7d0d565431..8d03d2e71a 100644 --- a/src/vm/win32threadpool.h +++ b/src/vm/win32threadpool.h @@ -293,7 +293,7 @@ public: ); static BOOL SetAppDomainRequestsActive(BOOL UnmanagedTP = FALSE); - static void ClearAppDomainRequestsActive(BOOL UnmanagedTP = FALSE, BOOL AdUnloading = FALSE, LONG index = -1); + static void ClearAppDomainRequestsActive(BOOL UnmanagedTP = FALSE, LONG index = -1); static inline void UpdateLastDequeueTime() { diff --git a/tests/src/GC/Stress/Framework/ReliabilityFramework.cs b/tests/src/GC/Stress/Framework/ReliabilityFramework.cs index f1a3afca2e..b3eb0e74fd 100644 --- a/tests/src/GC/Stress/Framework/ReliabilityFramework.cs +++ b/tests/src/GC/Stress/Framework/ReliabilityFramework.cs @@ -2490,36 +2490,6 @@ Thanks for contributing to CLR Stress! // opening tag. continue; } - /* - if (input.Substring(0, 6) == "UNLOAD") - { - int adUnloadedIndex = input.IndexOf("AppDomain Unloaded: "); - DateTime thisTime = DateTime.Parse(input.Substring(4, adUnloadedIndex - 4)); - string id = input.Substring(adUnloadedIndex + ("AppDomain Unloaded: ".Length)); - int curTest = FindTestByID(id); - - if (curTest != -1) - { - // wait until the time is appropriate. - if (baseTime == DateTime.MinValue) - { - baseTime = thisTime; // this is the 1st run command, this is our base time. - startTime = DateTime.Now; - } - else - { - if ((thisTime.Subtract(baseTime)) > (DateTime.Now.Subtract(startTime))) - { - // sleep for (thisTime - baseTime) - (DateTime.Now - startTime) - Thread.Sleep((int)(thisTime.Subtract(baseTime).Subtract(DateTime.Now.Subtract(startTime)).Ticks / TimeSpan.TicksPerMillisecond)); - } - } - - UnloadOnEvent(curTestSet.Tests[curTest].AppDomain, eReasonForUnload.Replay); - } - } - **/ - } while (_testsRunningCount != 0) // let the user know what tests haven't finished... -- cgit v1.2.3