summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2018-10-04 10:18:23 +0200
committerGitHub <noreply@github.com>2018-10-04 10:18:23 +0200
commit11832401739148f1f1e9419cb51180ba5263a41b (patch)
tree91e81791918d307b0bc9f8255d022fd2fbfbd970 /src
parent0068168531e849cbad8388f00f3f23e58d3a01b4 (diff)
downloadcoreclr-11832401739148f1f1e9419cb51180ba5263a41b.tar.gz
coreclr-11832401739148f1f1e9419cb51180ba5263a41b.tar.bz2
coreclr-11832401739148f1f1e9419cb51180ba5263a41b.zip
Remove AppDomain unload (#20250)
* Remove AppDomain unload This change removes all code in AppDomain that's related to AppDomain unloading which is obsolete in CoreCLR. It also removes all calls to the removed methods. In few places, I have made the change simpler by taking into account the fact that there is always just one AppDomain.
Diffstat (limited to 'src')
-rw-r--r--src/classlibnative/bcltype/system.cpp2
-rw-r--r--src/debug/daccess/dacdbiimpl.cpp28
-rw-r--r--src/debug/ee/debugger.cpp3
-rw-r--r--src/inc/clrconfigvalues.h1
-rw-r--r--src/inc/utilcode.h9
-rw-r--r--src/vm/amd64/UMThunkStub.asm139
-rw-r--r--src/vm/amd64/asmconstants.h10
-rw-r--r--src/vm/amd64/umthunkstub.S12
-rw-r--r--src/vm/appdomain.cpp1794
-rw-r--r--src/vm/appdomain.hpp452
-rw-r--r--src/vm/appdomain.inl126
-rw-r--r--src/vm/appdomainnative.cpp28
-rw-r--r--src/vm/appdomainnative.hpp3
-rw-r--r--src/vm/arm/asmconstants.h2
-rw-r--r--src/vm/arm/asmhelpers.S94
-rw-r--r--src/vm/arm/asmhelpers.asm95
-rw-r--r--src/vm/arm64/asmconstants.h2
-rw-r--r--src/vm/arm64/asmhelpers.S113
-rw-r--r--src/vm/arm64/asmhelpers.asm113
-rw-r--r--src/vm/callhelpers.cpp2
-rw-r--r--src/vm/ceemain.cpp15
-rw-r--r--src/vm/codeversion.cpp4
-rw-r--r--src/vm/comcallablewrapper.cpp50
-rw-r--r--src/vm/cominterfacemarshaler.cpp19
-rw-r--r--src/vm/comsynchronizable.cpp18
-rw-r--r--src/vm/comtoclrcall.cpp49
-rw-r--r--src/vm/corhost.cpp89
-rw-r--r--src/vm/delegateinfo.h17
-rw-r--r--src/vm/dispatchinfo.cpp3
-rw-r--r--src/vm/dllimportcallback.cpp173
-rw-r--r--src/vm/domainfile.cpp24
-rw-r--r--src/vm/domainfile.h1
-rw-r--r--src/vm/eeconfig.cpp2
-rw-r--r--src/vm/eeconfig.h2
-rw-r--r--src/vm/eepolicy.cpp75
-rw-r--r--src/vm/eepolicy.h2
-rw-r--r--src/vm/eventtrace.cpp34
-rw-r--r--src/vm/finalizerthread.cpp110
-rw-r--r--src/vm/finalizerthread.h15
-rw-r--r--src/vm/gcenv.ee.cpp10
-rw-r--r--src/vm/gchandleutilities.cpp7
-rw-r--r--src/vm/i386/asmconstants.h8
-rw-r--r--src/vm/i386/asmhelpers.S22
-rw-r--r--src/vm/i386/asmhelpers.asm25
-rw-r--r--src/vm/loaderallocator.cpp3
-rw-r--r--src/vm/marshalnative.cpp3
-rw-r--r--src/vm/methodtable.cpp2
-rw-r--r--src/vm/nativeoverlapped.cpp2
-rw-r--r--src/vm/object.cpp6
-rw-r--r--src/vm/profilingenumerators.cpp22
-rw-r--r--src/vm/stackprobe.cpp8
-rw-r--r--src/vm/stacksampler.cpp6
-rw-r--r--src/vm/stdinterfaces_wrapper.cpp5
-rw-r--r--src/vm/testhookmgr.cpp17
-rw-r--r--src/vm/threads.cpp353
-rw-r--r--src/vm/threads.h45
-rw-r--r--src/vm/threads.inl6
-rw-r--r--src/vm/threadsuspend.cpp180
-rw-r--r--src/vm/win32threadpool.h5
59 files changed, 139 insertions, 4326 deletions
diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp
index a28adace88..942ac3db0c 100644
--- a/src/classlibnative/bcltype/system.cpp
+++ b/src/classlibnative/bcltype/system.cpp
@@ -354,7 +354,7 @@ FCIMPL0(FC_BOOL_RET, SystemNative::HasShutdownStarted)
// aggressively finalize objects referred to by static variables OR
// if someone is unloading the current AppDomain AND we have started
// finalizing objects referred to by static variables.
- FC_RETURN_BOOL((g_fEEShutDown & ShutDown_Finalize2) || GetAppDomain()->IsFinalizing());
+ FC_RETURN_BOOL(g_fEEShutDown & ShutDown_Finalize2);
}
FCIMPLEND
diff --git a/src/debug/daccess/dacdbiimpl.cpp b/src/debug/daccess/dacdbiimpl.cpp
index bed03ad6c9..57f9f6be39 100644
--- a/src/debug/daccess/dacdbiimpl.cpp
+++ b/src/debug/daccess/dacdbiimpl.cpp
@@ -3604,10 +3604,6 @@ void DacDbiInterfaceImpl::GetCachedWinRTTypesForIIDs(
DD_ENTER_MAY_THROW;
AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
- if (pAppDomain->IsUnloading())
- {
- return;
- }
{
pTypes->Alloc(iids.Count());
@@ -3654,10 +3650,6 @@ void DacDbiInterfaceImpl::GetCachedWinRTTypes(
DD_ENTER_MAY_THROW;
AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
- if (pAppDomain->IsUnloading())
- {
- return;
- }
InlineSArray<PTR_MethodTable, 32> rgMT;
InlineSArray<GUID, 32> rgGuid;
@@ -4308,10 +4300,6 @@ void DacDbiInterfaceImpl::EnumerateAppDomains(
// It's critical that we don't yield appdomains after the unload event has been sent.
// See code:IDacDbiInterface#Enumeration for details.
AppDomain * pAppDomain = iterator.GetDomain();
- if (pAppDomain->IsUnloading())
- {
- continue;
- }
VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr();
vmAppDomain.SetHostPtr(pAppDomain);
@@ -4338,10 +4326,6 @@ void DacDbiInterfaceImpl::EnumerateAssembliesInAppDomain(
// in the domain. This is to enforce rules at code:IDacDbiInterface#Enumeration.
// See comment in code:DacDbiInterfaceImpl::EnumerateModulesInAssembly code for details.
AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
- if (pAppDomain->IsUnloading())
- {
- return;
- }
// Pass the magical flags to the loader enumerator to get all Execution-only assemblies.
iterator = pAppDomain->IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoading | kIncludeLoaded | kIncludeExecution));
@@ -4374,18 +4358,6 @@ void DacDbiInterfaceImpl::EnumerateModulesInAssembly(
DomainAssembly * pDomainAssembly = vmAssembly.GetDacPtr();
- // If the appdomain or assembly containing this module is unloading, then don't enumerate any modules.
- // in the domain. This is to enforce rules at code:IDacDbiInterface#Enumeration, specifically
- // that new objects are not available after the unload event is sent.
- // This is a very large hammer, but since modules only unload with appdomains or assemblies, we're
- // erring on the side of safety. If the debugger happens to have VMPTR_DomainFiles (CordbModules) already
- // cached, it can still use those until the unload event.
- if (pDomainAssembly->IsUnloading())
- {
- return;
- }
-
-
// If the domain is not yet fully-loaded, don't advertise it yet.
// It's not ready to be inspected.
DomainModuleIterator iterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded);
diff --git a/src/debug/ee/debugger.cpp b/src/debug/ee/debugger.cpp
index 839ed794b6..a2148b7cc7 100644
--- a/src/debug/ee/debugger.cpp
+++ b/src/debug/ee/debugger.cpp
@@ -10134,8 +10134,7 @@ BOOL Debugger::SendSystemClassLoadUnloadEvent(mdTypeDef classMetadataToken,
// triggers too early in the loading process. FindDomainFile will not become
// non-NULL until the module is fully loaded into the domain which is what we
// want.
- if ((classModule->FindDomainFile(pAppDomain) != NULL ) &&
- !(fIsLoadEvent && pAppDomain->IsUnloading()) )
+ if (classModule->FindDomainFile(pAppDomain) != NULL )
{
// Find the Left Side module that this class belongs in.
DebuggerModule* pModule = LookupOrCreateModule(classModule, pAppDomain);
diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h
index cf31bc575f..58c3113cd3 100644
--- a/src/inc/clrconfigvalues.h
+++ b/src/inc/clrconfigvalues.h
@@ -783,7 +783,6 @@ CONFIG_DWORD_INFO_EX(INTERNAL_ForceRelocs, W("ForceRelocs"), 0, "", CLRConfig::R
CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_GenerateLongJumpDispatchStubRatio, W("GenerateLongJumpDispatchStubRatio"), "Useful for testing VSD on AMD64")
CONFIG_DWORD_INFO_EX(INTERNAL_HashStack, W("HashStack"), 0, "", CLRConfig::REGUTIL_default)
CONFIG_DWORD_INFO(INTERNAL_HostManagerConfig, W("HostManagerConfig"), (DWORD)-1, "")
-CONFIG_DWORD_INFO(INTERNAL_HostTestADUnload, W("HostTestADUnload"), 0, "Allows setting Rude unload as default")
CONFIG_DWORD_INFO(INTERNAL_HostTestThreadAbort, W("HostTestThreadAbort"), 0, "")
RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_IgnoreDllMainReturn, W("IgnoreDllMainReturn"), 0, "Don't check the return value of DllMain if this is set", CLRConfig::ConfigFile_ApplicationFirst)
CONFIG_STRING_INFO(INTERNAL_InvokeHalt, W("InvokeHalt"), "Throws an assert when the given method is invoked through reflection.")
diff --git a/src/inc/utilcode.h b/src/inc/utilcode.h
index 2356316368..3c5a686a04 100644
--- a/src/inc/utilcode.h
+++ b/src/inc/utilcode.h
@@ -4610,15 +4610,6 @@ inline BOOL IsFinalizerThread ()
return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Finalizer);
}
-inline BOOL IsADUnloadHelperThread ()
-{
- STATIC_CONTRACT_NOTHROW;
- STATIC_CONTRACT_GC_NOTRIGGER;
- STATIC_CONTRACT_MODE_ANY;
-
- return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ADUnloadHelper);
-}
-
inline BOOL IsShutdownHelperThread ()
{
STATIC_CONTRACT_NOTHROW;
diff --git a/src/vm/amd64/UMThunkStub.asm b/src/vm/amd64/UMThunkStub.asm
index 123a630880..b7701d8e18 100644
--- a/src/vm/amd64/UMThunkStub.asm
+++ b/src/vm/amd64/UMThunkStub.asm
@@ -18,7 +18,6 @@ extern TheUMEntryPrestubWorker:proc
extern UMEntryPrestubUnwindFrameChainHandler:proc
extern UMThunkStubUnwindFrameChainHandler:proc
extern g_TrapReturningThreads:dword
-extern UM2MDoADCallBack:proc
extern UMThunkStubRareDisableWorker:proc
extern ReversePInvokeBadTransition:proc
@@ -188,14 +187,6 @@ HaveThread:
InCooperativeMode:
- mov rax, [r12 + OFFSETOF__Thread__m_pDomain]
- mov eax, [rax + OFFSETOF__AppDomain__m_dwId]
-
- mov r11d, [METHODDESC_REGISTER + OFFSETOF__UMEntryThunk__m_dwDomainId]
-
- cmp rax, r11
- jne WrongAppDomain
-
mov r11, [METHODDESC_REGISTER + OFFSETOF__UMEntryThunk__m_pUMThunkMarshInfo]
mov eax, [r11 + OFFSETOF__UMThunkMarshInfo__m_cbActualArgSize] ; stack_args
test rax, rax ; stack_args
@@ -322,137 +313,7 @@ CopyLoop:
jmp ArgumentsSetup
-
-WrongAppDomain:
- ;
- ; home register args to the stack
- ;
- mov [rbp + UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 0h], rcx
- mov [rbp + UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 8h], rdx
- mov [rbp + UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 10h], r8
- mov [rbp + UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 18h], r9
-
- ;
- ; save off xmm registers
- ;
- movdqa xmmword ptr [rbp + UMThunkStubAMD64_XMM_SAVE_OFFSET + 0h], xmm0
- movdqa xmmword ptr [rbp + UMThunkStubAMD64_XMM_SAVE_OFFSET + 10h], xmm1
- movdqa xmmword ptr [rbp + UMThunkStubAMD64_XMM_SAVE_OFFSET + 20h], xmm2
- movdqa xmmword ptr [rbp + UMThunkStubAMD64_XMM_SAVE_OFFSET + 30h], xmm3
-
- ;
- ; call our helper to perform the AD transtion
- ;
- mov rcx, METHODDESC_REGISTER
- lea r8, [rbp + UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET]
- mov rax, [METHODDESC_REGISTER + OFFSETOF__UMEntryThunk__m_pUMThunkMarshInfo]
- mov r9d, [rax + OFFSETOF__UMThunkMarshInfo__m_cbActualArgSize]
- call UM2MDoADCallBack
-
- ; restore return value
- mov rax, [rbp + UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 0h]
- movdqa xmm0, xmmword ptr [rbp + UMThunkStubAMD64_XMM_SAVE_OFFSET + 0h]
-
- jmp PostCall
-
NESTED_END UMThunkStub, _TEXT
-;
-; EXTERN_C void __stdcall UM2MThunk_WrapperHelper(
-; void *pThunkArgs, ; rcx
-; int argLen, ; rdx
-; void *pAddr, ; r8 // not used
-; UMEntryThunk *pEntryThunk, ; r9
-; Thread *pThread); ; [entry_sp + 28h]
-;
-NESTED_ENTRY UM2MThunk_WrapperHelper, _TEXT
-
-
-UM2MThunk_WrapperHelper_STACK_FRAME_SIZE = 0
-
-; number of integer registers saved in prologue
-UM2MThunk_WrapperHelper_NUM_REG_PUSHES = 3
-UM2MThunk_WrapperHelper_STACK_FRAME_SIZE = UM2MThunk_WrapperHelper_STACK_FRAME_SIZE + (UM2MThunk_WrapperHelper_NUM_REG_PUSHES * 8)
-
-UM2MThunk_WrapperHelper_CALLEE_SCRATCH_SIZE = SIZEOF_MAX_OUTGOING_ARGUMENT_HOMES
-UM2MThunk_WrapperHelper_STACK_FRAME_SIZE = UM2MThunk_WrapperHelper_STACK_FRAME_SIZE + UM2MThunk_WrapperHelper_CALLEE_SCRATCH_SIZE
-
-; Ensure that rsp remains 16-byte aligned
-if ((UM2MThunk_WrapperHelper_STACK_FRAME_SIZE + 8) MOD 16) ne 0 ; +8 for caller-pushed return address
-UM2MThunk_WrapperHelper_STACK_FRAME_SIZE = UM2MThunk_WrapperHelper_STACK_FRAME_SIZE + 8
-endif
-
-UM2MThunk_WrapperHelper_FRAME_OFFSET = UM2MThunk_WrapperHelper_CALLEE_SCRATCH_SIZE
-UM2MThunk_WrapperHelper_FIXED_STACK_ALLOC_SIZE = UM2MThunk_WrapperHelper_STACK_FRAME_SIZE - (UM2MThunk_WrapperHelper_NUM_REG_PUSHES * 8)
-
- push_nonvol_reg rsi
- push_nonvol_reg rdi
- push_nonvol_reg rbp
- alloc_stack UM2MThunk_WrapperHelper_FIXED_STACK_ALLOC_SIZE
- set_frame rbp, UM2MThunk_WrapperHelper_FRAME_OFFSET
- END_PROLOGUE
-
- ;
- ; We are in cooperative mode and in the correct domain.
- ; The host has also been notified that we've entered the
- ; runtime. All we have left to do is to copy the stack,
- ; setup the register args and then call the managed target
- ;
-
- test rdx, rdx
- jg CopyStackArgs
-
-ArgumentsSetup:
- mov METHODDESC_REGISTER, r9
-
- mov rsi, rcx ; rsi <- pThunkArgs
- mov rcx, [rsi + 0h]
- mov rdx, [rsi + 8h]
- mov r8, [rsi + 10h]
- mov r9, [rsi + 18h]
-
- movdqa xmm0, xmmword ptr [rsi + UMThunkStubAMD64_XMM_SAVE_OFFSET - UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 0h]
- movdqa xmm1, xmmword ptr [rsi + UMThunkStubAMD64_XMM_SAVE_OFFSET - UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 10h]
- movdqa xmm2, xmmword ptr [rsi + UMThunkStubAMD64_XMM_SAVE_OFFSET - UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 20h]
- movdqa xmm3, xmmword ptr [rsi + UMThunkStubAMD64_XMM_SAVE_OFFSET - UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 30h]
-
- mov rax, [METHODDESC_REGISTER + OFFSETOF__UMEntryThunk__m_pUMThunkMarshInfo] ; rax <- UMThunkMarshInfo*
- mov rax, [rax + OFFSETOF__UMThunkMarshInfo__m_pILStub] ; rax <- Stub*
- call rax
-
- ; make sure we don't trash the return value
- mov [rsi + 0h], rax
- movdqa xmmword ptr [rsi + UMThunkStubAMD64_XMM_SAVE_OFFSET - UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 0h], xmm0
-
- lea rsp, [rbp - UM2MThunk_WrapperHelper_FRAME_OFFSET + UM2MThunk_WrapperHelper_FIXED_STACK_ALLOC_SIZE]
- pop rbp
- pop rdi
- pop rsi
- ret
-
-
-CopyStackArgs:
- ; rdx = cbStackArgs (with 20h for register args subtracted out already)
- ; rcx = pSrcArgStack
-
- sub rsp, rdx
- and rsp, -16
-
- mov r8, rcx
-
- lea rsi, [rcx + SIZEOF_MAX_OUTGOING_ARGUMENT_HOMES]
- lea rdi, [rsp + UM2MThunk_WrapperHelper_CALLEE_SCRATCH_SIZE]
-
- mov rcx, rdx
- shr rcx, 3
-
- rep movsq
-
- mov rcx, r8
-
- jmp ArgumentsSetup
-
-NESTED_END UM2MThunk_WrapperHelper, _TEXT
-
end
diff --git a/src/vm/amd64/asmconstants.h b/src/vm/amd64/asmconstants.h
index cadc10ac56..1af07860ce 100644
--- a/src/vm/amd64/asmconstants.h
+++ b/src/vm/amd64/asmconstants.h
@@ -147,22 +147,22 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_pFrame
ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_State
== offsetof(Thread, m_State));
-#define OFFSETOF__Thread__m_pDomain 0x20
+#define OFFSETOF__Thread__m_pDomain 0x18
ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_pDomain
== offsetof(Thread, m_pDomain));
-#define OFFSETOF__Thread__m_dwLockCount 0x28
+#define OFFSETOF__Thread__m_dwLockCount 0x20
ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_dwLockCount
== offsetof(Thread, m_dwLockCount));
-#define OFFSETOF__Thread__m_ThreadId 0x2C
+#define OFFSETOF__Thread__m_ThreadId 0x24
ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_ThreadId
== offsetof(Thread, m_ThreadId));
-#define OFFSET__Thread__m_alloc_context__alloc_ptr 0x60
+#define OFFSET__Thread__m_alloc_context__alloc_ptr 0x58
ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr));
-#define OFFSET__Thread__m_alloc_context__alloc_limit 0x68
+#define OFFSET__Thread__m_alloc_context__alloc_limit 0x60
ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit));
#define OFFSETOF__gc_alloc_context__alloc_ptr 0x0
diff --git a/src/vm/amd64/umthunkstub.S b/src/vm/amd64/umthunkstub.S
index 3e60bedb3f..834f0ca0f8 100644
--- a/src/vm/amd64/umthunkstub.S
+++ b/src/vm/amd64/umthunkstub.S
@@ -196,15 +196,3 @@ LOCAL_LABEL(WrongAppDomain):
#endif
NESTED_END UMThunkStub, _TEXT
-
-//
-// EXTERN_C void __stdcall UM2MThunk_WrapperHelper(
-// void *pThunkArgs, // rdi
-// int argLen, // rsi
-// void *pAddr, // rdx // not used
-// UMEntryThunk *pEntryThunk, // rcx
-// Thread *pThread); // r8
-//
-NESTED_ENTRY UM2MThunk_WrapperHelper, _TEXT, NoHandler
- int3
-NESTED_END UM2MThunk_WrapperHelper, _TEXT
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp
index 18478eb0d4..8f8efcf0fc 100644
--- a/src/vm/appdomain.cpp
+++ b/src/vm/appdomain.cpp
@@ -142,11 +142,6 @@ CrstStatic SystemDomain::m_DelayedUnloadCrst;
ULONG SystemDomain::s_dNumAppDomains = 0;
-AppDomain * SystemDomain::m_pAppDomainBeingUnloaded = NULL;
-ADIndex SystemDomain::m_dwIndexOfAppDomainBeingUnloaded;
-Thread *SystemDomain::m_pAppDomainUnloadRequestingThread = 0;
-Thread *SystemDomain::m_pAppDomainUnloadingThread = 0;
-
ArrayListStatic SystemDomain::m_appDomainIdList;
DWORD SystemDomain::m_dwLowestFreeIndex = 0;
@@ -2215,8 +2210,7 @@ void SystemDomain::Stop()
AppDomainIterator i(TRUE);
while (i.Next())
- if (i.GetDomain()->m_Stage < AppDomain::STAGE_CLEARED)
- i.GetDomain()->Stop();
+ i.GetDomain()->Stop();
}
@@ -2476,21 +2470,6 @@ void SystemDomain::LazyInitGlobalStringLiteralMap()
}
}
-void AppDomain::CreateADUnloadStartEvent()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- SO_TOLERANT;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- g_pUnloadStartEvent = new CLREvent();
- g_pUnloadStartEvent->CreateAutoEvent(FALSE);
-}
-
/*static*/ void SystemDomain::EnumAllStaticGCRefs(promote_func* fn, ScanContext* sc)
{
CONTRACT_VOID
@@ -2526,7 +2505,7 @@ void AppDomain::CreateADUnloadStartEvent()
for (i = 0 ; i < count ; i++)
{
AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
- if (pAppDomain && pAppDomain->IsActive() && !pAppDomain->IsUnloading())
+ if (pAppDomain && pAppDomain->IsActive())
{
#ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
if (g_fEnableARM)
@@ -2654,7 +2633,7 @@ DWORD SystemDomain::GetTotalNumSizedRefHandles()
for (i = 0 ; i < count ; i++)
{
AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
- if (pAppDomain && pAppDomain->IsActive() && !pAppDomain->IsUnloading())
+ if (pAppDomain && pAppDomain->IsActive())
{
dwTotalNumSizedRefHandles += pAppDomain->GetNumSizedRefHandles();
}
@@ -2850,7 +2829,6 @@ void SystemDomain::LoadDomain(AppDomain *pDomain)
}
CONTRACTL_END;
- pDomain->SetCanUnload(); // by default can unload any domain
SystemDomain::System()->AddDomain(pDomain);
}
@@ -2995,12 +2973,8 @@ AppDomain *SystemDomain::GetAppDomainAtId(ADID index)
AppDomain * result = (AppDomain *)m_appDomainIdList.Get(requestedID);
#ifndef CROSSGEN_COMPILE
- if(result==NULL && GetThread() == FinalizerThread::GetFinalizerThread() &&
- SystemDomain::System()->AppDomainBeingUnloaded()!=NULL &&
- SystemDomain::System()->AppDomainBeingUnloaded()->GetId()==index)
- result=SystemDomain::System()->AppDomainBeingUnloaded();
// If the current thread can't enter the AppDomain, then don't return it.
- if (!result || !result->CanThreadEnter(GetThread()))
+ if (!result)
return NULL;
#endif // CROSSGEN_COMPILE
@@ -3913,11 +3887,6 @@ AppDomain::AppDomain()
CONTRACTL_END;
m_cRef=1;
- m_pNextInDelayedUnloadList = NULL;
- m_fRudeUnload = FALSE;
- m_pUnloadRequestThread = NULL;
- m_ADUnloadSink=NULL;
-
// Initialize Shared state. Assemblies are loaded
// into each domain by default.
@@ -3969,8 +3938,6 @@ AppDomain::AppDomain()
m_ForceTrivialWaitOperations = false;
m_Stage=STAGE_CREATING;
- m_bForceGCOnUnload=FALSE;
- m_bUnloadingFromUnloadEvent=FALSE;
#ifdef _DEBUG
m_dwIterHolders=0;
m_dwRefTakers=0;
@@ -4026,9 +3993,6 @@ AppDomain::~AppDomain()
m_AssemblyCache.Clear();
- if (m_ADUnloadSink)
- m_ADUnloadSink->Release();
-
if(!g_fEEInit)
Terminate();
@@ -4116,8 +4080,6 @@ void AppDomain::Init()
#ifndef CROSSGEN_COMPILE
PerAppDomainTPCountList::SetAppDomainId(m_tpIndex, m_dwId);
-
- m_ADUnloadSink=new ADUnloadSink();
#endif
BaseDomain::Init();
@@ -4226,85 +4188,6 @@ BOOL AppDomain::IsCompilationDomain()
#ifndef CROSSGEN_COMPILE
-extern int g_fADUnloadWorkerOK;
-
-// Notes:
-// This helper will send the AppDomain creation notifications for profiler / debugger.
-// If it throws, its backout code will also send a notification.
-// If it succeeds, then we still need to send a AppDomainCreateFinished notification.
-void AppDomain::CreateUnmanagedObject(AppDomainCreationHolder<AppDomain>& pDomain)
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- INJECT_FAULT(COMPlusThrowOM(););
- }
- CONTRACTL_END;
-
- GCX_PREEMP();
-
- pDomain.Assign(new AppDomain());
- if (g_fADUnloadWorkerOK<0)
- {
- AppDomain::CreateADUnloadWorker();
- }
-
- //@todo: B#25921
- // We addref Appdomain object here and notify a profiler that appdomain
- // creation has started, then return to managed code which will call
- // the function that releases the appdomain and notifies a profiler that we finished
- // creating the appdomain. If an exception is raised while we're in that managed code
- // we will leak memory and the profiler will not be notified about the failure
-
-#ifdef PROFILING_SUPPORTED
- // Signal profile if present.
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
- g_profControlBlock.pProfInterface->AppDomainCreationStarted((AppDomainID) (AppDomain*) pDomain);
- END_PIN_PROFILER();
- }
- EX_TRY
-#endif // PROFILING_SUPPORTED
- {
- {
- SystemDomain::LockHolder lh;
- pDomain->Init();
- // allocate a Virtual Call Stub Manager for this domain
- pDomain->InitVSD();
- }
-
- pDomain->SetCanUnload(); // by default can unload any domain
-
- #ifdef DEBUGGING_SUPPORTED
- // Notify the debugger here, before the thread transitions into the
- // AD to finish the setup, and before any assemblies are loaded into it.
- SystemDomain::PublishAppDomainAndInformDebugger(pDomain);
- #endif // DEBUGGING_SUPPORTED
-
- STRESS_LOG2 (LF_APPDOMAIN, LL_INFO100, "Create domain [%d] %p\n", pDomain->GetId().m_dwId, (AppDomain*)pDomain);
- pDomain->LoadSystemAssemblies();
- pDomain->SetupSharedStatics();
-
- pDomain->SetStage(AppDomain::STAGE_ACTIVE);
- }
-#ifdef PROFILING_SUPPORTED
- EX_HOOK
- {
- // Need the first assembly loaded in to get any data on an app domain.
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
- g_profControlBlock.pProfInterface->AppDomainCreationFinished((AppDomainID)(AppDomain*) pDomain, GET_EXCEPTION()->GetHR());
- END_PIN_PROFILER();
- }
- }
- EX_END_HOOK;
-
- // On success, caller must still send the AppDomainCreationFinished notification.
-#endif // PROFILING_SUPPORTED
-}
-
void AppDomain::Stop()
{
CONTRACTL
@@ -4517,20 +4400,6 @@ struct GetExposedObject_Args
OBJECTREF *ref;
};
-static void GetExposedObject_Wrapper(LPVOID ptr)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
- GetExposedObject_Args *args = (GetExposedObject_Args *) ptr;
- *(args->ref) = args->pDomain->GetExposedObject();
-}
-
-
OBJECTREF AppDomain::GetExposedObject()
{
CONTRACTL
@@ -4547,16 +4416,6 @@ OBJECTREF AppDomain::GetExposedObject()
{
APPDOMAINREF obj = NULL;
- Thread *pThread = GetThread();
- if (pThread->GetDomain() != this)
- {
- GCPROTECT_BEGIN(ref);
- GetExposedObject_Args args = {this, &ref};
- // call through DoCallBack with a domain transition
- pThread->DoADCallBack(this,GetExposedObject_Wrapper, &args,ADV_CREATING|ADV_RUNNINGIN);
- GCPROTECT_END();
- return ref;
- }
MethodTable *pMT = MscorlibBinder::GetClass(CLASS__APP_DOMAIN);
// Create the module object
@@ -5349,7 +5208,7 @@ CHECK AppDomain::CheckCanExecuteManagedCode(MethodDesc* pMD)
if (!pMD->IsInterface() || pMD->IsStatic()) //interfaces require no activation for instance methods
{
//cctor could have been interupted by ADU
- CHECK_MSG(HasUnloadStarted() || pModule->CheckActivated(),
+ CHECK_MSG(pModule->CheckActivated(),
"Managed code can only run when its module has been activated in the current app domain");
}
@@ -5652,17 +5511,6 @@ struct LoadFileArgs
DomainFile *result;
};
-#ifndef CROSSGEN_COMPILE
-static void LoadDomainFile_Wrapper(void *ptr)
-{
- WRAPPER_NO_CONTRACT;
- STATIC_CONTRACT_SO_INTOLERANT;
- GCX_PREEMP();
- LoadFileArgs *args = (LoadFileArgs *) ptr;
- args->result = GetAppDomain()->LoadDomainFile(args->pLock, args->targetLevel);
-}
-#endif // !CROSSGEN_COMPILE
-
DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetLevel)
{
CONTRACT(DomainFile *)
@@ -5716,28 +5564,6 @@ DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetL
RETURN pFile;
}
-#ifndef CROSSGEN_COMPILE
- // Make sure we are in the right domain. Many of the load operations require the target domain
- // to be the current app domain, most notably anything involving managed code or managed object
- // creation.
- if (this != GetAppDomain()
- && (!pFile->GetFile()->IsSystem() || targetLevel > FILE_LOAD_ALLOCATE))
- {
- // Transition to the correct app domain and perform the load there.
- GCX_COOP();
-
- // we will release the lock in the other app domain
- lockRef.SuppressRelease();
-
- if(!CanLoadCode() || GetDefaultContext() ==NULL)
- COMPlusThrow(kAppDomainUnloadedException);
- LoadFileArgs args = {pLock, targetLevel, NULL};
- GetThread()->DoADCallBack(this, LoadDomainFile_Wrapper, (void *) &args, ADV_CREATING);
-
- RETURN args.result;
- }
-#endif // CROSSGEN_COMPILE
-
// Initialize a loading queue. This will hold any loads which are triggered recursively but
// which cannot be immediately satisfied due to anti-deadlock constraints.
@@ -7280,7 +7106,7 @@ ULONG AppDomain::Release()
ULONG cRef = InterlockedDecrement(&m_cRef);
if (!cRef)
{
- _ASSERTE (m_Stage == STAGE_CREATING || m_Stage == STAGE_CLOSED);
+ _ASSERTE (m_Stage == STAGE_CREATING);
ADID adid=GetId();
delete this;
TESTHOOKCALL(AppDomainDestroyed(adid.m_dwId));
@@ -7289,101 +7115,8 @@ ULONG AppDomain::Release()
}
-AppDomain* AppDomain::s_pAppDomainToRaiseUnloadEvent;
-BOOL AppDomain::s_fProcessUnloadDomainEvent = FALSE;
-
#ifndef CROSSGEN_COMPILE
-void AppDomain::RaiseUnloadDomainEvent_Wrapper(LPVOID ptr)
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- INJECT_FAULT(COMPlusThrowOM(););
- SO_INTOLERANT;
- }
- CONTRACTL_END;
-
- AppDomain* pDomain = (AppDomain *) ptr;
- pDomain->RaiseUnloadDomainEvent();
-}
-
-void AppDomain::ProcessUnloadDomainEventOnFinalizeThread()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
- Thread *pThread = GetThread();
- _ASSERTE (pThread && IsFinalizerThread());
-
- // if we are not unloading domain now, do not process the event
- if (SystemDomain::AppDomainBeingUnloaded() == NULL)
- {
- s_pAppDomainToRaiseUnloadEvent->SetStage(STAGE_UNLOAD_REQUESTED);
- s_pAppDomainToRaiseUnloadEvent->EnableADUnloadWorker(
- s_pAppDomainToRaiseUnloadEvent->IsRudeUnload()?EEPolicy::ADU_Rude:EEPolicy::ADU_Safe);
- FastInterlockExchangePointer(&s_pAppDomainToRaiseUnloadEvent, NULL);
- return;
- }
- FastInterlockExchange((LONG*)&s_fProcessUnloadDomainEvent, TRUE);
- AppDomain::EnableADUnloadWorkerForFinalizer();
- pThread->SetThreadStateNC(Thread::TSNC_RaiseUnloadEvent);
- s_pAppDomainToRaiseUnloadEvent->RaiseUnloadDomainEvent();
- pThread->ResetThreadStateNC(Thread::TSNC_RaiseUnloadEvent);
- s_pAppDomainToRaiseUnloadEvent->EnableADUnloadWorker(
- s_pAppDomainToRaiseUnloadEvent->IsRudeUnload()?EEPolicy::ADU_Rude:EEPolicy::ADU_Safe);
- FastInterlockExchangePointer(&s_pAppDomainToRaiseUnloadEvent, NULL);
- FastInterlockExchange((LONG*)&s_fProcessUnloadDomainEvent, FALSE);
-
- if (pThread->IsAbortRequested())
- {
- pThread->UnmarkThreadForAbort(Thread::TAR_Thread);
- }
-}
-
-void AppDomain::RaiseUnloadDomainEvent()
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- SO_INTOLERANT;
- }
- CONTRACTL_END;
-
- Thread *pThread = GetThread();
- if (this != pThread->GetDomain())
- {
- pThread->DoADCallBack(this, AppDomain::RaiseUnloadDomainEvent_Wrapper, this,ADV_FINALIZER|ADV_COMPILATION);
- }
- else
- {
- struct _gc
- {
- APPDOMAINREF Domain;
- OBJECTREF Delegate;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
- gc.Domain = (APPDOMAINREF) GetRawExposedObject();
- if (gc.Domain != NULL)
- {
- gc.Delegate = gc.Domain->m_pDomainUnloadEventHandler;
- if (gc.Delegate != NULL)
- DistributeEvent(&gc.Delegate, (OBJECTREF *) &gc.Domain);
- }
- GCPROTECT_END();
- }
-}
-
void AppDomain::RaiseLoadingAssemblyEvent(DomainAssembly *pAssembly)
{
CONTRACTL
@@ -7593,8 +7326,6 @@ AppDomain::HasUnhandledExceptionEventHandler()
NOTHROW;
}
CONTRACTL_END;
- if (!CanThreadEnter(GetThread()))
- return FALSE;
if (GetRawExposedObject()==NULL)
return FALSE;
return (((APPDOMAINREF)GetRawExposedObject())->m_pUnhandledExceptionEventHandler!=NULL);
@@ -7962,708 +7693,6 @@ void AppDomain::DetachRCWs()
#endif // FEATURE_COMINTEROP
-BOOL AppDomain::CanThreadEnter(Thread *pThread)
-{
- WRAPPER_NO_CONTRACT;
-
- if (m_Stage < STAGE_EXITED)
- return TRUE;
-
- if (pThread == SystemDomain::System()->GetUnloadingThread())
- return m_Stage < STAGE_FINALIZING;
- if (pThread == FinalizerThread::GetFinalizerThread())
- return m_Stage < STAGE_FINALIZED;
-
- return FALSE;
-}
-
-void AppDomain::AllowThreadEntrance(AppDomain * pApp)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- FORBID_FAULT;
- PRECONDITION(CheckPointer(pApp));
- }
- CONTRACTL_END;
-
- if (pApp->GetUnloadRequestThread() == NULL)
- {
- // This is asynchonous unload, either by a host, or by AppDomain.Unload from AD unload event.
- if (!pApp->IsUnloadingFromUnloadEvent())
- {
- pApp->SetStage(STAGE_UNLOAD_REQUESTED);
- pApp->EnableADUnloadWorker(
- pApp->IsRudeUnload()?EEPolicy::ADU_Rude:EEPolicy::ADU_Safe);
- return;
- }
- }
-
- SystemDomain::LockHolder lh; // we don't want to reopen appdomain if other thread can be preparing to unload it
-
-#ifdef FEATURE_COMINTEROP
- if (pApp->m_pComCallWrapperCache)
- pApp->m_pComCallWrapperCache->ResetDomainIsUnloading();
-#endif // FEATURE_COMINTEROP
-
- pApp->SetStage(STAGE_OPEN);
-}
-
-void AppDomain::RestrictThreadEntrance(AppDomain * pApp)
-{
- CONTRACTL
- {
- DISABLED(NOTHROW);
- DISABLED(GC_TRIGGERS);
- MODE_ANY;
- DISABLED(FORBID_FAULT);
- PRECONDITION(CheckPointer(pApp));
- }
- CONTRACTL_END;
-
-#ifdef FEATURE_COMINTEROP
- // Set the flag on our CCW cache so stubs won't enter
- if (pApp->m_pComCallWrapperCache)
- pApp->m_pComCallWrapperCache->SetDomainIsUnloading();
-#endif // FEATURE_COMINTEROP
-
- SystemDomain::LockHolder lh; // we don't want to reopen appdomain if other thread can be preparing to unload it
- // Release our ID so remoting and thread pool won't enter
- pApp->SetStage(STAGE_EXITED);
-};
-
-void AppDomain::Exit(BOOL fRunFinalizers, BOOL fAsyncExit)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Exiting domain [%d] %#08x %ls\n",
- GetId().m_dwId, this, GetFriendlyNameForLogging()));
-
- RestrictEnterHolder RestrictEnter(this);
-
- {
- SystemDomain::LockHolder lh; // we don't want to close appdomain if other thread can be preparing to unload it
- SetStage(STAGE_EXITING); // Note that we're trying to exit
- }
-
- // Raise the event indicating the domain is being unloaded.
- if (GetDefaultContext())
- {
- FastInterlockExchangePointer(&s_pAppDomainToRaiseUnloadEvent, this);
-
- DWORD timeout = GetEEPolicy()->GetTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload);
- //if (timeout == INFINITE)
- //{
- // timeout = 20000; // 20 seconds
- //}
- DWORD timeoutForFinalizer = GetEEPolicy()->GetTimeout(OPR_FinalizerRun);
- ULONGLONG curTime = CLRGetTickCount64();
- ULONGLONG endTime = 0;
- if (timeout != INFINITE)
- {
- endTime = curTime + timeout;
- // We will try to kill AD unload event if it takes too long, and then we move on to the next registered caller.
- timeout /= 5;
- }
-
- while (s_pAppDomainToRaiseUnloadEvent != NULL)
- {
- FinalizerThread::FinalizerThreadWait(s_fProcessUnloadDomainEvent?timeout:timeoutForFinalizer);
- if (endTime != 0 && s_pAppDomainToRaiseUnloadEvent != NULL)
- {
- if (CLRGetTickCount64() >= endTime)
- {
- SString sThreadId;
- sThreadId.Printf(W("%x"), FinalizerThread::GetFinalizerThread()->GetThreadId());
- COMPlusThrow(kCannotUnloadAppDomainException,
- IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD,
- sThreadId);
- }
- }
- }
- }
-
- // Tell the tiered compilation manager to stop initiating any new work for background
- // jit optimization. Its possible the standard thread unwind mechanisms would pre-emptively
- // evacuate the jit threadpool worker threads from the domain on their own, but I see no reason
- // to take the risk of relying on them when we can easily augment with a cooperative
- // shutdown check. This notification only initiates the process of evacuating the threads
- // and then the UnwindThreads() call below is where blocking will occur to ensure the threads
- // have exited the domain.
- //
-#ifdef FEATURE_TIERED_COMPILATION
- m_tieredCompilationManager.Shutdown();
-#endif
-
- //
- // Set up blocks so no threads can enter except for the finalizer and the thread
- // doing the unload.
- //
-
- RestrictThreadEntrance(this);
-
- // Cause existing threads to abort out of this domain. This should ensure all
- // normal threads are outside the domain, and we've already ensured that no new threads
- // can enter.
-
- PerAppDomainTPCountList::AppDomainUnloadingHolder tpAdUnloadHolder(GetTPIndex());
-
-
- if (!NingenEnabled())
- {
- UnwindThreads();
- }
-
- TESTHOOKCALL(UnwoundThreads(GetId().m_dwId)) ;
- ProcessEventForHost(Event_DomainUnload, (PVOID)(UINT_PTR)GetId().m_dwId);
-
- RestrictEnter.SuppressRelease(); //after this point we don't guarantee appdomain consistency
-#ifdef PROFILING_SUPPORTED
- // Signal profile if present.
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->AppDomainShutdownStarted((AppDomainID) this);
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
- COUNTER_ONLY(GetPerfCounters().m_Loading.cAppDomains--);
- COUNTER_ONLY(GetPerfCounters().m_Loading.cAppDomainsUnloaded++);
-
- LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Domain [%d] %#08x %ls is exited.\n",
- GetId().m_dwId, this, GetFriendlyNameForLogging()));
-
- // Send ETW events for this domain's unload and potentially iterate through this
- // domain's modules & assemblies to send events for their unloads as well. This
- // needs to occur before STAGE_FINALIZED (to ensure everything is there), so we do
- // this before any finalization occurs at all.
- ETW::LoaderLog::DomainUnload(this);
-
- CodeVersionManager::OnAppDomainExit(this);
-
- //
- // Spin running finalizers until we flush them all. We need to make multiple passes
- // in case the finalizers create more finalizable objects. This is important to clear
- // the finalizable objects as roots, as well as to actually execute the finalizers. This
- // will only finalize instances instances of types that aren't potentially agile becuase we can't
- // risk finalizing agile objects. So we will be left with instances of potentially agile types
- // in handles or statics.
- //
- // <TODO>@todo: Need to ensure this will terminate in a reasonable amount of time. Eventually
- // we should probably start passing FALSE for fRunFinalizers. Also I'm not sure we
- // guarantee that FinalizerThreadWait will ever terminate in general.</TODO>
- //
-
- SetStage(STAGE_FINALIZING);
-
- // Flush finalizers now.
- FinalizerThread::UnloadAppDomain(this, fRunFinalizers);
-
- DWORD timeout = GetEEPolicy()->GetTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload);
- ULONGLONG startTime = CLRGetTickCount64();
- ULONGLONG elapsedTime = 0;
- DWORD finalizerWait = 0;
-
- while (FinalizerThread::GetUnloadingAppDomain() != NULL)
- {
-
- if (timeout != INFINITE)
- {
- elapsedTime = CLRGetTickCount64() - startTime;
- }
- if (timeout > elapsedTime)
- {
- finalizerWait = timeout - static_cast<DWORD>(elapsedTime);
- }
- FinalizerThread::FinalizerThreadWait(finalizerWait); //will set stage to finalized
- if (timeout != INFINITE && FinalizerThread::GetUnloadingAppDomain() != NULL)
- {
- elapsedTime = CLRGetTickCount64() - startTime;
- if (timeout <= elapsedTime)
- {
- SetRudeUnload();
- // TODO: Consider escalation from RudeAppDomain
- timeout = INFINITE;
- }
- }
- }
-
- tpAdUnloadHolder.SuppressRelease();
- PerAppDomainTPCountList::ResetAppDomainTPCounts(GetTPIndex());
-
- LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Domain [%d] %#08x %ls is finalized.\n",
- GetId().m_dwId, this, GetFriendlyNameForLogging()));
-
-
- AppDomainRefHolder This(this);
- AddRef(); // Hold a reference so CloseDomain won't delete us yet
- CloseDomain(); // Remove ourself from the list of app domains
-
- // This needs to be done prior to destroying the handle tables below.
- ReleaseDomainBoundInfo();
-
- //
- // It should be impossible to run non-mscorlib code in this domain now.
- // Cleanup all of our roots except the handles. We do this to allow as many
- // finalizers as possible to run correctly. If we delete the handles, they
- // can't run.
- //
- if (!NingenEnabled())
- {
- }
-
- ClearGCRoots();
- ClearGCHandles();
-
- LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Domain [%d] %#08x %ls is cleared.\n",
- GetId().m_dwId, this, GetFriendlyNameForLogging()));
-
- if (fAsyncExit && fRunFinalizers)
- {
- GCX_PREEMP();
- m_AssemblyCache.Clear();
- ClearFusionContext();
- ReleaseFiles();
- if (!NingenEnabled())
- {
- AddMemoryPressure();
- }
- }
- SystemDomain::System()->AddToDelayedUnloadList(this, fAsyncExit);
- SystemDomain::SetUnloadDomainCleared();
- if (m_dwId.m_dwId!=0)
- SystemDomain::ReleaseAppDomainId(m_dwId);
-#ifdef PROFILING_SUPPORTED
- // Always signal profile if present, even when failed.
- {
- BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
- GCX_PREEMP();
- g_profControlBlock.pProfInterface->AppDomainShutdownFinished((AppDomainID) this, S_OK);
- END_PIN_PROFILER();
- }
-#endif // PROFILING_SUPPORTED
-
-}
-
-void AppDomain::Close()
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- NOTHROW;
- }
- CONTRACTL_END;
-
- LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Domain [%d] %#08x %ls is collected.\n",
- GetId().m_dwId, this, GetFriendlyNameForLogging()));
-
- {
- GCX_PREEMP();
- RemoveMemoryPressure();
- }
- _ASSERTE(m_cRef>0); //should be alive at this point otherwise iterator can revive us and crash
- {
- SystemDomain::LockHolder lh; // Avoid races with AppDomainIterator
- SetStage(STAGE_CLOSED);
- }
-
- // CONSIDER: move releasing remoting cache from managed code to here.
-}
-
-
-void AppDomain::ResetUnloadRequestThread(ADID Id)
-{
- CONTRACTL
- {
- NOTHROW;
- MODE_ANY;
- PRECONDITION(!IsADUnloadHelperThread());
- }
- CONTRACTL_END;
-
- GCX_COOP();
- AppDomainFromIDHolder ad(Id, TRUE);
- if(!ad.IsUnloaded() && ad->m_Stage < STAGE_UNLOAD_REQUESTED)
- {
- Thread *pThread = ad->GetUnloadRequestThread();
- if(pThread==GetThread())
- {
- ad->m_dwThreadsStillInAppDomain=(ULONG)-1;
-
- if(pThread)
- {
- if (pThread->GetUnloadBoundaryFrame() && pThread->IsBeingAbortedForADUnload())
- {
- pThread->UnmarkThreadForAbort(Thread::TAR_ADUnload);
- }
- ad->GetUnloadRequestThread()->ResetUnloadBoundaryFrame();
- pThread->ResetBeginAbortedForADUnload();
- }
-
- ad->SetUnloadRequestThread(NULL);
- }
- }
-}
-
-
-int g_fADUnloadWorkerOK = -1;
-
-HRESULT AppDomain::UnloadById(ADID dwId, BOOL fSync,BOOL fExceptionsPassThrough)
-{
- CONTRACTL
- {
- if(fExceptionsPassThrough) {THROWS;} else {NOTHROW;}
- MODE_ANY;
- if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_TRIGGERS);}
- FORBID_FAULT;
- }
- CONTRACTL_END;
-
- if (dwId==(ADID)DefaultADID)
- return COR_E_CANNOTUNLOADAPPDOMAIN;
-
- Thread *pThread = GetThread();
-
- // Finalizer thread can not wait until AD unload is done,
- // because AD unload is going to wait for Finalizer Thread.
- if (fSync && pThread == FinalizerThread::GetFinalizerThread() &&
- !pThread->HasThreadStateNC(Thread::TSNC_RaiseUnloadEvent))
- return COR_E_CANNOTUNLOADAPPDOMAIN;
-
-
- // AD unload helper thread should have been created.
- _ASSERTE (g_fADUnloadWorkerOK == 1);
-
- _ASSERTE (!IsADUnloadHelperThread());
-
- BOOL fIsRaisingUnloadEvent = (pThread != NULL && pThread->HasThreadStateNC(Thread::TSNC_RaiseUnloadEvent));
-
- if (fIsRaisingUnloadEvent)
- {
- AppDomainFromIDHolder pApp(dwId, TRUE, AppDomainFromIDHolder::SyncType_GC);
-
- if (pApp.IsUnloaded() || ! pApp->CanLoadCode() || pApp->GetId().m_dwId == 0)
- return COR_E_APPDOMAINUNLOADED;
-
- pApp->EnableADUnloadWorker();
-
- return S_FALSE;
- }
-
-
- ADUnloadSinkHolder pSink;
-
- {
- SystemDomain::LockHolder ulh;
-
- AppDomainFromIDHolder pApp(dwId, TRUE, AppDomainFromIDHolder::SyncType_ADLock);
-
- if (pApp.IsUnloaded() || ! pApp->CanLoadCode() || pApp->GetId().m_dwId == 0)
- return COR_E_APPDOMAINUNLOADED;
-
- if (g_fADUnloadWorkerOK != 1)
- {
- _ASSERTE(FALSE);
- return E_UNEXPECTED;
- }
-
- if (!fSync)
- {
- pApp->EnableADUnloadWorker();
- return S_OK;
- }
-
- pSink = pApp->PrepareForWaitUnloadCompletion();
-
- pApp->EnableADUnloadWorker();
-
- // release the holders - we don't care anymore if the appdomain is gone
- }
-
-#ifdef FEATURE_TESTHOOKS
- if (fExceptionsPassThrough)
- {
- CONTRACT_VIOLATION(FaultViolation);
- return UnloadWaitNoCatch(dwId,pSink);
- }
-#endif
-
- return UnloadWait(dwId,pSink);
-}
-
-HRESULT AppDomain::UnloadWait(ADID Id, ADUnloadSink * pSink)
-{
- CONTRACTL
- {
- NOTHROW;
- MODE_ANY;
- if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_TRIGGERS);}
- }
- CONTRACTL_END;
-
- HRESULT hr=S_OK;
- EX_TRY
- {
- // IF you ever try to change this to something not using events, please address the fact that
- // AppDomain::StopEEAndUnwindThreads relies on that events are used.
-
- pSink->WaitUnloadCompletion();
- }
- EX_CATCH_HRESULT(hr);
-
- if (SUCCEEDED(hr))
- hr=pSink->GetUnloadResult();
-
- if (FAILED(hr))
- {
- ResetUnloadRequestThread(Id);
- }
- return hr;
-}
-
-#ifdef FEATURE_TESTHOOKS
-HRESULT AppDomain::UnloadWaitNoCatch(ADID Id, ADUnloadSink * pSink)
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_MODE_ANY;
-
- Holder<ADID, DoNothing<ADID>, AppDomain::ResetUnloadRequestThread> resetUnloadHolder(Id);
-
- // IF you ever try to change this to something not using events, please address the fact that
- // AppDomain::StopEEAndUnwindThreads relies on that events are used.
- pSink->WaitUnloadCompletion();
-
- HRESULT hr = pSink->GetUnloadResult();
-
- if (SUCCEEDED(hr))
- resetUnloadHolder.SuppressRelease();
-
- return hr;
-}
-#endif
-
-void AppDomain::Unload(BOOL fForceUnload)
-{
- CONTRACTL
- {
- THROWS;
- MODE_COOPERATIVE;
- GC_TRIGGERS;
- INJECT_FAULT(COMPlusThrowOM(););
- }
- CONTRACTL_END;
-
-#ifdef FEATURE_MULTICOREJIT
-
- // Avoid profiling file is partially written in ASP.net scenarios, call it earlier
- GetMulticoreJitManager().StopProfile(true);
-
-#endif
-
- Thread *pThread = GetThread();
-
-
- if (! fForceUnload && !g_pConfig->AppDomainUnload())
- return;
-
- EPolicyAction action;
- EClrOperation operation;
- if (!IsRudeUnload())
- {
- operation = OPR_AppDomainUnload;
- }
- else
- {
- operation = OPR_AppDomainRudeUnload;
- }
- action = GetEEPolicy()->GetDefaultAction(operation,NULL);
- GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
-
- switch (action)
- {
- case eUnloadAppDomain:
- break;
- case eRudeUnloadAppDomain:
- SetRudeUnload();
- break;
- case eExitProcess:
- case eFastExitProcess:
- case eRudeExitProcess:
- case eDisableRuntime:
- EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_ADUNLOAD);
- _ASSERTE (!"Should not get here");
- break;
- default:
- break;
- }
-
-#if (defined(_DEBUG) || defined(BREAK_ON_UNLOAD) || defined(AD_LOG_MEMORY) || defined(AD_SNAPSHOT))
- static int unloadCount = 0;
-#endif
-
-#ifdef AD_LOG_MEMORY
- {
- GCX_PREEMP();
- static int logMemory = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADLogMemory);
- typedef void (__cdecl *LogItFcn) ( int );
- static LogItFcn pLogIt = NULL;
-
- if (logMemory && ! pLogIt)
- {
- HMODULE hMod = CLRLoadLibrary(W("mpdh.dll"));
- if (hMod)
- {
- pLogIt = (LogItFcn)GetProcAddress(hMod, "logIt");
- if (pLogIt)
- {
- pLogIt(9999);
- pLogIt(9999);
- }
- }
- }
- }
-#endif // AD_LOG_MEMORY
-
- if (IsDefaultDomain() && !IsSingleAppDomain())
- COMPlusThrow(kCannotUnloadAppDomainException, IDS_EE_ADUNLOAD_DEFAULT);
-
- _ASSERTE(CanUnload());
-
- if (pThread == FinalizerThread::GetFinalizerThread() || GetUnloadRequestThread() == FinalizerThread::GetFinalizerThread())
- COMPlusThrow(kCannotUnloadAppDomainException, IDS_EE_ADUNLOAD_IN_FINALIZER);
-
- _ASSERTE(! SystemDomain::AppDomainBeingUnloaded());
-
- // should not be running in this AD because unload spawned thread in default domain
- if (!NingenEnabled())
- {
- _ASSERTE(!pThread->IsRunningIn(this, NULL));
- }
-
-
-#ifdef APPDOMAIN_STATE
- _ASSERTE_ALL_BUILDS("clr/src/VM/AppDomain.cpp", pThread->GetDomain()->IsDefaultDomain());
-#endif
-
- LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Unloading domain [%d] %#08x %ls\n", GetId().m_dwId, this, GetFriendlyName()));
-
- STRESS_LOG3 (LF_APPDOMAIN, LL_INFO100, "Unload domain [%d, %d] %p\n", GetId().m_dwId, GetIndex().m_dwIndex, this);
-
- UnloadHolder hold(this);
-
- SystemDomain::System()->SetUnloadRequestingThread(GetUnloadRequestThread());
- SystemDomain::System()->SetUnloadingThread(pThread);
-
-
-#ifdef _DEBUG
- static int dumpSB = -1;
-
- if (dumpSB == -1)
- dumpSB = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADDumpSB);
-
- if (dumpSB > 1)
- {
- LogSpewAlways("Starting unload %3.3d\n", unloadCount);
- DumpSyncBlockCache();
- }
-#endif // _DEBUG
-
- BOOL bForceGC=m_bForceGCOnUnload;
-
-#ifdef AD_LOG_MEMORY
- if (pLogIt)
- bForceGC=TRUE;
-#endif // AD_LOG_MEMORY
-
-#ifdef AD_SNAPSHOT
- static int takeSnapShot = -1;
-
- if (takeSnapShot == -1)
- takeSnapShot = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADTakeSnapShot);
-
- if (takeSnapShot)
- bForceGC=TRUE;
-#endif // AD_SNAPSHOT
-
-#ifdef _DEBUG
- if (dumpSB > 0)
- bForceGC=TRUE;
-#endif // _DEBUG
- static int cfgForceGC = -1;
-
- if (cfgForceGC == -1)
- cfgForceGC =!CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_ADULazyMemoryRelease);
-
- bForceGC=bForceGC||cfgForceGC;
- AppDomainRefHolder This(this);
- AddRef();
-
- // Do the actual unloading
- {
- // We do not want other threads to abort the current one.
- ThreadPreventAsyncHolder preventAsync;
- Exit(TRUE, !bForceGC);
- }
- if(bForceGC)
- {
- GCHeapUtilities::GetGCHeap()->GarbageCollect();
- FinalizerThread::FinalizerThreadWait();
- SetStage(STAGE_COLLECTED);
- Close(); //NOTHROW!
- }
-
-#ifdef AD_LOG_MEMORY
- if (pLogIt)
- {
- GCX_PREEMP();
- pLogIt(unloadCount);
- }
-#endif // AD_LOG_MEMORY
-
-#ifdef AD_SNAPSHOT
- if (takeSnapShot)
- {
- char buffer[1024];
- sprintf_s(buffer, _countof(buffer), "vadump -p %d -o > vadump.%d", GetCurrentProcessId(), unloadCount);
- system(buffer);
- sprintf_s(buffer, _countof(buffer), "umdh -p:%d -d -i:1 -f:umdh.%d", GetCurrentProcessId(), unloadCount);
- system(buffer);
- int takeDHSnapShot = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADTakeDHSnapShot);
- if (takeDHSnapShot)
- {
- sprintf_s(buffer, _countof(buffer), "dh -p %d -s -g -h -b -f dh.%d", GetCurrentProcessId(), unloadCount);
- system(buffer);
- }
- }
-#endif // AD_SNAPSHOT
-
-#ifdef _DEBUG
- if (dumpSB > 0)
- {
- // do extra finalizer wait to remove any leftover sb entries
- FinalizerThread::FinalizerThreadWait();
- GCHeapUtilities::GetGCHeap()->GarbageCollect();
- FinalizerThread::FinalizerThreadWait();
- LogSpewAlways("Done unload %3.3d\n", unloadCount);
- DumpSyncBlockCache();
- ShutdownLogging();
- WCHAR buffer[128];
- swprintf_s(buffer, NumItems(buffer), W("DumpSB.%d"), unloadCount);
- _ASSERTE(WszMoveFileEx(W("COMPLUS.LOG"), buffer, MOVEFILE_REPLACE_EXISTING));
- // this will open a new file
- InitLogging();
- }
-#endif // _DEBUG
-}
-
void AppDomain::ExceptionUnwind(Frame *pFrame)
{
CONTRACTL
@@ -8681,24 +7710,7 @@ void AppDomain::ExceptionUnwind(Frame *pFrame)
Thread *pThread = GetThread();
_ASSERTE(pThread);
- if (! pThread->ShouldChangeAbortToUnload(pFrame))
- {
- LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind: not first transition or abort\n"));
- return;
- }
-
- LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind: changing to unload\n"));
-
- GCX_COOP();
- OBJECTREF throwable = NULL;
- EEResourceException e(kAppDomainUnloadedException, W("Remoting_AppDomainUnloaded_ThreadUnwound"));
- throwable = e.GetThrowable();
-
- // reset the exception to an AppDomainUnloadedException
- if (throwable != NULL)
- {
- GetThread()->SafeSetThrowables(throwable);
- }
+ LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind: not first transition or abort\n"));
}
BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread)
@@ -8720,78 +7732,6 @@ BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnlo
if (pCurThread->CatchAtSafePoint())
pCurThread->PulseGCMode();
- {
- // We know which thread is not in the domain now. We just need to
- // work on those threads. We do not need to suspend the runtime.
- ThreadStoreLockHolder tsl;
-
- while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
- {
- if (pThread == pCurThread)
- {
- continue;
- }
-
- if (pThread == FinalizerThread::GetFinalizerThread())
- {
- continue;
- }
-
- if (pThread->GetUnloadBoundaryFrame() == NULL)
- {
- continue;
- }
-
- // A thread may have UnloadBoundaryFrame set if
- // 1. Being unloaded by AD unload helper thread
- // 2. Escalation from OOM or SO triggers AD unload
- // Here we only need to work on threads that are in the domain. If we work on other threads,
- // those threads may be stucked in a finally, and we will not be able to escalate for them,
- // therefore AD unload is blocked.
- if (pThread->IsBeingAbortedForADUnload() ||
- pThread == SystemDomain::System()->GetUnloadRequestingThread())
- {
- nThreadsNeedMoreWork++;
- }
-
- if (!(IsRudeUnload() ||
- (pThread != SystemDomain::System()->GetUnloadRequestingThread() || OnlyOneThreadLeft())))
- {
- continue;
- }
-
- if ((pThread == SystemDomain::System()->GetUnloadRequestingThread()) && *pFMarkUnloadRequestThread)
- {
- // Mark thread for abortion only once; later on interrupt only
- *pFMarkUnloadRequestThread = FALSE;
- pThread->SetAbortRequest(m_fRudeUnload? EEPolicy::TA_Rude : EEPolicy::TA_V1Compatible);
- }
- else
- {
- if (pThread->m_State & Thread::TS_Interruptible)
- {
- pThread->UserInterrupt(Thread::TI_Abort);
- }
- }
-
- if (pThread->PreemptiveGCDisabledOther())
- {
- #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
- Thread::SuspendThreadResult str = pThread->SuspendThread();
- if (str == Thread::STR_Success)
- {
- if (pThread->PreemptiveGCDisabledOther() &&
- (!pThread->IsAbortInitiated() || pThread->IsRudeAbort()))
- {
- pThread->HandleJITCaseForAbort();
- }
- pThread->ResumeThread();
- }
- #endif
- }
- }
- } // ThreadStoreLockHolder
-
m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork;
return !nThreadsNeedMoreWork;
}
@@ -8830,10 +7770,6 @@ BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnlo
Frame *pFrame = pThread->GetFirstTransitionInto(this, &count);
if (! pFrame) {
_ASSERTE(count == 0);
- if (pThread->IsBeingAbortedForADUnload())
- {
- pThread->ResetBeginAbortedForADUnload();
- }
continue;
}
@@ -8841,7 +7777,6 @@ BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnlo
{
totalADCount += count;
nThreadsNeedMoreWork++;
- pThread->SetUnloadBoundaryFrame(pFrame);
}
else
{
@@ -8849,8 +7784,7 @@ BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnlo
}
// 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 &&
- (pThread != SystemDomain::System()->GetUnloadRequestingThread() || OnlyOneThreadLeft()))
+ 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);
@@ -8869,13 +7803,7 @@ BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnlo
// 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() &&
- // If the domain is rudely unloaded, we will unwind the requesting thread out
- // Rude unload is going to succeed, or escalated to disable runtime or higher.
- (IsRudeUnload() ||
- (pThread != SystemDomain::System()->GetUnloadRequestingThread() || OnlyOneThreadLeft())
- )
- )
+ if (pThread != FinalizerThread::GetFinalizerThread())
{
STRESS_LOG2(LF_APPDOMAIN, LL_INFO100, "AppDomain::UnwindThreads stopping %x with %d transitions\n", pThread->GetThreadId(), count);
@@ -8883,12 +7811,7 @@ BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnlo
#if _DEBUG_ADUNLOAD
printf("AppDomain::UnwindThreads %x stopping %x with first frame %8.8p\n", GetThread()->GetThreadId(), pThread->GetThreadId(), pFrame);
#endif
- if (pThread == SystemDomain::System()->GetUnloadRequestingThread())
- {
- // Mark thread for abortion only once; later on interrupt only
- *pFMarkUnloadRequestThread = FALSE;
- }
- pThread->SetAbortRequest(m_fRudeUnload? EEPolicy::TA_Rude : EEPolicy::TA_V1Compatible);
+ pThread->SetAbortRequest(EEPolicy::TA_V1Compatible);
}
TESTHOOKCALL(UnwindingThreads(GetId().m_dwId)) ;
}
@@ -8903,18 +7826,6 @@ BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnlo
// exit the domain gracefully.
// m_dwThreadEnterCount = totalADCount;
- if (reKind != kLastException)
- {
- pThread = NULL;
- while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
- {
- if (pThread->IsBeingAbortedForADUnload())
- {
- pThread->ResetBeginAbortedForADUnload();
- }
- }
- }
-
// CommonTripThread will handle the abort for any threads that we've marked
ThreadSuspend::RestartEE(FALSE, TRUE);
if (reKind != kLastException)
@@ -8946,25 +7857,17 @@ void AppDomain::UnwindThreads()
m_dwThreadsStillInAppDomain=(ULONG)-1;
ULONGLONG startTime = CLRGetTickCount64();
- if (GetEEPolicy()->GetDefaultAction(OPR_AppDomainUnload, NULL) == eRudeUnloadAppDomain &&
- !IsRudeUnload())
- {
- GetEEPolicy()->NotifyHostOnDefaultAction(OPR_AppDomainUnload, eRudeUnloadAppDomain);
- SetRudeUnload();
- }
-
// Force threads to go through slow path during AD unload.
TSSuspendHolder shTrap;
- BOOL fCurrentUnloadMode = IsRudeUnload();
BOOL fMarkUnloadRequestThread = TRUE;
// now wait for all the threads running in our AD to get out
do
{
- DWORD timeout = GetEEPolicy()->GetTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload);
- EPolicyAction action = GetEEPolicy()->GetActionOnTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload, NULL);
- if (timeout != INFINITE && action > eUnloadAppDomain) {
+ 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;
@@ -8973,16 +7876,11 @@ void AppDomain::UnwindThreads()
// Escalate
switch (action)
{
- case eRudeUnloadAppDomain:
- GetEEPolicy()->NotifyHostOnTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload, action);
- SetRudeUnload();
- STRESS_LOG1(LF_APPDOMAIN, LL_INFO100,"Escalating to RADU, adid=%d",GetId().m_dwId);
- break;
case eExitProcess:
case eFastExitProcess:
case eRudeExitProcess:
case eDisableRuntime:
- GetEEPolicy()->NotifyHostOnTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload, action);
+ GetEEPolicy()->NotifyHostOnTimeout(OPR_AppDomainUnload, action);
EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_TIMEOUT);
_ASSERTE (!"Should not reach here");
break;
@@ -8995,14 +7893,6 @@ void AppDomain::UnwindThreads()
if (LoggingOn(LF_APPDOMAIN, LL_INFO100))
DumpADThreadTrack();
#endif // _DEBUG
- BOOL fNextUnloadMode = IsRudeUnload();
- if (fCurrentUnloadMode != fNextUnloadMode)
- {
- // We have changed from normal unload to rude unload. We need to mark the thread
- // with RudeAbort, but we can only do this safely if the runtime is suspended.
- fCurrentUnloadMode = fNextUnloadMode;
- retryCount = -1;
- }
if (StopEEAndUnwindThreads(retryCount, &fMarkUnloadRequestThread))
break;
if (timeout != INFINITE)
@@ -9034,24 +7924,6 @@ void AppDomain::UnwindThreads()
while (TRUE) ;
}
-void AppDomain::ClearGCHandles()
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- NOTHROW;
- }
- CONTRACTL_END;
-
- SetStage(STAGE_HANDLETABLE_NOACCESS);
-
- GCHeapUtilities::GetGCHeap()->WaitUntilConcurrentGCComplete();
-
- // Remove our handle store as a source of GC roots
- m_handleStore->Uproot();
-}
-
void AppDomain::ClearGCRoots()
{
CONTRACTL
@@ -10060,151 +8932,6 @@ void AppDomain::InitializeDefaultDomainManager()
GCPROTECT_END();
}
-CLREvent * AppDomain::g_pUnloadStartEvent;
-
-void AppDomain::CreateADUnloadWorker()
-{
- STANDARD_VM_CONTRACT;
-
- // Do not create adUnload thread if there is only default domain
- if(IsSingleAppDomain())
- return;
-
-Retry:
- BOOL fCreator = FALSE;
- if (FastInterlockCompareExchange((LONG *)&g_fADUnloadWorkerOK,-2,-1)==-1) //we're first
- {
-#ifdef _TARGET_X86_ // use the smallest possible stack on X86
- DWORD stackSize = 128 * 1024;
-#else
- DWORD stackSize = 512 * 1024; // leave X64 unchanged since we have plenty of VM
-#endif
- Thread *pThread = SetupUnstartedThread();
- if (pThread->CreateNewThread(stackSize, ADUnloadThreadStart, pThread))
- {
- fCreator = TRUE;
- DWORD dwRet;
- dwRet = pThread->StartThread();
-
- // When running under a user mode native debugger there is a race
- // between the moment we've created the thread (in CreateNewThread) and
- // the moment we resume it (in StartThread); the debugger may receive
- // the "ct" (create thread) notification, and it will attempt to
- // suspend/resume all threads in the process. Now imagine the debugger
- // resumes this thread first, and only later does it try to resume the
- // newly created thread (the ADU worker thread). In these conditions our
- // call to ResumeThread may come before the debugger's call to ResumeThread
- // actually causing dwRet to equal 2.
- // We cannot use IsDebuggerPresent() in the condition below because the
- // debugger may have been detached between the time it got the notification
- // and the moment we execute the test below.
- _ASSERTE(dwRet == 1 || dwRet == 2);
- }
- else
- {
- pThread->DecExternalCount(FALSE);
- FastInterlockExchange((LONG *)&g_fADUnloadWorkerOK, -1);
- ThrowOutOfMemory();
- }
- }
-
- YIELD_WHILE (g_fADUnloadWorkerOK == -2);
-
- if (g_fADUnloadWorkerOK == -1) {
- if (fCreator)
- {
- ThrowOutOfMemory();
- }
- else
- {
- goto Retry;
- }
- }
-}
-
-/*static*/ void AppDomain::ADUnloadWorkerHelper(AppDomain *pDomain)
-{
- STATIC_CONTRACT_NOTHROW;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
- ADUnloadSink* pADUnloadSink=pDomain->GetADUnloadSinkForUnload();
- HRESULT hr=S_OK;
-
- EX_TRY
- {
- pDomain->Unload(FALSE);
- }
- EX_CATCH_HRESULT(hr);
-
- if(pADUnloadSink)
- {
- SystemDomain::LockHolder lh;
- pADUnloadSink->ReportUnloadResult(hr,NULL);
- pADUnloadSink->Release();
- }
-}
-
-void AppDomain::DoADUnloadWork()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM(););
- }
- CONTRACTL_END;
-
- DWORD i = 1;
- while (TRUE) {
-
- AppDomain *pDomainToUnload = NULL;
-
- {
- // Take the lock so that no domain can be added or removed from the system domain
- SystemDomain::LockHolder lh;
-
- DWORD numDomain = SystemDomain::GetCurrentAppDomainMaxIndex();
- for (; i <= numDomain; i ++) {
- AppDomain * pDomain = SystemDomain::TestGetAppDomainAtIndex(ADIndex(i));
- //
- // @todo: We used to also select a domain if pDomain->IsUnload() returned true. But that causes
- // problems when we've failed to completely unload the AD in the past. If we've reached the CLEARED
- // stage, for instance, then there will be no default context and AppDomain::Exit() will simply crash.
- //
- if (pDomain && pDomain->IsUnloadRequested())
- {
- pDomainToUnload = pDomain;
- i ++;
- break;
- }
- }
- }
-
- if (!pDomainToUnload) {
- break;
- }
-
- // We are the only thread that can unload domains so no one else can delete the appdomain
- ADUnloadWorkerHelper(pDomainToUnload);
- }
-}
-
-static void DoADUnloadWorkHelper()
-{
- STATIC_CONTRACT_NOTHROW;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
-
- EX_TRY {
- AppDomain::DoADUnloadWork();
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(SwallowAllExceptions);
-}
-
ULONGLONG g_ObjFinalizeStartTime = 0;
Volatile<BOOL> g_FinalizerIsRunning = FALSE;
Volatile<ULONG> g_FinalizerLoopCount = 0;
@@ -10255,11 +8982,6 @@ void FinalizerThreadAbortOnTimeout()
EEPolicy::TA_Safe,
INFINITE,
Thread::UAC_FinalizerTimeout);
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
- }
}
break;
case eRudeUnloadAppDomain:
@@ -10269,11 +8991,6 @@ void FinalizerThreadAbortOnTimeout()
EEPolicy::TA_Rude,
INFINITE,
Thread::UAC_FinalizerTimeout);
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
- }
}
break;
case eExitProcess:
@@ -10298,321 +9015,12 @@ enum WorkType
{
WT_UnloadDomain = 0x1,
WT_ThreadAbort = 0x2,
- WT_FinalizerThread = 0x4,
- WT_ClearCollectedDomains=0x8
+ WT_FinalizerThread = 0x4
};
static Volatile<DWORD> s_WorkType = 0;
-
-DWORD WINAPI AppDomain::ADUnloadThreadStart(void *args)
-{
- CONTRACTL
- {
- NOTHROW;
- DISABLED(GC_TRIGGERS);
-
- // This function will always be at the very bottom of the stack. The only
- // user code it calls is the AppDomainUnload notifications which we will
- // not be hardenning for Whidbey.
- //
- ENTRY_POINT;
- }
- CONTRACTL_END;
-
- BEGIN_ENTRYPOINT_NOTHROW;
-
- ClrFlsSetThreadType (ThreadType_ADUnloadHelper);
-
- Thread *pThread = (Thread*)args;
- bool fOK = (pThread->HasStarted() != 0);
-
- {
- GCX_MAYBE_PREEMP(fOK);
-
- _ASSERTE (g_fADUnloadWorkerOK == -2);
-
- FastInterlockExchange((LONG *)&g_fADUnloadWorkerOK,fOK?1:-1);
-
- if (!fOK)
- {
- DestroyThread(pThread);
- goto Exit;
- }
-
- pThread->SetBackground(TRUE);
-
- pThread->SetThreadStateNC(Thread::TSNC_ADUnloadHelper);
-
- while (TRUE) {
- DWORD TAtimeout = INFINITE;
- ULONGLONG endTime = Thread::GetNextSelfAbortEndTime();
- ULONGLONG curTime = CLRGetTickCount64();
- if (endTime <= curTime) {
- TAtimeout = 5;
- }
- else
- {
- ULONGLONG diff = endTime - curTime;
- if (diff < MAXULONG)
- {
- TAtimeout = (DWORD)diff;
- }
- }
- ULONGLONG finalizeStartTime = GetObjFinalizeStartTime();
- DWORD finalizeTimeout = INFINITE;
- DWORD finalizeTimeoutSetting = GetEEPolicy()->GetTimeout(OPR_FinalizerRun);
- if (finalizeTimeoutSetting != INFINITE && g_FinalizerIsRunning)
- {
- if (finalizeStartTime == 0)
- {
- finalizeTimeout = finalizeTimeoutSetting;
- }
- else
- {
- endTime = finalizeStartTime + finalizeTimeoutSetting;
- if (endTime <= curTime) {
- finalizeTimeout = 0;
- }
- else
- {
- ULONGLONG diff = endTime - curTime;
- if (diff < MAXULONG)
- {
- finalizeTimeout = (DWORD)diff;
- }
- }
- }
- }
-
- if (AppDomain::HasWorkForFinalizerThread())
- {
- if (finalizeTimeout > finalizeTimeoutSetting)
- {
- finalizeTimeout = finalizeTimeoutSetting;
- }
- }
-
- DWORD timeout = INFINITE;
- if (finalizeTimeout <= TAtimeout)
- {
- timeout = finalizeTimeout;
- }
- else
- {
- timeout = TAtimeout;
- }
-
- if (timeout != 0)
- {
- LOG((LF_APPDOMAIN, LL_INFO10, "Waiting to start unload\n"));
- g_pUnloadStartEvent->Wait(timeout,FALSE);
- }
-
- if (finalizeTimeout != INFINITE || (s_WorkType & WT_FinalizerThread) != 0)
- {
- STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "ADUnloadThreadStart work for Finalizer thread\n");
- FastInterlockAnd(&s_WorkType, ~WT_FinalizerThread);
- // only watch finalizer thread is finalizer method or unloadevent is being processed
- if (GetObjFinalizeStartTime() == finalizeStartTime && finalizeStartTime != 0 && g_FinalizerIsRunning)
- {
- if (CLRGetTickCount64() >= finalizeStartTime+finalizeTimeoutSetting)
- {
- GCX_COOP();
- FinalizerThreadAbortOnTimeout();
- }
- }
- if (s_fProcessUnloadDomainEvent && g_FinalizerIsRunning)
- {
- GCX_COOP();
- FinalizerThreadAbortOnTimeout();
- }
- }
-
- if (TAtimeout != INFINITE || (s_WorkType & WT_ThreadAbort) != 0)
- {
- STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "ADUnloadThreadStart work for thread abort\n");
- FastInterlockAnd(&s_WorkType, ~WT_ThreadAbort);
- GCX_COOP();
- Thread::ThreadAbortWatchDog();
- }
-
- if ((s_WorkType & WT_UnloadDomain) != 0 && !AppDomain::HasWorkForFinalizerThread())
- {
- STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "ADUnloadThreadStart work for AD unload\n");
- FastInterlockAnd(&s_WorkType, ~WT_UnloadDomain);
- GCX_COOP();
- DoADUnloadWorkHelper();
- }
-
- if ((s_WorkType & WT_ClearCollectedDomains) != 0)
- {
- STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "ADUnloadThreadStart work for AD cleanup\n");
- FastInterlockAnd(&s_WorkType, ~WT_ClearCollectedDomains);
- GCX_COOP();
- SystemDomain::System()->ClearCollectedDomains();
- }
-
- }
-Exit:;
- }
-
- END_ENTRYPOINT_NOTHROW;
-
- return 0;
-}
-
-void AppDomain::EnableADUnloadWorker()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT; // Called during a SO
- }
- CONTRACTL_END;
-
- EEPolicy::AppDomainUnloadTypes type = EEPolicy::ADU_Safe;
-
-#ifdef _DEBUG
- DWORD hostTestADUnload = g_pConfig->GetHostTestADUnload();
- if (hostTestADUnload == 2) {
- type = EEPolicy::ADU_Rude;
- }
-#endif // _DEBUG
-
- EnableADUnloadWorker(type);
-}
-
-void AppDomain::EnableADUnloadWorker(EEPolicy::AppDomainUnloadTypes type, BOOL fHasStack)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT; // Called during a SO
- }
- CONTRACTL_END;
-
- FastInterlockOr (&s_WorkType, WT_UnloadDomain);
-
- LONG stage = m_Stage;
- static_assert_no_msg(sizeof(m_Stage) == sizeof(int));
-
- _ASSERTE(!IsDefaultDomain());
-
- // Mark unload requested.
- if (type == EEPolicy::ADU_Rude) {
- SetRudeUnload();
- }
- while (stage < STAGE_UNLOAD_REQUESTED) {
- stage = FastInterlockCompareExchange((LONG*)&m_Stage,STAGE_UNLOAD_REQUESTED,stage);
- }
-
- if (!fHasStack)
- {
- // Can not call Set due to limited stack.
- return;
- }
- LOG((LF_APPDOMAIN, LL_INFO10, "Enabling unload worker\n"));
- g_pUnloadStartEvent->Set();
-}
-
-void AppDomain::EnableADUnloadWorkerForThreadAbort()
-{
- LIMITED_METHOD_CONTRACT;
- STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "Enabling unload worker for thread abort\n");
- LOG((LF_APPDOMAIN, LL_INFO10, "Enabling unload worker for thread abort\n"));
- FastInterlockOr (&s_WorkType, WT_ThreadAbort);
- g_pUnloadStartEvent->Set();
-}
-
-
-void AppDomain::EnableADUnloadWorkerForFinalizer()
-{
- LIMITED_METHOD_CONTRACT;
- if (GetEEPolicy()->GetTimeout(OPR_FinalizerRun) != INFINITE)
- {
- LOG((LF_APPDOMAIN, LL_INFO10, "Enabling unload worker for Finalizer Thread\n"));
- FastInterlockOr (&s_WorkType, WT_FinalizerThread);
- g_pUnloadStartEvent->Set();
- }
-}
-
-void AppDomain::EnableADUnloadWorkerForCollectedADCleanup()
-{
- LIMITED_METHOD_CONTRACT;
- LOG((LF_APPDOMAIN, LL_INFO10, "Enabling unload worker for collected domains\n"));
- FastInterlockOr (&s_WorkType, WT_ClearCollectedDomains);
- g_pUnloadStartEvent->Set();
-}
-
-
-void SystemDomain::ClearCollectedDomains()
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- NOTHROW;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- AppDomain* pDomainsToClear=NULL;
- {
- CrstHolder lh(&m_DelayedUnloadCrst);
- for (AppDomain** ppDomain=&m_pDelayedUnloadList;(*ppDomain)!=NULL; )
- {
- if ((*ppDomain)->m_Stage==AppDomain::STAGE_COLLECTED)
- {
- AppDomain* pAppDomain=*ppDomain;
- *ppDomain=(*ppDomain)->m_pNextInDelayedUnloadList;
- pAppDomain->m_pNextInDelayedUnloadList=pDomainsToClear;
- pDomainsToClear=pAppDomain;
- }
- else
- ppDomain=&((*ppDomain)->m_pNextInDelayedUnloadList);
- }
- }
-
- for (AppDomain* pDomain=pDomainsToClear;pDomain!=NULL;)
- {
- AppDomain* pNext=pDomain->m_pNextInDelayedUnloadList;
- pDomain->Close(); //NOTHROW!
- pDomain->Release();
- pDomain=pNext;
- }
-}
-
-void SystemDomain::ProcessClearingDomains()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- CrstHolder lh(&m_DelayedUnloadCrst);
-
- for (AppDomain** ppDomain=&m_pDelayedUnloadList;(*ppDomain)!=NULL; )
- {
- if ((*ppDomain)->m_Stage==AppDomain::STAGE_HANDLETABLE_NOACCESS)
- {
- AppDomain* pAppDomain=*ppDomain;
- pAppDomain->SetStage(AppDomain::STAGE_CLEARED);
- }
- ppDomain=&((*ppDomain)->m_pNextInDelayedUnloadList);
- }
-
- if (!m_UnloadIsAsync)
- {
- // For synchronous mode, we are now done with the list.
- m_pDelayedUnloadList = NULL;
- }
-}
-
-void SystemDomain::ProcessDelayedUnloadDomains()
+void SystemDomain::ProcessDelayedUnloadLoaderAllocators()
{
CONTRACTL
{
@@ -10626,25 +9034,11 @@ void SystemDomain::ProcessDelayedUnloadDomains()
if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress())
iGCRefPoint--;
- BOOL bAppDomainToCleanup = FALSE;
LoaderAllocator * pAllocatorsToDelete = NULL;
{
CrstHolder lh(&m_DelayedUnloadCrst);
- for (AppDomain* pDomain=m_pDelayedUnloadList; pDomain!=NULL; pDomain=pDomain->m_pNextInDelayedUnloadList)
- {
- if (pDomain->m_Stage==AppDomain::STAGE_CLEARED)
- {
- // Compare with 0 to handle overflows gracefully
- if (0 < iGCRefPoint - pDomain->GetGCRefPoint())
- {
- bAppDomainToCleanup=TRUE;
- pDomain->SetStage(AppDomain::STAGE_COLLECTED);
- }
- }
- }
-
LoaderAllocator ** ppAllocator=&m_pDelayedUnloadListOfLoaderAllocators;
while (*ppAllocator!= NULL)
{
@@ -10663,9 +9057,6 @@ void SystemDomain::ProcessDelayedUnloadDomains()
}
}
- if (bAppDomainToCleanup)
- AppDomain::EnableADUnloadWorkerForCollectedADCleanup();
-
// Delete collected loader allocators on the finalizer thread. We cannot offload it to appdomain unload thread because of
// there is not guaranteed to be one, and it is not that expensive operation anyway.
while (pAllocatorsToDelete != NULL)
@@ -10678,159 +9069,6 @@ void SystemDomain::ProcessDelayedUnloadDomains()
#endif // CROSSGEN_COMPILE
-AppDomainFromIDHolder::AppDomainFromIDHolder(ADID adId, BOOL bUnsafePoint, SyncType synctype)
-{
- WRAPPER_NO_CONTRACT;
- ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
-#ifdef _DEBUG
- m_bAcquired=false;
- m_bChecked=false;
- m_type=synctype;
-
-#endif
- Assign(adId, bUnsafePoint);
-}
-
-AppDomainFromIDHolder::AppDomainFromIDHolder(SyncType synctype)
-{
- LIMITED_METHOD_CONTRACT;
- ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
- m_pDomain=NULL;
-#ifdef _DEBUG
- m_bAcquired=false;
- m_bChecked=false;
- m_type=synctype;
-#endif
-}
-
-#ifndef CROSSGEN_COMPILE
-void ADUnloadSink::ReportUnloadResult (HRESULT hr, OBJECTREF* pException)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- PRECONDITION(CheckPointer(this));
- PRECONDITION(m_UnloadCompleteEvent.IsValid());
- }
- CONTRACTL_END;
-
- //pException is unused;
- m_UnloadResult=hr;
- m_UnloadCompleteEvent.Set();
-};
-
-void ADUnloadSink::WaitUnloadCompletion()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- PRECONDITION(CheckPointer(this));
- PRECONDITION(m_UnloadCompleteEvent.IsValid());
- }
- CONTRACTL_END;
-
- CONTRACT_VIOLATION(FaultViolation);
- m_UnloadCompleteEvent.WaitEx(INFINITE, (WaitMode)(WaitMode_Alertable | WaitMode_ADUnload));
-};
-
-ADUnloadSink* AppDomain::PrepareForWaitUnloadCompletion()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- PRECONDITION(SystemDomain::IsUnderDomainLock());
- FORBID_FAULT;
- }
- CONTRACTL_END;
-
- ADUnloadSink* pADSink=GetADUnloadSink();
- PREFIX_ASSUME(pADSink!=NULL);
- if (m_Stage < AppDomain::STAGE_UNLOAD_REQUESTED) //we're first
- {
- pADSink->Reset();
- SetUnloadRequestThread(GetThread());
- }
- return pADSink;
-};
-
-ADUnloadSink::ADUnloadSink()
-{
- CONTRACTL
- {
- CONSTRUCTOR_CHECK;
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM(););
- }
- CONTRACTL_END;
-
- m_cRef=1;
- m_UnloadCompleteEvent.CreateManualEvent(FALSE);
- m_UnloadResult=S_OK;
-};
-
-ADUnloadSink::~ADUnloadSink()
-{
- CONTRACTL
- {
- DESTRUCTOR_CHECK;
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
- m_UnloadCompleteEvent.CloseEvent();
-
-};
-
-
-ULONG ADUnloadSink::AddRef()
-{
- LIMITED_METHOD_CONTRACT;
- return InterlockedIncrement(&m_cRef);
-};
-
-ULONG ADUnloadSink::Release()
-{
- LIMITED_METHOD_CONTRACT;
- ULONG ulRef = InterlockedDecrement(&m_cRef);
- if (ulRef == 0)
- {
- delete this;
- }
- return ulRef;
-};
-
-void ADUnloadSink::Reset()
-{
- LIMITED_METHOD_CONTRACT;
- m_UnloadResult=S_OK;
- m_UnloadCompleteEvent.Reset();
-}
-
-ADUnloadSink* AppDomain::GetADUnloadSink()
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(SystemDomain::IsUnderDomainLock());
- if(m_ADUnloadSink)
- m_ADUnloadSink->AddRef();
- return m_ADUnloadSink;
-};
-
-ADUnloadSink* AppDomain::GetADUnloadSinkForUnload()
-{
- // unload thread only. Doesn't need to have AD lock
- LIMITED_METHOD_CONTRACT;
- if(m_ADUnloadSink)
- m_ADUnloadSink->AddRef();
- return m_ADUnloadSink;
-}
-#endif // CROSSGEN_COMPILE
-
void AppDomain::EnumStaticGCRefs(promote_func* fn, ScanContext* sc)
{
CONTRACT_VOID
diff --git a/src/vm/appdomain.hpp b/src/vm/appdomain.hpp
index eb28f3ae11..5ffc1b2045 100644
--- a/src/vm/appdomain.hpp
+++ b/src/vm/appdomain.hpp
@@ -1230,8 +1230,6 @@ public:
STRINGREF *IsStringInterned(STRINGREF *pString);
STRINGREF *GetOrInternString(STRINGREF *pString);
- virtual BOOL CanUnload() { LIMITED_METHOD_CONTRACT; return FALSE; } // can never unload BaseDomain
-
// Returns an array of OBJECTREF* that can be used to store domain specific data.
// Statics and reflection info (Types, MemberInfo,..) are stored this way
// If ppLazyAllocate != 0, allocation will only take place if *ppLazyAllocate != 0 (and the allocation
@@ -1587,35 +1585,6 @@ enum
ATTACH_ALL = 0x7
};
-class ADUnloadSink
-{
-
-protected:
- ~ADUnloadSink();
- CLREvent m_UnloadCompleteEvent;
- HRESULT m_UnloadResult;
- Volatile<LONG> m_cRef;
-public:
- ADUnloadSink();
- void ReportUnloadResult (HRESULT hr, OBJECTREF* pException);
- void WaitUnloadCompletion();
- HRESULT GetUnloadResult() {LIMITED_METHOD_CONTRACT; return m_UnloadResult;};
- void Reset();
- ULONG AddRef();
- ULONG Release();
-};
-
-
-FORCEINLINE void ADUnloadSink__Release(ADUnloadSink* pADSink)
-{
- WRAPPER_NO_CONTRACT;
-
- if (pADSink)
- pADSink->Release();
-}
-
-typedef Wrapper <ADUnloadSink*,DoNothing,ADUnloadSink__Release,NULL> ADUnloadSinkHolder;
-
// This filters the output of IterateAssemblies. This ought to be declared more locally
// but it would result in really verbose callsites.
//
@@ -1957,7 +1926,6 @@ template <class AppDomainType> class AppDomainCreationHolder;
//
class AppDomain : public BaseDomain
{
- friend class ADUnloadSink;
friend class SystemDomain;
friend class AssemblySink;
friend class AppDomainNative;
@@ -1968,7 +1936,6 @@ class AppDomain : public BaseDomain
friend class RCWCache;
friend class ClrDataAccess;
friend class CheckAsmOffsets;
- friend class AppDomainFromIDHolder;
VPTR_VTABLE_CLASS(AppDomain, BaseDomain)
@@ -1977,7 +1944,6 @@ public:
AppDomain();
virtual ~AppDomain();
#endif
- static void DoADUnloadWork();
DomainAssembly* FindDomainAssembly(Assembly*);
void EnterContext(Thread* pThread, Context* pCtx,ContextTransitionFrame *pFrame);
@@ -1992,10 +1958,6 @@ public:
// Initializes an AppDomain. (this functions is not called from the SystemDomain)
void Init();
- // creates only unamaged part
- static void CreateUnmanagedObject(AppDomainCreationHolder<AppDomain>& result);
-
-
#if defined(FEATURE_COMINTEROP)
HRESULT SetWinrtApplicationContext(SString &appLocalWinMD);
#endif // FEATURE_COMINTEROP
@@ -2591,8 +2553,6 @@ public:
void SetupSharedStatics();
- ADUnloadSink* PrepareForWaitUnloadCompletion();
-
//****************************************************************************************
//
// Create a quick lookup for classes loaded into this domain based on their GUID.
@@ -2844,20 +2804,6 @@ public:
return dac_cast<PTR_CompilationDomain>(this);
}
- void SetCanUnload()
- {
- LIMITED_METHOD_CONTRACT;
-
- m_dwFlags |= APP_DOMAIN_CAN_BE_UNLOADED;
- }
-
- BOOL CanUnload()
- {
- LIMITED_METHOD_CONTRACT;
- STATIC_CONTRACT_SO_TOLERANT;
- return m_dwFlags & APP_DOMAIN_CAN_BE_UNLOADED;
- }
-
void SetRemotingConfigured()
{
LIMITED_METHOD_CONTRACT;
@@ -2886,14 +2832,6 @@ public:
return m_dwFlags & ORPHANED_LOCKS;
}
- // This function is used to relax asserts in the lock accounting.
- // It returns true if we are fine with hosed lock accounting in this domain.
- BOOL OkToIgnoreOrphanedLocks()
- {
- WRAPPER_NO_CONTRACT;
- return HasOrphanedLocks() && m_Stage >= STAGE_UNLOAD_REQUESTED;
- }
-
static void ExceptionUnwind(Frame *pFrame);
#ifdef _DEBUG
@@ -2974,7 +2912,7 @@ public:
BOOL CanLoadCode()
{
LIMITED_METHOD_CONTRACT;
- return m_Stage >= STAGE_READYFORMANAGEDCODE && m_Stage < STAGE_CLOSED;
+ return m_Stage >= STAGE_READYFORMANAGEDCODE;
}
void SetAnonymouslyHostedDynamicMethodsAssembly(DomainAssembly * pDomainAssembly)
@@ -2991,11 +2929,6 @@ public:
return m_anonymouslyHostedDynamicMethodsAssembly;
}
- BOOL HasUnloadStarted()
- {
- LIMITED_METHOD_CONTRACT;
- return m_Stage>=STAGE_EXITED;
- }
static void RefTakerAcquire(AppDomain* pDomain)
{
WRAPPER_NO_CONTRACT;
@@ -3052,7 +2985,7 @@ public:
{
LIMITED_METHOD_DAC_CONTRACT;
- return m_Stage >= STAGE_ACTIVE && m_Stage < STAGE_CLOSED;
+ return m_Stage >= STAGE_ACTIVE;
}
// Range for normal execution of code in the appdomain, currently used for
// appdomain resource monitoring since we don't care to update resource usage
@@ -3073,7 +3006,7 @@ public:
// There is no risk of races under DAC, so we will pretend to be unconditionally valid.
return TRUE;
#else
- return m_Stage > STAGE_CREATING && m_Stage < STAGE_CLOSED;
+ return m_Stage > STAGE_CREATING;
#endif
}
@@ -3103,14 +3036,6 @@ public:
#endif
BOOL IsRunningIn(Thread* pThread);
- BOOL IsUnloading()
- {
- LIMITED_METHOD_CONTRACT;
- SUPPORTS_DAC;
-
- return m_Stage > STAGE_UNLOAD_REQUESTED;
- }
-
BOOL NotReadyForManagedCode()
{
LIMITED_METHOD_CONTRACT;
@@ -3118,67 +3043,6 @@ public:
return m_Stage < STAGE_READYFORMANAGEDCODE;
}
- void SetFinalized()
- {
- LIMITED_METHOD_CONTRACT;
- SetStage(STAGE_FINALIZED);
- }
-
- BOOL IsFinalizing()
- {
- LIMITED_METHOD_CONTRACT;
-
- return m_Stage >= STAGE_FINALIZING;
- }
-
- BOOL IsFinalized()
- {
- LIMITED_METHOD_CONTRACT;
-
- return m_Stage >= STAGE_FINALIZED;
- }
-
- BOOL NoAccessToHandleTable()
- {
- LIMITED_METHOD_CONTRACT;
- SUPPORTS_DAC;
-
- return m_Stage >= STAGE_HANDLETABLE_NOACCESS;
- }
-
- // Checks whether the given thread can enter the app domain
- BOOL CanThreadEnter(Thread *pThread);
-
- // Following two are needed for the Holder
- static void SetUnloadInProgress(AppDomain *pThis) PUB;
- static void SetUnloadComplete(AppDomain *pThis) PUB;
- // Predicates for GC asserts
- BOOL ShouldHaveFinalization()
- {
- LIMITED_METHOD_CONTRACT;
-
- return ((DWORD) m_Stage) < STAGE_COLLECTED;
- }
- BOOL ShouldHaveCode()
- {
- LIMITED_METHOD_CONTRACT;
-
- return ((DWORD) m_Stage) < STAGE_COLLECTED;
- }
- BOOL ShouldHaveRoots()
- {
- LIMITED_METHOD_CONTRACT;
-
- return ((DWORD) m_Stage) < STAGE_CLEARED;
- }
- BOOL ShouldHaveInstances()
- {
- LIMITED_METHOD_CONTRACT;
-
- return ((DWORD) m_Stage) < STAGE_COLLECTED;
- }
-
-
static void RaiseExitProcessEvent();
Assembly* RaiseResourceResolveEvent(DomainAssembly* pAssembly, LPCSTR szName);
DomainAssembly* RaiseTypeResolveEventThrowing(DomainAssembly* pAssembly, LPCSTR szName, ASSEMBLYREF *pResultingAssemblyRef);
@@ -3376,20 +3240,7 @@ private:
friend class DomainAssembly;
-public:
- static void ProcessUnloadDomainEventOnFinalizeThread();
- static BOOL HasWorkForFinalizerThread()
- {
- LIMITED_METHOD_CONTRACT;
- return s_pAppDomainToRaiseUnloadEvent != NULL;
- }
-
private:
- static AppDomain* s_pAppDomainToRaiseUnloadEvent;
- static BOOL s_fProcessUnloadDomainEvent;
-
- void RaiseUnloadDomainEvent();
- static void RaiseUnloadDomainEvent_Wrapper(LPVOID /* AppDomain * */);
BOOL RaiseUnhandledExceptionEvent(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating);
BOOL HasUnhandledExceptionEventHandler();
@@ -3406,25 +3257,24 @@ private:
};
- static void AllowThreadEntrance(AppDomain *pApp);
- static void RestrictThreadEntrance(AppDomain *pApp);
-
- typedef Holder<AppDomain*,DoNothing<AppDomain*>,AppDomain::AllowThreadEntrance,NULL> RestrictEnterHolder;
-
enum Stage {
STAGE_CREATING,
STAGE_READYFORMANAGEDCODE,
STAGE_ACTIVE,
STAGE_OPEN,
- STAGE_UNLOAD_REQUESTED,
- STAGE_EXITING,
- STAGE_EXITED,
- STAGE_FINALIZING,
- STAGE_FINALIZED,
- STAGE_HANDLETABLE_NOACCESS,
- STAGE_CLEARED,
- STAGE_COLLECTED,
- STAGE_CLOSED
+ // Don't delete the following *_DONOTUSE members and in case a new member needs to be added,
+ // add it at the end. The reason is that debugger stuff has its own copy of this enum and
+ // it can use the members that are marked as *_DONOTUSE here when debugging older version
+ // of the runtime.
+ STAGE_UNLOAD_REQUESTED_DONOTUSE,
+ STAGE_EXITING_DONOTUSE,
+ STAGE_EXITED_DONOTUSE,
+ STAGE_FINALIZING_DONOTUSE,
+ STAGE_FINALIZED_DONOTUSE,
+ STAGE_HANDLETABLE_NOACCESS_DONOTUSE,
+ STAGE_CLEARED_DONOTUSE,
+ STAGE_COLLECTED_DONOTUSE,
+ STAGE_CLOSED_DONOTUSE
};
void SetStage(Stage stage)
{
@@ -3442,22 +3292,12 @@ private:
while (lastStage !=stage)
lastStage = (Stage)FastInterlockCompareExchange((LONG*)&m_Stage,stage,lastStage);
};
- void Exit(BOOL fRunFinalizers, BOOL fAsyncExit);
- void Close();
void ClearGCRoots();
- void ClearGCHandles();
void UnwindThreads();
// Return TRUE if EE is stopped
// Return FALSE if more work is needed
BOOL StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread);
- // Use Rude Abort to unload the domain.
- BOOL m_fRudeUnload;
-
- Thread *m_pUnloadRequestThread;
- ADUnloadSink* m_ADUnloadSink;
- BOOL m_bForceGCOnUnload;
- BOOL m_bUnloadingFromUnloadEvent;
AppDomainLoaderAllocator m_LoaderAllocator;
// List of unloaded LoaderAllocators, protected by code:GetLoaderAllocatorReferencesLock (for now)
@@ -3468,53 +3308,6 @@ public:
// Register the loader allocator for deletion in code:ShutdownFreeLoaderAllocators.
void RegisterLoaderAllocatorForDeletion(LoaderAllocator * pLoaderAllocator);
- AppDomain * m_pNextInDelayedUnloadList;
-
- void SetForceGCOnUnload(BOOL bSet)
- {
- m_bForceGCOnUnload=bSet;
- }
-
- void SetUnloadingFromUnloadEvent()
- {
- m_bUnloadingFromUnloadEvent=TRUE;
- }
-
- BOOL IsUnloadingFromUnloadEvent()
- {
- return m_bUnloadingFromUnloadEvent;
- }
-
- void SetRudeUnload()
- {
- LIMITED_METHOD_CONTRACT;
-
- m_fRudeUnload = TRUE;
- }
-
- BOOL IsRudeUnload()
- {
- LIMITED_METHOD_CONTRACT;
-
- return m_fRudeUnload;
- }
-
- ADUnloadSink* GetADUnloadSink();
- ADUnloadSink* GetADUnloadSinkForUnload();
- void SetUnloadRequestThread(Thread *pThread)
- {
- LIMITED_METHOD_CONTRACT;
-
- m_pUnloadRequestThread = pThread;
- }
-
- Thread *GetUnloadRequestThread()
- {
- LIMITED_METHOD_CONTRACT;
-
- return m_pUnloadRequestThread;
- }
-
public:
void SetGCRefPoint(int gccounter)
{
@@ -3538,17 +3331,9 @@ public:
void AddMemoryPressure();
void RemoveMemoryPressure();
- void Unload(BOOL fForceUnload);
- static HRESULT UnloadById(ADID Id, BOOL fSync, BOOL fExceptionsPassThrough=FALSE);
- static HRESULT UnloadWait(ADID Id, ADUnloadSink* pSink);
-#ifdef FEATURE_TESTHOOKS
- static HRESULT UnloadWaitNoCatch(ADID Id, ADUnloadSink* pSink);
-#endif
- static void ResetUnloadRequestThread(ADID Id);
void UnlinkClass(MethodTable *pMT);
- typedef Holder<AppDomain *, AppDomain::SetUnloadInProgress, AppDomain::SetUnloadComplete> UnloadHolder;
Assembly *GetRootAssembly()
{
LIMITED_METHOD_CONTRACT;
@@ -3745,7 +3530,6 @@ public:
LOAD_SYSTEM_ASSEMBLY_EVENT_SENT = 0x0040,
REMOTING_CONFIGURED_FOR_DOMAIN = 0x0100,
COMPILATION_DOMAIN = 0x0400, // Are we ngenning?
- APP_DOMAIN_CAN_BE_UNLOADED = 0x0800, // if need extra bits, can derive this at runtime
ORPHANED_LOCKS = 0x1000, // Orphaned locks exist in this appdomain.
PASSIVE_DOMAIN = 0x2000, // Can we execute code in this AppDomain
VERIFICATION_DOMAIN = 0x4000, // This is a verification domain
@@ -3764,30 +3548,8 @@ public:
ArrayList m_NativeDllSearchDirectories;
BOOL m_ReversePInvokeCanEnter;
bool m_ForceTrivialWaitOperations;
- // Section to support AD unload due to escalation
-public:
- static void CreateADUnloadWorker();
-
- static void CreateADUnloadStartEvent();
-
- static DWORD WINAPI ADUnloadThreadStart(void *args);
- // Default is safe unload with test hook
- void EnableADUnloadWorker();
-
- // If called to handle stack overflow, we can not set event, since the thread has limit stack.
- void EnableADUnloadWorker(EEPolicy::AppDomainUnloadTypes type, BOOL fHasStack = TRUE);
-
- static void EnableADUnloadWorkerForThreadAbort();
- static void EnableADUnloadWorkerForFinalizer();
- static void EnableADUnloadWorkerForCollectedADCleanup();
-
- BOOL IsUnloadRequested()
- {
- LIMITED_METHOD_CONTRACT;
-
- return (m_Stage == STAGE_UNLOAD_REQUESTED);
- }
+public:
BOOL IsImageFromTrustedPath(PEImage* pImage);
@@ -3800,8 +3562,6 @@ public:
#endif
private:
- static void ADUnloadWorkerHelper(AppDomain *pDomain);
- static CLREvent * g_pUnloadStartEvent;
#ifdef DACCESS_COMPILE
public:
@@ -4070,50 +3830,6 @@ typedef Wrapper<AppDomain*,AppDomain::RefTakerAcquire,AppDomain::RefTakerRelease
// Just a ref holder
typedef ReleaseHolder<AppDomain> AppDomainRefHolder;
-// This class provides a way to access AppDomain by ID
-// without risking the appdomain getting invalid in the process
-class AppDomainFromIDHolder
-{
-public:
- enum SyncType
- {
- SyncType_GC, // Prevents AD from being unloaded by forbidding GC for the lifetime of the object
- SyncType_ADLock // Prevents AD from being unloaded by requiring ownership of DomainLock for the lifetime of the object
- };
-protected:
- AppDomain* m_pDomain;
-#ifdef _DEBUG
- BOOL m_bAcquired;
- BOOL m_bChecked;
- SyncType m_type;
-#endif
-public:
- DEBUG_NOINLINE AppDomainFromIDHolder(ADID adId, BOOL bUnsafePoint, SyncType synctype=SyncType_GC);
- DEBUG_NOINLINE AppDomainFromIDHolder(SyncType synctype=SyncType_GC);
- DEBUG_NOINLINE ~AppDomainFromIDHolder();
-
- void* GetAddress() { return m_pDomain; } // Used to get an identfier for ETW
- void Assign(ADID adId, BOOL bUnsafePoint);
- void ThrowIfUnloaded();
- void Release();
- BOOL IsUnloaded()
- {
- LIMITED_METHOD_CONTRACT;
-#ifdef _DEBUG
- m_bChecked=TRUE;
- if (m_pDomain==NULL)
- {
- // no need to enforce anything
- Release();
- }
-#endif
- return m_pDomain==NULL;
- };
- AppDomain* operator->();
-}; // class AppDomainFromIDHolder
-
-
-
typedef VPTR(class SystemDomain) PTR_SystemDomain;
class SystemDomain : public BaseDomain
@@ -4122,7 +3838,6 @@ class SystemDomain : public BaseDomain
friend class AppDomainIterator;
friend class UnsafeAppDomainIterator;
friend class ClrDataAccess;
- friend class AppDomainFromIDHolder;
friend Frame *Thread::IsRunningIn(AppDomain* pDomain, int *count);
VPTR_VTABLE_CLASS(SystemDomain, BaseDomain)
@@ -4280,15 +3995,6 @@ public:
// Use an already exising & inited Application Domain (e.g. a subclass).
static void LoadDomain(AppDomain *pDomain);
-#ifndef DACCESS_COMPILE
- static void MakeUnloadable(AppDomain* pApp)
- {
- WRAPPER_NO_CONTRACT;
- System()->AddDomain(pApp);
- pApp->SetCanUnload();
- }
-#endif // DACCESS_COMPILE
-
//****************************************************************************************
// Methods used to get the callers module and hence assembly and app domain.
__declspec(deprecated("This method is deprecated, use the version that takes a StackCrawlMark instead"))
@@ -4403,31 +4109,7 @@ public:
DWORD RequireAppDomainCleanup()
{
LIMITED_METHOD_CONTRACT;
- return m_pDelayedUnloadList != 0 || m_pDelayedUnloadListOfLoaderAllocators != 0;
- }
-
- void AddToDelayedUnloadList(AppDomain* pDomain, BOOL bAsync)
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
- m_UnloadIsAsync = bAsync;
-
- CrstHolder lh(&m_DelayedUnloadCrst);
- pDomain->m_pNextInDelayedUnloadList=m_pDelayedUnloadList;
- m_pDelayedUnloadList=pDomain;
- if (m_UnloadIsAsync)
- {
- pDomain->AddRef();
- int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration());
- if (GCHeapUtilities::IsGCInProgress())
- iGCRefPoint++;
- pDomain->SetGCRefPoint(iGCRefPoint);
- }
+ return m_pDelayedUnloadListOfLoaderAllocators != 0;
}
void AddToDelayedUnloadList(LoaderAllocator * pAllocator)
@@ -4450,74 +4132,8 @@ public:
pAllocator->SetGCRefPoint(iGCRefPoint);
}
- void ClearCollectedDomains();
- void ProcessClearingDomains();
- void ProcessDelayedUnloadDomains();
+ void ProcessDelayedUnloadLoaderAllocators();
- static void SetUnloadInProgress(AppDomain *pDomain)
- {
- WRAPPER_NO_CONTRACT;
-
- _ASSERTE(m_pAppDomainBeingUnloaded == NULL);
- m_pAppDomainBeingUnloaded = pDomain;
- m_dwIndexOfAppDomainBeingUnloaded = pDomain->GetIndex();
- }
-
- static void SetUnloadDomainCleared()
- {
- LIMITED_METHOD_CONTRACT;
-
- // about to delete, so clear this pointer so nobody uses it
- m_pAppDomainBeingUnloaded = NULL;
- }
- static void SetUnloadComplete()
- {
- LIMITED_METHOD_CONTRACT;
-
- // should have already cleared the AppDomain* prior to delete
- // either we succesfully unloaded and cleared or we failed and restored the ID
- _ASSERTE(m_pAppDomainBeingUnloaded == NULL && m_dwIndexOfAppDomainBeingUnloaded.m_dwIndex != 0
- || m_pAppDomainBeingUnloaded && SystemDomain::GetAppDomainAtId(m_pAppDomainBeingUnloaded->GetId()) != NULL);
- m_pAppDomainBeingUnloaded = NULL;
- m_pAppDomainUnloadingThread = NULL;
- }
-
- static AppDomain *AppDomainBeingUnloaded()
- {
- LIMITED_METHOD_CONTRACT;
- return m_pAppDomainBeingUnloaded;
- }
-
- static ADIndex IndexOfAppDomainBeingUnloaded()
- {
- LIMITED_METHOD_CONTRACT;
- return m_dwIndexOfAppDomainBeingUnloaded;
- }
-
- static void SetUnloadRequestingThread(Thread *pRequestingThread)
- {
- LIMITED_METHOD_CONTRACT;
- m_pAppDomainUnloadRequestingThread = pRequestingThread;
- }
-
- static Thread *GetUnloadRequestingThread()
- {
- LIMITED_METHOD_CONTRACT;
- return m_pAppDomainUnloadRequestingThread;
- }
-
- static void SetUnloadingThread(Thread *pUnloadingThread)
- {
- LIMITED_METHOD_CONTRACT;
- m_pAppDomainUnloadingThread = pUnloadingThread;
- }
-
- static Thread *GetUnloadingThread()
- {
- LIMITED_METHOD_CONTRACT;
- return m_pAppDomainUnloadingThread;
- }
-
static void EnumAllStaticGCRefs(promote_func* fn, ScanContext* sc);
#endif // DACCESS_COMPILE
@@ -4620,9 +4236,7 @@ private:
STANDARD_VM_CONTRACT;
m_pDefaultDomain = NULL;
- m_pDelayedUnloadList=NULL;
m_pDelayedUnloadListOfLoaderAllocators=NULL;
- m_UnloadIsAsync = FALSE;
m_GlobalAllocator.Init(this);
}
@@ -4650,9 +4264,6 @@ private:
// Global domain that every one uses
SPTR_DECL(SystemDomain, m_pSystemDomain);
- AppDomain* m_pDelayedUnloadList;
- BOOL m_UnloadIsAsync;
-
LoaderAllocator * m_pDelayedUnloadListOfLoaderAllocators;
#ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
@@ -4668,20 +4279,6 @@ private:
static ArrayListStatic m_appDomainIdList;
- // only one ad can be unloaded at a time
- static AppDomain* m_pAppDomainBeingUnloaded;
- // need this so can determine AD being unloaded after it has been deleted
- static ADIndex m_dwIndexOfAppDomainBeingUnloaded;
-
- // if had to spin off a separate thread to do the unload, this is the original thread.
- // allows us to delay aborting it until it's the last one so that it can receive
- // notification of an unload failure
- static Thread *m_pAppDomainUnloadRequestingThread;
-
- // this is the thread doing the actual unload. He's allowed to enter the domain
- // even if have started unloading.
- static Thread *m_pAppDomainUnloadingThread;
-
static GlobalStringLiteralMap *m_pGlobalStringLiteralMap;
static ULONG s_dNumAppDomains; // Maintain a count of children app domains.
@@ -5082,17 +4679,6 @@ protected:
{
m_pDomain->Release();
}
- else
- {
- STRESS_LOG2 (LF_APPDOMAIN, LL_INFO100, "Unload domain during creation [%d] %p\n", m_pDomain->GetId().m_dwId, m_pDomain);
- SystemDomain::MakeUnloadable(m_pDomain);
-#ifdef _DEBUG
- DWORD hostTestADUnload = g_pConfig->GetHostTestADUnload();
- m_pDomain->EnableADUnloadWorker(hostTestADUnload != 2?EEPolicy::ADU_Safe:EEPolicy::ADU_Rude);
-#else
- m_pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
-#endif
- }
};
public:
diff --git a/src/vm/appdomain.inl b/src/vm/appdomain.inl
index 7fb4a9593d..37fb501361 100644
--- a/src/vm/appdomain.inl
+++ b/src/vm/appdomain.inl
@@ -19,20 +19,6 @@
#include "appdomain.hpp"
-inline void AppDomain::SetUnloadInProgress(AppDomain *pThis)
-{
- WRAPPER_NO_CONTRACT;
-
- SystemDomain::System()->SetUnloadInProgress(pThis);
-}
-
-inline void AppDomain::SetUnloadComplete(AppDomain *pThis)
-{
- GCX_COOP();
-
- SystemDomain::System()->SetUnloadComplete();
-}
-
inline void AppDomain::EnterContext(Thread* pThread, Context* pCtx,ContextTransitionFrame *pFrame)
{
CONTRACTL
@@ -48,118 +34,6 @@ inline void AppDomain::EnterContext(Thread* pThread, Context* pCtx,ContextTrans
pThread->EnterContextRestricted(pCtx,pFrame);
};
-
-inline AppDomainFromIDHolder::~AppDomainFromIDHolder()
-{
- WRAPPER_NO_CONTRACT;
-#ifdef _DEBUG
- if(m_bAcquired)
- Release();
-#endif
-}
-
-inline void AppDomainFromIDHolder::Release()
-{
- //do not use real contract here!
- WRAPPER_NO_CONTRACT;
-#ifdef _DEBUG
- if(m_bAcquired)
- {
- if (m_type==SyncType_GC)
-#ifdef ENABLE_CONTRACTS_IMPL
- {
- if (GetThread())
- {
- STRESS_LOG1(LF_APPDOMAIN, LL_INFO10000, "AppDomainFromIDHolder::Assign is allowing GC - %08x",this);
- GetThread()->EndForbidGC();
- }
- else
- {
- if (!IsGCThread())
- {
- _ASSERTE(!"Should not be called from a non GC thread");
- }
- }
- }
-#else
- m_pDomain=NULL;
-#endif
- else
- if (m_type==SyncType_ADLock)
- SystemDomain::m_SystemDomainCrst.SetCantLeave(FALSE);
- else
- {
- _ASSERTE(!"Unknown type");
- }
- m_pDomain=NULL;
- m_bAcquired=FALSE;
- }
-#endif
-}
-
-inline void AppDomainFromIDHolder::Assign(ADID id, BOOL bUnsafePoint)
-{
- //do not use real contract here!
- WRAPPER_NO_CONTRACT;
- TESTHOOKCALL(AppDomainCanBeUnloaded(id.m_dwId, bUnsafePoint));
-#ifdef _DEBUG
- m_bChecked=FALSE;
- if (m_type==SyncType_GC)
- {
-#ifdef ENABLE_CONTRACTS_IMPL
- if (GetThread())
- {
- _ASSERTE(GetThread()->PreemptiveGCDisabled());
- STRESS_LOG1(LF_APPDOMAIN, LL_INFO10000, "AppDomainFromIDHolder::Assign is forbidding GC - %08x",this);
- GetThread()->BeginForbidGC(__FILE__, __LINE__);
- }
- else
- {
- if (!IsGCThread())
- {
- _ASSERTE(!"Should not be called from a non GC thread");
- }
- }
-#endif
- }
- else
- if (m_type==SyncType_ADLock)
- {
- _ASSERTE(SystemDomain::m_SystemDomainCrst.OwnedByCurrentThread());
- SystemDomain::m_SystemDomainCrst.SetCantLeave(TRUE);
- }
- else
- {
- _ASSERT(!"NI");
- }
-
- m_bAcquired=TRUE;
- #endif
- m_pDomain=SystemDomain::GetAppDomainAtId(id);
-
-}
-
-
-
-inline void AppDomainFromIDHolder::ThrowIfUnloaded()
-{
- STATIC_CONTRACT_THROWS;
- if (IsUnloaded())
- {
- COMPlusThrow(kAppDomainUnloadedException);
- }
-#ifdef _DEBUG
- m_bChecked=TRUE;
-#endif
-}
-
-inline AppDomain* AppDomainFromIDHolder::operator ->()
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(m_bChecked && m_bAcquired);
- return m_pDomain;
-}
-
inline DomainAssembly* AppDomain::FindDomainAssembly(Assembly* assembly)
{
CONTRACTL
diff --git a/src/vm/appdomainnative.cpp b/src/vm/appdomainnative.cpp
index 713856f1d8..3b2a53846e 100644
--- a/src/vm/appdomainnative.cpp
+++ b/src/vm/appdomainnative.cpp
@@ -302,34 +302,6 @@ FCIMPL2(Object*, AppDomainNative::GetAssemblies, AppDomainBaseObject* refThisUNS
} // AppDomainNative::GetAssemblies
FCIMPLEND
-
-FCIMPL1(void, AppDomainNative::Unload, INT32 dwId)
-{
- FCALL_CONTRACT;
-
- HELPER_METHOD_FRAME_BEGIN_0();
-
- IfFailThrow(AppDomain::UnloadById(ADID(dwId),TRUE));
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-FCIMPL1(FC_BOOL_RET, AppDomainNative::IsDomainIdValid, INT32 dwId)
-{
- FCALL_CONTRACT;
-
- BOOL retVal = FALSE;
- HELPER_METHOD_FRAME_BEGIN_RET_0()
-
- AppDomainFromIDHolder ad((ADID)dwId, TRUE);
- retVal=!ad.IsUnloaded();
- HELPER_METHOD_FRAME_END();
- FC_RETURN_BOOL(retVal);
-}
-FCIMPLEND
-
-
FCIMPL1(INT32, AppDomainNative::GetId, AppDomainBaseObject* refThisUNSAFE)
{
FCALL_CONTRACT;
diff --git a/src/vm/appdomainnative.hpp b/src/vm/appdomainnative.hpp
index 9728ef8ec0..dc1b133d2d 100644
--- a/src/vm/appdomainnative.hpp
+++ b/src/vm/appdomainnative.hpp
@@ -28,11 +28,8 @@ public:
static FCDECL2(Object*, GetOrInternString, AppDomainBaseObject* refThisUNSAFE, StringObject* pStringUNSAFE);
static FCDECL1(void, CreateContext, AppDomainBaseObject *refThisUNSAFE);
static void QCALLTYPE SetupBindingPaths(__in_z LPCWSTR wszTrustedPlatformAssemblies, __in_z LPCWSTR wszPlatformResourceRoots, __in_z LPCWSTR wszAppPaths, __in_z LPCWSTR wszAppNiPaths, __in_z LPCWSTR appLocalWinMD);
- static FCDECL1(void, Unload, INT32 dwId);
static FCDECL1(Object*, GetDynamicDir, AppDomainBaseObject* refThisUNSAFE);
static FCDECL1(INT32, GetId, AppDomainBaseObject* refThisUNSAFE);
- static FCDECL1(INT32, GetIdForUnload, AppDomainBaseObject* refDomainUNSAFE);
- static FCDECL1(FC_BOOL_RET, IsDomainIdValid, INT32 dwId);
static FCDECL1(void, ForceToSharedDomain, Object* pObjectUNSAFE);
static FCDECL1(LPVOID, GetFusionContext, AppDomainBaseObject* refThis);
static FCDECL2(Object*, IsStringInterned, AppDomainBaseObject* refThis, StringObject* pString);
diff --git a/src/vm/arm/asmconstants.h b/src/vm/arm/asmconstants.h
index 5af778ba36..c57c92a95b 100644
--- a/src/vm/arm/asmconstants.h
+++ b/src/vm/arm/asmconstants.h
@@ -179,7 +179,7 @@ ASMCONSTANTS_C_ASSERT(Thread__m_pFrame == offsetof(Thread, m_pFrame));
#define Thread_m_pFrame Thread__m_pFrame
#ifndef CROSSGEN_COMPILE
-#define Thread__m_pDomain 0x14
+#define Thread__m_pDomain 0x10
ASMCONSTANTS_C_ASSERT(Thread__m_pDomain == offsetof(Thread, m_pDomain));
#define AppDomain__m_dwId 0x04
diff --git a/src/vm/arm/asmhelpers.S b/src/vm/arm/asmhelpers.S
index 22ec7c1171..feadaa87ba 100644
--- a/src/vm/arm/asmhelpers.S
+++ b/src/vm/arm/asmhelpers.S
@@ -341,14 +341,7 @@ LOCAL_LABEL(UMThunkStub_HaveThread):
LOCAL_LABEL(UMThunkStub_InCooperativeMode):
ldr r12, [r7, #UMThunkStub_HiddenArgOffset]
-
- ldr r0, [r5, #Thread__m_pDomain]
- ldr r1, [r12, #UMEntryThunk__m_dwDomainId]
- ldr r0, [r0, #AppDomain__m_dwId]
ldr r3, [r12, #UMEntryThunk__m_pUMThunkMarshInfo]
- cmp r0, r1
- bne LOCAL_LABEL(UMThunkStub_WrongAppDomain)
-
ldr r2, [r3, #UMThunkMarshInfo__m_cbActualArgSize]
cbz r2, LOCAL_LABEL(UMThunkStub_ArgumentsSetup)
@@ -401,95 +394,8 @@ LOCAL_LABEL(UMThunkStub_DoTrapReturningThreads):
add sp, #SIZEOF__FloatArgumentRegisters
b LOCAL_LABEL(UMThunkStub_InCooperativeMode)
-LOCAL_LABEL(UMThunkStub_WrongAppDomain):
- sub sp, #SIZEOF__FloatArgumentRegisters
- vstm sp, {d0-d7}
-
- ldr r0, [r7, #UMThunkStub_HiddenArgOffset] // UMEntryThunk* pUMEntry
- mov r2, r7 // void * pArgs
- // remaining arguments are unused
- bl C_FUNC(UM2MDoADCallBack)
-
- // Restore non-FP return value.
- ldr r0, [r7, #0]
- ldr r1, [r7, #4]
-
- // Restore FP return value or HFA.
- vldm sp, {d0-d3}
- b LOCAL_LABEL(UMThunkStub_PostCall)
-
NESTED_END UMThunkStub,_TEXT
-// UM2MThunk_WrapperHelper(void *pThunkArgs, // r0
-// int cbStackArgs, // r1 (unused)
-// void *pAddr, // r2 (unused)
-// UMEntryThunk *pEntryThunk, // r3
-// Thread *pThread) // [sp, #0]
-
- NESTED_ENTRY UM2MThunk_WrapperHelper, _TEXT, NoHandler
-
- PROLOG_PUSH "{r4-r7,r11,lr}"
- PROLOG_STACK_SAVE_OFFSET r7, #12
-
- CHECK_STACK_ALIGNMENT
-
- mov r12, r3 // r12 = UMEntryThunk *
-
- //
- // Note that layout of the arguments is given by UMThunkStub frame
- //
- mov r5, r0 // r5 = pArgs
-
- ldr r3, [r12, #UMEntryThunk__m_pUMThunkMarshInfo]
-
- ldr r2, [r3, #UMThunkMarshInfo__m_cbActualArgSize]
- cbz r2, LOCAL_LABEL(UM2MThunk_WrapperHelper_ArgumentsSetup)
-
- add r0, r5, #UMThunkStub_StackArgsSize // Source pointer
- add r0, r0, r2
- lsr r1, r2, #2 // Count of stack slots to copy
-
- and r2, r2, #4 // Align the stack
- sub sp, sp, r2
-
-LOCAL_LABEL(UM2MThunk_WrapperHelper_StackLoop):
- ldr r2, [r0,#-4]!
- str r2, [sp,#-4]!
- subs r1, r1, #1
- bne LOCAL_LABEL(UM2MThunk_WrapperHelper_StackLoop)
-
-LOCAL_LABEL(UM2MThunk_WrapperHelper_ArgumentsSetup):
- ldr r4, [r3, #UMThunkMarshInfo__m_pILStub]
-
- // reload floating point registers
- sub r6, r5, #SIZEOF__FloatArgumentRegisters
- vldm r6, {d0-d7}
-
- // reload argument registers
- ldm r5, {r0-r3}
-
- CHECK_STACK_ALIGNMENT
-
- blx r4
-
- // Save non-floating point return
- str r0, [r5, #0]
- str r1, [r5, #4]
-
- // Save FP return value or HFA.
- vstm r6, {d0-d3}
-
-#ifdef _DEBUG
- // trash the floating point registers to ensure that the HFA return values
- // won't survive by accident
- vldm sp, {d0-d3}
-#endif
-
- EPILOG_STACK_RESTORE_OFFSET r7, #12
- EPILOG_POP "{r4-r7,r11,pc}"
-
- NESTED_END UM2MThunk_WrapperHelper, _TEXT
-
// ------------------------------------------------------------------
NESTED_ENTRY ThePreStub, _TEXT, NoHandler
diff --git a/src/vm/arm/asmhelpers.asm b/src/vm/arm/asmhelpers.asm
index 60def084e7..c0fef0c705 100644
--- a/src/vm/arm/asmhelpers.asm
+++ b/src/vm/arm/asmhelpers.asm
@@ -22,7 +22,6 @@
IMPORT TheUMEntryPrestubWorker
IMPORT CreateThreadBlockThrow
IMPORT UMThunkStubRareDisableWorker
- IMPORT UM2MDoADCallBack
IMPORT PreStubWorker
IMPORT PreStubGetMethodDescForCompactEntryPoint
IMPORT NDirectImportWorker
@@ -404,13 +403,7 @@ UMThunkStub_HaveThread
UMThunkStub_InCooperativeMode
ldr r12, [r7, #UMThunkStub_HiddenArg]
- ldr r0, [r5, #Thread__m_pDomain]
- ldr r1, [r12, #UMEntryThunk__m_dwDomainId]
- ldr r0, [r0, #AppDomain__m_dwId]
ldr r3, [r12, #UMEntryThunk__m_pUMThunkMarshInfo]
- cmp r0, r1
- bne UMThunkStub_WrongAppDomain
-
ldr r2, [r3, #UMThunkMarshInfo__m_cbActualArgSize]
cbz r2, UMThunkStub_ArgumentsSetup
@@ -463,96 +456,8 @@ UMThunkStub_DoTrapReturningThreads
add sp, #SIZEOF__FloatArgumentRegisters
b UMThunkStub_InCooperativeMode
-UMThunkStub_WrongAppDomain
- sub sp, #SIZEOF__FloatArgumentRegisters
- vstm sp, {d0-d7}
-
- ldr r0, [r7, #UMThunkStub_HiddenArg] ; UMEntryThunk* pUMEntry
- mov r2, r7 ; void * pArgs
- ; remaining arguments are unused
- bl UM2MDoADCallBack
-
- ; Restore non-FP return value.
- ldr r0, [r7, #0]
- ldr r1, [r7, #4]
-
- ; Restore FP return value or HFA.
- vldm sp, {d0-d3}
- b UMThunkStub_PostCall
-
- NESTED_END
-
-; UM2MThunk_WrapperHelper(void *pThunkArgs, // r0
-; int cbStackArgs, // r1 (unused)
-; void *pAddr, // r2 (unused)
-; UMEntryThunk *pEntryThunk, // r3
-; Thread *pThread) // [sp, #0]
-
- NESTED_ENTRY UM2MThunk_WrapperHelper
-
- PROLOG_PUSH {r4-r7,r11,lr}
- PROLOG_STACK_SAVE r7
-
- CHECK_STACK_ALIGNMENT
-
- mov r12, r3 // r12 = UMEntryThunk *
-
- ;
- ; Note that layout of the arguments is given by UMThunkStub frame
- ;
- mov r5, r0 // r5 = pArgs
-
- ldr r3, [r12, #UMEntryThunk__m_pUMThunkMarshInfo]
-
- ldr r2, [r3, #UMThunkMarshInfo__m_cbActualArgSize]
- cbz r2, UM2MThunk_WrapperHelper_ArgumentsSetup
-
- add r0, r5, #UMThunkStub_StackArgs ; Source pointer
- add r0, r0, r2
- lsr r1, r2, #2 ; Count of stack slots to copy
-
- and r2, r2, #4 ; Align the stack
- sub sp, sp, r2
-
-UM2MThunk_WrapperHelper_StackLoop
- ldr r2, [r0,#-4]!
- str r2, [sp,#-4]!
- subs r1, r1, #1
- bne UM2MThunk_WrapperHelper_StackLoop
-
-UM2MThunk_WrapperHelper_ArgumentsSetup
- ldr r4, [r3, #UMThunkMarshInfo__m_pILStub]
-
- ; reload floating point registers
- sub r6, r5, #SIZEOF__FloatArgumentRegisters
- vldm r6, {d0-d7}
-
- ; reload argument registers
- ldm r5, {r0-r3}
-
- CHECK_STACK_ALIGNMENT
-
- blx r4
-
- ; Save non-floating point return
- str r0, [r5, #0]
- str r1, [r5, #4]
-
- ; Save FP return value or HFA.
- vstm r6, {d0-d3}
-
-#ifdef _DEBUG
- ;; trash the floating point registers to ensure that the HFA return values
- ;; won't survive by accident
- vldm sp, {d0-d3}
-#endif
-
- EPILOG_STACK_RESTORE r7
- EPILOG_POP {r4-r7,r11,pc}
-
NESTED_END
-
; ------------------------------------------------------------------
NESTED_ENTRY ThePreStub
diff --git a/src/vm/arm64/asmconstants.h b/src/vm/arm64/asmconstants.h
index 262e481b53..7d0a9f734b 100644
--- a/src/vm/arm64/asmconstants.h
+++ b/src/vm/arm64/asmconstants.h
@@ -46,7 +46,7 @@ ASMCONSTANTS_C_ASSERT(Thread__m_pFrame == offsetof(Thread, m_pFrame));
#define Thread_m_fPreemptiveGCDisabled Thread__m_fPreemptiveGCDisabled
#ifndef CROSSGEN_COMPILE
-#define Thread__m_pDomain 0x20
+#define Thread__m_pDomain 0x18
ASMCONSTANTS_C_ASSERT(Thread__m_pDomain == offsetof(Thread, m_pDomain));
#define AppDomain__m_dwId 0x08
diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S
index e138feb402..aa79b4d477 100644
--- a/src/vm/arm64/asmhelpers.S
+++ b/src/vm/arm64/asmhelpers.S
@@ -767,15 +767,6 @@ LOCAL_LABEL(UMThunkStub_HaveThread):
LOCAL_LABEL(UMThunkStub_InCooperativeMode):
ldr x12, [fp, #UMThunkStub_HiddenArg] // x12 = UMEntryThunk*
-
- ldr x0, [x19, #Thread__m_pDomain]
-
- // m_dwDomainId is 4 bytes so using 32-bit variant
- ldr w1, [x12, #UMEntryThunk__m_dwDomainId]
- ldr w0, [x0, #AppDomain__m_dwId]
- cmp w0, w1
- bne LOCAL_LABEL(UMThunkStub_WrongAppDomain)
-
ldr x3, [x12, #UMEntryThunk__m_pUMThunkMarshInfo] // x3 = m_pUMThunkMarshInfo
// m_cbActualArgSize is UINT32 and hence occupies 4 bytes
@@ -846,112 +837,8 @@ LOCAL_LABEL(UMThunkStub_DoTrapReturningThreads):
add sp, sp, #SIZEOF__FloatArgumentRegisters
b LOCAL_LABEL(UMThunkStub_InCooperativeMode)
-LOCAL_LABEL(UMThunkStub_WrongAppDomain):
- // Saving FP Args as this is read by UM2MThunk_WrapperHelper
- sub sp, sp, #SIZEOF__FloatArgumentRegisters
- SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0
-
- // UMEntryThunk* pUMEntry
- ldr x0, [fp, #UMThunkStub_HiddenArg]
-
- // void * pArgs
- add x2, fp, #16
-
- // remaining arguments are unused
- bl C_FUNC(UM2MDoADCallBack)
-
- // restore integral return value
- ldp x0, x1, [fp, #16]
-
- // restore FP or HFA return value
- RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 0
-
- b LOCAL_LABEL(UMThunkStub_PostCall)
-
NESTED_END UMThunkStub, _TEXT
-
-// UM2MThunk_WrapperHelper(void *pThunkArgs, // x0
-// int cbStackArgs, // x1 (unused)
-// void *pAddr, // x2 (unused)
-// UMEntryThunk *pEntryThunk,// x3
-// Thread *pThread) // x4
-
-// pThunkArgs points to the argument registers pushed on the stack by UMThunkStub
-
-NESTED_ENTRY UM2MThunk_WrapperHelper, _TEXT, NoHandler
-
- PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32
- PROLOG_SAVE_REG x19, 16
-
-
- // save pThunkArgs in non-volatile reg. It is required after return from call to ILStub
- mov x19, x0
-
- // ARM64TODO - Is this required by ILStub
- mov x12, x3 //// x12 = UMEntryThunk *
-
- //
- // Note that layout of the arguments is given by UMThunkStub frame
- //
- ldr x3, [x3, #UMEntryThunk__m_pUMThunkMarshInfo]
-
- // m_cbActualArgSize is 4-byte field
- ldr w2, [x3, #UMThunkMarshInfo__m_cbActualArgSize]
- cbz w2, LOCAL_LABEL(UM2MThunk_WrapperHelper_RegArgumentsSetup)
-
- // extend to 64- bits
- uxtw x2, w2
-
- // Source pointer. Subtracting 16 bytes due to fp & lr
- add x6, x0, #(UMThunkStub_StackArgs-16)
-
- // move source ptr to end of Stack Args
- add x6, x6, x2
-
- // Count of stack slot pairs to copy (divide by 16)
- lsr x1, x2, #4
-
- // Is there an extra stack slot? (can happen when stack arg bytes not multiple of 16)
- and x2, x2, #8
-
- // If yes then start source pointer from 16 byte aligned stack slot
- add x6, x6, x2
-
- // increment stack slot pair count by 1 if x2 is not zero
- add x1, x1, x2, LSR #3
-
-LOCAL_LABEL(UM2MThunk_WrapperHelper_StackLoop):
- ldp x4, x5, [x6, #-16]!
- stp x4, x5, [sp, #-16]!
- subs x1, x1, #1
- bne LOCAL_LABEL(UM2MThunk_WrapperHelper_StackLoop)
-
-LOCAL_LABEL(UM2MThunk_WrapperHelper_RegArgumentsSetup):
- ldr x16, [x3, #(UMThunkMarshInfo__m_pILStub)]
-
- // reload floating point registers
- RESTORE_FLOAT_ARGUMENT_REGISTERS x0, -1 * (SIZEOF__FloatArgumentRegisters + 16)
-
- // reload argument registers
- RESTORE_ARGUMENT_REGISTERS x0, 0
-
- blr x16
-
- // save integral return value
- stp x0, x1, [x19]
-
- // save FP/HFA return values
- SAVE_FLOAT_ARGUMENT_REGISTERS x19, -1 * (SIZEOF__FloatArgumentRegisters + 16)
-
- EPILOG_STACK_RESTORE
- EPILOG_RESTORE_REG x19, 16
- EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 32
- EPILOG_RETURN
-
-NESTED_END UM2MThunk_WrapperHelper, _TEXT
-
-
#ifdef FEATURE_HIJACK
// ------------------------------------------------------------------
// Hijack function for functions which return a scalar type or a struct (value type)
diff --git a/src/vm/arm64/asmhelpers.asm b/src/vm/arm64/asmhelpers.asm
index 7346c468a0..e9edec17e5 100644
--- a/src/vm/arm64/asmhelpers.asm
+++ b/src/vm/arm64/asmhelpers.asm
@@ -27,7 +27,6 @@
IMPORT GetThread
IMPORT CreateThreadBlockThrow
IMPORT UMThunkStubRareDisableWorker
- IMPORT UM2MDoADCallBack
IMPORT GetCurrentSavedRedirectContext
IMPORT LinkFrameAndThrow
IMPORT FixContextHandler
@@ -754,15 +753,6 @@ UMThunkStub_HaveThread
UMThunkStub_InCooperativeMode
ldr x12, [fp, #UMThunkStub_HiddenArg] ; x12 = UMEntryThunk*
-
- ldr x0, [x19, #Thread__m_pDomain]
-
- ; m_dwDomainId is 4 bytes so using 32-bit variant
- ldr w1, [x12, #UMEntryThunk__m_dwDomainId]
- ldr w0, [x0, #AppDomain__m_dwId]
- cmp w0, w1
- bne UMThunkStub_WrongAppDomain
-
ldr x3, [x12, #UMEntryThunk__m_pUMThunkMarshInfo] ; x3 = m_pUMThunkMarshInfo
; m_cbActualArgSize is UINT32 and hence occupies 4 bytes
@@ -833,109 +823,6 @@ UMThunkStub_DoTrapReturningThreads
add sp, sp, #SIZEOF__FloatArgumentRegisters
b UMThunkStub_InCooperativeMode
-UMThunkStub_WrongAppDomain
- ; Saving FP Args as this is read by UM2MThunk_WrapperHelper
- sub sp, sp, #SIZEOF__FloatArgumentRegisters
- SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0
-
- ; UMEntryThunk* pUMEntry
- ldr x0, [fp, #UMThunkStub_HiddenArg]
-
- ; void * pArgs
- add x2, fp, #16
-
- ; remaining arguments are unused
- bl UM2MDoADCallBack
-
- ; restore any integral return value(s)
- ldp x0, x1, [fp, #16]
-
- ; restore any FP or HFA return value(s)
- RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 0
-
- b UMThunkStub_PostCall
-
- NESTED_END
-
-
-; UM2MThunk_WrapperHelper(void *pThunkArgs, // x0
-; int cbStackArgs, // x1 (unused)
-; void *pAddr, // x2 (unused)
-; UMEntryThunk *pEntryThunk, // x3
-; Thread *pThread) // x4
-
-; pThunkArgs points to the argument registers pushed on the stack by UMThunkStub
-
- NESTED_ENTRY UM2MThunk_WrapperHelper
-
- PROLOG_SAVE_REG_PAIR fp, lr, #-32!
- PROLOG_SAVE_REG x19, #16
-
-
- ; save pThunkArgs in non-volatile reg. It is required after return from call to ILStub
- mov x19, x0
-
- ; ARM64TODO - Is this required by ILStub
- mov x12, x3 ; // x12 = UMEntryThunk *
-
- ;
- ; Note that layout of the arguments is given by UMThunkStub frame
- ;
- ldr x3, [x3, #UMEntryThunk__m_pUMThunkMarshInfo]
-
- ; m_cbActualArgSize is 4-byte field
- ldr w2, [x3, #UMThunkMarshInfo__m_cbActualArgSize]
- cbz w2, UM2MThunk_WrapperHelper_RegArgumentsSetup
-
- ; extend to 64- bits
- uxtw x2, w2
-
- ; Source pointer. Subtracting 16 bytes due to fp & lr
- add x6, x0, #(UMThunkStub_StackArgs-16)
-
- ; move source ptr to end of Stack Args
- add x6, x6, x2
-
- ; Count of stack slot pairs to copy (divide by 16)
- lsr x1, x2, #4
-
- ; Is there an extra stack slot? (can happen when stack arg bytes not multiple of 16)
- and x2, x2, #8
-
- ; If yes then start source pointer from 16 byte aligned stack slot
- add x6, x6, x2
-
- ; increment stack slot pair count by 1 if x2 is not zero
- add x1, x1, x2, LSR #3
-
-UM2MThunk_WrapperHelper_StackLoop
- ldp x4, x5, [x6, #-16]!
- stp x4, x5, [sp, #-16]!
- subs x1, x1, #1
- bne UM2MThunk_WrapperHelper_StackLoop
-
-UM2MThunk_WrapperHelper_RegArgumentsSetup
- ldr x16, [x3, #(UMThunkMarshInfo__m_pILStub)]
-
- ; reload floating point registers
- RESTORE_FLOAT_ARGUMENT_REGISTERS x0, -1 * (SIZEOF__FloatArgumentRegisters + 16)
-
- ; reload argument registers
- RESTORE_ARGUMENT_REGISTERS x0, 0
-
- blr x16
-
- ; save any integral return value(s)
- stp x0, x1, [x19]
-
- ; save any FP or HFA return value(s)
- SAVE_FLOAT_ARGUMENT_REGISTERS x19, -1 * (SIZEOF__FloatArgumentRegisters + 16)
-
- EPILOG_STACK_RESTORE
- EPILOG_RESTORE_REG x19, #16
- EPILOG_RESTORE_REG_PAIR fp, lr, #32!
- EPILOG_RETURN
-
NESTED_END
#ifdef FEATURE_HIJACK
diff --git a/src/vm/callhelpers.cpp b/src/vm/callhelpers.cpp
index d11c4e83d4..b11f9d73e9 100644
--- a/src/vm/callhelpers.cpp
+++ b/src/vm/callhelpers.cpp
@@ -404,8 +404,6 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT *
//
ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
- _ASSERTE(GetAppDomain()->ShouldHaveCode());
-
#ifdef FEATURE_INTERPRETER
_ASSERTE(isCallConv(m_methodSig.GetCallingConvention(), IMAGE_CEE_CS_CALLCONV_DEFAULT)
|| isCallConv(m_methodSig.GetCallingConvention(), CorCallingConvention(IMAGE_CEE_CS_CALLCONV_C))
diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp
index 9874d26f4d..04b12264a8 100644
--- a/src/vm/ceemain.cpp
+++ b/src/vm/ceemain.cpp
@@ -950,8 +950,6 @@ void EEStartupHelper(COINITIEE fFlags)
StackwalkCache::Init();
- AppDomain::CreateADUnloadStartEvent();
-
// In coreclr, clrjit is compiled into it, but SO work in clrjit has not been done.
#ifdef FEATURE_STACK_PROBE
if (CLRHosted() && GetEEPolicy()->GetActionOnFailure(FAIL_StackOverflow) == eRudeUnloadAppDomain)
@@ -996,19 +994,6 @@ void EEStartupHelper(COINITIEE fFlags)
SystemDomain::NotifyProfilerStartup();
#endif // PROFILING_SUPPORTED
-#ifndef CROSSGEN_COMPILE
- if (CLRHosted()
-#ifdef _DEBUG
- || ((fFlags & COINITEE_DLL) == 0 &&
- g_pConfig->GetHostTestADUnload())
-#endif
- ) {
- // If we are hosted, a host may specify unloading AD when a managed allocation in
- // critical region fails. We need to precreate a thread to unload AD.
- AppDomain::CreateADUnloadWorker();
- }
-#endif // CROSSGEN_COMPILE
-
g_fEEInit = false;
SystemDomain::System()->DefaultDomain()->LoadSystemAssemblies();
diff --git a/src/vm/codeversion.cpp b/src/vm/codeversion.cpp
index 5f7ef16f7b..06451e9e94 100644
--- a/src/vm/codeversion.cpp
+++ b/src/vm/codeversion.cpp
@@ -2383,10 +2383,6 @@ HRESULT CodeVersionManager::EnumerateClosedMethodDescs(
while (appDomainIterator.Next())
{
AppDomain * pAppDomain = appDomainIterator.GetDomain();
- if (pAppDomain->IsUnloading())
- {
- continue;
- }
hr = EnumerateDomainClosedMethodDescs(
pAppDomain,
pModule,
diff --git a/src/vm/comcallablewrapper.cpp b/src/vm/comcallablewrapper.cpp
index 4d116c157f..49802ff9d0 100644
--- a/src/vm/comcallablewrapper.cpp
+++ b/src/vm/comcallablewrapper.cpp
@@ -751,10 +751,7 @@ HRESULT WeakReferenceImpl::Cleanup()
//
GCX_COOP_THREAD_EXISTS(GET_THREAD());
- AppDomainFromIDHolder ad(m_adid, TRUE);
-
- if (!ad.IsUnloaded())
- DestroyShortWeakHandle(m_ppObject);
+ DestroyShortWeakHandle(m_ppObject);
m_ppObject = NULL;
}
@@ -1103,18 +1100,7 @@ VOID SimpleComCallWrapper::Cleanup()
// so we must release it if the AD wasn't unloaded
if (IsAgile() && m_hOrigDomainHandle)
{
- // the domain which the original handle belongs to might be already unloaded
- if (GetRawDomainID()==::GetAppDomain()->GetId())
- DestroyRefcountedHandle(m_hOrigDomainHandle);
- else
- {
- GCX_COOP();
- {
- AppDomainFromIDHolder ad(GetRawDomainID(), TRUE);
- if (!ad.IsUnloaded())
- DestroyRefcountedHandle(m_hOrigDomainHandle);
- }
- }
+ DestroyRefcountedHandle(m_hOrigDomainHandle);
m_hOrigDomainHandle = NULL;
}
@@ -2127,10 +2113,7 @@ void ComCallWrapper::MarkHandleWeak()
MODE_ANY;
}
CONTRACTL_END;
-#ifdef _DEBUG
- AppDomainFromIDHolder ad(GetSimpleWrapper()->GetDomainID(), TRUE);
- _ASSERTE(!ad.IsUnloaded());
-#endif
+
SyncBlock* pSyncBlock = GetSyncBlock();
_ASSERTE(pSyncBlock);
@@ -2152,10 +2135,6 @@ void ComCallWrapper::ResetHandleStrength()
}
CONTRACTL_END;
-#ifdef _DEBUG
- AppDomainFromIDHolder ad(GetSimpleWrapper()->GetDomainID(), TRUE);
- _ASSERTE(!ad.IsUnloaded());
-#endif
SyncBlock* pSyncBlock = GetSyncBlock();
_ASSERTE(pSyncBlock);
@@ -2511,27 +2490,10 @@ void ComCallWrapper::Cleanup()
ClearSimpleWrapper(this);
}
+ if (fOwnsHandle && m_ppThis)
{
- // Switch to cooperative mode for AppDomainFromIDHolder
- // AppDomainFromIDHolder.Assign might forbid GC and AppDomainFromIDHolder.Release might re-enable GC.
- // The state is stored in ClrDebugState, which GCX_COOP() macros will push into stack & pop from stack
- // So use GCX_COOP() around all these statements for AppDomainFromIDHolder
- GCX_COOP();
-
- // deregister the handle, in the first block. If no domain, then it's already done
- AppDomainFromIDHolder pTgtDomain;
- if (domainId != CURRENT_APPDOMAIN_ID)
- {
- pTgtDomain.Assign(domainId, FALSE);
- }
-
- if (fOwnsHandle && m_ppThis && !pTgtDomain.IsUnloaded())
- {
- LOG((LF_INTEROP, LL_INFO100, "ComCallWrapper::Cleanup on Object %8.8x\n", m_ppThis));
- ClearHandle();
- }
-
- pTgtDomain.Release();
+ LOG((LF_INTEROP, LL_INFO100, "ComCallWrapper::Cleanup on Object %8.8x\n", m_ppThis));
+ ClearHandle();
}
m_ppThis = NULL;
diff --git a/src/vm/cominterfacemarshaler.cpp b/src/vm/cominterfacemarshaler.cpp
index 9b9d56a6ff..4a74ddd4d4 100644
--- a/src/vm/cominterfacemarshaler.cpp
+++ b/src/vm/cominterfacemarshaler.cpp
@@ -341,21 +341,10 @@ OBJECTREF COMInterfaceMarshaler::GetCCWObject()
if (m_dwServerSyncBlockIndex != 0)
{
AppDomain* pCurrDomain = m_pThread->GetDomain();
- if (m_dwServerDomainId == pCurrDomain->GetId())
- {
- // if we are in the right AD, we know for sure that the object is still alive
- // since we keep the CCW addref'ed and the AD could not have been unloaded
- oref = ObjectToOBJECTREF(g_pSyncTable[m_dwServerSyncBlockIndex].m_Object);
- }
- else
- {
- // otherwise we have to make sure that the AD hasn't been unloaded
- AppDomainFromIDHolder ad(m_dwServerDomainId, TRUE);
- if (!ad.IsUnloaded())
- {
- oref = ObjectToOBJECTREF(g_pSyncTable[m_dwServerSyncBlockIndex].m_Object);
- }
- }
+
+ // if we are in the right AD, we know for sure that the object is still alive
+ // since we keep the CCW addref'ed
+ oref = ObjectToOBJECTREF(g_pSyncTable[m_dwServerSyncBlockIndex].m_Object);
}
return oref;
diff --git a/src/vm/comsynchronizable.cpp b/src/vm/comsynchronizable.cpp
index 0a6447bd9b..5f54bcda93 100644
--- a/src/vm/comsynchronizable.cpp
+++ b/src/vm/comsynchronizable.cpp
@@ -52,10 +52,9 @@ struct SharedState
MODE_COOPERATIVE;
}
CONTRACTL_END;
- AppDomainFromIDHolder ad(internal->GetKickOffDomainId(), TRUE);
- if (ad.IsUnloaded())
- COMPlusThrow(kAppDomainUnloadedException);
+ AppDomain *ad = SystemDomain::GetAppDomainFromId(internal->GetKickOffDomainId(), ADV_CURRENTAD);
+
m_Threadable = ad->CreateHandle(threadable);
m_ThreadStartArg = ad->CreateHandle(threadStartArg);
@@ -72,17 +71,8 @@ struct SharedState
}
CONTRACTL_END;
- // It's important to have no GC rendez-vous point between the checking and the clean-up below.
- // The three handles below could be in an appdomain which is just starting to be unloaded, or an appdomain
- // which has been unloaded already. Thus, we need to check whether the appdomain is still valid before
- // we do the clean-up. Since we suspend all runtime threads when we try to do the unload, there will be no
- // race condition between the checking and the clean-up as long as this thread cannot be suspended in between.
- AppDomainFromIDHolder ad(m_Internal->GetKickOffDomainId(), TRUE);
- if (!ad.IsUnloaded())
- {
- DestroyHandle(m_Threadable);
- DestroyHandle(m_ThreadStartArg);
- }
+ DestroyHandle(m_Threadable);
+ DestroyHandle(m_ThreadStartArg);
}
};
diff --git a/src/vm/comtoclrcall.cpp b/src/vm/comtoclrcall.cpp
index 2a60f8c2df..df1ba64a8e 100644
--- a/src/vm/comtoclrcall.cpp
+++ b/src/vm/comtoclrcall.cpp
@@ -615,62 +615,13 @@ void COMToCLRWorkerBodyWithADTransition(
BEGIN_SO_INTOLERANT_CODE_NOTHROW(pThread, { *pRetValOut = COR_E_STACKOVERFLOW; return; } );
EX_TRY
{
- bool fNeedToTranslateTAEtoADUE = false;
ADID pTgtDomain = pWrap->GetDomainID();
ENTER_DOMAIN_ID(pTgtDomain)
{
fEnteredDomain = TRUE;
COMToCLRWorkerBody_SOIntolerant(pThread, pFrame, pWrap, pRetValOut);
-
- //
- // Below is some logic adapted from Thread::RaiseCrossContextExceptionHelper, which we now
- // bypass because the IL stub is catching the ThreadAbortException instead of a proper domain
- // transition, where the logic typically resides. This code applies some policy to transform
- // the ThreadAbortException into an AppDomainUnloadedException and sets up the HRESULT and
- // IErrorInfo accordingly.
- //
-
- // If the IL stub caught a TAE...
- if (COR_E_THREADABORTED == ((HRESULT)*pRetValOut))
- {
- // ...first, make sure it was actually an HRESULT return value...
- ComCallMethodDesc* pCMD = pFrame->GetComCallMethodDesc();
- if (pCMD->IsNativeHResultRetVal())
- {
- // There may be multiple AD transitions on the stack so the current unload boundary may
- // not be the transition frame that was set up to make our AD switch. Detect that by
- // comparing the unload boundary's Next with our ComMethodFrame and proceed to translate
- // the exception to ADUE only if they match. Otherwise the exception should stay as TAE.
-
- Frame* pUnloadBoundary = pThread->GetUnloadBoundaryFrame();
- // ...and we are at an unload boundary with a pending unload...
- if ( ( pUnloadBoundary != NULL
- && (pUnloadBoundary->Next() == pFrame
- && pThread->ShouldChangeAbortToUnload(pUnloadBoundary, pUnloadBoundary))
- )
- // ... or we don't have an unload boundary, but we're otherwise unloading
- // this domain from another thread (and we aren't the finalizer)...
- || ( (NULL == pUnloadBoundary)
- && (pThread->GetDomain() == SystemDomain::AppDomainBeingUnloaded())
- && (pThread != SystemDomain::System()->GetUnloadingThread())
- && (pThread != FinalizerThread::GetFinalizerThread())
- )
- )
- {
- // ... we take note and then create an ADUE in the domain we're returning to.
- fNeedToTranslateTAEtoADUE = true;
- }
- }
- }
}
END_DOMAIN_TRANSITION;
-
- if (fNeedToTranslateTAEtoADUE)
- {
- EEResourceException ex(kAppDomainUnloadedException, W("Remoting_AppDomainUnloaded_ThreadUnwound"));
- OBJECTREF oEx = CLRException::GetThrowableFromException(&ex);
- *pRetValOut = SetupErrorInfo(oEx, pFrame->GetComCallMethodDesc());
- }
}
EX_CATCH
{
diff --git a/src/vm/corhost.cpp b/src/vm/corhost.cpp
index ef99dec970..f9785ab19f 100644
--- a/src/vm/corhost.cpp
+++ b/src/vm/corhost.cpp
@@ -1180,48 +1180,7 @@ HRESULT CorRuntimeHostBase::UnloadAppDomain2(DWORD dwDomainId, BOOL fWaitUntilDo
}
CONTRACTL_END;
- HRESULT hr = S_OK;
-
- // No point going further if the runtime is not running...
- {
- // In IsRuntimeActive, we will call CanRunManagedCode that will
- // check if the current thread has taken the loader lock or not,
- // if MDA is supported. To do the check, MdaLoaderLock::ReportViolation
- // will be invoked that will internally end up invoking
- // MdaFactory<MdaXmlElement>::GetNext that will use the "new" operator
- // that has the "FAULT" contract set, resulting in FAULT_VIOLATION since
- // this method has the FORBID_FAULT contract set above.
- //
- // However, for a thread that holds the loader lock, unloading the appDomain is
- // not a supported scenario. Thus, we should not be ending up in this code
- // path for the FAULT violation.
- //
- // Hence, the CONTRACT_VIOLATION below for overriding the FORBID_FAULT
- // for this scope only.
- CONTRACT_VIOLATION(FaultViolation);
- if (!IsRuntimeActive()
- || !m_fStarted
- )
- {
- return HOST_E_CLRNOTAVAILABLE;
- }
- }
-
- BEGIN_ENTRYPOINT_NOTHROW;
-
- // We do not use BEGIN_EXTERNAL_ENTRYPOINT here because
- // we do not want to setup Thread. Process may be OOM, and we want Unload
- // to work.
- hr = AppDomain::UnloadById(ADID(dwDomainId), fWaitUntilDone);
-
- END_ENTRYPOINT_NOTHROW;
-
- if (pLatchedExitCode)
- {
- *pLatchedExitCode = GetLatchedExitCode();
- }
-
- return hr;
+ return COR_E_CANNOTUNLOADAPPDOMAIN;
}
//*****************************************************************************
@@ -1924,18 +1883,11 @@ public:
BEGIN_ENTRYPOINT_NOTHROW;
SystemDomain::LockHolder lh;
- AppDomainFromIDHolder pAppDomain((ADID)dwAppDomainId, TRUE, AppDomainFromIDHolder::SyncType_ADLock);
- if (!pAppDomain.IsUnloaded())
+ AppDomain* pAppDomain = SystemDomain::GetAppDomainFromId((ADID)dwAppDomainId, ADV_CURRENTAD);
+ if (pBytesAllocated)
{
- if (pBytesAllocated)
- {
- *pBytesAllocated = pAppDomain->GetAllocBytes();
- }
- }
- else
- {
- hr = COR_E_APPDOMAINUNLOADED;
+ *pBytesAllocated = pAppDomain->GetAllocBytes();
}
END_ENTRYPOINT_NOTHROW;
@@ -1959,22 +1911,15 @@ public:
BEGIN_ENTRYPOINT_NOTHROW;
SystemDomain::LockHolder lh;
- AppDomainFromIDHolder pAppDomain((ADID)dwAppDomainId, TRUE, AppDomainFromIDHolder::SyncType_ADLock);
- if (pAppDomain.IsUnloaded())
+ AppDomain* pAppDomain = SystemDomain::GetAppDomainFromId((ADID)dwAppDomainId, ADV_CURRENTAD);
+ if (pAppDomainBytesSurvived)
{
- hr = COR_E_APPDOMAINUNLOADED;
+ *pAppDomainBytesSurvived = pAppDomain->GetSurvivedBytes();
}
- else
+ if (pTotalBytesSurvived)
{
- if (pAppDomainBytesSurvived)
- {
- *pAppDomainBytesSurvived = pAppDomain->GetSurvivedBytes();
- }
- if (pTotalBytesSurvived)
- {
- *pTotalBytesSurvived = SystemDomain::GetTotalSurvivedBytes();
- }
+ *pTotalBytesSurvived = SystemDomain::GetTotalSurvivedBytes();
}
END_ENTRYPOINT_NOTHROW;
@@ -2000,20 +1945,10 @@ public:
{
SystemDomain::LockHolder lh;
+ AppDomain* pAppDomain = SystemDomain::GetAppDomainFromId((ADID)dwAppDomainId, ADV_CURRENTAD);
+ if (pMilliseconds)
{
- AppDomainFromIDHolder pAppDomain((ADID)dwAppDomainId, TRUE, AppDomainFromIDHolder::SyncType_ADLock);
-
- if (!pAppDomain.IsUnloaded())
- {
- if (pMilliseconds)
- {
- *pMilliseconds = pAppDomain->QueryProcessorUsage() / 10000;
- }
- }
- else
- {
- hr = COR_E_APPDOMAINUNLOADED;
- }
+ *pMilliseconds = pAppDomain->QueryProcessorUsage() / 10000;
}
}
diff --git a/src/vm/delegateinfo.h b/src/vm/delegateinfo.h
index 80a69a63c3..8bc21b0155 100644
--- a/src/vm/delegateinfo.h
+++ b/src/vm/delegateinfo.h
@@ -43,17 +43,12 @@ struct DelegateInfo
CONTRACTL_END;
- AppDomainFromIDHolder ad(m_appDomainId, FALSE);
- if (!ad.IsUnloaded())
- {
- if (m_stateHandle)
- DestroyHandle(m_stateHandle);
- if (m_eventHandle)
- DestroyHandle(m_eventHandle);
- if (m_registeredWaitHandle)
- DestroyHandle(m_registeredWaitHandle);
- }
-
+ if (m_stateHandle)
+ DestroyHandle(m_stateHandle);
+ if (m_eventHandle)
+ DestroyHandle(m_eventHandle);
+ if (m_registeredWaitHandle)
+ DestroyHandle(m_registeredWaitHandle);
}
#endif
diff --git a/src/vm/dispatchinfo.cpp b/src/vm/dispatchinfo.cpp
index f7b3068428..393c2aaf95 100644
--- a/src/vm/dispatchinfo.cpp
+++ b/src/vm/dispatchinfo.cpp
@@ -3315,8 +3315,7 @@ DispatchMemberInfo* DispatchExInfo::CreateDispatchMemberInfoInstance(DISPID Disp
DispatchMemberInfo* pInfo = new DispatchMemberInfo(this, DispID, strMemberName, MemberInfoObj);
- AppDomainFromIDHolder pDomain(m_pSimpleWrapperOwner->GetDomainID(), FALSE);
- pDomain.ThrowIfUnloaded();
+ AppDomain* pDomain = SystemDomain::GetAppDomainFromId(m_pSimpleWrapperOwner->GetDomainID(), ADV_CURRENTAD);
pInfo->SetHandle(pDomain->CreateHandle(MemberInfoObj));
diff --git a/src/vm/dllimportcallback.cpp b/src/vm/dllimportcallback.cpp
index 2becba5bfe..c064872981 100644
--- a/src/vm/dllimportcallback.cpp
+++ b/src/vm/dllimportcallback.cpp
@@ -106,70 +106,6 @@ private:
static UMEntryThunkFreeList s_thunkFreeList(DEFAULT_THUNK_FREE_LIST_THRESHOLD);
-EXTERN_C void STDCALL UM2MThunk_WrapperHelper(void *pThunkArgs,
- int argLen,
- void *pAddr,
- UMEntryThunk *pEntryThunk,
- Thread *pThread);
-
-// This is used as target of callback from DoADCallBack. It sets up the environment and effectively
-// calls back into the thunk that needed to switch ADs.
-void UM2MThunk_Wrapper(LPVOID ptr) // UM2MThunk_Args
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
- STATIC_CONTRACT_SO_INTOLERANT;
-
- UM2MThunk_Args *pArgs = (UM2MThunk_Args *) ptr;
- Thread* pThread = GetThread();
-
- BEGIN_CALL_TO_MANAGED();
-
- // return value is saved to pArgs->pThunkArgs
- UM2MThunk_WrapperHelper(pArgs->pThunkArgs,
- pArgs->argLen,
- pArgs->pAddr,
- pArgs->pEntryThunk,
- pThread);
-
- END_CALL_TO_MANAGED();
-}
-
-EXTERN_C void STDCALL UM2MDoADCallBack(UMEntryThunk *pEntryThunk,
- void *pAddr,
- void *pArgs,
- int argLen)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- ENTRY_POINT;
- PRECONDITION(CheckPointer(pEntryThunk));
- PRECONDITION(CheckPointer(pArgs));
- }
- CONTRACTL_END;
-
- UM2MThunk_Args args = { pEntryThunk, pAddr, pArgs, argLen };
-
-
- INSTALL_MANAGED_EXCEPTION_DISPATCHER;
- INSTALL_UNWIND_AND_CONTINUE_HANDLER;
- {
- AppDomainFromIDHolder domain(pEntryThunk->GetDomainId(),FALSE);
- domain.ThrowIfUnloaded();
- if(!domain->CanReversePInvokeEnter())
- COMPlusThrow(kNotSupportedException);
- }
-
- GetThread()->DoADCallBack(pEntryThunk->GetDomainId(), UM2MThunk_Wrapper, &args);
-
- UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
- UNINSTALL_MANAGED_EXCEPTION_DISPATCHER;
-}
-
#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL)
EXTERN_C VOID __cdecl UMThunkStubRareDisable();
@@ -198,10 +134,6 @@ VOID UMEntryThunk::CompileUMThunkWorker(UMThunkStubInfo *pInfo,
CodeLabel* pRejoinThreadLabel = pcpusl->NewCodeLabel();
CodeLabel* pDisableGCLabel = pcpusl->NewCodeLabel();
CodeLabel* pRejoinGCLabel = pcpusl->NewCodeLabel();
- CodeLabel* pDoADCallBackLabel = pcpusl->NewCodeLabel();
- CodeLabel* pDoneADCallBackLabel = pcpusl->NewCodeLabel();
- CodeLabel* pADCallBackEpilog = pcpusl->NewCodeLabel();
- CodeLabel* pDoADCallBackStartLabel = pcpusl->NewAbsoluteCodeLabel();
// We come into this code with UMEntryThunk in EAX
const X86Reg kEAXentryThunk = kEAX;
@@ -318,22 +250,6 @@ VOID UMEntryThunk::CompileUMThunkWorker(UMThunkStubInfo *pInfo,
// lea ebx, [ebp + 8]
pcpusl->X86EmitIndexLea(kEBX, kEBP, 8);
- // Load pThread->m_pDomain into edx
- // mov edx,[ecx + offsetof(Thread, m_pAppDomain)]
- pcpusl->X86EmitIndexRegLoad(kEDX, kECXthread, Thread::GetOffsetOfAppDomain());
-
- // Load pThread->m_pAppDomain->m_dwId into edx
- // mov edx,[edx + offsetof(AppDomain, m_dwId)]
- pcpusl->X86EmitIndexRegLoad(kEDX, kEDX, AppDomain::GetOffsetOfId());
-
- // check if the app domain of the thread matches that of delegate
- // cmp edx,[eax + offsetof(UMEntryThunk, m_dwDomainId))]
- pcpusl->X86EmitOffsetModRM(0x3b, kEDX, kEAXentryThunk, offsetof(UMEntryThunk, m_dwDomainId));
-
- // jne pWrongAppDomain ; mismatch. This will call back into the stub with the
- // correct AppDomain through DoADCallBack
- pcpusl->X86EmitCondJump(pDoADCallBackLabel, X86CondCode::kJNE);
-
//
// ----------------------------------------------------------------------------------------------
//
@@ -376,14 +292,6 @@ VOID UMEntryThunk::CompileUMThunkWorker(UMThunkStubInfo *pInfo,
// +-------------------------+
//
- // It's important that the "restart" after an AppDomain switch will skip
- // the check for g_TrapReturningThreads. That's because, during shutdown,
- // we can only go through the UMThunkStubRareDisable pathway if we have
- // not yet pushed a frame. (Once pushed, the frame cannot be popped
- // without coordinating with the GC. During shutdown, such coordination
- // would deadlock).
- pcpusl->EmitLabel(pDoADCallBackStartLabel);
-
// save the thread pointer
pcpusl->X86EmitPushReg(kECXthread);
@@ -564,33 +472,13 @@ VOID UMEntryThunk::CompileUMThunkWorker(UMThunkStubInfo *pInfo,
// restore the thread pointer
pcpusl->X86EmitPopReg(kECXthread);
-
- // Check whether we got here via the switch AD case. We can tell this by looking at whether the
- // caller's arguments immediately precede our EBP frame (they will for the non-switch case but
- // otherwise we will have pushed several frames in the interim). If we did switch now is the time
- // to jump to our inner epilog which will clean up the inner stack frame and return to the runtime
- // AD switching code.
-
- // Does EBX (argument pointer) == EBP + 8?
- // sub ebx, 8
- pcpusl->X86EmitSubReg(kEBX, 8);
-
- // cmp ebx, ebp
- pcpusl->X86EmitR2ROp(0x3B, kEBX, kEBP);
-
- // jne pADCallBackEpilog
- pcpusl->X86EmitCondJump(pADCallBackEpilog, X86CondCode::kJNE);
-
//
// Once we reach this point in the code we're back to a single scenario: the outer frame of the
- // reverse p/invoke. Either we never had to switch AppDomains or the AD switch code has already
- // unwound and returned here to pop off the outer frame.
+ // reverse p/invoke.
//
// ----------------------------------------------------------------------------------------------
//
- pcpusl->EmitLabel(pDoneADCallBackLabel);
-
// move byte ptr [ecx + Thread.m_fPreemptiveGCDisabled],0
pcpusl->X86EmitOffsetModRM(0xc6, (X86Reg)0, kECXthread, Thread::GetOffsetOfGCFlag());
pcpusl->Emit8(0);
@@ -693,47 +581,6 @@ VOID UMEntryThunk::CompileUMThunkWorker(UMThunkStubInfo *pInfo,
pcpusl->X86EmitNearJump(pRejoinGCLabel);
//-------------------------------------------------------------
- // coming here if appdomain didn't match
- //
-
- pcpusl->EmitLabel(pDoADCallBackLabel);
-
- // we will call DoADCallBack which calls into managed code to switch ADs and then calls us
- // back. So when come in the second time the ADs will match and just keep processing.
- // So we need to setup the parms to pass to DoADCallBack one of which is an address inside
- // the stub that will branch back to the top of the stub to start again. Need to setup
- // the parms etc so that when we return from the 2nd call we pop things properly.
-
- // save thread pointer
- pcpusl->X86EmitPushReg(kECXthread);
-
- // push values for UM2MThunk_Args
-
- // Move address of args (EBX) into EDX since some paths below use EBX.
- pcpusl->X86EmitMovRegReg(kEDX, kEBX);
-
- // size of args
- pcpusl->X86EmitPushImm32(pInfo->m_cbSrcStack);
-
- // address of args
- pcpusl->X86EmitPushReg(kEDX);
-
- // addr to call
- pcpusl->X86EmitPushImm32(*pDoADCallBackStartLabel);
-
- // UMEntryThunk
- pcpusl->X86EmitPushReg(kEAXentryThunk);
-
- // call UM2MDoADCallBack
- pcpusl->X86EmitCall(pcpusl->NewExternalCodeLabel((LPVOID) UM2MDoADCallBack), 8);
-
- // We need to clear the thread off the top of the stack and place it in ECX. Two birds with one stone.
- pcpusl->X86EmitPopReg(kECX);
-
- // Re-join the original stub to perform the last parts of the epilog.
- pcpusl->X86EmitNearJump(pDoneADCallBackLabel);
-
- //-------------------------------------------------------------
// Coming here for rare case when enabling GC pre-emptive mode
//
@@ -751,15 +598,6 @@ VOID UMEntryThunk::CompileUMThunkWorker(UMThunkStubInfo *pInfo,
// return to mainline of function
pcpusl->X86EmitNearJump(pEnableRejoin);
-
- //-------------------------------------------------------------
- // Coming here when we switched AppDomain and have successfully called the target. We must return
- // into the runtime code (which will eventually unwind the AD transition and return us to the
- // mainline stub in order to run the outer epilog).
- //
-
- pcpusl->EmitLabel(pADCallBackEpilog);
- pcpusl->X86EmitReturn(0);
}
// Compiles an unmanaged to managed thunk for the given signature.
@@ -1105,15 +943,6 @@ void STDCALL UMEntryThunk::DoRunTimeInit(UMEntryThunk* pUMEntryThunk)
// exceptions don't leak out into managed code.
INSTALL_UNWIND_AND_CONTINUE_HANDLER;
- // The thread object is guaranteed to have been set up at this point.
- Thread *pThread = GetThread();
-
- if (pThread->GetDomain()->GetId() != pUMEntryThunk->GetDomainId())
- {
- // call ourselves again through DoCallBack with a domain transition
- pThread->DoADCallBack(pUMEntryThunk->GetDomainId(), RunTimeInit_Wrapper, pUMEntryThunk);
- }
- else
{
GCX_PREEMP();
pUMEntryThunk->RunTimeInit();
diff --git a/src/vm/domainfile.cpp b/src/vm/domainfile.cpp
index ded1e5715b..2a1b5e5fea 100644
--- a/src/vm/domainfile.cpp
+++ b/src/vm/domainfile.cpp
@@ -37,24 +37,6 @@
#include "perfmap.h"
#endif // FEATURE_PERFMAP
-BOOL DomainAssembly::IsUnloading()
-{
- WRAPPER_NO_CONTRACT;
- SUPPORTS_DAC;
-
- BOOL fIsUnloading = FALSE;
-
- fIsUnloading = this->GetAppDomain()->IsUnloading();
-
- if (!fIsUnloading)
- {
- fIsUnloading = m_fDebuggerUnloadStarted;
- }
-
- return fIsUnloading;
-}
-
-
#ifndef DACCESS_COMPILE
DomainFile::DomainFile(AppDomain *pDomain, PEFile *pFile)
: m_pDomain(pDomain),
@@ -1379,11 +1361,7 @@ BOOL DomainFile::PropagateNewActivation(Module *pModuleFrom, Module *pModuleTo)
while (ai.Next())
{
STRESS_LOG3(LF_LOADER, LL_INFO100,"Attempting to propagate domain-neutral conditional module dependency %p -> %p to AppDomain %i\n",pModuleFrom,pModuleTo,ai.GetDomain()->GetId().m_dwId);
- // This is to minimize the chances of trying to run code in an appdomain that's shutting down.
- if (ai.GetDomain()->CanThreadEnter(pThread))
- {
- completed &= PropagateActivationInAppDomain(pModuleFrom,pModuleTo,ai.GetDomain());
- }
+ completed &= PropagateActivationInAppDomain(pModuleFrom,pModuleTo,ai.GetDomain());
}
}
else
diff --git a/src/vm/domainfile.h b/src/vm/domainfile.h
index 070c616ecb..58706518c7 100644
--- a/src/vm/domainfile.h
+++ b/src/vm/domainfile.h
@@ -709,7 +709,6 @@ public:
BOOL IsVisibleToDebugger();
BOOL NotifyDebuggerLoad(int flags, BOOL attaching);
void NotifyDebuggerUnload();
- BOOL IsUnloading();
inline BOOL IsCollectible();
//
diff --git a/src/vm/eeconfig.cpp b/src/vm/eeconfig.cpp
index 37864f1f83..0b3e413a0e 100644
--- a/src/vm/eeconfig.cpp
+++ b/src/vm/eeconfig.cpp
@@ -345,7 +345,6 @@ HRESULT EEConfig::Init()
#ifdef _DEBUG
fShouldInjectFault = 0;
testThreadAbort = 0;
- testADUnload = 0;
#endif
#ifdef FEATURE_COMINTEROP
@@ -1175,7 +1174,6 @@ HRESULT EEConfig::sync()
fShouldInjectFault = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_InjectFault);
testThreadAbort = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_HostTestThreadAbort);
- testADUnload = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_HostTestADUnload);
#endif //_DEBUG
diff --git a/src/vm/eeconfig.h b/src/vm/eeconfig.h
index 60d8b70157..68f160edea 100644
--- a/src/vm/eeconfig.h
+++ b/src/vm/eeconfig.h
@@ -822,7 +822,6 @@ public:
GCPollType GetGCPollType() { LIMITED_METHOD_CONTRACT; return iGCPollType; }
#ifdef _DEBUG
- DWORD GetHostTestADUnload() const {LIMITED_METHOD_CONTRACT; return testADUnload;}
DWORD GetHostTestThreadAbort() const {LIMITED_METHOD_CONTRACT; return testThreadAbort;}
@@ -1100,7 +1099,6 @@ private: //----------------------------------------------------------------
#ifdef _DEBUG
DWORD fShouldInjectFault;
- DWORD testADUnload;
DWORD testThreadAbort;
#endif
diff --git a/src/vm/eepolicy.cpp b/src/vm/eepolicy.cpp
index efa5fc0667..4cd4d0a03c 100644
--- a/src/vm/eepolicy.cpp
+++ b/src/vm/eepolicy.cpp
@@ -682,47 +682,6 @@ EPolicyAction EEPolicy::DetermineResourceConstraintAction(Thread *pThread)
return action;
}
-
-void EEPolicy::PerformADUnloadAction(EPolicyAction action, BOOL haveStack, BOOL forStackOverflow)
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
-
- STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::PerformADUnloadAction\n");
-
- Thread *pThread = GetThread();
-
- AppDomain *pDomain = GetAppDomain();
-
- if (!IsFinalizerThread())
- {
- int count = 0;
- Frame *pFrame = pThread->GetFirstTransitionInto(GetAppDomain(), &count);
- {
- pThread->SetUnloadBoundaryFrame(pFrame);
- }
- }
-
- pDomain->EnableADUnloadWorker(action==eUnloadAppDomain? ADU_Safe : ADU_Rude);
- // Can't perform a join when we are handling a true SO. We need to enable the unload woker but let the thread continue running
- // through EH processing so that we can recover the stack and reset the guard page.
- if (haveStack)
- {
- pThread->SetAbortRequest(action==eUnloadAppDomain? EEPolicy::TA_V1Compatible : EEPolicy::TA_Rude);
- if (forStackOverflow)
- {
- OBJECTREF exceptObj = CLRException::GetPreallocatedRudeThreadAbortException();
- pThread->SetAbortInitiated();
- RaiseTheExceptionInternalOnly(exceptObj, FALSE, TRUE);
- }
-
- OBJECTREF exceptObj = CLRException::GetPreallocatedThreadAbortException();
- pThread->SetAbortInitiated();
- RaiseTheExceptionInternalOnly(exceptObj, FALSE, FALSE);
- }
-}
-
void EEPolicy::PerformResourceConstraintAction(Thread *pThread, EPolicyAction action, UINT exitCode, BOOL haveStack)
{
WRAPPER_NO_CONTRACT;
@@ -740,13 +699,6 @@ void EEPolicy::PerformResourceConstraintAction(Thread *pThread, EPolicyAction ac
case eRudeAbortThread:
pThread->UserAbort(Thread::TAR_Thread, TA_Rude, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
break;
- case eUnloadAppDomain:
- case eRudeUnloadAppDomain:
- {
- GCX_ASSERT_COOP();
- PerformADUnloadAction(action,haveStack);
- }
- break;
case eExitProcess:
case eFastExitProcess:
case eRudeExitProcess:
@@ -985,12 +937,6 @@ void EEPolicy::HandleStackOverflow(StackOverflowDetector detector, void * pLimit
// But here we know that if we have only one page, we will only update states of the Domain.
CONTRACT_VIOLATION(SOToleranceViolation);
- // Mark the current domain requested for rude unload
- if (!fInDefaultDomain)
- {
- pCurrentDomain->EnableADUnloadWorker(ADU_Rude, FALSE);
- }
-
pThread->PrepareThreadForSOWork();
pThread->MarkThreadForAbort(
@@ -1051,13 +997,6 @@ void EEPolicy::HandleSoftStackOverflow(BOOL fSkipDebugger)
{
Thread* pThread = GetThread();
- if (pThread && pThread->PreemptiveGCDisabled())
- {
- // Mark the current domain requested for rude unload
- GCX_ASSERT_COOP();
- EEPolicy::PerformADUnloadAction(eRudeUnloadAppDomain, TRUE, TRUE);
- }
-
// We are leaving VM boundary, either entering managed code, or entering
// non-VM unmanaged code.
// We should not throw internal C++ exception. Instead we throw an exception
@@ -1608,20 +1547,6 @@ void EEPolicy::HandleCodeContractFailure(LPCWSTR pMessage, LPCWSTR pCondition, L
case eRudeAbortThread:
pThread->UserAbort(Thread::TAR_Thread, TA_Rude, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
break;
- case eUnloadAppDomain:
- // Register an appdomain unload, which starts on a separate thread.
- IfFailThrow(AppDomain::UnloadById(pCurrentDomain->GetId(), FALSE));
- // Don't continue execution on this thread.
- pThread->UserAbort(Thread::TAR_Thread, TA_Safe, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
- break;
- case eRudeUnloadAppDomain:
- pCurrentDomain->SetRudeUnload();
- // Register an appdomain unload, which starts on a separate thread.
- IfFailThrow(AppDomain::UnloadById(pCurrentDomain->GetId(), FALSE));
- // Don't continue execution on this thread.
- pThread->UserAbort(Thread::TAR_Thread, TA_Rude, GetEEPolicy()->GetTimeout(OPR_ThreadAbort), Thread::UAC_Normal);
- break;
-
case eExitProcess: // Merged w/ default case
default:
_ASSERTE(action == eExitProcess);
diff --git a/src/vm/eepolicy.h b/src/vm/eepolicy.h
index 44e0073754..9ca09bb67b 100644
--- a/src/vm/eepolicy.h
+++ b/src/vm/eepolicy.h
@@ -112,8 +112,6 @@ public:
static void PerformResourceConstraintAction(Thread *pThread, EPolicyAction action, UINT exitCode, BOOL haveStack);
- static void PerformADUnloadAction(EPolicyAction action, BOOL haveStack, BOOL forStackOverflow = FALSE);
-
static void HandleOutOfMemory();
static void HandleStackOverflow(StackOverflowDetector detector, void * pLimitFrame);
diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp
index be83f1c7a4..6179b6c561 100644
--- a/src/vm/eventtrace.cpp
+++ b/src/vm/eventtrace.cpp
@@ -4804,20 +4804,17 @@ VOID ETW::LoaderLog::DomainUnload(AppDomain *pDomain)
TRACE_LEVEL_INFORMATION,
KEYWORDZERO))
{
- if(!pDomain->NoAccessToHandleTable())
- {
- DWORD enumerationOptions = ETW::EnumerationLog::GetEnumerationOptionsFromRuntimeKeywords();
-
- // Domain unload also causes type unload events
- if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context,
- TRACE_LEVEL_INFORMATION,
- CLR_TYPE_KEYWORD))
- {
- enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::TypeUnload;
- }
+ DWORD enumerationOptions = ETW::EnumerationLog::GetEnumerationOptionsFromRuntimeKeywords();
- ETW::EnumerationLog::EnumerationHelper(NULL, pDomain, enumerationOptions);
+ // Domain unload also causes type unload events
+ if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context,
+ TRACE_LEVEL_INFORMATION,
+ CLR_TYPE_KEYWORD))
+ {
+ enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::TypeUnload;
}
+
+ ETW::EnumerationLog::EnumerationHelper(NULL, pDomain, enumerationOptions);
}
} EX_CATCH { } EX_END_CATCH(SwallowAllExceptions);
}
@@ -7006,21 +7003,8 @@ VOID ETW::EnumerationLog::IterateAppDomain(AppDomain * pAppDomain, DWORD enumera
// ensure the App Domain does not get finalized until we're all done
SystemDomain::LockHolder lh;
- if (pAppDomain->IsFinalized())
- {
- return;
- }
-
- // Since we're not FINALIZED yet, the handle table should remain intact,
- // as should all type information in this AppDomain
- _ASSERTE(!pAppDomain->NoAccessToHandleTable());
-
// Now it's safe to do the iteration
IterateDomain(pAppDomain, enumerationOptions);
-
- // Since we're holding the system domain lock, the AD type info should be
- // there throughout the entire iteration we just did
- _ASSERTE(!pAppDomain->NoAccessToHandleTable());
}
/********************************************************************************/
diff --git a/src/vm/finalizerthread.cpp b/src/vm/finalizerthread.cpp
index 62816ebacb..9e2e8d06e2 100644
--- a/src/vm/finalizerthread.cpp
+++ b/src/vm/finalizerthread.cpp
@@ -29,8 +29,6 @@ ULONGLONG FinalizerThread::LastHeapDumpTime = 0;
Volatile<BOOL> g_TriggerHeapDump = FALSE;
#endif // __linux__
-AppDomain * FinalizerThread::UnloadingAppDomain;
-
CLREvent * FinalizerThread::hEventFinalizer = NULL;
CLREvent * FinalizerThread::hEventFinalizerDone = NULL;
CLREvent * FinalizerThread::hEventShutDownToFinalizer = NULL;
@@ -143,7 +141,7 @@ Object * FinalizerThread::DoOneFinalization(Object* fobj, Thread* pThread,int bi
AppDomain* targetAppDomain = fobj->GetAppDomain();
AppDomain* currentDomain = pThread->GetDomain();
- if (! targetAppDomain || ! targetAppDomain->CanThreadEnter(pThread))
+ if (! targetAppDomain)
{
// if can't get into domain to finalize it, then it must be agile so finalize in current domain
targetAppDomain = currentDomain;
@@ -151,48 +149,39 @@ Object * FinalizerThread::DoOneFinalization(Object* fobj, Thread* pThread,int bi
if (targetAppDomain == currentDomain)
{
- if (!targetAppDomain->IsRudeUnload() ||
- fobj->GetMethodTable()->HasCriticalFinalizer())
+ class ResetFinalizerStartTime
{
- class ResetFinalizerStartTime
+ public:
+ ResetFinalizerStartTime()
{
- public:
- ResetFinalizerStartTime()
+ if (CLRHosted())
{
- if (CLRHosted())
- {
- g_ObjFinalizeStartTime = CLRGetTickCount64();
- }
- }
- ~ResetFinalizerStartTime()
- {
- if (g_ObjFinalizeStartTime)
- {
- g_ObjFinalizeStartTime = 0;
- }
- }
- };
+ g_ObjFinalizeStartTime = CLRGetTickCount64();
+ }
+ }
+ ~ResetFinalizerStartTime()
{
- ThreadLocaleHolder localeHolder;
-
+ if (g_ObjFinalizeStartTime)
{
- ResetFinalizerStartTime resetTime;
- CallFinalizer(fobj);
+ g_ObjFinalizeStartTime = 0;
}
}
- pThread->InternalReset(FALSE);
+ };
+ {
+ ThreadLocaleHolder localeHolder;
+
+ {
+ ResetFinalizerStartTime resetTime;
+ CallFinalizer(fobj);
+ }
}
+ pThread->InternalReset(FALSE);
}
else
{
- if (! targetAppDomain->GetDefaultContext())
- {
- // Can no longer enter domain becuase the handle containing the context has been
- // destroyed so just bail. Should only get this if are at the stage of nuking the
- // handles in the domain if it's still open.
- _ASSERTE(targetAppDomain->IsUnloading() && targetAppDomain->ShouldHaveFinalization());
- }
- else if (!currentDomain->IsDefaultDomain())
+ _ASSERTE(targetAppDomain->GetDefaultContext());
+
+ if (!currentDomain->IsDefaultDomain())
{
// this means we are in some other domain, so need to return back out through the DoADCallback
// and handle the object from there in another domain.
@@ -239,10 +228,6 @@ Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck)
if (fobj == NULL)
{
- if (AppDomain::HasWorkForFinalizerThread())
- {
- return NULL;
- }
fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable();
}
@@ -264,10 +249,6 @@ Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck)
if (fobj->GetHeader()->GetBits() & bitToCheck)
{
- if (AppDomain::HasWorkForFinalizerThread())
- {
- return NULL;
- }
fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable();
}
else
@@ -281,10 +262,6 @@ Object * FinalizerThread::FinalizeAllObjects(Object* fobj, int bitToCheck)
if (fobj == NULL)
{
- if (AppDomain::HasWorkForFinalizerThread())
- {
- return NULL;
- }
fobj = GCHeapUtilities::GetGCHeap()->GetNextFinalizable();
}
}
@@ -621,44 +598,9 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args)
GetFinalizerThread()->EEResetAbort(Thread::TAR_ALL);
}
FastInterlockExchange ((LONG*)&g_FinalizerIsRunning, TRUE);
- AppDomain::EnableADUnloadWorkerForFinalizer();
-
- do
- {
- FinalizeAllObjects(NULL, 0);
- _ASSERTE(GetFinalizerThread()->GetDomain()->IsDefaultDomain());
- if (AppDomain::HasWorkForFinalizerThread())
- {
- AppDomain::ProcessUnloadDomainEventOnFinalizeThread();
- }
- else if (UnloadingAppDomain == NULL)
- break;
- else if (!GCHeapUtilities::GetGCHeap()->FinalizeAppDomain(UnloadingAppDomain, !!fRunFinalizersOnUnload))
- {
- break;
- }
- // Now schedule any objects from an unloading app domain for finalization
- // on the next pass (even if they are reachable.)
- // Note that it may take several passes to complete the unload, if new objects are created during
- // finalization.
- }
- while(TRUE);
-
- if (UnloadingAppDomain != NULL)
- {
- SyncBlockCache::GetSyncBlockCache()->CleanupSyncBlocksInAppDomain(UnloadingAppDomain);
- {
- // Before we continue with AD unloading, mark the stage as
- // FINALIZED under the SystemDomain lock so that this portion
- // of unloading may be serialized with other parts of the CLR
- // that require the AD stage to be < FINALIZED, in particular
- // ETW's AD enumeration code used during its rundown events.
- SystemDomain::LockHolder lh;
- UnloadingAppDomain->SetFinalized(); // All finalizers have run except for FinalizableAndAgile objects
- }
- UnloadingAppDomain = NULL;
- }
+ FinalizeAllObjects(NULL, 0);
+ _ASSERTE(GetFinalizerThread()->GetDomain()->IsDefaultDomain());
FastInterlockExchange ((LONG*)&g_FinalizerIsRunning, FALSE);
// We may still have the finalizer thread for abort. If so the abort request is for previous finalizer method, not for next one.
@@ -1006,7 +948,7 @@ void FinalizerThread::FinalizerThreadWait(DWORD timeout)
if (status == WAIT_TIMEOUT)
{
ULONGLONG finalizeStartTime = GetObjFinalizeStartTime();
- if (finalizeStartTime || AppDomain::HasWorkForFinalizerThread())
+ if (finalizeStartTime)
{
if (CLRGetTickCount64() >= finalizeStartTime+timeout)
{
diff --git a/src/vm/finalizerthread.h b/src/vm/finalizerthread.h
index be684514b5..bb1cfe4a74 100644
--- a/src/vm/finalizerthread.h
+++ b/src/vm/finalizerthread.h
@@ -10,7 +10,6 @@ class FinalizerThread
{
static BOOL fRunFinalizersOnUnload;
static BOOL fQuitFinalizer;
- static AppDomain *UnloadingAppDomain;
#if defined(__linux__) && defined(FEATURE_EVENT_TRACE)
static ULONGLONG LastHeapDumpTime;
@@ -60,20 +59,6 @@ public:
return g_pFinalizerThread;
}
- // Start unloading app domain
- static void UnloadAppDomain(AppDomain *pDomain, BOOL fRunFinalizers)
- {
- LIMITED_METHOD_CONTRACT;
- UnloadingAppDomain = pDomain;
- fRunFinalizersOnUnload = fRunFinalizers;
- }
-
- static AppDomain* GetUnloadingAppDomain()
- {
- LIMITED_METHOD_CONTRACT;
- return UnloadingAppDomain;
- }
-
static BOOL IsCurrentThreadFinalizer();
static void EnableFinalization();
diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp
index 3dd22dafdf..34645b302c 100644
--- a/src/vm/gcenv.ee.cpp
+++ b/src/vm/gcenv.ee.cpp
@@ -193,9 +193,6 @@ void GCToEEInterface::GcStartWork (int condemned, int max_gen)
}
CONTRACTL_END;
- // Update AppDomain stage here.
- SystemDomain::System()->ProcessClearingDomains();
-
#ifdef VERIFY_HEAP
// Validate byrefs pinned by IL stubs since the last GC.
StubHelpers::ProcessByrefValidationList();
@@ -1450,14 +1447,14 @@ bool GCToEEInterface::AppDomainCanAccessHandleTable(uint32_t appDomainID)
ADIndex index(appDomainID);
AppDomain *pDomain = SystemDomain::GetAppDomainAtIndex(index);
- return (pDomain != NULL) && !pDomain->NoAccessToHandleTable();
+ return (pDomain != NULL);
}
uint32_t GCToEEInterface::GetIndexOfAppDomainBeingUnloaded()
{
LIMITED_METHOD_CONTRACT;
- return SystemDomain::IndexOfAppDomainBeingUnloaded().m_dwIndex;
+ return 0xFFFFFFFF;
}
uint32_t GCToEEInterface::GetTotalNumSizedRefHandles()
@@ -1472,8 +1469,7 @@ bool GCToEEInterface::AppDomainIsRudeUnload(void *appDomain)
{
LIMITED_METHOD_CONTRACT;
- AppDomain *realPtr = static_cast<AppDomain *>(appDomain);
- return realPtr->IsRudeUnload() != FALSE;
+ return false;
}
bool GCToEEInterface::AnalyzeSurvivorsRequested(int condemnedGeneration)
diff --git a/src/vm/gchandleutilities.cpp b/src/vm/gchandleutilities.cpp
index 4361778fb9..220445a1cc 100644
--- a/src/vm/gchandleutilities.cpp
+++ b/src/vm/gchandleutilities.cpp
@@ -18,7 +18,6 @@ void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex)
// Access to a handle in an unloaded domain is not allowed
assert(domain != nullptr);
- assert(!domain->NoAccessToHandleTable());
#endif // _DEBUG_IMPL
}
@@ -36,12 +35,6 @@ void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef)
IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
ADIndex appDomainIndex = ADIndex(reinterpret_cast<DWORD>(mgr->GetHandleContext(handle)));
- AppDomain *unloadingDomain = SystemDomain::AppDomainBeingUnloaded();
- if (unloadingDomain && unloadingDomain->GetIndex() == appDomainIndex && unloadingDomain->NoAccessToHandleTable())
- {
- _ASSERTE (!"Access to a handle in unloaded domain is not allowed");
- }
-
ValidateObjectAndAppDomain(objRef, appDomainIndex);
#endif // _DEBUG_IMPL
}
diff --git a/src/vm/i386/asmconstants.h b/src/vm/i386/asmconstants.h
index 70f6e30c4a..e17cec7227 100644
--- a/src/vm/i386/asmconstants.h
+++ b/src/vm/i386/asmconstants.h
@@ -175,7 +175,7 @@ ASMCONSTANTS_C_ASSERT(CORINFO_ArgumentException_ASM == CORINFO_ArgumentException
#ifndef CROSSGEN_COMPILE
// from clr/src/vm/threads.h
-#define Thread_m_Context 0x38
+#define Thread_m_Context 0x34
ASMCONSTANTS_C_ASSERT(Thread_m_Context == offsetof(Thread, m_Context))
#define Thread_m_State 0x04
@@ -193,10 +193,10 @@ ASMCONSTANTS_C_ASSERT(Thread_m_pFrame == offsetof(Thread, m_pFrame))
#endif // CROSSGEN_COMPILE
#ifndef CROSSGEN_COMPILE
-#define Thread_m_dwLockCount 0x18
+#define Thread_m_dwLockCount 0x14
ASMCONSTANTS_C_ASSERT(Thread_m_dwLockCount == offsetof(Thread, m_dwLockCount))
-#define Thread_m_ThreadId 0x1C
+#define Thread_m_ThreadId 0x18
ASMCONSTANTS_C_ASSERT(Thread_m_ThreadId == offsetof(Thread, m_ThreadId))
#ifdef FEATURE_HIJACK
@@ -338,7 +338,7 @@ ASMCONSTANTS_C_ASSERT(UMThunkMarshInfo__m_cbRetPop == offsetof(UMThunkMarshInfo,
#endif //FEATURE_STUBS_AS_IL
#ifndef CROSSGEN_COMPILE
-#define Thread__m_pDomain 0x14
+#define Thread__m_pDomain 0x10
ASMCONSTANTS_C_ASSERT(Thread__m_pDomain == offsetof(Thread, m_pDomain));
#endif
diff --git a/src/vm/i386/asmhelpers.S b/src/vm/i386/asmhelpers.S
index 2052088f51..09fb50266f 100644
--- a/src/vm/i386/asmhelpers.S
+++ b/src/vm/i386/asmhelpers.S
@@ -555,28 +555,6 @@ LEAF_ENTRY PrecodeFixupThunk, _TEXT
jmp C_FUNC(ThePreStub)
LEAF_END PrecodeFixupThunk, _TEXT
-// void __stdcall UM2MThunk_WrapperHelper(void *pThunkArgs,
-// int argLen,
-// void *pAddr,
-// UMEntryThunk *pEntryThunk,
-// Thread *pThread)
-NESTED_ENTRY UM2MThunk_WrapperHelper, _TEXT, NoHandler
- push ebx
-
- mov eax, [esp + 20] // pEntryThunk
- mov ecx, [esp + 24] // pThread
- mov ebx, [esp + 8] // pThunkArgs
-
- sub esp, 8
- CHECK_STACK_ALIGNMENT
- call [esp + 16 + 8] // pAddr
- add esp, 8
-
- pop ebx
-
- ret 20
-NESTED_END UM2MThunk_WrapperHelper, _TEXT
-
NESTED_ENTRY UMThunkStubRareDisable, _TEXT, NoHandler
push eax
push ecx
diff --git a/src/vm/i386/asmhelpers.asm b/src/vm/i386/asmhelpers.asm
index 17d521fb92..18b5c6eb98 100644
--- a/src/vm/i386/asmhelpers.asm
+++ b/src/vm/i386/asmhelpers.asm
@@ -926,31 +926,6 @@ getFPReturn4:
retn 8
_getFPReturn@8 endp
-; void __stdcall UM2MThunk_WrapperHelper(void *pThunkArgs,
-; int argLen,
-; void *pAddr,
-; UMEntryThunk *pEntryThunk,
-; Thread *pThread)
-UM2MThunk_WrapperHelper proc stdcall public,
- pThunkArgs : DWORD,
- argLen : DWORD,
- pAddr : DWORD,
- pEntryThunk : DWORD,
- pThread : DWORD
- UNREFERENCED argLen
-
- push ebx
-
- mov eax, pEntryThunk
- mov ecx, pThread
- mov ebx, pThunkArgs
- call pAddr
-
- pop ebx
-
- ret
-UM2MThunk_WrapperHelper endp
-
; VOID __cdecl UMThunkStubRareDisable()
;<TODO>
; @todo: this is very similar to StubRareDisable
diff --git a/src/vm/loaderallocator.cpp b/src/vm/loaderallocator.cpp
index 77f0c9e3c1..cb5f81752d 100644
--- a/src/vm/loaderallocator.cpp
+++ b/src/vm/loaderallocator.cpp
@@ -1550,7 +1550,7 @@ BOOL AppDomainLoaderAllocator::CanUnload()
SO_TOLERANT;
} CONTRACTL_END;
- return m_Id.GetAppDomain()->CanUnload();
+ return FALSE;
}
BOOL AssemblyLoaderAllocator::CanUnload()
@@ -1750,7 +1750,6 @@ void AssemblyLoaderAllocator::CleanupHandles()
CONTRACTL_END;
_ASSERTE(GetDomain()->IsAppDomain());
- _ASSERTE(!GetDomain()->AsAppDomain()->NoAccessToHandleTable());
// This method doesn't take a lock around RemoveHead because it's supposed to
// be called only from Terminate
diff --git a/src/vm/marshalnative.cpp b/src/vm/marshalnative.cpp
index 133cbf9069..2ce0bdaa4c 100644
--- a/src/vm/marshalnative.cpp
+++ b/src/vm/marshalnative.cpp
@@ -2256,13 +2256,10 @@ FCIMPL2(void, MarshalNative::ChangeWrapperHandleStrength, Object* orefUNSAFE, CL
if (pWrap == NULL)
COMPlusThrowOM();
- AppDomainFromIDHolder pDomain(pWrap->GetDomainID(), FALSE);
- pDomain.ThrowIfUnloaded();
if (fIsWeak != 0)
pWrap->MarkHandleWeak();
else
pWrap->ResetHandleStrength();
- pDomain.Release();
}
HELPER_METHOD_FRAME_END();
diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp
index a768ded29b..53a0be79a5 100644
--- a/src/vm/methodtable.cpp
+++ b/src/vm/methodtable.cpp
@@ -10075,7 +10075,7 @@ BOOL MethodTable::Validate()
NOINLINE BYTE *MethodTable::GetLoaderAllocatorObjectForGC()
{
WRAPPER_NO_CONTRACT;
- if (!Collectible() || ((PTR_AppDomain)GetLoaderModule()->GetDomain())->NoAccessToHandleTable())
+ if (!Collectible())
{
return NULL;
}
diff --git a/src/vm/nativeoverlapped.cpp b/src/vm/nativeoverlapped.cpp
index 94e61c63fd..f808496657 100644
--- a/src/vm/nativeoverlapped.cpp
+++ b/src/vm/nativeoverlapped.cpp
@@ -107,7 +107,7 @@ FCIMPL1(LPOVERLAPPED, AllocateNativeOverlapped, OverlappedDataObject* overlapped
g_pOverlappedDataClass = MscorlibBinder::GetClass(CLASS__OVERLAPPEDDATA);
// We have optimization to avoid creating event if IO is in default domain. This depends on default domain
// can not be unloaded.
- _ASSERTE(IsSingleAppDomain() || !SystemDomain::System()->DefaultDomain()->CanUnload());
+ _ASSERTE(IsSingleAppDomain());
_ASSERTE(SystemDomain::System()->DefaultDomain()->GetId().m_dwId == DefaultADID);
}
diff --git a/src/vm/object.cpp b/src/vm/object.cpp
index a0427cdcb9..ca54ba2848 100644
--- a/src/vm/object.cpp
+++ b/src/vm/object.cpp
@@ -244,12 +244,6 @@ TypeHandle Object::GetGCSafeTypeHandleIfPossible() const
Module * pLoaderModule = pMTToCheck->GetLoaderModule();
BaseDomain * pBaseDomain = pLoaderModule->GetDomain();
- if ((pBaseDomain != NULL) &&
- (pBaseDomain->IsAppDomain()) &&
- (pBaseDomain->AsAppDomain()->IsUnloading()))
- {
- return NULL;
- }
// Don't look up types that are unloading due to Collectible Assemblies. Haven't been
// able to find a case where we actually encounter objects like this that can cause
diff --git a/src/vm/profilingenumerators.cpp b/src/vm/profilingenumerators.cpp
index a6b0a640f1..b5c1e57b60 100644
--- a/src/vm/profilingenumerators.cpp
+++ b/src/vm/profilingenumerators.cpp
@@ -177,33 +177,16 @@ HRESULT IterateAppDomains(CallbackObject * callbackObj,
// AD available in catch-up enumeration
// < AppDomainCreationFinished issued
// < AD NOT available from catch-up enumeration
- // < AppDomainShutdownStarted issued
//
// The AppDomainIterator constructor parameter m_bActive is set to be TRUE below,
- // meaning only AppDomains in the range [STAGE_ACTIVE;STAGE_CLOSED) will be included
+ // meaning only AppDomains in stage STAGE_ACTIVE or higher will be included
// in the iteration.
// * AppDomainCreationFinished (with S_OK hrStatus) is issued once the AppDomain
// reaches STAGE_ACTIVE.
- // * AppDomainShutdownStarted is issued while the AppDomain is in STAGE_EXITED,
- // just before it hits STAGE_FINALIZING. (STAGE_EXITED < STAGE_CLOSED)
- // * To prevent AppDomains from appearing in the enumeration after we would have
- // sent the AppDomainShutdownStarted event for them, we must add an
- // additional check in the enumeration loop to exclude ADs such that
- // pAppDomain->IsUnloading() (i.e., > STAGE_UNLOAD_REQUESTED). Thus, for an
- // AD for which AppDomainShutdownStarted callback is issued, we have AD >=
- // STAGE_EXITED > STAGE_UNLOAD_REQUESTED, and thus, that AD will be excluded
- // by the pAppDomain->IsUnloading() check.
AppDomainIterator appDomainIterator(TRUE);
while (appDomainIterator.Next())
{
AppDomain * pAppDomain = appDomainIterator.GetDomain();
- if (pAppDomain->IsUnloading())
- {
- // Must skip app domains that are in the process of unloading, to ensure
- // the rules around which entities the profiler should find in the
- // enumeration. See code:#ProfilerEnumAppDomains for details.
- continue;
- }
// Of course, the AD could start unloading here, but if it does we're guaranteed
// the profiler has had a chance to see the Unload callback for the AD, and thus
@@ -271,9 +254,6 @@ HRESULT IterateUnsharedModules(AppDomain * pAppDomain,
// * AssemblyLoadFinished is issued once the Assembly reaches
// code:FILE_LOAD_LOADLIBRARY
// * AssemblyUnloadStarted is issued as a result of either:
- // * AppDomain unloading. In this case such assemblies / modules would be
- // excluded by the AD iterator above, because it excludes ADs if
- // pAppDomain->IsUnloading()
// * Collectible assemblies unloading. Such assemblies will no longer be
// enumerable.
//
diff --git a/src/vm/stackprobe.cpp b/src/vm/stackprobe.cpp
index fd0488c222..6663300e90 100644
--- a/src/vm/stackprobe.cpp
+++ b/src/vm/stackprobe.cpp
@@ -93,14 +93,6 @@ void SOTolerantCode_RecoverStack(DWORD dwFlags)
{
pThread->DisablePreemptiveGC();
}
- // PerformADUnloadAction is SO_INTOLERANT, but we might be
- // calling BEGIN_SO_TOLERANT_CODE from an entry point method
- BEGIN_CONTRACT_VIOLATION(SOToleranceViolation);
- BEGIN_GCX_ASSERT_COOP;
- // We have enough stack now. Start unload
- EEPolicy::PerformADUnloadAction(eRudeUnloadAppDomain, TRUE, TRUE);
- END_GCX_ASSERT_COOP;
- END_CONTRACT_VIOLATION;
}
COMPlusThrowSO();
}
diff --git a/src/vm/stacksampler.cpp b/src/vm/stacksampler.cpp
index d95adb1f63..51e4b9df5d 100644
--- a/src/vm/stacksampler.cpp
+++ b/src/vm/stacksampler.cpp
@@ -195,11 +195,7 @@ ADID StackSampler::GetDomainId(MethodDesc* pMD, const ADID& defaultId)
}
if (bPresent != FALSE)
{
- AppDomainFromIDHolder pDomain(adId, FALSE);
- if (!pDomain.IsUnloaded())
- {
- return adId;
- }
+ return adId;
}
return defaultId;
}
diff --git a/src/vm/stdinterfaces_wrapper.cpp b/src/vm/stdinterfaces_wrapper.cpp
index c33c330798..62657519da 100644
--- a/src/vm/stdinterfaces_wrapper.cpp
+++ b/src/vm/stdinterfaces_wrapper.cpp
@@ -475,11 +475,6 @@ HRESULT __stdcall Unknown_QueryInterface_ICCW(IUnknown *pUnk, REFIID riid, void
SimpleComCallWrapper *pSimpleWrap = pWrap->GetSimpleWrapper();
- AppDomainFromIDHolder ad((ADID)pSimpleWrap->GetRawDomainID(), TRUE);
-
- if (ad.IsUnloaded() || ad->IsUnloading())
- return COR_E_APPDOMAINUNLOADED;
-
//
// For CCWs that have outstanding Jupiter-reference, they could be either:
// 1. Neutered - in this case it is unsafe to touch m_ppThis
diff --git a/src/vm/testhookmgr.cpp b/src/vm/testhookmgr.cpp
index 991b6c64cd..f72f69de43 100644
--- a/src/vm/testhookmgr.cpp
+++ b/src/vm/testhookmgr.cpp
@@ -603,22 +603,7 @@ HRESULT CLRTestHookManager::CheckConfig()
HRESULT CLRTestHookManager::UnloadAppDomain(DWORD adid,DWORD flags)
{
- HRESULT hr = S_OK;
- BEGIN_ENTRYPOINT_NOTHROW;
- // We do not use BEGIN_EXTERNAL_ENTRYPOINT here because
- // we do not want to setup Thread. Process may be OOM, and we want Unload
- // to work.
- if (flags==ADUF_FORCEFULLGC)
- {
- SystemDomain::LockHolder ulh;
- ADID id(adid);
- AppDomainFromIDHolder pApp(id,TRUE,AppDomainFromIDHolder::SyncType_ADLock);//, AppDomainFromIDHolder::SyncType_ADLock);
- if(!pApp.IsUnloaded())
- pApp->SetForceGCOnUnload(TRUE);
- }
- hr = AppDomain::UnloadById(ADID(adid), flags!=ADUF_ASYNCHRONOUS,TRUE);
- END_ENTRYPOINT_NOTHROW;
- return hr;
+ return COR_E_CANNOTUNLOADAPPDOMAIN;
}
VOID CLRTestHookManager::DoAppropriateWait( int cObjs, HANDLE *pObjs, INT32 iTimeout, BOOL bWaitAll, int* res)
diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp
index ddf31f4f5b..9a0ebdc7ca 100644
--- a/src/vm/threads.cpp
+++ b/src/vm/threads.cpp
@@ -1350,9 +1350,6 @@ void CheckADValidity(AppDomain* pDomain, DWORD ADValidityKind)
if ((ADValidityKind & ADV_FINALIZER) &&
IsFinalizerThread())
return;
- if ((ADValidityKind & ADV_ADUTHREAD) &&
- IsADUnloadHelperThread())
- return;
if ((ADValidityKind & ADV_RUNNINGIN) &&
pDomain->IsRunningIn(GetThread()))
return;
@@ -1377,7 +1374,6 @@ Thread::Thread()
CONTRACTL_END;
m_pFrame = FRAME_TOP;
- m_pUnloadBoundaryFrame = NULL;
m_fPreemptiveGCDisabled = 0;
@@ -7438,7 +7434,6 @@ VOID Thread::RestoreGuardPage()
}
FinishSOWork();
- //GetAppDomain()->EnableADUnloadWorker(EEPolicy::ADU_Rude);
INDEBUG(DebugLogStackMBIs());
@@ -7680,8 +7675,7 @@ void MakeCallWithAppDomainTransition(
Thread* _ctx_trans_pThread = GetThread();
TESTHOOKCALL(EnteringAppDomain((TargetDomain.m_dwId)));
- AppDomainFromIDHolder pTargetDomain(TargetDomain, TRUE);
- pTargetDomain.ThrowIfUnloaded();
+ AppDomain* pTargetDomain = SystemDomain::GetAppDomainFromId(TargetDomain, ADV_CURRENTAD);
_ASSERTE(_ctx_trans_pThread != NULL);
_ASSERTE(_ctx_trans_pThread->GetDomain()->GetId()!= TargetDomain);
@@ -7695,7 +7689,6 @@ void MakeCallWithAppDomainTransition(
pTargetDomain->GetDefaultContext(),
_ctx_trans_pFrame);
- pTargetDomain.Release();
args->pCtxFrame = _ctx_trans_pFrame;
TESTHOOKCALL(EnteredAppDomain((TargetDomain.m_dwId)));
/* work around unreachable code warning */
@@ -7809,11 +7802,8 @@ void Thread::DoContextCallBack(ADID appDomain, Context *pContext, Context::ADCal
Context* pCurrDefCtx = pCurrDomain->GetDefaultContext();
BOOL bDefaultTargetCtx=FALSE;
- {
- AppDomainFromIDHolder ad(appDomain, TRUE);
- ad.ThrowIfUnloaded();
- bDefaultTargetCtx=(ad->GetDefaultContext()==pContext);
- }
+ AppDomain* ad = SystemDomain::GetAppDomainFromId(appDomain, ADV_CURRENTAD);
+ bDefaultTargetCtx=(ad->GetDefaultContext()==pContext);
if (pCurrDefCtx == pThread->GetContext() && bDefaultTargetCtx)
{
@@ -7828,156 +7818,6 @@ void Thread::DoContextCallBack(ADID appDomain, Context *pContext, Context::ADCal
LOG((LF_APPDOMAIN, LL_INFO100, "Thread::DoADCallBack Done at esp %p\n", espVal));
}
-
-void Thread::DoADCallBack(AppDomain* pDomain , Context::ADCallBackFcnType pTarget, LPVOID args, DWORD dwADV,
- BOOL fSetupEHAtTransition /* = TRUE */)
-{
-
-
-#ifdef _DEBUG
- TADDR espVal = (TADDR)GetCurrentSP();
-
- LOG((LF_APPDOMAIN, LL_INFO100, "Thread::DoADCallBack Calling %p at esp %p in [%d]\n",
- pTarget, espVal, pDomain->GetId().m_dwId));
-#endif
- Thread* pThread = GetThread();
-
- // Get the default context for the current domain as well as for the
- // destination domain.
- AppDomain* pCurrDomain = pThread->GetContext()->GetDomain();
-
- if (pCurrDomain!=pDomain)
- {
- // use the target domain's default context as the target context
- // so that the actual call to a transparent proxy would enter the object into the correct context.
-
- BOOL fThrow = FALSE;
-
-#ifdef FEATURE_PAL
- // FEATURE_PAL must setup EH at AD transition - the option to omit the setup
- // is only for regular Windows builds.
- _ASSERTE(fSetupEHAtTransition);
-#endif // FEATURE_PAL
-
- LOG((LF_APPDOMAIN, LL_INFO10, "Thread::DoADCallBack - performing AD transition with%s EH at transition boundary.\n",
- (fSetupEHAtTransition == FALSE)?"out":""));
-
- if (fSetupEHAtTransition)
- {
- ENTER_DOMAIN_PTR(pDomain,dwADV)
- {
- (pTarget)(args);
-
- // unloadBoundary is cleared by ReturnToContext, so get it now.
- Frame* unloadBoundaryFrame = pThread->GetUnloadBoundaryFrame();
- fThrow = pThread->ShouldChangeAbortToUnload(GET_CTX_TRANSITION_FRAME(), unloadBoundaryFrame);
- }
- END_DOMAIN_TRANSITION;
- }
-#ifndef FEATURE_PAL
- else
- {
- ENTER_DOMAIN_PTR_NO_EH_AT_TRANSITION(pDomain,dwADV)
- {
- (pTarget)(args);
-
- // unloadBoundary is cleared by ReturnToContext, so get it now.
- Frame* unloadBoundaryFrame = pThread->GetUnloadBoundaryFrame();
- fThrow = pThread->ShouldChangeAbortToUnload(GET_CTX_TRANSITION_FRAME(), unloadBoundaryFrame);
- }
- END_DOMAIN_TRANSITION_NO_EH_AT_TRANSITION;
- }
-#endif // !FEATURE_PAL
-
- // if someone caught the abort before it got back out to the AD transition (like DispatchEx_xxx does)
- // then need to turn the abort into an unload, as they're gonna keep seeing it anyway
- if (fThrow)
- {
- LOG((LF_APPDOMAIN, LL_INFO10, "Thread::DoADCallBack turning abort into unload\n"));
- COMPlusThrow(kAppDomainUnloadedException, W("Remoting_AppDomainUnloaded_ThreadUnwound"));
- }
- }
- else
- {
- UNREACHABLE();
- }
- LOG((LF_APPDOMAIN, LL_INFO100, "Thread::DoADCallBack Done at esp %p\n", espVal));
-}
-
-void Thread::DoADCallBack(ADID appDomainID , Context::ADCallBackFcnType pTarget, LPVOID args, BOOL fSetupEHAtTransition /* = TRUE */)
-{
-
-
-#ifdef _DEBUG
- TADDR espVal = (TADDR)GetCurrentSP();
-
- LOG((LF_APPDOMAIN, LL_INFO100, "Thread::DoADCallBack Calling %p at esp %p in [%d]\n",
- pTarget, espVal, appDomainID.m_dwId));
-#endif
- Thread* pThread = GetThread();
-
- // Get the default context for the current domain as well as for the
- // destination domain.
- AppDomain* pCurrDomain = pThread->GetContext()->GetDomain();
-
- if (pCurrDomain->GetId()!=appDomainID)
- {
- // use the target domain's default context as the target context
- // so that the actual call to a transparent proxy would enter the object into the correct context.
-
- BOOL fThrow = FALSE;
-
-#ifdef FEATURE_PAL
- // FEATURE_PAL must setup EH at AD transition - the option to omit the setup
- // is only for regular Windows builds.
- _ASSERTE(fSetupEHAtTransition);
-#endif // FEATURE_PAL
-
- LOG((LF_APPDOMAIN, LL_INFO10, "Thread::DoADCallBack - performing AD transition with%s EH at transition boundary.\n",
- (fSetupEHAtTransition == FALSE)?"out":""));
-
- if (fSetupEHAtTransition)
- {
- ENTER_DOMAIN_ID(appDomainID)
- {
- (pTarget)(args);
-
- // unloadBoundary is cleared by ReturnToContext, so get it now.
- Frame* unloadBoundaryFrame = pThread->GetUnloadBoundaryFrame();
- fThrow = pThread->ShouldChangeAbortToUnload(GET_CTX_TRANSITION_FRAME(), unloadBoundaryFrame);
- }
- END_DOMAIN_TRANSITION;
- }
-#ifndef FEATURE_PAL
- else
- {
- ENTER_DOMAIN_ID_NO_EH_AT_TRANSITION(appDomainID)
- {
- (pTarget)(args);
-
- // unloadBoundary is cleared by ReturnToContext, so get it now.
- Frame* unloadBoundaryFrame = pThread->GetUnloadBoundaryFrame();
- fThrow = pThread->ShouldChangeAbortToUnload(GET_CTX_TRANSITION_FRAME(), unloadBoundaryFrame);
- }
- END_DOMAIN_TRANSITION_NO_EH_AT_TRANSITION;
- }
-#endif // !FEATURE_PAL
-
- // if someone caught the abort before it got back out to the AD transition (like DispatchEx_xxx does)
- // then need to turn the abort into an unload, as they're gonna keep seeing it anyway
- if (fThrow)
- {
- LOG((LF_APPDOMAIN, LL_INFO10, "Thread::DoADCallBack turning abort into unload\n"));
- COMPlusThrow(kAppDomainUnloadedException, W("Remoting_AppDomainUnloaded_ThreadUnwound"));
- }
- }
- else
- {
- UNREACHABLE();
- }
- LOG((LF_APPDOMAIN, LL_INFO100, "Thread::DoADCallBack Done at esp %p\n", espVal));
-}
-
void Thread::EnterContextRestricted(Context *pContext, ContextTransitionFrame *pFrame)
{
CONTRACTL {
@@ -7996,12 +7836,6 @@ void Thread::EnterContextRestricted(Context *pContext, ContextTransitionFrame *p
// and it should always have an AD set
_ASSERTE(pDomain);
- if (m_pDomain != pDomain && !pDomain->CanThreadEnter(this))
- {
- pFrame->SetReturnContext(NULL);
- COMPlusThrow(kAppDomainUnloadedException);
- }
-
pFrame->SetReturnContext(m_Context);
pFrame->SetReturnExecutionContext(NULL);
@@ -8147,18 +7981,6 @@ void Thread::ReturnToContext(ContextTransitionFrame *pFrame)
EPolicyAction action = GetEEPolicy()->GetActionOnFailure(FAIL_OrphanedLock);
switch (action)
{
- case eUnloadAppDomain:
- if (!pFromDomain->IsDefaultDomain())
- {
- pFromDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
- }
- break;
- case eRudeUnloadAppDomain:
- if (!pFromDomain->IsDefaultDomain())
- {
- pFromDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
- }
- break;
case eExitProcess:
case eFastExitProcess:
case eRudeExitProcess:
@@ -8222,16 +8044,6 @@ void Thread::ReturnToContext(ContextTransitionFrame *pFrame)
m_pDomain = pReturnDomain;
SetAppDomain(pReturnDomain);
- if (pFrame == m_pUnloadBoundaryFrame)
- {
- m_pUnloadBoundaryFrame = NULL;
- if (IsAbortRequested())
- {
- EEResetAbort(TAR_ADUnload);
- }
- ResetBeginAbortedForADUnload();
- }
-
// Restore the last thrown object to what it was before the AD transition. Note that if
// an exception was thrown out of the AD we transitionned into, it will be raised in
// RaiseCrossContextException and the EH system will store it as the last thrown
@@ -8265,18 +8077,6 @@ void Thread::ReturnToContext(ContextTransitionFrame *pFrame)
// _ASSERTE (action == eThrowException || !pReturnDomain->IsDefaultDomain());
switch (action)
{
- case eUnloadAppDomain:
- if (!pReturnDomain->IsDefaultDomain())
- {
- pReturnDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
- }
- break;
- case eRudeUnloadAppDomain:
- if (!pReturnDomain->IsDefaultDomain())
- {
- pReturnDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
- }
- break;
case eExitProcess:
case eFastExitProcess:
case eRudeExitProcess:
@@ -8483,64 +8283,6 @@ AppDomain *Thread::GetInitialDomain()
return pDomain;
}
-#ifndef DACCESS_COMPILE
-void Thread::SetUnloadBoundaryFrame(Frame *pFrame)
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE((this == GetThread() && PreemptiveGCDisabled()) ||
- ThreadStore::HoldingThreadStore());
- if ((ULONG_PTR)m_pUnloadBoundaryFrame < (ULONG_PTR)pFrame)
- {
- m_pUnloadBoundaryFrame = pFrame;
- }
- if (pFrame == NULL)
- {
- ResetBeginAbortedForADUnload();
- }
-}
-
-void Thread::ResetUnloadBoundaryFrame()
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(this == GetThread() && PreemptiveGCDisabled());
- m_pUnloadBoundaryFrame=NULL;
- ResetBeginAbortedForADUnload();
-}
-
-#endif
-
-BOOL Thread::ShouldChangeAbortToUnload(Frame *pFrame, Frame *pUnloadBoundaryFrame)
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- if (! pUnloadBoundaryFrame)
- pUnloadBoundaryFrame = GetUnloadBoundaryFrame();
-
- // turn the abort request into an AD unloaded exception when go past the boundary.
- if (pFrame != pUnloadBoundaryFrame)
- return FALSE;
-
- // Only time have an unloadboundaryframe is when have specifically marked that thread for aborting
- // during unload processing, so this won't trigger UnloadedException if have simply thrown a ThreadAbort
- // past an AD transition frame
- _ASSERTE (IsAbortRequested());
-
- EEResetAbort(TAR_ADUnload);
-
- if (m_AbortType == EEPolicy::TA_None)
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
BOOL Thread::HaveExtraWorkForFinalizer()
{
LIMITED_METHOD_CONTRACT;
@@ -8550,7 +8292,6 @@ BOOL Thread::HaveExtraWorkForFinalizer()
|| ExecutionManager::IsCacheCleanupRequired()
|| Thread::CleanupNeededForFinalizedThread()
|| (m_DetachCount > 0)
- || AppDomain::HasWorkForFinalizerThread()
|| SystemDomain::System()->RequireAppDomainCleanup()
|| ThreadStore::s_pThreadStore->ShouldTriggerGCForDeadThreads();
}
@@ -8573,11 +8314,6 @@ void Thread::DoExtraWorkForFinalizer()
}
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
- if (AppDomain::HasWorkForFinalizerThread())
- {
- AppDomain::ProcessUnloadDomainEventOnFinalizeThread();
- }
-
if (RequireSyncBlockCleanup())
{
#ifndef FEATURE_PAL
@@ -8592,7 +8328,7 @@ void Thread::DoExtraWorkForFinalizer()
}
if (SystemDomain::System()->RequireAppDomainCleanup())
{
- SystemDomain::System()->ProcessDelayedUnloadDomains();
+ SystemDomain::System()->ProcessDelayedUnloadLoaderAllocators();
}
if(m_DetachCount > 0 || Thread::CleanupNeededForFinalizedThread())
@@ -8766,46 +8502,6 @@ protected:
static void ManagedThreadBase_DispatchOuter(ManagedThreadCallState *pCallState);
-
-// Here's the tricky part. *IF and only IF* we took an AppDomain transition at the base, then we
-// now want to push another complete set of handlers above us. The reason is that we want the
-// Watson report and the unhandled exception event to occur in the target AppDomain. If we don't
-// do this apparently redundant push of handlers, then we will marshal back the exception to the
-// handlers on the Default AppDomain side. This will erase all the important exception state by
-// unwinding (catch and rethrow) in DoADCallBack. And it will cause all unhandled exceptions to
-// be reported from the Default AppDomain, which is annoying to any AppDomain.UnhandledException
-// event listeners.
-//
-// So why not skip the handlers that are in the Default AppDomain and just push the ones after the
-// transition? Well, transitioning out of the Default AppDomain into the target AppDomain could
-// fail. We need handlers pushed for that case. And in that case it's perfectly reasonable to
-// report the problem as occurring in the Default AppDomain, which is what the base handlers will
-// do.
-
-static void ManagedThreadBase_DispatchInCorrectAD(LPVOID args)
-{
- CONTRACTL
- {
- GC_TRIGGERS;
- THROWS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- ManagedThreadCallState *pCallState = (ManagedThreadCallState *) args;
-
- // Ensure we aren't going to infinitely recurse.
- _ASSERTE(pCallState->IsAppDomainEqual(GetThread()->GetDomain()));
-
- // And then go round one more time. But this time we want to ensure that the filter contains
- // any exceptions that aren't swallowed. These must be treated as unhandled, rather than
- // propagated through the AppDomain boundary in search of an outer handler. Otherwise we
- // will not get correct Watson behavior.
- pCallState->flags = MTCSF_ContainToAppDomain;
- ManagedThreadBase_DispatchOuter(pCallState);
- pCallState->flags = MTCSF_NormalBase;
-}
-
static void ManagedThreadBase_DispatchInner(ManagedThreadCallState *pCallState)
{
CONTRACTL
@@ -8816,41 +8512,8 @@ static void ManagedThreadBase_DispatchInner(ManagedThreadCallState *pCallState)
}
CONTRACTL_END;
-
- Thread *pThread = GetThread();
-
- if (!pCallState->IsAppDomainEqual(pThread->GetDomain()))
- {
- // On Win7 and later, AppDomain transitions at the threadbase will *not* have EH setup at transition boundary.
- // This implies that an unhandled exception from the base domain (i.e. AD in which the thread starts) will
- // not return to DefDomain but will continue to go up the stack with the thread still being in base domain.
- // We have a holder in ENTER_DOMAIN_*_NO_EH_AT_TRANSITION macro (ReturnToPreviousAppDomainHolder) that will
- // revert AD context at threadbase if an unwind is triggered after the exception has gone unhandled.
- //
- // This also implies that there will be no exception object marshalling (and it may not be required after all)
- // as well and once the holder reverts the AD context, the LastThrownObject in Thread will be set to NULL.
-#ifndef FEATURE_PAL
- BOOL fSetupEHAtTransition = FALSE;
-#else // !FEATURE_PAL
- BOOL fSetupEHAtTransition = TRUE;
-#endif // !FEATURE_PAL
-
- if (pCallState->bDomainIsAsID)
- pThread->DoADCallBack(pCallState->pAppDomainId,
- ManagedThreadBase_DispatchInCorrectAD,
- pCallState, fSetupEHAtTransition);
- else
- pThread->DoADCallBack(pCallState->pUnsafeAppDomain,
- ManagedThreadBase_DispatchInCorrectAD,
- pCallState, ADV_FINALIZER, fSetupEHAtTransition);
- }
- else
- {
- // Since no AppDomain transition is necessary, we need no additional handlers pushed
- // *AFTER* the transition. We now have adequate handlers below us. Go ahead and
- // dispatch the call.
- (*pCallState->pTarget) (pCallState->args);
- }
+ // Go ahead and dispatch the call.
+ (*pCallState->pTarget) (pCallState->args);
}
static void ManagedThreadBase_DispatchMiddle(ManagedThreadCallState *pCallState)
@@ -10758,10 +10421,6 @@ ETaskType GetCurrentTaskType()
{
TaskType = TT_THREADPOOL_WAIT;
}
- else if (type & ThreadType_ADUnloadHelper)
- {
- TaskType = TT_ADUNLOAD;
- }
else if (type & ThreadType_Threadpool_IOCompletion)
{
TaskType = TT_THREADPOOL_IOCOMPLETION;
diff --git a/src/vm/threads.h b/src/vm/threads.h
index e4b6487f55..dc468630f5 100644
--- a/src/vm/threads.h
+++ b/src/vm/threads.h
@@ -448,8 +448,6 @@ inline void CommonTripThread() { }
#define ADV_COMPILATION 0x10
// finalizer thread - synchronized with ADU
#define ADV_FINALIZER 0x40
-// adu thread - cannot race with itself
-#define ADV_ADUTHREAD 0x80
// held by AppDomainRefTaker
#define ADV_REFTAKER 0x100
@@ -1586,7 +1584,6 @@ public:
Volatile<ULONG> m_fPreemptiveGCDisabled;
PTR_Frame m_pFrame; // The Current Frame
- PTR_Frame m_pUnloadBoundaryFrame;
//-----------------------------------------------------------
// If the thread has wandered in from the outside this is
@@ -2012,17 +2009,6 @@ public:
bool DetectHandleILStubsForDebugger();
-#ifndef DACCESS_COMPILE
- void SetUnloadBoundaryFrame(Frame *pFrame);
- void ResetUnloadBoundaryFrame();
-#endif
-
- PTR_Frame GetUnloadBoundaryFrame()
- {
- LIMITED_METHOD_CONTRACT;
- return m_pUnloadBoundaryFrame;
- }
-
void SetWin32FaultAddress(DWORD eip)
{
LIMITED_METHOD_CONTRACT;
@@ -2441,14 +2427,6 @@ public:
return m_Context;
}
-
- // This callback is used when we are executing in the EE and discover that we need
- // to switch appdomains.
- //
- // Set the last parameter to FALSE if you want to perform the AD transition *without*
- // EH (this can affect marshalling of exceptions).
- void DoADCallBack(ADID appDomain , Context::ADCallBackFcnType pTarget, LPVOID args, BOOL fSetupEHAtTransition = TRUE);
- void DoADCallBack(AppDomain* pDomain , Context::ADCallBackFcnType pTarget, LPVOID args, DWORD dwADV, BOOL fSetupEHAtTransition = TRUE);
void DoContextCallBack(ADID appDomain, Context* c , Context::ADCallBackFcnType pTarget, LPVOID args);
// Except for security and the call in from the remoting code in mscorlib, you should never do an
@@ -2544,8 +2522,6 @@ public:
Frame *IsRunningIn(AppDomain* pDomain, int *count);
Frame *GetFirstTransitionInto(AppDomain *pDomain, int *count);
- BOOL ShouldChangeAbortToUnload(Frame *pFrame, Frame *pUnloadBoundaryFrame=NULL);
-
// Get outermost (oldest) AppDomain for this thread.
AppDomain *GetInitialDomain();
@@ -2806,7 +2782,6 @@ public:
enum ThreadAbortRequester
{
TAR_Thread = 0x00000001, // Request by Thread
- TAR_ADUnload = 0x00000002, // Request by AD unload
TAR_FuncEval = 0x00000004, // Request by Func-Eval
TAR_StackOverflow = 0x00000008, // Request by StackOverflow. TAR_THREAD should be set at the same time.
TAR_ALL = 0xFFFFFFFF,
@@ -2828,7 +2803,6 @@ private:
TAI_FuncEvalAbort = 0x00000040,
TAI_FuncEvalV1Abort = 0x00000080,
TAI_FuncEvalRudeAbort = 0x00000100,
- TAI_ForADUnloadThread = 0x10000000, // AD unload thread is working on the thread
};
static const DWORD TAI_AnySafeAbort = (TAI_ThreadAbort |
@@ -2887,14 +2861,6 @@ private:
typedef Holder<Thread*, Thread::AcquireAbortControl, Thread::ReleaseAbortControl> AbortControlHolder;
- BOOL IsBeingAbortedForADUnload()
- {
- LIMITED_METHOD_CONTRACT;
- return (m_AbortInfo & TAI_ForADUnloadThread) != 0;
- }
-
- void ResetBeginAbortedForADUnload();
-
public:
#ifdef _DEBUG
BOOL m_fRudeAborted;
@@ -2965,8 +2931,6 @@ public:
}
BOOL IsRudeAbort();
- BOOL IsRudeAbortOnlyForADUnload();
- BOOL IsRudeUnload();
BOOL IsFuncEvalAbort();
#if defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK)
@@ -6974,19 +6938,16 @@ private:
#define ENTER_DOMAIN_SWITCH_CTX_BY_ADID(_pCurrDomainPtr,_pDestDomainId,_bUnsafePoint) \
AppDomain* _ctx_trans_pCurrDomain=_pCurrDomainPtr; \
_ctx_trans_pDestDomainId=(ADID)_pDestDomainId; \
- BOOL _ctx_trans_bUnsafePoint=_bUnsafePoint; \
if (_ctx_trans_fPredicate && \
(_ctx_trans_pCurrDomain==NULL || \
(_ctx_trans_pCurrDomain->GetId() != _ctx_trans_pDestDomainId))) \
{ \
- AppDomainFromIDHolder _ctx_trans_ad(_ctx_trans_pDestDomainId,_ctx_trans_bUnsafePoint); \
- _ctx_trans_ad.ThrowIfUnloaded(); \
+ AppDomain* _ctx_trans_ad = SystemDomain::GetAppDomainFromId(_ctx_trans_pDestDomainId, ADV_CURRENTAD); \
\
_ctx_trans_ad->EnterContext(_ctx_trans_pThread, \
_ctx_trans_ad->GetDefaultContext(), \
_ctx_trans_pFrame); \
\
- _ctx_trans_ad.Release(); \
_ctx_trans_fTransitioned = true; \
}
@@ -6999,8 +6960,6 @@ private:
{ \
TESTHOOKCALL(AppDomainCanBeUnloaded(_ctx_trans_pDestDomain->GetId().m_dwId,FALSE)); \
GCX_FORBID(); \
- if (!_ctx_trans_pDestDomain->CanThreadEnter(_ctx_trans_pThread)) \
- COMPlusThrow(kAppDomainUnloadedException); \
\
_ctx_trans_pThread->EnterContextRestricted( \
_ctx_trans_pDestDomain->GetDefaultContext(), \
@@ -7089,8 +7048,6 @@ private:
#define ADV_COMPILATION 0x10
// finalizer thread - synchronized with ADU
#define ADV_FINALIZER 0x40
-// adu thread - cannot race with itself
-#define ADV_ADUTHREAD 0x80
// held by AppDomainRefTaker
#define ADV_REFTAKER 0x100
diff --git a/src/vm/threads.inl b/src/vm/threads.inl
index f5a439c350..1c07070068 100644
--- a/src/vm/threads.inl
+++ b/src/vm/threads.inl
@@ -46,14 +46,14 @@ inline void Thread::IncLockCount()
LIMITED_METHOD_CONTRACT;
_ASSERTE(GetThread() == this);
m_dwLockCount++;
- _ASSERTE(m_dwLockCount != 0 || HasThreadStateNC(TSNC_UnbalancedLocks) || GetDomain()->OkToIgnoreOrphanedLocks());
+ _ASSERTE(m_dwLockCount != 0 || HasThreadStateNC(TSNC_UnbalancedLocks));
}
inline void Thread::DecLockCount()
{
LIMITED_METHOD_CONTRACT;
_ASSERTE(GetThread() == this);
- _ASSERTE(m_dwLockCount > 0 || HasThreadStateNC(TSNC_UnbalancedLocks) || GetDomain()->OkToIgnoreOrphanedLocks());
+ _ASSERTE(m_dwLockCount > 0 || HasThreadStateNC(TSNC_UnbalancedLocks));
m_dwLockCount--;
}
@@ -167,8 +167,6 @@ inline void Thread::FinishSOWork()
if (HasThreadStateNC(TSNC_SOWorkNeeded))
{
ResetThreadStateNC(TSNC_SOWorkNeeded);
- // Wake up AD unload thread to finish SO work that is delayed due to limit stack
- AppDomain::EnableADUnloadWorkerForThreadAbort();
}
#else
_ASSERTE(!HasThreadStateNC(TSNC_SOWorkNeeded));
diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp
index 6c761f3da1..abf9597074 100644
--- a/src/vm/threadsuspend.cpp
+++ b/src/vm/threadsuspend.cpp
@@ -639,13 +639,7 @@ void Thread::ClearAbortReason(BOOL pNoLock)
// If there is an OBJECTHANDLE, try to clear it.
if (oh != 0 && adid.m_dwId != 0)
- { // See if the domain is still valid; if so, destroy the ObjectHandle
- AppDomainFromIDHolder ad(adid, TRUE);
- if (!ad.IsUnloaded())
- { // Still a valid domain, so destroy the handle.
- DestroyHandle(oh);
- }
- }
+ DestroyHandle(oh);
}
@@ -1272,31 +1266,6 @@ BOOL Thread::IsRudeAbort()
return (IsAbortRequested() && (m_AbortType == EEPolicy::TA_Rude));
}
-BOOL Thread::IsRudeAbortOnlyForADUnload()
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return (IsAbortRequested() &&
- (m_AbortInfo & TAI_ADUnloadRudeAbort) &&
- !(m_AbortInfo & (TAI_ThreadRudeAbort | TAI_FuncEvalRudeAbort))
- );
-}
-
-BOOL Thread::IsRudeUnload()
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- return (IsAbortRequested() && (m_AbortInfo & TAI_ADUnloadRudeAbort));
-}
-
BOOL Thread::IsFuncEvalAbort()
{
CONTRACTL {
@@ -1451,33 +1420,7 @@ Thread::UserAbort(ThreadAbortRequester requester,
GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
break;
case eUnloadAppDomain:
- {
- AppDomain *pDomain = GetDomain();
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
- }
- }
- // AD unload does not abort finalizer thread.
- if (this != FinalizerThread::GetFinalizerThread())
- {
- if (this == GetThread())
- {
- Join(INFINITE,TRUE);
- }
- return S_OK;
- }
- break;
case eRudeUnloadAppDomain:
- {
- AppDomain *pDomain = GetDomain();
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
- }
- }
// AD unload does not abort finalizer thread.
if (this != FinalizerThread::GetFinalizerThread())
{
@@ -1545,13 +1488,6 @@ Thread::UserAbort(ThreadAbortRequester requester,
m_dwAbortPoint = 1;
#endif
- if (CLRHosted() && GetAbortEndTime() != MAXULONGLONG)
- {
- // ToDo: Skip debugger funcval
- // Use our helper thread to watch abort.
- AppDomain::EnableADUnloadWorkerForThreadAbort();
- }
-
GCX_COOP();
OBJECTREF exceptObj;
@@ -1583,7 +1519,6 @@ Thread::UserAbort(ThreadAbortRequester requester,
{
// A host may call ICLRTask::Abort on a critical thread. We don't want to
// block this thread.
- AppDomain::EnableADUnloadWorkerForThreadAbort();
return S_OK;
}
@@ -2120,14 +2055,6 @@ LPrepareRetry:
SetRudeAbortEndTimeFromEEPolicy();
goto LRetry;
case eUnloadAppDomain:
- {
- AppDomain *pDomain = GetDomain();
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnTimeout(operation1, action1);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
- }
- }
// AD unload does not abort finalizer thread.
if (this == FinalizerThread::GetFinalizerThread())
{
@@ -2146,14 +2073,6 @@ LPrepareRetry:
}
break;
case eRudeUnloadAppDomain:
- {
- AppDomain *pDomain = GetDomain();
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnTimeout(operation1, action1);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
- }
- }
// AD unload does not abort finalizer thread.
if (this == FinalizerThread::GetFinalizerThread())
{
@@ -2285,26 +2204,6 @@ void Thread::ThreadAbortWatchDogEscalate(Thread *pThread)
GetEEPolicy()->NotifyHostOnTimeout(operation,action);
pThread->UserAbort(Thread::TAR_Thread, EEPolicy::TA_Rude, INFINITE, Thread::UAC_WatchDog);
break;
- case eUnloadAppDomain:
- {
- AppDomain *pDomain = pThread->GetDomain();
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnTimeout(operation,action);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
- }
- }
- break;
- case eRudeUnloadAppDomain:
- {
- AppDomain *pDomain = pThread->GetDomain();
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnTimeout(operation,action);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
- }
- }
- break;
case eExitProcess:
case eFastExitProcess:
case eRudeExitProcess:
@@ -2463,26 +2362,6 @@ void Thread::MarkThreadForAbort(ThreadAbortRequester requester, EEPolicy::Thread
}
}
- if (requester & TAR_ADUnload)
- {
- if (abortType == EEPolicy::TA_Safe)
- {
- abortInfo |= TAI_ADUnloadAbort;
- }
- else if (abortType == EEPolicy::TA_Rude)
- {
- abortInfo |= TAI_ADUnloadRudeAbort;
- }
- else if (abortType == EEPolicy::TA_V1Compatible)
- {
- abortInfo |= TAI_ADUnloadV1Abort;
- }
- if (IsADUnloadHelperThread())
- {
- abortInfo |= TAI_ForADUnloadThread;
- }
- }
-
if (requester & TAR_FuncEval)
{
if (abortType == EEPolicy::TA_Safe)
@@ -2534,14 +2413,8 @@ void Thread::MarkThreadForAbort(ThreadAbortRequester requester, EEPolicy::Thread
{
m_RudeAbortEndTime = endTime;
}
- // We can not call into host if we are in the middle of stack overflow.
- // And we don't need to wake up our watchdog if there is no timeout.
- if (GetThread() == this && (requester & TAR_StackOverflow) == 0)
- {
- AppDomain::EnableADUnloadWorkerForThreadAbort();
}
}
- }
if (abortInfo == (m_AbortInfo & abortInfo))
{
@@ -2658,13 +2531,6 @@ void Thread::UnmarkThreadForAbort(ThreadAbortRequester requester, BOOL fForce)
}
}
- if (requester & TAR_ADUnload)
- {
- m_AbortInfo &= ~(TAI_ADUnloadAbort |
- TAI_ADUnloadV1Abort |
- TAI_ADUnloadRudeAbort);
- }
-
if (requester & TAR_FuncEval)
{
m_AbortInfo &= ~(TAI_FuncEvalAbort |
@@ -2718,21 +2584,6 @@ void Thread::UnmarkThreadForAbort(ThreadAbortRequester requester, BOOL fForce)
STRESS_LOG3(LF_APPDOMAIN, LL_ALWAYS, "Unmark Thread %p Thread Id = %x for abort from requester %d\n", this, GetThreadId(), requester);
}
-// Make sure that when AbortRequest bit is cleared, we also dec TrapReturningThreads count.
-void Thread::ResetBeginAbortedForADUnload()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- AbortRequestLockHolder lh(this);
-
- m_AbortInfo &= ~TAI_ForADUnloadThread;
-}
-
void Thread::InternalResetAbort(ThreadAbortRequester requester, BOOL fResetRudeAbort)
{
CONTRACTL {
@@ -2762,7 +2613,7 @@ void Thread::SetAbortRequest(EEPolicy::ThreadAbortTypes abortType)
}
CONTRACTL_END;
- MarkThreadForAbort(TAR_ADUnload, abortType);
+ MarkThreadForAbort(TAR_Thread, abortType);
if (m_State & TS_Interruptible)
{
@@ -3212,26 +3063,6 @@ void Thread::HandleThreadAbortTimeout()
GetEEPolicy()->NotifyHostOnTimeout(operation,action);
MarkThreadForAbort(TAR_Thread, EEPolicy::TA_Rude);
break;
- case eUnloadAppDomain:
- {
- AppDomain *pDomain = GetDomain();
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnTimeout(operation,action);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
- }
- }
- break;
- case eRudeUnloadAppDomain:
- {
- AppDomain *pDomain = GetDomain();
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnTimeout(operation,action);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
- }
- }
- break;
case eExitProcess:
case eFastExitProcess:
case eRudeExitProcess:
@@ -3345,13 +3176,6 @@ void Thread::PreWorkForThreadAbort()
EPolicyAction action = GetEEPolicy()->GetDefaultAction(OPR_ThreadRudeAbortInCriticalRegion, this);
switch (action)
{
- case eRudeUnloadAppDomain:
- if (!pDomain->IsDefaultDomain())
- {
- GetEEPolicy()->NotifyHostOnDefaultAction(OPR_ThreadRudeAbortInCriticalRegion,action);
- pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
- }
- break;
case eExitProcess:
case eFastExitProcess:
case eRudeExitProcess:
diff --git a/src/vm/win32threadpool.h b/src/vm/win32threadpool.h
index 2a3a3bbb24..ddbd34a3c3 100644
--- a/src/vm/win32threadpool.h
+++ b/src/vm/win32threadpool.h
@@ -476,10 +476,7 @@ private:
{
GCX_COOP();
- AppDomainFromIDHolder ad(pDelegate->m_appDomainId, TRUE);
- if (!ad.IsUnloaded())
- // if no domain then handle already gone or about to go.
- StoreObjectInHandle(pDelegate->m_registeredWaitHandle, NULL);
+ StoreObjectInHandle(pDelegate->m_registeredWaitHandle, NULL);
}
}