summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve MacLean <stmaclea@microsoft.com>2019-03-05 06:29:18 -0500
committerJan Kotas <jkotas@microsoft.com>2019-03-05 03:29:18 -0800
commitdc11162e1c36624d3cabb6e0bf6583a94ab2e30c (patch)
treeeb44fd174038cecc76e18a482bd1478d2434c3af
parentb54752c8869f55c82cc24b49fbb1b48a87090943 (diff)
downloadcoreclr-dc11162e1c36624d3cabb6e0bf6583a94ab2e30c.tar.gz
coreclr-dc11162e1c36624d3cabb6e0bf6583a94ab2e30c.tar.bz2
coreclr-dc11162e1c36624d3cabb6e0bf6583a94ab2e30c.zip
Remove dead AppDomain unload code (#23026)
-rw-r--r--src/ToolBox/SOS/Strike/strike.cpp4
-rw-r--r--src/debug/ee/debugger.cpp2
-rw-r--r--src/vm/appdomain.cpp290
-rw-r--r--src/vm/appdomain.hpp9
-rw-r--r--src/vm/dllimportcallback.h2
-rw-r--r--src/vm/eepolicy.cpp6
-rw-r--r--src/vm/eepolicy.h3
-rw-r--r--src/vm/excep.cpp6
-rw-r--r--src/vm/finalizerthread.cpp47
-rw-r--r--src/vm/syncblk.cpp31
-rw-r--r--src/vm/syncblk.h4
-rw-r--r--src/vm/synch.h3
-rw-r--r--src/vm/threadpoolrequest.cpp108
-rw-r--r--src/vm/threadpoolrequest.h58
-rw-r--r--src/vm/threads.cpp18
-rw-r--r--src/vm/threads.h22
-rw-r--r--src/vm/threadsuspend.cpp217
-rw-r--r--src/vm/win32threadpool.cpp25
-rw-r--r--src/vm/win32threadpool.h2
-rw-r--r--tests/src/GC/Stress/Framework/ReliabilityFramework.cs30
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>@todo: what to do with any threads that didn't stop?</TODO>
- _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>@todo: need real synchronization here!!!</TODO>
- 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<cfg_any>::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<BOOL> g_FinalizerIsRunning = FALSE;
Volatile<ULONG> 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
@@ -174,45 +174,6 @@ void PerAppDomainTPCountList::ResetAppDomainIndex(TPIndex index)
}
//---------------------------------------------------------------------------
-//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<PTR_IPerAppDomainTPCount>(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.
//This function is called at end of thread quantum to see if the thread needs to
@@ -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<PTR_IPerAppDomainTPCount> (s_appDomainIndexList.Get(index.m_dwIndex-1));
- _ASSERTE(pAdCount);
- pAdCount->SetAppDomainUnloading();
- }
-
- static void ClearAppDomainUnloading(TPIndex index)
- {
- WRAPPER_NO_CONTRACT;
- IPerAppDomainTPCount * pAdCount = dac_cast<PTR_IPerAppDomainTPCount> (s_appDomainIndexList.Get(index.m_dwIndex-1));
- _ASSERTE(pAdCount);
- pAdCount->ClearAppDomainUnloading();
- }
- typedef Holder<TPIndex, SetAppDomainUnloading, ClearAppDomainUnloading> AppDomainUnloadingHolder;
-
inline static IPerAppDomainTPCount* GetPerAppdomainCount(TPIndex index)
{
return dac_cast<PTR_IPerAppDomainTPCount>(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 <TestRun> 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...