summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
}
}