Thread * pThread = vmThread.GetDacPtr();
_ASSERTE(pThread != NULL);
- if (CLRTaskHosted())
- {
- return pThread->GetThreadId();
- }
- else
- {
- return pThread->GetOSThreadId();
- }
+ return pThread->GetOSThreadId();
}
// Return the object handle to the managed Exception object of the current exception
//
public:
- // Once we support debugging + fibermode (which was cut in V2.0), we may need some Thread::BeginThreadAffinity() calls
- // associated with the controller lock because this lock wraps context operations.
class ControllerLockHolder : public CrstHolder
{
public:
return fGuardPageGone;
}
-
-// This is called from AppDomainEnumerationIPCBlock::Lock and Unlock
-void BeginThreadAffinityHelper()
-{
- WRAPPER_NO_CONTRACT;
-
- Thread::BeginThreadAffinity();
-}
-void EndThreadAffinityHelper()
-{
- WRAPPER_NO_CONTRACT;
- Thread::EndThreadAffinity();
-}
-
//-----------------------------------------------------------------------------
// LSPTR_XYZ is a type-safe wrapper around an opaque reference type XYZ in the left-side.
// But TypeHandles are value-types that can't be directly converted into a pointer.
return S_OK;
}
-//
-// Wrapper function for debugger to WaitForSingleObject. If CLR is hosted,
-// notify host before we leave runtime.
-//
-DWORD Debugger::WaitForSingleObjectHelper(HANDLE handle, DWORD dwMilliseconds)
-{
- CONTRACTL
- {
- SO_NOT_MAINLINE;
- NOTHROW;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- DWORD dw = 0;
- EX_TRY
- {
-
- // make sure that we let host know that we are leaving runtime.
- LeaveRuntimeHolder holder((size_t)(::WaitForSingleObject));
- dw = ::WaitForSingleObject(handle,dwMilliseconds);
- }
- EX_CATCH
- {
- // Only possibility to enter here is when Thread::LeaveRuntime
- // throws exception.
- dw = WAIT_ABANDONED;
- }
- EX_END_CATCH(SwallowAllExceptions);
- return dw;
-
-}
-
/* ------------------------------------------------------------------------ *
* EE Interface routines
/******************************************************************************
*
* Helper for debugger to get an unique thread id
- * If we are not in Fiber mode, we can safely use OSThreadId
- * Otherwise, we will use our own unique ID.
- *
- * We will return our unique ID when our host is hosting Thread.
- *
*
******************************************************************************/
DWORD Debugger::GetThreadIdHelper(Thread *pThread)
{
WRAPPER_NO_CONTRACT;
- if (!CLRTaskHosted())
- {
- // use the plain old OS Thread ID
- return pThread->GetOSThreadId();
- }
- else
- {
- // use our unique thread ID
- return pThread->GetThreadId();
- }
+ return pThread->GetOSThreadId();
}
//-----------------------------------------------------------------------------
// uninited values.
ZeroMemory(m_pAppDomainCB, sizeof(*m_pAppDomainCB));
- // Fix for issue: whidbey 143061
- // We are creating the mutex as hold, when we unlock, the EndThreadAffinity in
- // hosting case will be unbalanced.
- // Ideally, I would like to fix this by creating mutex not-held and call Lock method.
- // This way, when we clean up the OOM, (as you can tell, we never release the mutex in
- // some error cases), we can change it to holder class.
- //
- Thread::BeginThreadAffinity();
-
// Create a mutex to allow the Left and Right Sides to properly
// synchronize. The Right Side will spin until m_hMutex is valid,
// then it will acquire it before accessing the data.
// now wait for notification from the right side about whether or not
// the out-of-proc debugger is handling ControlC events.
- WaitForSingleObjectHelper(GetCtrlCMutex(), INFINITE);
+ ::WaitForSingleObject(GetCtrlCMutex(), INFINITE);
return GetDebuggerHandlingCtrlC();
}
bool ResumeThreads(AppDomain* pAppDomain);
- static DWORD WaitForSingleObjectHelper(HANDLE handle, DWORD dwMilliseconds);
-
void ProcessAnyPendingEvals(Thread *pThread);
bool HasLazyData();
class AppDomain;
-void BeginThreadAffinityHelper();
-void EndThreadAffinityHelper();
-
-
// AppDomainInfo contains information about an AppDomain
// All pointers are for the left side, and we do not own any of the memory
struct AppDomainInfo
*************************************************************************/
BOOL Lock()
{
- BeginThreadAffinityHelper();
-
DWORD dwRes = WaitForSingleObject(m_hMutex, 3000);
if (dwRes == WAIT_TIMEOUT)
{
// Lock may or may not be valid at this point. Thus Release may fail,
// but we'll just ignore that.
ReleaseMutex(m_hMutex);
- EndThreadAffinityHelper();
-
}
/*************************************************************************
#if defined(MULTIPLE_HEAPS) && !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
// Currently there is no way for us to specific the numa node to allocate on via hosting interfaces to
// a host. This will need to be added later.
+#if !defined(FEATURE_CORECLR)
if (!CLRMemoryHosted())
+#endif
{
if (NumaNodeInfo::CanEnableGCNumaAware())
{
#include <windowsstring.h>
#include "holder.h"
-#ifdef FEATURE_LEAVE_RUNTIME_HOLDER
- #define HR_LEAVE_RUNTIME_HOLDER(X) \
- GCX_PREEMP(); \
- LeaveRuntimeHolderNoThrow lrh(X); \
- if (FAILED(lrh.GetHR())) \
- { \
- return lrh.GetHR(); \
- }
-#else
- #define HR_LEAVE_RUNTIME_HOLDER(X) (void *)0;
-#endif
-
#ifndef IID_INS_ARGS
#define IID_INS_ARGS(ppType) __uuidof(**(ppType)), IID_INS_ARGS_Helper(ppType)
#endif
__deref_out ItfT** ppItf)
{
LIMITED_METHOD_CONTRACT;
- HR_LEAVE_RUNTIME_HOLDER(::RoGetActivationFactory);
+ GCX_PREEMP();
return GetActivationFactory(wzActivatableClassId.Get(), ppItf);
}
__in typename ReleaseHolder<ItfT>& hItf)
{
LIMITED_METHOD_CONTRACT;
- HR_LEAVE_RUNTIME_HOLDER(::RoGetActivationFactory);
+ GCX_PREEMP();
return GetActivationFactory(wzActivatableClassId.Get(), (ItfT**)&hItf);
}
} // namespace winrt
} // namespace clr
#endif //CROSSGEN_COMPILE
-#undef HR_LEAVE_RUNTIME_HOLDER
#endif // WindowsRuntime_h
public static readonly int processorCount = Environment.ProcessorCount;
- public static readonly bool tpHosted = ThreadPool.IsThreadPoolHosted();
-
public static volatile bool vmTpInitialized;
public static bool enableWorkerTracking;
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void NotifyWorkItemProgressNative();
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern bool IsThreadPoolHosted();
-
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
private static extern void InitializeVMTp(ref bool enableWorkerTracking);
include_directories(${ARCH_SOURCES_DIR})
-add_definitions(-DFEATURE_LEAVE_RUNTIME_HOLDER=1)
-
add_definitions(-DUNICODE)
add_definitions(-D_UNICODE)
extern UMThunkStubUnwindFrameChainHandler:proc
extern g_TrapReturningThreads:dword
extern UM2MDoADCallBack:proc
-extern ReverseEnterRuntimeHelper:proc
-extern ReverseLeaveRuntimeHelper:proc
extern UMThunkStubRareDisableWorker:proc
extern ReversePInvokeBadTransition:proc
#ifndef CROSSGEN_COMPILE
ECall::PopulateManagedStringConstructors();
-
- if (CLRIoCompletionHosted())
- {
- g_pOverlappedDataClass = MscorlibBinder::GetClass(CLASS__OVERLAPPEDDATA);
- _ASSERTE (g_pOverlappedDataClass);
- if (CorHost2::GetHostOverlappedExtensionSize() != 0)
- {
- // Overlapped may have an extension if a host hosts IO completion subsystem
- DWORD instanceFieldBytes = g_pOverlappedDataClass->GetNumInstanceFieldBytes() + CorHost2::GetHostOverlappedExtensionSize();
- _ASSERTE (instanceFieldBytes + ObjSizeOf(Object) >= MIN_OBJECT_SIZE);
- DWORD baseSize = (DWORD) (instanceFieldBytes + ObjSizeOf(Object));
- baseSize = (baseSize + ALLOC_ALIGN_CONSTANT) & ~ALLOC_ALIGN_CONSTANT; // m_BaseSize must be aligned
- DWORD adjustSize = baseSize - g_pOverlappedDataClass->GetBaseSize();
- CGCDesc* map = CGCDesc::GetCGCDescFromMT(g_pOverlappedDataClass);
- CGCDescSeries * cur = map->GetHighestSeries();
- _ASSERTE ((SSIZE_T)map->GetNumSeries() == 1);
- cur->SetSeriesSize(cur->GetSeriesSize() - adjustSize);
- g_pOverlappedDataClass->SetBaseSize(baseSize);
- }
- }
#endif // CROSSGEN_COMPILE
g_pExceptionClass = MscorlibBinder::GetClass(CLASS__EXCEPTION);
}
} // ThreadStoreLockHolder
- if (nThreadsNeedMoreWork && CLRTaskHosted())
- {
- // In case a thread is the domain is blocked due to its scheduler being
- // occupied by another thread.
- Thread::ThreadAbortWatchDog();
- }
m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork;
return !nThreadsNeedMoreWork;
}
{
GCX_MAYBE_PREEMP(fOK);
- if (fOK)
- {
- EX_TRY
- {
- if (CLRTaskHosted())
- {
- // ADUnload helper thread is critical. We do not want it to share scheduler
- // with other tasks.
- pThread->LeaveRuntime(0);
- }
- }
- EX_CATCH
- {
- fOK = false;
- }
- EX_END_CATCH(SwallowAllExceptions);
- }
-
_ASSERTE (g_fADUnloadWorkerOK == -2);
FastInterlockExchange((LONG *)&g_fADUnloadWorkerOK,fOK?1:-1);
{
GCX_PREEMP();
- LeaveRuntimeHolder lrh(::RoInitialize);
// Prefer MultiThreaded when AnyThreadedMultiPreferred is specified.
hr = ::RoInitialize((threadingModel == SingleThreaded) ? RO_INIT_SINGLETHREADED
#ifdef FEATURE_PREJIT
- // Initialize the sweeper thread. THis is violating our rules with hosting
- // so we only do it in the non-hosted case
- if (g_pConfig->GetZapBBInstr() != NULL && !CLRTaskHosted())
+ // Initialize the sweeper thread.
+ if (g_pConfig->GetZapBBInstr() != NULL)
{
DWORD threadID;
HANDLE hBBSweepThread = ::CreateThread(NULL,
if (dwReason == DLL_THREAD_DETACH || dwReason == DLL_PROCESS_DETACH)
{
- if (CLRMemoryHosted())
- {
- // A host may not support memory operation inside OS loader lock.
- // We will free these memory on finalizer thread.
- CExecutionEngine::DetachTlsInfo(param.pTlsData);
- }
- else
- {
- CExecutionEngine::ThreadDetaching(param.pTlsData);
- }
+ CExecutionEngine::ThreadDetaching(param.pTlsData);
}
return TRUE;
}
static LPVOID* GetTlsData();
static BOOL SetTlsData (void** ppTlsInfo);
- static BOOL HasDetachedTlsInfo();
-
- static void CleanupDetachedTlsInfo();
-
- static void DetachTlsInfo(void **pTlsData);
-
//***************************************************************************
// private implementation:
//***************************************************************************
EX_TRY
{
- LeaveRuntimeHolderNoThrow lrh((size_t)::SetErrorInfo);
- ::SetErrorInfo(0, pErrorInfo);
- pErrorInfo->Release();
+ ::SetErrorInfo(0, pErrorInfo);
+ pErrorInfo->Release();
// Success in setting the ErrorInfo on the thread
hr = S_OK;
TypeHandle th;
- // If this is the GC thread, and we're hosted, we're in a sticky situation with
- // SQL where we may have suspended another thread while doing Thread::SuspendRuntime.
- // In this case, we have the issue that a thread holding this lock could be
- // suspended, perhaps implicitly because the active thread on the SQL scheduler
- // has been suspended by the GC thread. In such a case, we need to skip taking
- // the lock. We can be sure that there will be no races in such a condition because
- // we will only be looking for types that are already loaded, or for a type that
- // is not loaded, but we will never cause the type to get loaded, and so the result
- // of the lookup will not change.
-#ifndef DACCESS_COMPILE
- if (fCheckUnderLock && !(IsGCThread() && CLRTaskHosted()))
-#else
if (fCheckUnderLock)
-#endif // DACCESS_COMPILE
{
th = LookupTypeKeyUnderLock(pKey, pTable, pLock);
}
else
{
// QI failed, put the IErrorInfo back
- LeaveRuntimeHolderNoThrow lrh((size_t)SetErrorInfo);
- if (SUCCEEDED(lrh.GetHR()))
- {
- SetErrorInfo(0, pErrorInfo);
- }
+ SetErrorInfo(0, pErrorInfo);
}
}
}
EX_TRY
{
- LeaveRuntimeHolder lrHolder(**(size_t**)(IContextCallback*)pCallback);
hr = ((IContextCallback*)pCallback)->ContextCallback(EnterContextCallback, &callBackData, IID_IEnterActivityWithNoLock, 2, NULL);
}
EX_CATCH
LOG((LF_INTEROP, LL_INFO100, "Entering into context 0x08X has failed since the debugger is blocking it\n", m_pCtxCookie));
// put the IErrorInfo back
- {
- LeaveRuntimeHolderNoThrow lrh((size_t)SetErrorInfo);
- if (SUCCEEDED(lrh.GetHR()))
- {
- SetErrorInfo(0, pErrorInfo);
- }
- }
+ SetErrorInfo(0, pErrorInfo);
}
else
{
if (!CanRunManagedCode())
return;
SO_INTOLERANT_CODE_NOTHROW(GetThread(), return; );
- ReverseEnterRuntimeHolderNoThrow REHolder;
- if (CLRTaskHosted())
- {
- HRESULT hr = REHolder.AcquireNoThrow();
- if (FAILED(hr))
- return;
- }
m_pWrap->Cleanup();
}
#include "threads.h"
#include "clrex.inl"
#ifdef FEATURE_COMINTEROP
- // These need to be included *after* threads.h so that they can properly use LeaveRuntimeHolder
#include "windowsruntime.h"
#include "windowsstring.h"
#endif
END_QCALL;
}
-
-FCIMPL0(FC_BOOL_RET, ThreadPoolNative::IsThreadPoolHosted)
-{
- FCALL_CONTRACT;
-
- FCUnique(0x22);
-
- FC_RETURN_BOOL(ThreadpoolMgr::IsThreadPoolHosted());
-}
-FCIMPLEND
-
/*****************************************************************************************************/
struct RegisterWaitForSingleObjectCallback_Args
static FCDECL1(void, ReportThreadStatus, CLR_BOOL isWorking);
- static FCDECL0(FC_BOOL_RET, IsThreadPoolHosted);
-
static FCDECL7(LPVOID, CorRegisterWaitForSingleObject,
Object* waitObjectUNSAFE,
#endif // _TARGET_X86_
-NOINLINE
-void InvokeStub_Hosted(ComCallMethodDesc *pCMD, PCODE pManagedTarget, OBJECTREF orThis, ComMethodFrame *pFrame, Thread *pThread,
- UINT64* pRetValOut)
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(CLRTaskHosted());
-
- ReverseEnterRuntimeHolderNoThrow REHolder;
- HRESULT hr = REHolder.AcquireNoThrow();
- if (FAILED(hr))
- {
- *pRetValOut = hr;
- return;
- }
-
- InvokeStub(pCMD, pManagedTarget, orThis, pFrame, pThread, pRetValOut);
-}
-
#if defined(_MSC_VER) && !defined(_DEBUG)
#pragma optimize("t", on) // optimize for speed
#endif
}
#endif // DEBUGGING_SUPPORTED
-
- if (CLRTaskHosted())
- {
- InvokeStub_Hosted(pCMD, pManagedTarget, pObject, pFrame, pThread, pRetValOut);
- }
- else
- {
- InvokeStub(pCMD, pManagedTarget, pObject, pFrame, pThread, pRetValOut);
- }
+ InvokeStub(pCMD, pManagedTarget, pObject, pFrame, pThread, pRetValOut);
}
bool COMToCLRWorkerBody_SecurityCheck(ComCallMethodDesc * pCMD, MethodDesc * pMD, Thread * pThread, UINT64 * pRetValOut)
}
CONTRACTL_END;
- ReverseEnterRuntimeHolder REHolder(TRUE);
-
IUnknown** pip = (IUnknown **)pFrame->GetPointerToArguments();
IUnknown* pUnk = (IUnknown *)*pip;
_ASSERTE(pUnk != NULL);
BOOL bDaclPresent;
BOOL bDaclDefault;
- LeaveRuntimeHolder holder((size_t)(::GetSecurityDescriptorDacl));
::GetSecurityDescriptorDacl(pSA->lpSecurityDescriptor, &bDaclPresent, &pDefaultACL, &bDaclDefault);
}
EX_CATCH
#endif // FEATURE_IMPLICIT_TLS
-static VolatilePtr<ClrTlsInfo> g_pDetachedTlsInfo;
-
-BOOL CExecutionEngine::HasDetachedTlsInfo()
-{
- LIMITED_METHOD_CONTRACT;
-
- return g_pDetachedTlsInfo.Load() != NULL;
-}
-
-void CExecutionEngine::CleanupDetachedTlsInfo()
-{
- WRAPPER_NO_CONTRACT;
-
- if (g_pDetachedTlsInfo.Load() == NULL)
- {
- return;
- }
- ClrTlsInfo *head = FastInterlockExchangePointer(g_pDetachedTlsInfo.GetPointer(), NULL);
-
- while (head)
- {
- ClrTlsInfo *node = head;
- head = head->next;
- DeleteTLS(node->data);
- }
-}
-
-void CExecutionEngine::DetachTlsInfo(void **pTlsData)
-{
- LIMITED_METHOD_CONTRACT;
-
- if (pTlsData == NULL)
- {
- return;
- }
-
- if (CExecutionEngine::GetTlsData() == pTlsData)
- {
- CExecutionEngine::SetTlsData(0);
- }
-
-#ifdef HAS_FLS_SUPPORT
- if (fHasFlsSupport && pFlsGetValue(FlsIndex) == pTlsData)
- {
- pFlsSetValue(FlsIndex, NULL);
- }
-#endif
-
- ClrTlsInfo *pTlsInfo = DataToClrTlsInfo(pTlsData);
- // PREFIX_ASSUME needs TLS. If we use it here, we may do memory allocation.
-#if defined(_PREFAST_) || defined(_PREFIX_)
- if (pTlsInfo == NULL) __UNREACHABLE();
-#else
- _ASSERTE(pTlsInfo != NULL);
-#endif // _PREFAST_ || _PREFIX_
-
- if (pTlsInfo->data[TlsIdx_StressLog])
- {
-#ifdef STRESS_LOG
- CantAllocHolder caHolder;
- StressLog::ThreadDetach ((ThreadStressLog *)pTlsInfo->data[TlsIdx_StressLog]);
- pTlsInfo->data[TlsIdx_StressLog] = NULL;
-#else
- _ASSERTE (!"Shouldn't have stress log!");
-#endif
- }
-
- while (TRUE)
- {
- ClrTlsInfo *head = g_pDetachedTlsInfo.Load();
- pTlsInfo->next = head;
- if (FastInterlockCompareExchangePointer(g_pDetachedTlsInfo.GetPointer(), pTlsInfo, head) == head)
- {
- return;
- }
- }
-}
-
//---------------------------------------------------------------------------------------
//
// Returns the current logical thread's data block (ClrTlsInfo::data).
// If we have a thread object or are on a non-fiber thread, we are safe for fiber switching.
if (!fHasFlsSupport ||
GetThread() ||
- ((g_fEEStarted || g_fEEInit) && !CLRTaskHosted()) ||
+ (g_fEEStarted || g_fEEInit) ||
(((size_t)pTlsInfo->data[TlsIdx_ThreadType]) & (ThreadType_GC | ThreadType_Gate | ThreadType_Timer | ThreadType_DbgHelper)))
{
#ifdef _DEBUG
{
STATIC_CONTRACT_WRAPPER;
STATIC_CONTRACT_SO_TOLERANT;
- LeaveRuntimeHolder holder((size_t)(::WaitForSingleObject));
return ::WaitForSingleObject(handle,dwMilliseconds);
}
CONTRACTL {
THROWS;
WRAPPER(GC_TRIGGERS);
- } CONTRACTL_END;
-
- // Disallow creation of Crst before EE starts. But only complain if we end up
- // being hosted, since such Crsts have escaped the hosting net and will cause
- // AVs on next use.
-#ifdef _DEBUG
- static bool fEarlyInit; // = false
-
- if (!g_fEEStarted)
- {
- if (!CLRSyncHosted())
- fEarlyInit = true;
- }
-
- // If we are now hosted, we better not have *ever* created some Crsts that are
- // not known to our host.
- _ASSERTE(!fEarlyInit || !CLRSyncHosted());
-
-#endif
+ } CONTRACTL_END;
_ASSERTE((flags & CRST_INITIALIZED) == 0);
}
}
- {
- if (CLRTaskHosted())
- {
- Thread::BeginThreadAffinity();
- }
-
- UnsafeEnterCriticalSection(&m_criticalsection);
-
- }
-
+ UnsafeEnterCriticalSection(&m_criticalsection);
#ifdef _DEBUG
PostEnter();
Thread * pThread = GetThread();
#endif
- {
- UnsafeLeaveCriticalSection(&m_criticalsection);
-
-
- if (CLRTaskHosted()) {
- Thread::EndThreadAffinity();
- }
- }
+ UnsafeLeaveCriticalSection(&m_criticalsection);
// Check for both rare case using one if-check
if (m_dwFlags & (CRST_TAKEN_DURING_SHUTDOWN | CRST_DEBUGGER_THREAD))
UMEntryThunk *pEntryThunk,
Thread *pThread);
-EXTERN_C void __fastcall ReverseEnterRuntimeHelper(Thread *pThread)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- SO_TOLERANT;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // ReverseEnterRuntimeThrowComplus probes.
- //BEGIN_ENTRYPOINT_THROWS;
-
- _ASSERTE (pThread == GetThread());
-
-#ifdef FEATURE_STACK_PROBE
- // The thread is calling into managed code. If we have the following sequence on stack
- // Managed code 1 -> Unmanaged code -> Managed code 2,
- // and we hit SO in managed code 2, in order to unwind stack for managed code 1, we need
- // to make sure the thread is in cooperative gc mode. Due to unmanaged code in between,
- // when we reach managed code 1, the thread is in preemptive GC mode. In order to switch
- // to cooperative, we need to have enough stack. This means that we need to reclaim stack
- // for managed code 2. Therefore we require that we have some amount of stack before entering
- // managed code 2.
- RetailStackProbe(static_cast<UINT>(ADJUST_PROBE(BACKOUT_CODE_STACK_LIMIT)),pThread);
-#endif
- pThread->ReverseEnterRuntimeThrowComplus();
- //END_ENTRYPOINT_THROWS
-}
-
-EXTERN_C void __fastcall ReverseLeaveRuntimeHelper(Thread *pThread)
-{
- WRAPPER_NO_CONTRACT;
-
- _ASSERTE (pThread == GetThread());
- pThread->ReverseLeaveRuntime();
-}
-
#ifdef MDA_SUPPORTED
EXTERN_C void __fastcall CallbackOnCollectedDelegateHelper(UMEntryThunk *pEntryThunk)
{
CONTRACT_VIOLATION(ThrowsViolation);
- LeaveRuntimeHolder holder(reinterpret_cast< size_t >(WaitForSingleObject));
return WaitForSingleObject(handle, timeout);
} // DWORD ClrWaitForSingleObject()
continue;
}
- Thread::BeginThreadAffinity();
// we timed-out waiting for DW to respond.
DWORD dw = WaitForSingleObject(hMutex, DW_TIMEOUT_VALUE);
ReleaseMutex(hMutex);
}
- Thread::EndThreadAffinity();
}
// Go ahead and bail if Watson didn't exit for some reason.
FCFuncElement("GetMaxThreadsNative", ThreadPoolNative::CorGetMaxThreads)
FCFuncElement("NotifyWorkItemComplete", ThreadPoolNative::NotifyRequestComplete)
FCFuncElement("NotifyWorkItemProgressNative", ThreadPoolNative::NotifyRequestProgress)
- FCFuncElement("IsThreadPoolHosted", ThreadPoolNative::IsThreadPoolHosted)
QCFuncElement("InitializeVMTp", ThreadPoolNative::InitializeVMTp)
FCFuncElement("ReportThreadStatus", ThreadPoolNative::ReportThreadStatus)
QCFuncElement("RequestWorkerThread", ThreadPoolNative::RequestWorkerThread)
switch (detector)
{
case SOD_ManagedFrameHandler:
- if (!pThread->PreemptiveGCDisabled() && !fInCLR && fInSoTolerant
- &&
- // Before we call managed code, we probe inside ReverseEnterRuntime for BACKOUT_CODE_STACK_LIMIT pages
- // If we hit hard so here, we are still in our stub
- (!CLRTaskHosted() || (UINT_PTR)pThread->m_pFrame - pThread->GetLastAllowableStackAddress() >=
- ADJUST_PROBE(BACKOUT_CODE_STACK_LIMIT) * OS_PAGE_SIZE)
- )
+ if (!pThread->PreemptiveGCDisabled() && !fInCLR && fInSoTolerant)
{
// Managed exception handler detects SO, but the thread is in preemptive GC mode,
// and the IP is outside CLR. This means we are inside a PINVOKE call.
}
#endif // _DEBUG
- // We need to ReverseLeaveRuntime if we are unwinding (since there is no
- // frame to do this for us...
- if (IS_UNWINDING(pExceptionRecord->ExceptionFlags))
- {
- BYTE bFlag;
-
-#ifdef _TARGET_AMD64_
- bFlag = *(BYTE*)(pDispatcherContext->ContextRecord->Rbp + UMTHUNKSTUB_HOST_NOTIFY_FLAG_RBPOFFSET);
-#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
- // On ARM, we do not need to do anything here. If required, ReverseEnterRuntime should happen
- // in the VM in UMThunkStubWorker via a holder so that during an exceptional case, we will
- // automatically perform the ReverseLeaveRuntime.
- bFlag = 0;
-#else
- bFlag = 0;
- PORTABILITY_ASSERT("NYI -- UMThunkStubUnwindFrameChainHandler notify host of ReverseLeaveRuntime");
-#endif // _TARGET_AMD64_
-
- if (0 != bFlag)
- {
- GetThread()->ReverseLeaveRuntime();
- }
- }
-
EXCEPTION_DISPOSITION disposition = UMThunkUnwindFrameChainHandler(
pExceptionRecord,
MemoryStackFp,
STATIC_CONTRACT_GC_NOTRIGGER;
STATIC_CONTRACT_MODE_ANY;
- if (CLRMemoryHosted() ||
- CLRSyncHosted() ||
- (MHandles[kProfilingAPIAttach] == NULL))
+ if (MHandles[kProfilingAPIAttach] == NULL)
{
return;
}
void FinalizerThread::WaitForFinalizerEvent (CLREvent *event)
{
- // TODO wwl: merge the following two blocks
- if (!CLRMemoryHosted() && !CLRSyncHosted()) {
- // Non-host environment
-
- // We don't want kLowMemoryNotification to starve out kFinalizer
- // (as the latter may help correct the former), and we don't want either
- // to starve out kProfilingAPIAttach, as we want decent responsiveness
- // to a user trying to attach a profiler. So check in this order:
- // kProfilingAPIAttach alone (0 wait)
- // kFinalizer alone (2s wait)
- // all events together (infinite wait)
+ // Non-host environment
+
+ // We don't want kLowMemoryNotification to starve out kFinalizer
+ // (as the latter may help correct the former), and we don't want either
+ // to starve out kProfilingAPIAttach, as we want decent responsiveness
+ // to a user trying to attach a profiler. So check in this order:
+ // kProfilingAPIAttach alone (0 wait)
+ // kFinalizer alone (2s wait)
+ // all events together (infinite wait)
#ifdef FEATURE_PROFAPI_ATTACH_DETACH
- // NULL means check attach event now, and don't worry about how long it was since
- // the last time the event was checked.
- ProcessProfilerAttachIfNecessary(NULL);
+ // NULL means check attach event now, and don't worry about how long it was since
+ // the last time the event was checked.
+ ProcessProfilerAttachIfNecessary(NULL);
#endif // FEATURE_PROFAPI_ATTACH_DETACH
- //give a chance to the finalizer event (2s)
- switch (event->Wait(2000, FALSE))
- {
- case (WAIT_OBJECT_0):
- return;
- case (WAIT_ABANDONED):
- return;
- case (WAIT_TIMEOUT):
- break;
- }
- MHandles[kFinalizer] = event->GetHandleUNHOSTED();
- while (1)
- {
- // WaitForMultipleObjects will wait on the event handles in MHandles
- // starting at this offset
- UINT uiEventIndexOffsetForWait = 0;
+ //give a chance to the finalizer event (2s)
+ switch (event->Wait(2000, FALSE))
+ {
+ case (WAIT_OBJECT_0):
+ return;
+ case (WAIT_ABANDONED):
+ return;
+ case (WAIT_TIMEOUT):
+ break;
+ }
+ MHandles[kFinalizer] = event->GetHandleUNHOSTED();
+ while (1)
+ {
+ // WaitForMultipleObjects will wait on the event handles in MHandles
+ // starting at this offset
+ UINT uiEventIndexOffsetForWait = 0;
- // WaitForMultipleObjects will wait on this number of event handles
- DWORD cEventsForWait = kHandleCount;
-
- // #MHandleTypeValues:
- // WaitForMultipleObjects will now wait on a subset of the events in the
- // MHandles array. At this point kFinalizer should have a non-NULL entry
- // in the array. Wait on the following events:
- //
- // * kLowMemoryNotification (if it's non-NULL && g_fEEStarted)
- // * kFinalizer (always)
- // * kProfilingAPIAttach (if it's non-NULL)
- //
- // The enum code:MHandleType values become important here, as
- // WaitForMultipleObjects needs to wait on a contiguous set of non-NULL
- // entries in MHandles, so we'll assert the values are contiguous as we
- // expect.
- _ASSERTE(kLowMemoryNotification == 0);
- _ASSERTE((kFinalizer == 1) && (MHandles[1] != NULL));
+ // WaitForMultipleObjects will wait on this number of event handles
+ DWORD cEventsForWait = kHandleCount;
+
+ // #MHandleTypeValues:
+ // WaitForMultipleObjects will now wait on a subset of the events in the
+ // MHandles array. At this point kFinalizer should have a non-NULL entry
+ // in the array. Wait on the following events:
+ //
+ // * kLowMemoryNotification (if it's non-NULL && g_fEEStarted)
+ // * kFinalizer (always)
+ // * kProfilingAPIAttach (if it's non-NULL)
+ //
+ // The enum code:MHandleType values become important here, as
+ // WaitForMultipleObjects needs to wait on a contiguous set of non-NULL
+ // entries in MHandles, so we'll assert the values are contiguous as we
+ // expect.
+ _ASSERTE(kLowMemoryNotification == 0);
+ _ASSERTE((kFinalizer == 1) && (MHandles[1] != NULL));
#ifdef FEATURE_PROFAPI_ATTACH_DETACH
- _ASSERTE(kProfilingAPIAttach == 2);
+ _ASSERTE(kProfilingAPIAttach == 2);
#endif //FEATURE_PROFAPI_ATTACH_DETACH
- // Exclude the low-memory notification event from the wait if the event
- // handle is NULL or the EE isn't fully started up yet.
- if ((MHandles[kLowMemoryNotification] == NULL) || !g_fEEStarted)
- {
- uiEventIndexOffsetForWait = kLowMemoryNotification + 1;
- cEventsForWait--;
- }
+ // Exclude the low-memory notification event from the wait if the event
+ // handle is NULL or the EE isn't fully started up yet.
+ if ((MHandles[kLowMemoryNotification] == NULL) || !g_fEEStarted)
+ {
+ uiEventIndexOffsetForWait = kLowMemoryNotification + 1;
+ cEventsForWait--;
+ }
#ifdef FEATURE_PROFAPI_ATTACH_DETACH
- // Exclude kProfilingAPIAttach if it's NULL
- if (MHandles[kProfilingAPIAttach] == NULL)
- {
- cEventsForWait--;
- }
+ // Exclude kProfilingAPIAttach if it's NULL
+ if (MHandles[kProfilingAPIAttach] == NULL)
+ {
+ cEventsForWait--;
+ }
#endif //FEATURE_PROFAPI_ATTACH_DETACH
- switch (WaitForMultipleObjectsEx(
- cEventsForWait, // # objects to wait on
- &(MHandles[uiEventIndexOffsetForWait]), // array of objects to wait on
- FALSE, // bWaitAll == FALSE, so wait for first signal
+ switch (WaitForMultipleObjectsEx(
+ cEventsForWait, // # objects to wait on
+ &(MHandles[uiEventIndexOffsetForWait]), // array of objects to wait on
+ FALSE, // bWaitAll == FALSE, so wait for first signal
#if defined(__linux__) && defined(FEATURE_EVENT_TRACE)
- LINUX_HEAP_DUMP_TIME_OUT,
+ LINUX_HEAP_DUMP_TIME_OUT,
#else
- INFINITE, // timeout
+ INFINITE, // timeout
#endif
- FALSE) // alertable
+ FALSE) // alertable
- // Adjust the returned array index for the offset we used, so the return
- // value is relative to entire MHandles array
- + uiEventIndexOffsetForWait)
+ // Adjust the returned array index for the offset we used, so the return
+ // value is relative to entire MHandles array
+ + uiEventIndexOffsetForWait)
+ {
+ case (WAIT_OBJECT_0 + kLowMemoryNotification):
+ //short on memory GC immediately
+ GetFinalizerThread()->DisablePreemptiveGC();
+ GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE);
+ GetFinalizerThread()->EnablePreemptiveGC();
+ //wait only on the event for 2s
+ switch (event->Wait(2000, FALSE))
{
- case (WAIT_OBJECT_0 + kLowMemoryNotification):
- //short on memory GC immediately
- GetFinalizerThread()->DisablePreemptiveGC();
- GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE);
- GetFinalizerThread()->EnablePreemptiveGC();
- //wait only on the event for 2s
- switch (event->Wait(2000, FALSE))
- {
- case (WAIT_OBJECT_0):
- return;
- case (WAIT_ABANDONED):
- return;
- case (WAIT_TIMEOUT):
- break;
- }
- break;
- case (WAIT_OBJECT_0 + kFinalizer):
+ case (WAIT_OBJECT_0):
return;
-#ifdef FEATURE_PROFAPI_ATTACH_DETACH
- case (WAIT_OBJECT_0 + kProfilingAPIAttach):
- // Spawn thread to perform the profiler attach, then resume our wait
- ProfilingAPIAttachDetach::ProcessSignaledAttachEvent();
+ case (WAIT_ABANDONED):
+ return;
+ case (WAIT_TIMEOUT):
break;
+ }
+ break;
+ case (WAIT_OBJECT_0 + kFinalizer):
+ return;
+#ifdef FEATURE_PROFAPI_ATTACH_DETACH
+ case (WAIT_OBJECT_0 + kProfilingAPIAttach):
+ // Spawn thread to perform the profiler attach, then resume our wait
+ ProfilingAPIAttachDetach::ProcessSignaledAttachEvent();
+ break;
#endif // FEATURE_PROFAPI_ATTACH_DETACH
#if defined(__linux__) && defined(FEATURE_EVENT_TRACE)
- case (WAIT_TIMEOUT + kLowMemoryNotification):
- case (WAIT_TIMEOUT + kFinalizer):
- if (g_TriggerHeapDump)
- {
- return;
- }
-
- break;
-#endif
- default:
- //what's wrong?
- _ASSERTE (!"Bad return code from WaitForMultipleObjects");
+ case (WAIT_TIMEOUT + kLowMemoryNotification):
+ case (WAIT_TIMEOUT + kFinalizer):
+ if (g_TriggerHeapDump)
+ {
return;
}
- }
- }
- else {
- static LONG sLastLowMemoryFromHost = 0;
- while (1) {
-#if defined(__linux__) && defined(FEATURE_EVENT_TRACE)
- DWORD timeout = LINUX_HEAP_DUMP_TIME_OUT;
-#else
- DWORD timeout = INFINITE;
-#endif
- if (!CLRMemoryHosted())
- {
- if (WaitForSingleObject(MHandles[kLowMemoryNotification], 0) == WAIT_OBJECT_0) {
- //short on memory GC immediately
- GetFinalizerThread()->DisablePreemptiveGC();
- GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE);
- GetFinalizerThread()->EnablePreemptiveGC();
- }
- //wait only on the event for 2s
- // The previous GC might not wake up finalizer thread if there is
- // no objects to be finalized.
- timeout = 2000;
- }
- switch (event->Wait(timeout, FALSE))
- {
- case (WAIT_OBJECT_0):
- if (CLRMemoryHosted())
- {
- if (sLastLowMemoryFromHost != g_bLowMemoryFromHost)
- {
- sLastLowMemoryFromHost = g_bLowMemoryFromHost;
- if (sLastLowMemoryFromHost != 0)
- {
- GetFinalizerThread()->DisablePreemptiveGC();
- GCHeapUtilities::GetGCHeap()->GarbageCollect(0, TRUE);
- GetFinalizerThread()->EnablePreemptiveGC();
- }
- }
- }
- return;
- case (WAIT_ABANDONED):
- return;
- case (WAIT_TIMEOUT):
-#if defined(__linux__) && defined(FEATURE_EVENT_TRACE)
- if (g_TriggerHeapDump)
- {
- return;
- }
+ break;
#endif
- break;
- }
+ default:
+ //what's wrong?
+ _ASSERTE (!"Bad return code from WaitForMultipleObjects");
+ return;
}
}
}
_ASSERTE(s_FinalizerThreadOK);
_ASSERTE(GetThread() == GetFinalizerThread());
- // workaround wwl: avoid oom problem for finalizer thread startup.
- if (CLRTaskHosted())
- {
- SignalFinalizationDone(TRUE);
- // SQL's scheduler may give finalizer thread a very small slice of CPU if finalizer thread
- // shares a scheduler with other tasks. This can cause severe problem for finalizer thread.
- // To reduce pain here, we move finalizer thread off SQL's scheduler.
- // But SQL's scheduler does not support IHostTask::Alert on a task off scheduler, so we need
- // to return finalizer thread back to scheduler when we wait alertably.
- // GetFinalizerThread()->LeaveRuntime((size_t)SetupThreadNoThrow);
- }
-
// finalizer should always park in default domain
if (s_FinalizerThreadOK)
} CONTRACTL_END;
#ifndef FEATURE_PAL
- if (!CLRMemoryHosted())
- {
- MHandles[kLowMemoryNotification] =
- CreateMemoryResourceNotification(LowMemoryResourceNotification);
- }
+ MHandles[kLowMemoryNotification] =
+ CreateMemoryResourceNotification(LowMemoryResourceNotification);
#endif // FEATURE_PAL
hEventFinalizerDone = new CLREvent();
// 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);
-
- // workaround wwl: make sure finalizer is ready. This avoids OOM problem on finalizer
- // thread startup.
- if (CLRTaskHosted()) {
- FinalizerThreadWait(INFINITE);
- if (!s_FinalizerThreadOK)
- {
- ThrowOutOfMemory();
- }
- }
}
}
}
CONTRACTL_END;
- if (CLRTaskHosted())
- {
- Thread *pThread = GetThread();
- if (pThread && pThread->HasThreadState(Thread::TS_YieldRequested))
- {
- pThread->ResetThreadState(Thread::TS_YieldRequested);
- }
- }
-
if (dwSleepMSec > 0)
{
// when called with goThroughOS make sure to not call into the host. This function
pErr = (IErrorInfo *)GetComIPFromObjectRef(&pThrownObject, IID_IErrorInfo);
{
GCX_PREEMP();
- LeaveRuntimeHolder lrh((size_t)SetErrorInfo);
SetErrorInfo(0, pErr);
}
}
MdaReportAvOnComRelease* pProbe = MDA_GET_ASSISTANT_EX(ReportAvOnComRelease);
if (pProbe && pProbe->AllowAV())
{
- LeaveRuntimeHolderNoThrow lrh(*((*(size_t**)pUnk)+2));
- if (FAILED(lrh.GetHR()))
- return -1;
return pUnk->Release();
}
#endif // MDA_SUPPORTED
// down the Runtime. Mark that an AV is alright, and handled, in this scope using this holder.
AVInRuntimeImplOkayHolder AVOkay(pThread);
- if (CLRTaskHosted()) // Check hoisted out of LeaveRuntimeHolder to
- { // keep LeaveRuntimeHolder off of common path.
- LeaveRuntimeHolder lrh(*((*(size_t**)pUnk)+2));
- res = pUnk->Release();
- }
- else
- {
- res = pUnk->Release();
- }
+ res = pUnk->Release();
+
SCAN_EHMARKER_END_TRY();
}
PAL_CPP_CATCH_ALL
MdaReportAvOnComRelease* pProbe = MDA_GET_ASSISTANT_EX(ReportAvOnComRelease);
if (pProbe && pProbe->AllowAV())
{
- LeaveRuntimeHolderNoThrow lrh(*((*(size_t**)pUnk)+2));
- if (FAILED(lrh.GetHR()))
- return -1;
return pUnk->Release();
}
#endif // MDA_SUPPORTED
// down the Runtime. Mark that an AV is alright, and handled, in this scope using this holder.
AVInRuntimeImplOkayHolder AVOkay(pThread);
- if (CLRTaskHosted()) // Check hoisted out of LeaveRuntimeHolder to
- { // keep LeaveRuntimeHolder off of common path.
- LeaveRuntimeHolder lrh(*((*(size_t**)pUnk)+2));
- res = pUnk->Release();
- }
- else
- {
- res = pUnk->Release();
- }
+ res = pUnk->Release();
+
SCAN_EHMARKER_END_TRY();
}
PAL_CPP_CATCH_ALL
HRESULT hr = S_OK;
EX_TRY
{
- LeaveRuntimeHolder lrh((size_t)GetErrorInfo);
hr = GetErrorInfo(0, ppIErrInfo);
}
EX_CATCH
#endif
}
-HRESULT SafeQueryInterfaceHosted(IUnknown* pUnk, REFIID riid, IUnknown** pResUnk)
-{
- CONTRACTL
- {
- THROWS; // message pump could happen, so arbitrary managed code could run
- GC_TRIGGERS;
- DISABLED(MODE_PREEMPTIVE); // disabled because I couldn't figure out how to tell SCAN about my
- // manual mode change in SafeQueryInterface
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- LeaveRuntimeHolder lrh(*((*(size_t**)pUnk)+0));
- return pUnk->QueryInterface(riid, (void**) pResUnk);
-}
-
#include <optsmallperfcritical.h>
//--------------------------------------------------------------------------------
#define PAL_TRY_REFARG(argName) (pParam->argName)
PAL_TRY(Param * const, pParam, ¶m)
{
- if (CLRTaskHosted())
- {
- PAL_TRY_ARG(hr) = SafeQueryInterfaceHosted(PAL_TRY_ARG(pUnk), PAL_TRY_REFARG(riid), PAL_TRY_ARG(pResUnk));
- }
- else
- {
- PAL_TRY_ARG(hr) = PAL_TRY_ARG(pUnk)->QueryInterface(PAL_TRY_REFARG(riid), (void**) PAL_TRY_ARG(pResUnk));
- }
+ PAL_TRY_ARG(hr) = PAL_TRY_ARG(pUnk)->QueryInterface(PAL_TRY_REFARG(riid), (void**) PAL_TRY_ARG(pResUnk));
}
PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
#define PAL_TRY_REFARG(argName) (pParam->argName)
PAL_TRY(Param * const, pParam, ¶m)
{
- if (CLRTaskHosted())
- {
- PAL_TRY_ARG(hr) = SafeQueryInterfaceHosted(PAL_TRY_ARG(pUnk), PAL_TRY_REFARG(riid), PAL_TRY_ARG(pResUnk));
- }
- else
- {
- PAL_TRY_ARG(hr) = PAL_TRY_ARG(pUnk)->QueryInterface(PAL_TRY_REFARG(riid), (void**) PAL_TRY_ARG(pResUnk));
- }
+ PAL_TRY_ARG(hr) = PAL_TRY_ARG(pUnk)->QueryInterface(PAL_TRY_REFARG(riid), (void**) PAL_TRY_ARG(pResUnk));
}
PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
EX_TRY
{
- LeaveRuntimeHolder lrh((size_t)QueryPathOfRegTypeLib);
hr = QueryPathOfRegTypeLib(guid, wVerMajor, wVerMinor, LOCALE_USER_DEFAULT, &wzPath);
}
EX_CATCH
HRESULT hr = S_OK;
#ifdef FEATURE_CORESYSTEM
- LeaveRuntimeHolderNoThrow lrh((size_t)CLSIDFromProgID);
-#else
- LeaveRuntimeHolderNoThrow lrh((size_t)CLSIDFromProgIDEx);
-#endif
- hr = lrh.GetHR();
- if (FAILED(hr))
- return hr;
-
-#ifdef FEATURE_CORESYSTEM
return CLSIDFromProgID(strProgId, pGuid);
#else
return CLSIDFromProgIDEx(strProgId, pGuid);
}
#endif // FEATURE_CLASSIC_COMINTEROP
-NOINLINE ULONG SafeAddRefHosted(IUnknown* pUnk)
-{
- CONTRACTL
- {
- THROWS; // arbitrary managed code could run
- GC_TRIGGERS;
- MODE_PREEMPTIVE;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- LeaveRuntimeHolderNoThrow lrh(*((*(size_t**)pUnk)+1));
- if (FAILED(lrh.GetHR()))
- return ~0;
-
- return pUnk->AddRef();
-}
-
#include <optsmallperfcritical.h>
//--------------------------------------------------------------------------------
// AddRef helper, enables and disables GC during call-outs
CONTRACT_VIOLATION(ThrowsViolation); // arbitrary managed code could run
- if (CLRTaskHosted()) // Check hoisted out of LeaveRuntimeHolder to
- { // keep LeaveRuntimeHolder off of common path.
- res = SafeAddRefHosted(pUnk);
- }
- else
- {
- res = pUnk->AddRef();
- }
+ res = pUnk->AddRef();
GCX_PREEMP_NO_DTOR_END();
CONTRACT_VIOLATION(ThrowsViolation); // arbitrary managed code could run
- if (CLRTaskHosted()) // Check hoisted out of LeaveRuntimeHolder to
- { // keep LeaveRuntimeHolder off of common path.
- res = SafeAddRefHosted(pUnk);
- }
- else
- {
- res = pUnk->AddRef();
- }
+ res = pUnk->AddRef();
return res;
}
GCX_PREEMP();
EX_TRY
{
- LeaveRuntimeHolderNoThrow lrh((size_t)VariantChangeType);
- hr = lrh.GetHR();
-
- if (!FAILED(hr))
- hr = VariantChangeType(pVarRes, pVarSrc, wFlags, vt);
+ hr = VariantChangeType(pVarRes, pVarSrc, wFlags, vt);
}
EX_CATCH
{
_ASSERTE(GetModuleHandleA("oleaut32.dll") != NULL);
CONTRACT_VIOLATION(ThrowsViolation);
- HRESULT hr = S_OK;
- LeaveRuntimeHolderNoThrow lrh((size_t)VariantChangeTypeEx);
- hr = lrh.GetHR();
-
- if (!FAILED(hr))
- hr = VariantChangeTypeEx (pVarRes, pVarSrc,lcid,wFlags,vt);
+ HRESULT hr = VariantChangeTypeEx (pVarRes, pVarSrc,lcid,wFlags,vt);
return hr;
}
GCX_PREEMP();
{
- HRESULT hr = S_OK;
-
- LeaveRuntimeHolderNoThrow lrh((size_t)CoReleaseMarshalData);
- hr = lrh.GetHR();
-
- if (!FAILED(hr))
- {
- hr = CoReleaseMarshalData(pStream);
+ HRESULT hr = CoReleaseMarshalData(pStream);
#ifdef _DEBUG
wchar_t logStr[200];
LogInterop(logStr);
}
#endif
- }
}
ULONG cbRef = SafeReleasePreemp(pStream);
if (pDispEx)
{
- LeaveRuntimeHolder holder(**(size_t**)pDispEx);
hr = InvokeExHelper(pDispEx, MemberID, lcid, flags, pDispParams,
pVarResult, &ExcepInfo, NULL);
}
else
{
- LeaveRuntimeHolder holder(**(size_t**)pDisp);
hr = InvokeHelper( pDisp, MemberID, IID_NULL, lcid, flags,
pDispParams, pVarResult, &ExcepInfo, &iArgErr);
}
if (!bstrTmpName)
COMPlusThrowOM();
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pDispEx);
hr = pDispEx->GetDispID(bstrTmpName, fdexNameCaseSensitive, aDispID);
}
else
{
// Call GetIdsOfNames() to retrieve the DISPID's of the method and of the arguments.
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pDisp);
hr = pDisp->GetIDsOfNames(
IID_NULL,
aNamesToConvert,
{
GCX_PREEMP();
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pclsInfo);
hr = pclsInfo->GetClassInfo(&pTypeInfo);
}
{
{
GCX_PREEMP();
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pTypeInfo);
hr = pTypeInfo->GetTypeAttr(&ptattr);
}
WinRtString winrtClassName;
{
GCX_PREEMP();
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pInsp);
if (FAILED(pInsp->GetRuntimeClassName(winrtClassName.Address())))
{
RETURN TypeHandle();
ABI::Windows::Foundation::IUriRuntimeClassFactory* pFactory = marshalingInfo->GetUriFactory();
SafeComHolder<ABI::Windows::Foundation::IUriRuntimeClass> pIUriRC;
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pFactory);
HRESULT hrCreate = pFactory->CreateUri(WinRtStringRef(wszUri, cchUri), &pIUriRC);
if (FAILED(hrCreate))
{
void CEEInfo::yieldExecution()
{
WRAPPER_NO_CONTRACT;
- // DDR: 17066 - Performance degrade
- // The JIT should not give up it's time slice when we are not hosted
- if (CLRTaskHosted())
- {
- // SwitchToTask forces the current thread to give up quantum, while a host can decide what
- // to do with Sleep if the current thread has not run out of quantum yet.
- ClrSleepEx(0, FALSE);
- }
}
OVERLAPPEDDATAREF overlapped = ObjectToOVERLAPPEDDATAREF(OverlappedDataObject::GetOverlapped(*lpOverlapped));
_ASSERTE(overlapped->GetAppDomainId() == adid);
- _ASSERTE(CLRIoCompletionHosted() == FALSE);
if(overlapped->m_iocb == NULL)
{
INDEBUG(VerifyMessageStructureLayout());
- // If the CLR is being memory- or sync-hosted, then attach is not supported
- // (see comments above)
- if (CLRMemoryHosted() || CLRSyncHosted())
- {
- LOG((
- LF_CORPROF,
- LL_INFO10,
- "**PROF: Process is running with a host that implements custom memory or "
- "synchronization management. So it will not be possible to attach a "
- "profiler to this process.\n"));
-
- // NOTE: Intentionally not logging this to the event log, as it would be
- // obnoxious to see such a message every time SQL started up
-
- return S_FALSE;
- }
-
InitializeAttachThreadingMode();
if (s_attachThreadingMode == kOnDemand)
FrameWithCookie<DebuggerExitFrame> __def;
{
GCX_PREEMP();
- {
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pClassFact);
- hr = pClassFact->CreateInstance(punkOuter, IID_IUnknown, (void **)&pUnk);
- }
+ hr = pClassFact->CreateInstance(punkOuter, IID_IUnknown, (void **)&pUnk);
if (FAILED(hr) && punkOuter)
{
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pClassFact);
hr = pClassFact->CreateInstance(NULL, IID_IUnknown, (void**)&pUnk);
if (pfDidContainment)
*pfDidContainment = TRUE;
FrameWithCookie<DebuggerExitFrame> __def;
{
GCX_PREEMP();
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pClassFact);
hr = pClassFact->CreateInstance(punkOuter, IID_IUnknown, (void **)&pUnk);
if (FAILED(hr) && punkOuter)
{
{
// Either it's design time, or the current context doesn't
// supply a runtime license key.
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pClassFact);
hr = pClassFact->CreateInstance(punkOuter, IID_IUnknown, (void **)&pUnk);
if (FAILED(hr) && punkOuter)
{
{
// It's runtime, and we do have a non-null license key.
_ASSERTE(bstrKey != NULL);
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pClassFact);
hr = pClassFact2->CreateInstanceLic(punkOuter, NULL, IID_IUnknown, bstrKey, (void**)&pUnk);
if (FAILED(hr) && punkOuter)
{
ServerInfo.pwszName = m_pwszServer;
// Try to retrieve the IClassFactory passing in CLSCTX_REMOTE_SERVER.
- LeaveRuntimeHolder lrh((size_t)CoGetClassObject);
hr = CoGetClassObject(m_rclsid, CLSCTX_REMOTE_SERVER, &ServerInfo, IID_IClassFactory, (void**)&pClassFactory);
}
else
{
// No server name is specified so we use CLSCTX_SERVER.
- LeaveRuntimeHolder lrh((size_t)CoGetClassObject);
#ifdef FEATURE_CLASSIC_COMINTEROP
// If the CLSID is hosted by the CLR itself, then we do not want to go through the COM registration
IfFailThrow(E_FAIL);
}
#endif
-
- LeaveRuntimeHolder lrh((size_t)CoCreateInstanceFromApp);
if (m_pwszServer)
{
// We are about to make a call to COM so switch to preemptive GC.
GCX_PREEMP();
- // Can not get the IP for pDisp->Invoke, instead using the first IP in vtable.
- LeaveRuntimeHolder holder (**(size_t**)((IDispatch*)pDisp));
-
// Call invoke with DISPID_NEWENUM to see if such a member exists.
hr = pDisp->Invoke(
DISPID_NEWENUM,
if (SUCCEEDED(hr))
{
GCX_PREEMP(); // make sure we switch to preemptive mode before calling the external COM object
- LeaveRuntimeHolder lrh(*((*(size_t**)(IConnectionPointContainer*)pCPC)+4));
hr = pCPC->FindConnectionPoint(SrcItfIID, &pCP);
if (SUCCEEDED(hr))
{
}
CONTRACTL_END;
- // Disallow creation of locks before EE starts. But only complain if we end up
- // being hosted, since such locks have escaped the hosting net and will cause
- // AVs on next use.
-#ifdef _DEBUG
- static bool fEarlyInit; // = false
-
- if (!(g_fEEStarted || g_fEEInit))
- {
- if (!CLRSyncHosted())
- fEarlyInit = true;
- }
-
- // If we are now hosted, we better not have *ever* created some locks that are
- // not known to our host.
- _ASSERTE(!fEarlyInit || !CLRSyncHosted());
-
-#endif
-
if (m_Initialized == Initialized)
{
_ASSERTE (type == m_LockType);
}
CONTRACTL_END;
- _ASSERTE (!CLRSyncHosted());
-
DWORD backoffs = 0;
ULONG ulSpins = 0;
{ \
ULONGLONG __entryTime = 0; \
__int64 __entryTimeStamp = 0; \
- if (CLRTaskHosted()) \
- { \
- __entryTimeStamp = getTimeStamp(); \
- __entryTime = CLRGetTickCount64(); \
- } \
_ASSERTE(CanThisThreadCallIntoHost()); \
_ASSERTE((pThread == NULL) || \
(pThread->GetClrDebugState() == NULL) || \
DEBUG_ASSURE_NO_RETURN_END(STACK_PROBE) \
boundary_guard_XXX.SetNoExceptionNoPop(); \
} \
- if (CLRTaskHosted()) \
- { \
- ULONGLONG __endTime = CLRGetTickCount64(); \
- ULONGLONG __elapse = __endTime - __entryTime; \
- if (__elapse > 20000 && __entryTimeStamp) \
- { \
- STRESS_LOG4(LF_EH, LL_INFO10, \
- "CALLING HOST takes %d ms: line %d in %s(%s)\n", \
- (int)__elapse, __LINE__, __FUNCTION__, __FILE__); \
- } \
- } \
}
//-----------------------------------------------------------------------------
pDisp = (IDispatch*)pCCW->GetIClassXIP();
}
- LeaveRuntimeHolder holder(**(size_t**)pTI);
-
hr = pTI->Invoke(pDisp, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
}
EX_CATCH
GCX_PREEMP();
// Get the RawUri string from the WinRT URI object
- {
- LeaveRuntimeHolder lrh(**(size_t**)(IUnknown*)pIUriRC);
- IfFailThrow(pIUriRC->get_RawUri(hsRawUriName.Address()));
- }
+ IfFailThrow(pIUriRC->get_RawUri(hsRawUriName.Address()));
pwszRawUri = hsRawUriName.GetRawBuffer(&cchRawUri);
}
SafeComHolderPreemp<IInspectable> pInner;
HRESULT hr;
- {
- LeaveRuntimeHolder lrh(**(size_t **)(IUnknown *)pFactory);
- hr = pFactory->CreateInstanceWithAllParameters(
- (ABI::Windows::UI::Xaml::Interop::NotifyCollectionChangedAction)action,
- (ABI::Windows::UI::Xaml::Interop::IBindableVector *)newItem,
- (ABI::Windows::UI::Xaml::Interop::IBindableVector *)oldItem,
- newIndex,
- oldIndex,
- NULL,
- &pInner,
- &pArgsRC);
- }
+ hr = pFactory->CreateInstanceWithAllParameters(
+ (ABI::Windows::UI::Xaml::Interop::NotifyCollectionChangedAction)action,
+ (ABI::Windows::UI::Xaml::Interop::IBindableVector *)newItem,
+ (ABI::Windows::UI::Xaml::Interop::IBindableVector *)oldItem,
+ newIndex,
+ oldIndex,
+ NULL,
+ &pInner,
+ &pArgsRC);
IfFailThrow(hr);
END_QCALL;
SafeComHolderPreemp<IInspectable> pInner;
HRESULT hr;
- {
- LeaveRuntimeHolder lrh(**(size_t **)(IUnknown *)pFactory);
- hr = pFactory->CreateInstance(
- name,
- NULL,
- &pInner,
- &pArgsRC);
- }
+ hr = pFactory->CreateInstance(
+ name,
+ NULL,
+ &pInner,
+ &pArgsRC);
IfFailThrow(hr);
END_QCALL;
STATIC_CONTRACT_THROWS;
STATIC_CONTRACT_SO_TOLERANT;
- LeaveRuntimeHolder holder((size_t)WaitForSingleObjectEx);
return WaitForSingleObjectEx(handle,dwMilliseconds,alertable);
}
LIMITED_METHOD_CONTRACT;
if (m_handle != INVALID_HANDLE_VALUE) {
- if (!CLRSyncHosted()) {
- CloseHandle(m_handle);
- }
+ CloseHandle(m_handle);
m_handle = INVALID_HANDLE_VALUE;
}
}
DWORD result = WAIT_FAILED;
EX_TRY
{
- LeaveRuntimeHolder holder((size_t)WaitForSingleObjectEx);
result = WaitForSingleObjectEx(m_handle,dwMilliseconds,alertable);
}
EX_CATCH
}
CONTRACTL_END;
- if (bInitialOwner)
- {
- Thread::BeginThreadAffinity();
- }
m_handle = WszCreateMutex(lpMutexAttributes,bInitialOwner,lpName);
if (m_handle == NULL)
{
- if (bInitialOwner)
- {
- Thread::EndThreadAffinity();
- }
ThrowOutOfMemory();
}
}
BOOL fRet = ReleaseMutex(m_handle);
if (fRet)
{
- Thread::EndThreadAffinity();
EE_LOCK_RELEASED(this);
}
return fRet;
}
CONTRACTL_END;
- Thread::BeginThreadAffinity();
DWORD fRet = WaitForSingleObjectEx(m_handle, dwMilliseconds, bAlertable);
- if ((fRet != WAIT_OBJECT_0) && (fRet != WAIT_ABANDONED))
- {
- Thread::EndThreadAffinity();
- }
if (fRet == WAIT_OBJECT_0)
{
#ifndef DACCESS_COMPILE
HANDLE GetHandleUNHOSTED() {
LIMITED_METHOD_CONTRACT;
- _ASSERTE (IsOSEvent() || !CLRSyncHosted());
return m_handle;
}
#endif // DACCESS_COMPILE
result=thread->DoAppropriateWait(cObjs,pObjs,bWaitAll,iTimeout,WaitMode_Alertable,NULL);
else
{
- LeaveRuntimeHolder holder((size_t)WaitForSingleObjectEx);
result = WaitForMultipleObjectsEx(cObjs,pObjs,bWaitAll,iTimeout,TRUE);
}
}
return fRetVal;
}
-struct HostJoinOnThreadArgs
-{
- WaitMode mode;
-};
-
-DWORD HostJoinOnThread (void *args, DWORD timeout, DWORD option)
-{
- CONTRACTL {
- THROWS;
- if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
- }
- CONTRACTL_END;
-
- _ASSERTE (!"Unknown host join status\n");
- return E_FAIL;
-}
-
DWORD Thread::Join(DWORD timeout, BOOL alertable)
{
_ASSERTE (m_Creater.IsCurrentThread());
m_Creater.Clear();
#endif
- {
- _ASSERTE (GetThreadHandle() != INVALID_HANDLE_VALUE &&
- GetThreadHandle() != SWITCHOUT_HANDLE_VALUE);
- dwRetVal = ::ResumeThread(GetThreadHandle());
- }
+
+ _ASSERTE (GetThreadHandle() != INVALID_HANDLE_VALUE &&
+ GetThreadHandle() != SWITCHOUT_HANDLE_VALUE);
+ dwRetVal = ::ResumeThread(GetThreadHandle());
+
return dwRetVal;
}
EnsurePreemptiveModeIfException ensurePreemptive;
#ifdef _DEBUG
- // Verify that for fiber mode, we do not have a thread that matches the current StackBase.
- if (CLRTaskHosted()) {
-
- }
-#endif
-
-#ifdef _DEBUG
CHECK chk;
if (g_pConfig->SuppressChecks())
{
DWORD_PTR *ttInfo = NULL;
size_t nBytes = MaxThreadRecord *
(sizeof(FiberSwitchInfo)-sizeof(size_t)+MaxStackDepth*sizeof(size_t));
- if (CLRTaskHosted() || g_pConfig->SaveThreadInfo()) {
+ if (g_pConfig->SaveThreadInfo()) {
ttInfo = new DWORD_PTR[(nBytes/sizeof(DWORD_PTR))*ThreadTrackInfo_Max];
memset(ttInfo,0,nBytes*ThreadTrackInfo_Max);
}
m_OSContext = new CONTEXT();
NewHolder<CONTEXT> contextHolder(m_OSContext);
- if (CLRTaskHosted())
- {
- m_pSavedRedirectContext = new CONTEXT();
- }
- else
- {
- m_pSavedRedirectContext = NULL;
- }
+ m_pSavedRedirectContext = NULL;
NewHolder<CONTEXT> savedRedirectContextHolder(m_pSavedRedirectContext);
#ifdef FEATURE_COMINTEROP
m_fCompletionPortDrained = FALSE;
- m_WorkingOnThreadContext = NULL;
m_debuggerActivePatchSkipper = NULL;
m_dwThreadHandleBeingUsed = 0;
SetProfilerCallbacksAllowed(TRUE);
#ifndef FEATURE_PAL
// workaround: Remove this when we flow impersonation token to host.
- ThreadAffinityHolder affinityHolder(FALSE);
BOOL reverted = FALSE;
HANDLE threadToken = INVALID_HANDLE_VALUE;
#endif // !FEATURE_PAL
// THREAD_SUSPEND_RESUME nor THREAD_GET_CONTEXT. We need to be able to suspend the thread, and we need to be
// able to get its context. Therefore, if we're impersonating, we revert to self, dup the handle, then
// re-impersonate before we leave this routine.
- if (!RevertIfImpersonated(&reverted, &threadToken, &affinityHolder))
+ if (!RevertIfImpersonated(&reverted, &threadToken))
{
COMPlusThrowWin32();
}
}
#ifndef FEATURE_PAL
-BOOL RevertIfImpersonated(BOOL *bReverted, HANDLE *phToken, ThreadAffinityHolder *pTAHolder)
+BOOL RevertIfImpersonated(BOOL *bReverted, HANDLE *phToken)
{
WRAPPER_NO_CONTRACT;
BOOL bImpersonated = OpenThreadToken(GetCurrentThread(), // we are assuming that if this call fails,
- TOKEN_IMPERSONATE, // we are not impersonating. There is no win32
- TRUE, // api to figure this out. The only alternative
+ TOKEN_IMPERSONATE, // we are not impersonating. There is no win32
+ TRUE, // api to figure this out. The only alternative
phToken); // is to use NtCurrentTeb->IsImpersonating().
if (bImpersonated)
{
- pTAHolder->Acquire();
*bReverted = RevertToSelf();
return *bReverted;
_ASSERTE(stackSize <= 0xFFFFFFFF);
#ifndef FEATURE_PAL
- ThreadAffinityHolder affinityHolder(FALSE);
HandleHolder token;
BOOL bReverted = FALSE;
- bRet = RevertIfImpersonated(&bReverted, &token, &affinityHolder);
+ bRet = RevertIfImpersonated(&bReverted, &token);
if (bRet != TRUE)
return bRet;
#endif // !FEATURE_PAL
m_StateNC = (ThreadStateNoConcurrency)((ULONG)m_StateNC | TSNC_CLRCreatedThread);
- if (!CLRTaskHosted()) {
- bRet = CreateNewOSThread(stackSize, start, args);
- }
- else {
- bRet = CreateNewHostTask(stackSize, start, args);
- }
+ bRet = CreateNewOSThread(stackSize, start, args);
#ifndef FEATURE_PAL
UndoRevert(bReverted, token);
#endif // !FEATURE_PAL
return TRUE;
}
-
-
-BOOL Thread::CreateNewHostTask(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, void *args)
-{
- CONTRACTL {
- NOTHROW;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- // Make sure we have all our handles, in case someone tries to suspend us
- // as we are starting up.
-
- if (!AllocHandles())
- {
- return FALSE;
- }
-
- return FALSE;
-}
-
//
// #threadDestruction
//
DoAppropriateWaitWorkerAlertableHelper(mode);
}
- LeaveRuntimeHolder holder((size_t)WaitForMultipleObjectsEx);
StateHolder<MarkOSAlertableWait,UnMarkOSAlertableWait> OSAlertableWait(alertable);
ThreadStateHolder tsh(alertable, TS_Interruptible | TS_Interrupted);
DoAppropriateWaitWorkerAlertableHelper(WaitMode_None);
}
- LeaveRuntimeHolder holder((size_t)WaitForMultipleObjectsEx);
StateHolder<MarkOSAlertableWait,UnMarkOSAlertableWait> OSAlertableWait(alertable);
ThreadStateHolder tsh(alertable, TS_Interruptible | TS_Interrupted);
|| ExecutionManager::IsCacheCleanupRequired()
|| Thread::CleanupNeededForFinalizedThread()
|| (m_DetachCount > 0)
- || CExecutionEngine::HasDetachedTlsInfo()
|| AppDomain::HasWorkForFinalizerThread()
|| SystemDomain::System()->RequireAppDomainCleanup();
}
SystemDomain::System()->ProcessDelayedUnloadDomains();
}
- CExecutionEngine::CleanupDetachedTlsInfo();
-
if(m_DetachCount > 0 || Thread::CleanupNeededForFinalizedThread())
{
Thread::CleanupDetachedThreads();
EnsureTlsData ensure(this);
-#ifdef _DEBUG
- if (CLRTaskHosted()) {
- }
-#endif
-
if (SetThread(this))
{
Thread *pThread = GetThread();
BEGIN_SO_INTOLERANT_CODE_NOPROBE;
#ifdef _DEBUG
- if (CLRTaskHosted()) {
- }
-
_ASSERTE (GetThread() == this);
#ifdef _TARGET_X86_
_ASSERTE (GetExceptionState()->GetContextRecord() == NULL);
}
-BOOL IsHostedThread()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- if (!CLRTaskHosted())
- {
- return FALSE;
- }
- return FALSE;
-}
-
-
-void __stdcall Thread::LeaveRuntime(size_t target)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- HRESULT hr = LeaveRuntimeNoThrow(target);
- if (FAILED(hr))
- ThrowHR(hr);
-}
-
-HRESULT Thread::LeaveRuntimeNoThrow(size_t target)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- if (!CLRTaskHosted())
- {
- return S_OK;
- }
-
- if (!IsHostedThread())
- {
- return S_OK;
- }
-
- HRESULT hr = S_OK;
-
-
- return hr;
-}
-
-void __stdcall Thread::LeaveRuntimeThrowComplus(size_t target)
-{
-
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- ENTRY_POINT;
- }
- CONTRACTL_END;
-
- HRESULT hr = S_OK;
-
- if (!CLRTaskHosted())
- {
- goto Exit;
- }
-
- if (!IsHostedThread())
- {
- goto Exit;
- }
-
-
- if (FAILED(hr))
- {
- INSTALL_UNWIND_AND_CONTINUE_HANDLER;
- ThrowHR(hr);
- UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
- }
-
-
-Exit:
-;
-
-}
-
-void __stdcall Thread::EnterRuntime()
-{
- if (!CLRTaskHosted())
- {
- // optimize for the most common case
- return;
- }
-
- DWORD dwLastError = GetLastError();
-
- CONTRACTL {
- THROWS;
- ENTRY_POINT;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- //BEGIN_ENTRYPOINT_THROWS;
-
- HRESULT hr = EnterRuntimeNoThrowWorker();
- if (FAILED(hr))
- ThrowHR(hr);
-
- SetLastError(dwLastError);
- //END_ENTRYPOINT_THROWS;
-
-}
-
-HRESULT Thread::EnterRuntimeNoThrow()
-{
- if (!CLRTaskHosted())
- {
- // optimize for the most common case
- return S_OK;
- }
-
- DWORD dwLastError = GetLastError();
-
- // This function can be called during a hard SO when managed code has called out to native
- // which has SOd, so we can't probe here. We already probe in LeaveRuntime, which will be
- // called at roughly the same stack level as LeaveRuntime, so we assume that the probe for
- // LeaveRuntime will cover us here.
-
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- HRESULT hr = EnterRuntimeNoThrowWorker();
-
- SetLastError(dwLastError);
-
- return hr;
-}
-
-HRESULT Thread::EnterRuntimeNoThrowWorker()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- if (!IsHostedThread())
- {
- return S_OK;
- }
-
- HRESULT hr = S_OK;
-
-
- return hr;
-}
-
-void Thread::ReverseEnterRuntime()
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- SO_TOLERANT;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- HRESULT hr = ReverseEnterRuntimeNoThrow();
-
- if (hr != S_OK)
- ThrowHR(hr);
-}
-
-__declspec(noinline) void Thread::ReverseEnterRuntimeThrowComplusHelper(HRESULT hr)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- SO_TOLERANT;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- INSTALL_UNWIND_AND_CONTINUE_HANDLER;
- ThrowHR(hr);
- UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
-}
-
-void Thread::ReverseEnterRuntimeThrowComplus()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- SO_TOLERANT;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- HRESULT hr = ReverseEnterRuntimeNoThrow();
-
- if (hr != S_OK)
- {
- ReverseEnterRuntimeThrowComplusHelper(hr);
- }
-}
-
-
-HRESULT Thread::ReverseEnterRuntimeNoThrow()
-{
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- if (!CLRTaskHosted())
- {
- return S_OK;
- }
-
- if (!IsHostedThread())
- {
- return S_OK;
- }
-
- HRESULT hr = S_OK;
-
-
- return hr;
-}
-
-void Thread::ReverseLeaveRuntime()
-{
- // This function can be called during a hard SO so we can't probe here. We already probe in
- // ReverseEnterRuntime, which will be called at roughly the same stack level as ReverseLeaveRuntime,
- // so we assume that the probe for ReverseEnterRuntime will cover us here.
-
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- }
- CONTRACTL_END;
-
- // SetupForComCallHR calls this inside a CATCH, but it triggers a THROWs violation
- CONTRACT_VIOLATION(ThrowsViolation);
-
- if (!CLRTaskHosted())
- {
- return;
- }
-
- if (!IsHostedThread())
- {
- return;
- }
-
- HRESULT hr = S_OK;
-
-
- if (hr != S_OK)
- ThrowHR(hr);
-
-}
-
-// For OS EnterCriticalSection, call host to enable ThreadAffinity
-void Thread::BeginThreadAffinity()
-{
- LIMITED_METHOD_CONTRACT;
-
-}
-
-
-// For OS EnterCriticalSection, call host to enable ThreadAffinity
-void Thread::EndThreadAffinity()
-{
- LIMITED_METHOD_CONTRACT;
-
-}
-
void Thread::SetupThreadForHost()
{
CONTRACTL
static void ObjectRefProtected(const OBJECTREF* ref) { }
static void ObjectRefNew(const OBJECTREF* ref) { }
- static void ReverseLeaveRuntime();
- static void __stdcall EnterRuntime();
-
- static void BeginThreadAffinity() { }
- static void EndThreadAffinity() { }
-
void EnablePreemptiveGC() { }
void DisablePreemptiveGC() { }
}
};
-class LeaveRuntimeHolder
-{
-public:
- template <typename T>
- LeaveRuntimeHolder(T target)
- {
- STATIC_CONTRACT_LIMITED_METHOD;
- }
-};
-
-class LeaveRuntimeHolderNoThrow
-{
-public:
- template <typename T>
- LeaveRuntimeHolderNoThrow(T target)
- {
- STATIC_CONTRACT_LIMITED_METHOD;
- }
-
- HRESULT GetHR() const
- {
- STATIC_CONTRACT_LIMITED_METHOD;
- return S_OK;
- }
-};
-
inline BOOL dbgOnly_IsSpecialEEThread() { return FALSE; }
#define INCTHREADLOCKCOUNT() { }
#endif
public:
- static void __stdcall LeaveRuntime(size_t target);
- static HRESULT LeaveRuntimeNoThrow(size_t target);
- static void __stdcall LeaveRuntimeThrowComplus(size_t target);
- static void __stdcall EnterRuntime();
- static HRESULT EnterRuntimeNoThrow();
- static HRESULT EnterRuntimeNoThrowWorker();
-
- // Reverse PInvoke hook for host
- static void ReverseEnterRuntime();
- static HRESULT ReverseEnterRuntimeNoThrow();
- static void ReverseEnterRuntimeThrowComplusHelper(HRESULT hr);
- static void ReverseEnterRuntimeThrowComplus();
- static void ReverseLeaveRuntime();
-
- // Hook for OS Critical Section, Mutex, and others that require thread affinity
- static void BeginThreadAffinity();
- static void EndThreadAffinity();
-
BOOL HasThreadAffinity()
{
DWORD m_OSThreadId;
BOOL CreateNewOSThread(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, void *args);
- BOOL CreateNewHostTask(SIZE_T stackSize, LPTHREAD_START_ROUTINE start, void *args);
OBJECTHANDLE m_ExposedObject;
OBJECTHANDLE m_StrongHndToExposedObject;
static BOOL GetProcessDefaultStackSize(SIZE_T* reserveSize, SIZE_T* commitSize);
private:
- // YieldTask, ThreadAbort, GC all change thread context. ThreadAbort and GC uses ThreadStore lock to synchronize. But YieldTask can
- // not block. We use a counter to allow one thread to change thread context.
-
- Volatile<PVOID> m_WorkingOnThreadContext;
// Although this is a pointer, it is used as a flag to indicate the current context is unsafe
// to inspect. When NULL the context is safe to use, otherwise it points to the active patch skipper
{
return FALSE;
}
- if (CLRTaskHosted())
- {
- PVOID myID = ClrTeb::GetFiberPtrId();
- PVOID id = FastInterlockCompareExchangePointer(pThread->m_WorkingOnThreadContext.GetPointer(), myID, NULL);
- return id == NULL || id == myID;
- }
- else
- {
- return TRUE;
- }
+ return TRUE;
}
static void LeaveWorkingOnThreadContext(Thread *pThread)
{
LIMITED_METHOD_CONTRACT;
-
- if (pThread->m_WorkingOnThreadContext == ClrTeb::GetFiberPtrId())
- {
- pThread->m_WorkingOnThreadContext = NULL;
- }
}
typedef ConditionalStateHolder<Thread *, Thread::EnterWorkingOnThreadContext, Thread::LeaveWorkingOnThreadContext> WorkingOnThreadContextHolder;
- BOOL WorkingOnThreadContext()
- {
- LIMITED_METHOD_CONTRACT;
-
- return !CLRTaskHosted() || m_WorkingOnThreadContext == ClrTeb::GetFiberPtrId();
- }
-
public:
void PrepareThreadForSOWork()
{
LCID GetThreadCultureIdNoThrow(Thread *pThread, BOOL bUICulture);
-typedef StateHolder<Thread::BeginThreadAffinity, Thread::EndThreadAffinity> ThreadAffinityHolder;
-
typedef Thread::ForbidSuspendThreadHolder ForbidSuspendThreadHolder;
typedef Thread::ThreadPreventAsyncHolder ThreadPreventAsyncHolder;
typedef Thread::ThreadPreventAbortHolder ThreadPreventAbortHolder;
-typedef StateHolder<Thread::ReverseEnterRuntime, Thread::ReverseLeaveRuntime> ReverseEnterRuntimeHolder;
// Combines ForBindSuspendThreadHolder and CrstHolder into one.
class ForbidSuspendThreadCrstHolder
CrstHolder m_lock_holder;
};
-// Non-throwing flavor of ReverseEnterRuntimeHolder that requires explicit call to AcquireNoThrow to acquire
-class ReverseEnterRuntimeHolderNoThrow : StateHolder<DoNothing, Thread::ReverseLeaveRuntime>
-{
-public:
- ReverseEnterRuntimeHolderNoThrow()
- : StateHolder<DoNothing, Thread::ReverseLeaveRuntime>(FALSE)
- {
- }
-
- HRESULT AcquireNoThrow()
- {
- WRAPPER_NO_CONTRACT;
-
- HRESULT hr = Thread::ReverseEnterRuntimeNoThrow();
- if (SUCCEEDED(hr))
- Acquire();
- return hr;
- }
-};
-
ETaskType GetCurrentTaskType();
-class LeaveRuntimeHolder
-{
-public:
- template <typename T>
- LeaveRuntimeHolder(T target)
- {
- STATIC_CONTRACT_WRAPPER;
- if (!CLRTaskHosted())
- return;
-
- Thread::LeaveRuntime((size_t)target);
- }
-
- ~LeaveRuntimeHolder()
- {
- STATIC_CONTRACT_WRAPPER;
- if (!CLRTaskHosted())
- return;
-
- Thread::EnterRuntime();
- }
-};
-
-class LeaveRuntimeHolderNoThrow
-{
-public:
- template <typename T>
- LeaveRuntimeHolderNoThrow(T target)
- {
- STATIC_CONTRACT_WRAPPER;
- if (!CLRTaskHosted())
- {
- hr = S_OK;
- return;
- }
-
- hr = Thread::LeaveRuntimeNoThrow((size_t)target);
- }
-
- ~LeaveRuntimeHolderNoThrow()
- {
- STATIC_CONTRACT_WRAPPER;
- if (!CLRTaskHosted())
- {
- hr = S_OK;
- return;
- }
-
- hr = Thread::EnterRuntimeNoThrow();
- }
-
- HRESULT GetHR() const
- {
- LIMITED_METHOD_CONTRACT;
- return hr;
- }
-
-private:
- HRESULT hr;
-};
-
typedef Thread::AVInRuntimeImplOkayHolder AVInRuntimeImplOkayHolder;
-BOOL RevertIfImpersonated(BOOL *bReverted, HANDLE *phToken, ThreadAffinityHolder *pTAHolder);
+BOOL RevertIfImpersonated(BOOL *bReverted, HANDLE *phToken);
void UndoRevert(BOOL bReverted, HANDLE hToken);
// ---------------------------------------------------------------------------
DWORD elapsed_time = 0;
#endif
- ThreadAffinityHolder affinity;
// We do not want this thread to be alerted.
ThreadPreventAsyncHolder preventAsync(pCurThread != NULL);
}
}
- // ThreadStoreLock is a critical lock used by GC, ThreadAbort, AD unload, Yield.
- // If a task is switched out while it owns ThreadStoreLock, it may not be able to
- // release it because the scheduler may be running managed code without yielding.
- Thread::BeginThreadAffinity();
-
// This is shutdown aware. If we're in shutdown, and not helper/finalizer/shutdown
// then this will not take the lock and just block forever.
ThreadStore::s_pThreadStore->Enter();
ThreadStore::s_pThreadStore->m_holderthreadid.Clear();
ThreadStore::s_pThreadStore->Leave();
- Thread::EndThreadAffinity();
-
// We're out of the critical area for managed/unmanaged debugging.
if (!bThreadDestroyed && pCurThread)
pCurThread->SetDebugCantStop(false);
if (!IsContextSafeToRedirect(pCtx))
return (FALSE);
- if (CLRTaskHosted())
- {
- PCODE dwOrigEip = GetIP(pCtx);
- if (!ExecutionManager::IsManagedCode(dwOrigEip))
- return FALSE;
- }
-
////////////////////////////////////////////////////
// Now redirect the thread to the helper function
}
}
-#ifdef FEATURE_STACK_PROBE
- // If CLR is hosted with IHostTaskManager and escalation policy for StackOverflow,
- // we need to make sure a thread is never blocked with a small stack, because the thread can
- // not be moved from scheduler in the host, and the scheduler may hold some resource needed by
- // suspension thread.
-
- // If we need to handle SO, GC will wait until a target thread has finished LeaveRuntime call. At
- // this point, the thread is off scheduler. If it hits SO, we will kill the process. If the thread hits
- // SO while calling LeaveRuntime, we treat this as SO in managed code, and unload the domain instead.
- BOOL fConsiderSO = (CLRTaskHosted() &&
- GetEEPolicy()->GetActionOnFailure(FAIL_StackOverflow) == eRudeUnloadAppDomain);
-#endif
-
// From this point until the end of the function, consider all active thread
// suspension to be in progress. This is mainly to give the profiler API a hint
// that trying to suspend a thread (in order to walk its stack) could delay the
QueueUserAPC((PAPCFUNC)PauseAPC, handle, APC_Code);
}
}
-
-#ifdef FEATURE_STACK_PROBE
- if (thread->m_fPreemptiveGCDisabled.Load() == 0 && fConsiderSO)
- {
- if ((UINT_PTR)thread->m_pFrame - thread->GetLastAllowableStackAddress() <
- ADJUST_PROBE(BACKOUT_CODE_STACK_LIMIT) * OS_PAGE_SIZE)
- {
- if (!thread->HasThreadState(Thread::TS_GCSuspendPending))
- {
- thread->SetThreadState(Thread::TS_GCSuspendPending);
- countThreads++;
- STRESS_LOG2(LF_SYNC, LL_INFO1000, " Setting thread 0x%x ID 0x%x for GC (SO)\n",
- thread, thread->GetThreadId());
- }
- }
- }
-#endif
}
#ifdef _DEBUG
if (!thread->m_fPreemptiveGCDisabled)
{
-#ifdef FEATURE_STACK_PROBE
- if (fConsiderSO && (UINT_PTR)thread->m_pFrame - thread->GetLastAllowableStackAddress() <
- ADJUST_PROBE(BACKOUT_CODE_STACK_LIMIT) * OS_PAGE_SIZE)
+ // Inlined N/Direct can sneak out to preemptive without actually checking.
+ // If we find one, we can consider it suspended (since it can't get back in).
+ STRESS_LOG1(LF_SYNC, LL_INFO1000, " Thread %x went preemptive it is at a GC safe point\n", thread);
+ countThreads--;
+ thread->ResetThreadState(Thread::TS_GCSuspendPending);
+
+ // To ensure 0 CPU utilization for FAS (see implementation of PauseAPC)
+ // we queue the APC to all interruptable threads.
+ if(g_IsPaused && (thread->m_State & Thread::TS_Interruptible))
{
- // The thread is not ready for GC.
- }
- else
-#endif
- {
- // Inlined N/Direct can sneak out to preemptive without actually checking.
- // If we find one, we can consider it suspended (since it can't get back in).
- STRESS_LOG1(LF_SYNC, LL_INFO1000, " Thread %x went preemptive it is at a GC safe point\n", thread);
- countThreads--;
- thread->ResetThreadState(Thread::TS_GCSuspendPending);
-
- // To ensure 0 CPU utilization for FAS (see implementation of PauseAPC)
- // we queue the APC to all interruptable threads.
- if(g_IsPaused && (thread->m_State & Thread::TS_Interruptible))
- {
- HANDLE handle = thread->GetThreadHandle();
- QueueUserAPC((PAPCFUNC)PauseAPC, handle, APC_Code);
- }
+ HANDLE handle = thread->GetThreadHandle();
+ QueueUserAPC((PAPCFUNC)PauseAPC, handle, APC_Code);
}
}
}
ExecutionState esb;
StackWalkAction action;
- _ASSERTE(WorkingOnThreadContext());
-
CONTEXT ctx;
REGDISPLAY rd;
if (!GetSafelyRedirectableThreadContext(
// a Suspend to the end of a Restart. We can compute 'avg' using 'cnt' and 'tot' values.
MinMaxTot suspend, restart, paused;
- // We know there can be contention on acquiring the ThreadStoreLock, or yield points when hosted (like
- // BeginThreadAffinity on the leading edge and EndThreadAffinity on the trailing edge).
+ // We know there can be contention on acquiring the ThreadStoreLock.
MinMaxTot acquireTSL, releaseTSL;
// And if we OS suspend a thread that is blocking or perhaps throwing an exception and is therefore
STATIC_CONTRACT_FORBID_FAULT;
STATIC_CONTRACT_SO_TOLERANT;
- ThreadAffinityHolder affinity;
-
HMODULE hMod = WszGetModuleHandle(lpModuleFileName);
return hMod;
}
STATIC_CONTRACT_FORBID_FAULT;
STATIC_CONTRACT_SO_TOLERANT;
- ThreadAffinityHolder affinity;
-
HMODULE hMod = WszGetModuleHandle(NULL);
return hMod;
}
STATIC_CONTRACT_FAULT;
STATIC_CONTRACT_SO_TOLERANT;
- ThreadAffinityHolder affinity;
HMODULE hMod;
UINT last = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS);
{
STATIC_CONTRACT_FAULT;
STATIC_CONTRACT_SO_TOLERANT;
- ThreadAffinityHolder affinity;
HMODULE hMod;
UINT last = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS);
{
STATIC_CONTRACT_FORBID_FAULT;
STATIC_CONTRACT_SO_TOLERANT;
- ThreadAffinityHolder affinity;
return FreeLibrary(hModule);
}
STATIC_CONTRACT_FORBID_FAULT;
STATIC_CONTRACT_SO_TOLERANT;
- ThreadAffinityHolder affinity;
-
// This is no-return
FreeLibraryAndExitThread(hModule,dwExitCode);
}
return g_fHostConfig;
}
-inline BOOL CLRMemoryHosted()
-{
- LIMITED_METHOD_CONTRACT;
- return FALSE;
-}
-
-inline BOOL CLRTaskHosted()
-{
- LIMITED_METHOD_DAC_CONTRACT;
- return FALSE;
-}
-
-inline BOOL CLRSyncHosted()
-{
- LIMITED_METHOD_CONTRACT;
- return FALSE;
-}
-
-inline BOOL CLRIoCompletionHosted()
-{
- LIMITED_METHOD_CONTRACT;
- return FALSE;
-}
-
-inline BOOL CLRAssemblyHosted()
-{
- LIMITED_METHOD_CONTRACT;
- return FALSE;
-}
-
-inline BOOL CLRGCHosted()
-{
- LIMITED_METHOD_CONTRACT;
- return FALSE;
-}
-
-inline BOOL CLRSecurityHosted()
-{
- LIMITED_METHOD_CONTRACT;
- return FALSE;
-}
-
#ifndef FEATURE_PAL
HMODULE CLRGetModuleHandle(LPCWSTR lpModuleFileName);
SetupThreadForComCall(OOMRetVal); \
if (CheckCanRunManagedCode && !CanRunManagedCode()) \
return CannotEnterRetVal; \
-SO_INTOLERANT_CODE_NOTHROW(CURRENT_THREAD, return SORetVal) \
-
-#define ComCallHostNotificationHR() \
-ReverseEnterRuntimeHolderNoThrow REHolder; \
-if (CLRTaskHosted()) \
-{ \
- HRESULT hr = REHolder.AcquireNoThrow(); \
- if (FAILED(hr)) \
- { \
- return hr; \
- } \
-}
+SO_INTOLERANT_CODE_NOTHROW(CURRENT_THREAD, return SORetVal)
#define SetupForComCallHRNoHostNotif() InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, true)
#define SetupForComCallHRNoHostNotifNoCheckCanRunManagedCode() InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, false)
#define SetupForComCallDWORDNoHostNotif() InternalSetupForComCall(-1, -1, -1, true)
#define SetupForComCallHR() \
-InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, true) \
-ComCallHostNotificationHR()
+InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, true)
#define SetupForComCallHRNoCheckCanRunManagedCode() \
-InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, false) \
-ComCallHostNotificationHR()
+InternalSetupForComCall(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, false)
#ifdef FEATURE_CORRUPTING_EXCEPTIONS
#define BeginSetupForComCallHRWithEscapingCorruptingExceptions() \
HRESULT __hr = S_OK; \
InternalSetupForComCallWithEscapingCorruptingExceptions(HOST_E_CLRNOTAVAILABLE, E_OUTOFMEMORY, COR_E_STACKOVERFLOW, true) \
-ReverseEnterRuntimeHolderNoThrow REHolder; \
-if (CLRTaskHosted()) \
-{ \
- __hr = REHolder.AcquireNoThrow(); \
-} \
\
if (SUCCEEDED(__hr)) \
{ \
#endif // FEATURE_CORRUPTING_EXCEPTIONS
#define SetupForComCallDWORD() \
-InternalSetupForComCall(-1, -1, -1, true) \
-ReverseEnterRuntimeHolderNoThrow REHolder; \
-if (CLRTaskHosted()) \
-{ \
- if (FAILED(REHolder.AcquireNoThrow())) \
- { \
- return -1; \
- } \
-}
+InternalSetupForComCall(-1, -1, -1, true)
// Special version of SetupForComCallDWORD that doesn't call
// CanRunManagedCode() to avoid firing LoaderLock MDA
#define SetupForComCallDWORDNoCheckCanRunManagedCode() \
-InternalSetupForComCall(-1, -1, -1, false) \
-ReverseEnterRuntimeHolderNoThrow REHolder; \
-if (CLRTaskHosted()) \
-{ \
- if (FAILED(REHolder.AcquireNoThrow())) \
- { \
- return -1; \
- } \
-}
+InternalSetupForComCall(-1, -1, -1, false)
#include "unsafe.h"
{
LIMITED_METHOD_CONTRACT;
- _ASSERTE(!CLRMemoryHosted());
-
#pragma push_macro("GetProcessHeap")
#pragma push_macro("HeapFree")
#undef GetProcessHeap
#ifndef FEATURE_PAL
EnsureInitialized();
- // if hosted then we need to queue to worker thread, since hosting API doesn't include this method
- if (CLRIoCompletionHosted())
- {
- PostRequestHolder postRequest = MakePostRequest(Function, lpOverlapped);
- if (postRequest)
- {
- // Will execute in the Default AppDomain
- if (FALSE == QueueUserWorkItem(QUWIPostCompletion, postRequest, QUEUE_ONLY))
- {
- return FALSE;
- }
- else
- {
- postRequest.SuppressRelease();
- return TRUE;
- }
- }
- else
- return FALSE;
- }
-
_ASSERTE(GlobalCompletionPort != NULL);
if (!InitCompletionPortThreadpool)
}
-DWORD __stdcall ThreadpoolMgr::QUWIPostCompletion(PVOID pArgs)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- SO_INTOLERANT;
- }
- CONTRACTL_END;
-
- PostRequest* postRequest = (PostRequest*) pArgs;
-
- EX_TRY
- {
- (postRequest->Function)(postRequest->errorCode, postRequest->numBytesTransferred, postRequest->lpOverlapped);
- }
- EX_CATCH
- {
- RecycleMemory( postRequest, MEMTYPE_PostRequest );
- if (!SwallowUnhandledExceptions())
- EX_RETHROW;
- }
- EX_END_CATCH(SwallowAllExceptions);
- return ERROR_SUCCESS;
-
-}
-
-
// This is either made by a worker thread or a CP thread
// indicated by threadTypeStatus
void ThreadpoolMgr::EnsureGateThreadRunning()
{
LIMITED_METHOD_CONTRACT;
- // The gate thread is only needed if the CLR is providing part of the ThreadPool implementation.
- _ASSERTE(!CLRIoCompletionHosted());
-
while (true)
{
switch (GateThreadStatus)
{
LIMITED_METHOD_CONTRACT;
- // The gate thread is only needed if the CLR is providing part of the ThreadPool implementation.
- _ASSERTE(!CLRIoCompletionHosted());
-
_ASSERTE(GateThreadStatus == GATE_THREAD_STATUS_WAITING_FOR_REQUEST ||
GateThreadStatus == GATE_THREAD_STATUS_REQUESTED);
return;
}
- if(IsThreadPoolHosted())
- {
- //Only managed callBacks go this route under hosts.
- //Also, since if we came here, atleast one managed requests was
- //created, and that means atleast one app domain exists.
-
- if (index == -1)
- {
- index = 1;
- }
- }
-
if (index == -1)
{
pAdCount = PerAppDomainTPCountList::GetUnmanagedTPCount();
case MEMTYPE_WorkRequest:
result = new WorkRequest;
break;
- case MEMTYPE_PostRequest:
- result = new PostRequest;
- break;
default:
_ASSERTE(!"Unknown Memtype");
result = NULL;
case MEMTYPE_WorkRequest:
delete (WorkRequest*) mem;
break;
- case MEMTYPE_PostRequest:
- delete (PostRequest*) mem;
- break;
default:
_ASSERTE(!"Unknown Memtype");
}
else {
#ifndef FEATURE_PAL
- ThreadAffinityHolder affinityHolder(FALSE);
HandleHolder token;
BOOL bReverted = FALSE;
- bOK = RevertIfImpersonated(&bReverted, &token, &affinityHolder);
+ bOK = RevertIfImpersonated(&bReverted, &token);
if (bOK != TRUE)
return NULL;
#endif // !FEATURE_PAL
{
LIMITED_METHOD_CONTRACT;
- // The gate thread is only needed if the CLR is providing part of the ThreadPool implementation.
- _ASSERTE(!CLRIoCompletionHosted());
-
HANDLE threadHandle = Thread::CreateUtilityThread(Thread::StackSize_Small, GateThreadStart, NULL);
if (threadHandle)
}
CONTRACTL_END;
- _ASSERTE (!CLRIoCompletionHosted());
-
DWORD numBytes=0;
size_t key=0;
{
_ASSERTE (context == NULL || context->lpOverlapped == NULL);
- LeaveRuntimeHolder holder((size_t)GetQueuedCompletionStatus);
-
BOOL status = GetQueuedCompletionStatus(
GlobalCompletionPort,
&numBytes,
OVERLAPPEDDATAREF overlapped=NULL;
BOOL ManagedCallback=FALSE;
- if (CLRIoCompletionHosted())
- {
- return NULL;
- }
-
*pErrorCode = S_OK;
- LeaveRuntimeHolder holder((size_t)GetQueuedCompletionStatus);
-
//Very Very Important!
//Do not change the timeout for GetQueuedCompletionStatus to a non-zero value.
}
CONTRACTL_END;
- // The gate thread is only needed if the CLR is providing part of the ThreadPool implementation.
- _ASSERTE(!CLRIoCompletionHosted());
-
_ASSERTE(GateThreadStatus == GATE_THREAD_STATUS_REQUESTED);
GateThreadTimer timer;
// don't mess with CP thread pool settings if not initialized yet
if (InitCompletionPortThreadpool)
{
- _ASSERTE (!CLRIoCompletionHosted());
-
ThreadCounter::Counts oldCounts, newCounts;
oldCounts = CPThreadCounter.GetCleanCounts();
MEMTYPE_AsyncCallback = 0,
MEMTYPE_DelegateInfo = 1,
MEMTYPE_WorkRequest = 2,
- MEMTYPE_PostRequest = 3,
- MEMTYPE_COUNT = 4,
+ MEMTYPE_COUNT = 3,
};
static BOOL Initialize();
static BOOL HaveTimerInfosToFlush() { return TimerInfosToBeRecycled != NULL; }
- inline static BOOL IsThreadPoolHosted()
- {
- return FALSE;
- }
-
#ifndef FEATURE_PAL
static LPOVERLAPPED CompletionPortDispatchWorkWithinAppDomain(Thread* pThread, DWORD* pErrorCode, DWORD* pNumBytes, size_t* pKey, DWORD adid);
static void StoreOverlappedInfoInThread(Thread* pThread, DWORD dwErrorCode, DWORD dwNumBytes, size_t key, LPOVERLAPPED lpOverlapped);
wr->next = NULL;
return wr;
}
-
- struct PostRequest {
- LPOVERLAPPED_COMPLETION_ROUTINE Function;
- DWORD errorCode;
- DWORD numBytesTransferred;
- LPOVERLAPPED lpOverlapped;
- };
-
-
- inline static PostRequest* MakePostRequest(LPOVERLAPPED_COMPLETION_ROUTINE function, LPOVERLAPPED overlapped)
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;;
-
- PostRequest* pr = (PostRequest*) GetRecycledMemory(MEMTYPE_PostRequest);
- _ASSERTE(pr);
- if (NULL == pr)
- return NULL;
- pr->Function = function;
- pr->errorCode = 0;
- pr->numBytesTransferred = 0;
- pr->lpOverlapped = overlapped;
-
- return pr;
- }
-
- inline static void ReleasePostRequest(PostRequest *postRequest)
- {
- WRAPPER_NO_CONTRACT;
- ThreadpoolMgr::RecycleMemory(postRequest, MEMTYPE_PostRequest);
- }
-
- typedef Wrapper< PostRequest *, DoNothing<PostRequest *>, ThreadpoolMgr::ReleasePostRequest > PostRequestHolder;
#endif // #ifndef DACCESS_COMPILE
static void QueueTimerInfoForRelease(TimerInfo *pTimerInfo);
- static DWORD __stdcall QUWIPostCompletion(PVOID pArgs);
-
static void DeactivateWait(WaitInfo* waitInfo);
static void DeactivateNthWait(WaitInfo* waitInfo, DWORD index);