summaryrefslogtreecommitdiff
path: root/src/vm/threadsuspend.cpp
diff options
context:
space:
mode:
authordanmosemsft <danmose@microsoft.com>2017-02-10 17:12:53 -0800
committerdanmosemsft <danmose@microsoft.com>2017-02-10 21:36:06 -0800
commit54891e0650e69f08832f75a40dc102efc6115d38 (patch)
tree0e032a0b337767801f696cbaeacded267c694f32 /src/vm/threadsuspend.cpp
parent396f7d43b3c0f3ca7034a6d1d9cd7d6914778a1e (diff)
downloadcoreclr-54891e0650e69f08832f75a40dc102efc6115d38.tar.gz
coreclr-54891e0650e69f08832f75a40dc102efc6115d38.tar.bz2
coreclr-54891e0650e69f08832f75a40dc102efc6115d38.zip
Remove always defined FEATURE_CORECLR
Diffstat (limited to 'src/vm/threadsuspend.cpp')
-rw-r--r--src/vm/threadsuspend.cpp471
1 files changed, 0 insertions, 471 deletions
diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp
index cdfbd79497..d65f3a3af9 100644
--- a/src/vm/threadsuspend.cpp
+++ b/src/vm/threadsuspend.cpp
@@ -3328,32 +3328,6 @@ void Thread::RareDisablePreemptiveGC()
#endif // PROFILING_SUPPORTED
-#if !defined(FEATURE_CORECLR) // simple hosting
- // First, check to see if there's an IDbgThreadControl interface that needs
- // notification of the suspension
- if (m_State & TS_DebugSuspendPending)
- {
- IDebuggerThreadControl *pDbgThreadControl = CorHost::GetDebuggerThreadControl();
-
- if (pDbgThreadControl)
- pDbgThreadControl->ThreadIsBlockingForDebugger();
-
- }
-
- if (CLRGCHosted())
- {
- BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
- CorHost2::GetHostGCManager()->ThreadIsBlockingForSuspension();
- END_SO_TOLERANT_CODE_CALLING_HOST;
- }
-
- // If not, check to see if there's an IGCThreadControl interface that needs
- // notification of the suspension
- IGCThreadControl *pGCThreadControl = CorHost::GetGCThreadControl();
-
- if (pGCThreadControl)
- pGCThreadControl->ThreadIsBlockingForSuspension();
-#endif // !defined(FEATURE_CORECLR)
DWORD status = S_OK;
SetThreadStateNC(TSNC_WaitUntilGCFinished);
@@ -3453,32 +3427,6 @@ void Thread::RareDisablePreemptiveGC()
#endif // PROFILING_SUPPORTED
-#if !defined(FEATURE_CORECLR) // simple hosting
- // First, check to see if there's an IDbgThreadControl interface that needs
- // notification of the suspension
- if (m_State & TS_DebugSuspendPending)
- {
- IDebuggerThreadControl *pDbgThreadControl = CorHost::GetDebuggerThreadControl();
-
- if (pDbgThreadControl)
- pDbgThreadControl->ThreadIsBlockingForDebugger();
-
- }
-
- if (CLRGCHosted())
- {
- BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
- CorHost2::GetHostGCManager()->ThreadIsBlockingForSuspension();
- END_SO_TOLERANT_CODE_CALLING_HOST;
- }
-
- // If not, check to see if there's an IGCThreadControl interface that needs
- // notification of the suspension
- IGCThreadControl *pGCThreadControl = CorHost::GetGCThreadControl();
-
- if (pGCThreadControl)
- pGCThreadControl->ThreadIsBlockingForSuspension();
-#endif // !defined(FEATURE_CORECLR)
// The thread is blocked for shutdown. We do not concern for GC violation.
CONTRACT_VIOLATION(GCViolation);
@@ -3819,34 +3767,12 @@ void Thread::RareEnablePreemptiveGC()
// Life's much simpler this way...
-#if !defined(FEATURE_CORECLR) // simple hosting
- // Check to see if there's an IDbgThreadControl interface that needs
- // notification of the suspension
- if (m_State & TS_DebugSuspendPending)
- {
- IDebuggerThreadControl *pDbgThreadControl = CorHost::GetDebuggerThreadControl();
-
- if (pDbgThreadControl)
- pDbgThreadControl->ThreadIsBlockingForDebugger();
-
- }
-#endif // !defined(FEATURE_CORECLR)
#endif // DEBUGGING_SUPPORTED
#ifdef LOGGING
-#if !defined(FEATURE_CORECLR) // simple hosting
- if (!CorHost::IsDebuggerSpecialThread(GetThreadId()))
-#endif // !defined(FEATURE_CORECLR)
{
LOG((LF_CORDB, LL_INFO1000, "[0x%x] SUSPEND: suspended while enabling gc.\n", GetThreadId()));
}
-#if !defined(FEATURE_CORECLR) // simple hosting
- else
- {
- LOG((LF_CORDB, LL_INFO1000,
- "[0x%x] ALERT: debugger special thread did not suspend while enabling gc.\n", GetThreadId()));
- }
-#endif // !defined(FEATURE_CORECLR)
#endif
WaitSuspendEvents(); // sets bits, too
@@ -4186,20 +4112,8 @@ void __stdcall Thread::RedirectedHandledJITCase(RedirectReason reason)
// Notify the interface of the pending suspension
switch (reason) {
case RedirectReason_GCSuspension:
-#if !defined(FEATURE_CORECLR) // simple hosting
- if (CorHost::GetGCThreadControl())
- CorHost::GetGCThreadControl()->ThreadIsBlockingForSuspension();
- if (CLRGCHosted())
- {
- NotifyHostOnGCSuspension();
- }
-#endif // !defined(FEATURE_CORECLR)
break;
case RedirectReason_DebugSuspension:
-#if !defined(FEATURE_CORECLR) // simple hosting
- if (CorHost::GetDebuggerThreadControl() && CorHost::IsDebuggerSpecialThread(pThread->GetThreadId()))
- CorHost::GetDebuggerThreadControl()->ThreadIsBlockingForDebugger();
-#endif // !defined(FEATURE_CORECLR)
break;
case RedirectReason_UserSuspension:
// Do nothing;
@@ -4857,21 +4771,6 @@ HRESULT ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason)
STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime(reason=0x%x)\n", reason);
-#if !defined(FEATURE_CORECLR) // simple hosting
- // Alert the host that a GC is starting, in case the host is scheduling threads
- // for non-runtime tasks during GC.
- IGCThreadControl *pGCThreadControl = CorHost::GetGCThreadControl();
-
- if (pGCThreadControl)
- pGCThreadControl->SuspensionStarting();
-
- if (CLRGCHosted())
- {
- BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
- CorHost2::GetHostGCManager()->SuspensionStarting();
- END_SO_TOLERANT_CODE_CALLING_HOST;
- }
-#endif // !defined(FEATURE_CORECLR)
#ifdef PROFILING_SUPPORTED
// If the profiler desires information about GCs, then let it know that one
@@ -5562,33 +5461,6 @@ void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded)
// Notify everyone who cares, that this suspension is over, and this thread is going to go do other things.
//
-#if !defined(FEATURE_CORECLR) // simple hosting
- // Alert the host that a GC is ending, in case the host is scheduling threads
- // for non-runtime tasks during GC.
- IGCThreadControl *pGCThreadControl = CorHost::GetGCThreadControl();
-
- if (pGCThreadControl)
- {
- // If we the suspension was for a GC, tell the host what generation GC.
- DWORD Generation = (bFinishedGC
- ? GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration()
- : ~0U);
-
- pGCThreadControl->SuspensionEnding(Generation);
- }
-
- if (CLRGCHosted())
- {
- // If we the suspension was for a GC, tell the host what generation GC.
- DWORD Generation = (bFinishedGC
- ? GCHeapUtilities::GetGCHeap()->GetCondemnedGeneration()
- : ~0U);
-
- BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
- CorHost2::GetHostGCManager()->SuspensionEnding(Generation);
- END_SO_TOLERANT_CODE_CALLING_HOST;
- }
-#endif // !defined(FEATURE_CORECLR)
#ifdef PROFILING_SUPPORTED
// Need to give resume event for the GC thread
@@ -5961,13 +5833,6 @@ bool Thread::SysStartSuspendForDebug(AppDomain *pAppDomain)
// Caller is expected to be holding the ThreadStore lock
_ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit());
-#if !defined(FEATURE_CORECLR) // simple hosting
- // If there is a debugging thread control object, tell it we're suspending the Runtime.
- IDebuggerThreadControl *pDbgThreadControl = CorHost::GetDebuggerThreadControl();
-
- if (pDbgThreadControl)
- pDbgThreadControl->StartBlockingForDebugger(0);
-#endif // !defined(FEATURE_CORECLR)
// NOTE::NOTE::NOTE::NOTE::NOTE
// This function has parallel logic in SuspendRuntime. Please make
@@ -6341,16 +6206,6 @@ void Thread::SysResumeFromDebug(AppDomain *pAppDomain)
LOG((LF_CORDB, LL_INFO1000, "RESUME: starting resume AD:0x%x.\n", pAppDomain));
-#if !defined(FEATURE_CORECLR) // simple hosting
- // Notify the client that it should release any threads that it had doing work
- // while the runtime was debugger-suspended.
- IDebuggerThreadControl *pIDTC = CorHost::GetDebuggerThreadControl();
- if (pIDTC)
- {
- LOG((LF_CORDB, LL_INFO1000, "RESUME: notifying IDebuggerThreadControl client.\n"));
- pIDTC->ReleaseAllRuntimeThreads();
- }
-#endif // !defined(FEATURE_CORECLR)
// Make sure we completed the previous sync
_ASSERTE(m_DebugWillSyncCount == -1);
@@ -6407,321 +6262,6 @@ void Thread::SysResumeFromDebug(AppDomain *pAppDomain)
LOG((LF_CORDB, LL_INFO1000, "RESUME: resume complete. Trap count: %d\n", g_TrapReturningThreads.Load()));
}
-#ifndef FEATURE_CORECLR
-
-// Suspend a thread at the system level. We distinguish between user suspensions,
-// and system suspensions so that a VB program cannot resume a thread we have
-// suspended for GC.
-//
-// This service won't return until the suspension is complete. This deserves some
-// explanation. The thread is considered to be suspended if it can make no further
-// progress within the EE. For example, a thread that has exited the EE via
-// COM Interop or N/Direct is considered suspended -- if we've arranged it so that
-// the thread cannot return back to the EE without blocking.
-void Thread::UserSuspendThread()
-{
- CONTRACTL {
- NOTHROW;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- // Read the general comments on thread suspension earlier, to understand why we
- // take these locks.
-
- // GC can occur in here:
- STRESS_LOG0(LF_SYNC, LL_INFO100, "UserSuspendThread obtain lock\n");
- ThreadStoreLockHolder tsl;
-
- // User suspensions (e.g. from VB and C#) are distinguished from internal
- // suspensions so a poorly behaved program cannot resume a thread that the system
- // has suspended for GC.
- if (m_State & TS_UserSuspendPending)
- {
- // This thread is already experiencing a user suspension, so ignore the
- // new request.
- _ASSERTE(!ThreadStore::HoldingThreadStore(this));
- }
- else
- if (this != GetThread())
- {
- // First suspension of a thread other than the current one.
- if (m_State & TS_Unstarted)
- {
- // There is an important window in here. T1 can call T2.Start() and then
- // T2.Suspend(). Suspend is disallowed on an unstarted thread. But from T1's
- // point of view, T2 is started. In reality, T2 hasn't been scheduled by the
- // OS, so it is still an unstarted thread. We don't want to perform a normal
- // suspension on it in this case, because it is currently contributing to the
- // PendingThreadCount. We want to get it fully started before we suspend it.
- // This is particularly important if its background status is changing
- // underneath us because otherwise we might not detect that the process should
- // be exited at the right time.
- //
- // It turns out that this is a simple situation to implement. We are holding
- // the ThreadStoreLock. TransferStartedThread will likewise acquire that
- // lock. So if we detect it, we simply set a bit telling the thread to
- // suspend itself. This is NOT the normal suspension request because we don't
- // want the thread to suspend until it has fully started.
- FastInterlockOr((ULONG *) &m_State, TS_SuspendUnstarted);
- }
- else if (m_State & (TS_Detached | TS_Dead))
- {
- return;
- }
- else
- {
- // We just want to trap this thread if it comes back into cooperative mode
- SetupForSuspension(TS_UserSuspendPending);
- m_SafeEvent.Reset();
-
- // Pause it so we can operate on it without it squirming under us.
-RetrySuspension:
- // We can not allocate memory after we suspend a thread.
- // Otherwise, we may deadlock the process when CLR is hosted.
- ThreadStore::AllocateOSContext();
-
- SuspendThreadResult str = SuspendThread();
-
- // The only safe place to suspend a thread asynchronously is if it is in
- // fully interruptible cooperative JIT code. Preemptive mode can hold all
- // kinds of locks that make it unsafe to suspend. All other cases are
- // handled somewhat synchronously (e.g. through hijacks, GC mode toggles, etc.)
- //
- // For example, on a SMP if the thread is blocked waiting for the ThreadStore
- // lock, it can cause a deadlock if we suspend it (even though it is in
- // preemptive mode).
- //
- // If a thread is in preemptive mode (including the tricky optimized N/Direct
- // case), we can just mark it for suspension. It will make no further progress
- // in the EE.
- if (str == STR_NoStressLog)
- {
- // We annot assume anything about the thread's current state.
- goto RetrySuspension;
- }
- else if (!m_fPreemptiveGCDisabled)
- {
- MarkForSuspension(TS_UserSuspendPending);
-
- // Let the thread run until it reaches a safe spot.
- if (str == STR_Success)
- {
- ResumeThread();
- }
- }
- else if (str == STR_Failure || str == STR_UnstartedOrDead)
- {
- // The thread cannot be unstarted, as we have already
- // checked for that above.
- _ASSERTE(!(m_State & TS_Unstarted));
-
- // Nothing to do if the thread has already terminated.
- }
- else if (str == STR_SwitchedOut)
- {
- goto RetrySuspension;
- }
- else
- {
- _ASSERTE(str == STR_Success);
-#if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
- WorkingOnThreadContextHolder workingOnThreadContext(this);
- if (workingOnThreadContext.Acquired() && HandledJITCase())
- {
- _ASSERTE(m_fPreemptiveGCDisabled);
- // Redirect thread so we can capture a good thread context
- // (GetThreadContext is not sufficient, due to an OS bug).
- // If we don't succeed (should only happen on Win9X, due to
- // a different OS bug), we must resume the thread and try
- // again.
- if (!CheckForAndDoRedirectForUserSuspend())
- {
- ResumeThread();
- goto RetrySuspension;
- }
- }
-#endif // FEATURE_HIJACK && !PLATFORM_UNIX
-
- // Thread is executing in cooperative mode. We're going to have to
- // move it to a safe spot.
- MarkForSuspension(TS_UserSuspendPending);
-
- // Let the thread run until it reaches a safe spot.
- ResumeThread();
-
- // wait until it leaves cooperative GC mode or is JIT suspended
- FinishSuspendingThread();
- }
- }
- }
- else
- {
- GCX_PREEMP();
- SetupForSuspension(TS_UserSuspendPending);
- MarkForSuspension(TS_UserSuspendPending);
-
- // prepare to block ourselves
- tsl.Release();
- _ASSERTE(!ThreadStore::HoldingThreadStore(this));
-
- WaitSuspendEvents();
- }
-}
-
-
-// if the only suspension of this thread is user imposed, resume it. But don't
-// resume from any system suspensions (like GC).
-BOOL Thread::UserResumeThread()
-{
- CONTRACTL {
- NOTHROW;
- GC_TRIGGERS;
- }
- CONTRACTL_END;
-
- // If we are attempting to resume when we aren't in a user suspension,
- // its an error.
- BOOL res = FALSE;
-
- // Note that the model does not count. In other words, you can call Thread.Suspend()
- // five times and Thread.Resume() once. The result is that the thread resumes.
-
- STRESS_LOG0(LF_SYNC, INFO3, "UserResumeThread obtain lock\n");
- ThreadStoreLockHolder TSLockHolder;
-
- // If we have marked a thread for suspension, while that thread is still starting
- // up, simply remove the bit to resume it.
- if (m_State & TS_SuspendUnstarted)
- {
- _ASSERTE((m_State & TS_UserSuspendPending) == 0);
- FastInterlockAnd((ULONG *) &m_State, ~TS_SuspendUnstarted);
- res = TRUE;
- }
-
- // If we are still trying to suspend the thread, forget about it.
- if (m_State & TS_UserSuspendPending)
- {
- ReleaseFromSuspension(TS_UserSuspendPending);
- SetSafeEvent();
- res = TRUE;
- }
-
- return res;
-}
-
-
-// We are asynchronously trying to suspend this thread. Stay here until we achieve
-// that goal (in fully interruptible JIT code), or the thread dies, or it leaves
-// the EE (in which case the Pending flag will cause it to synchronously suspend
-// itself later, or if the thread tells us it is going to synchronously suspend
-// itself because of hijack activity, etc.
-void Thread::FinishSuspendingThread()
-{
- CONTRACTL {
- NOTHROW;
- if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
- }
- CONTRACTL_END;
-
- DWORD res;
-
- // There are two threads of interest -- the current thread and the thread we are
- // going to wait for. Since the current thread is about to wait, it's important
- // that it be in preemptive mode at this time.
-
-#if _DEBUG
- DWORD dbgTotalTimeout = 0;
-#endif
-
- // Wait for us to enter the ping period, then check if we are in interruptible
- // JIT code.
- while (TRUE)
- {
- ThreadSuspend::UnlockThreadStore();
- res = m_SafeEvent.Wait(PING_JIT_TIMEOUT,FALSE);
- STRESS_LOG0(LF_SYNC, INFO3, "FinishSuspendingThread obtain lock\n");
- ThreadSuspend::LockThreadStore(ThreadSuspend::SUSPEND_OTHER);
-
- if (res == WAIT_TIMEOUT)
- {
-#ifdef _DEBUG
- if ((dbgTotalTimeout += PING_JIT_TIMEOUT) >= g_pConfig->SuspendDeadlockTimeout())
- {
- _ASSERTE(!"Timeout detected trying to synchronously suspend a thread");
- dbgTotalTimeout = 0;
- }
-#endif
- // Suspend the thread and see if we are in interruptible code (placing
- // a hijack if warranted).
-#if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
- RetrySuspension:
-#endif
- // The thread is detached/dead. Suspend is no op.
- if (m_State & (TS_Detached | TS_Dead))
- {
- return;
- }
-
- // We can not allocate memory after we suspend a thread.
- // Otherwise, we may deadlock the process when CLR is hosted.
- ThreadStore::AllocateOSContext();
-
- SuspendThreadResult str = SuspendThread();
-
- if (m_fPreemptiveGCDisabled && str == STR_Success)
- {
-#if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
- WorkingOnThreadContextHolder workingOnThreadContext(this);
- if (workingOnThreadContext.Acquired() && HandledJITCase())
- {
- _ASSERTE(m_State & TS_UserSuspendPending);
- // Redirect thread so we can capture a good thread context
- // (GetThreadContext is not sufficient, due to an OS bug).
- // If we don't succeed (should only happen on Win9X, due to
- // a different OS bug), we must resume the thread and try
- // again.
- if (!CheckForAndDoRedirectForUserSuspend())
- {
- ResumeThread();
- goto RetrySuspension;
- }
- }
-#endif // FEATURE_HIJACK && !PLATFORM_UNIX
- // Keep trying...
- ResumeThread();
- }
- else if (!m_fPreemptiveGCDisabled)
- {
- // The thread has transitioned out of the EE. It can't get back in
- // without synchronously suspending itself. We can now return to our
- // caller since this thread cannot make further progress within the
- // EE.
- if (str == STR_Success)
- {
- ResumeThread();
- }
- break;
- }
- else if (str == STR_SwitchedOut)
- {
- // The task has been switched out while in Cooperative GC mode.
- // We will wait for the thread again.
- }
- }
- else
- {
- // SafeEvent has been set so we don't need to actually suspend. Either
- // the thread died, or it will enter a synchronous suspension based on
- // the UserSuspendPending bit.
- _ASSERTE(res == WAIT_OBJECT_0);
- _ASSERTE(!ThreadStore::HoldingThreadStore(this));
- break;
- }
- }
-}
-
-#endif // FEATURE_CORECLR
void Thread::SetSafeEvent()
@@ -7008,12 +6548,6 @@ StackWalkAction SWCB_GetExecutionState(CrawlFrame *pCF, VOID *pData)
else
#endif // FEATURE_CONSERVATIVE_GC
{
-#ifndef HIJACK_NONINTERRUPTIBLE_THREADS
- if (!pES->m_IsInterruptible)
- {
- notJittedCase = true;
- }
-#else // HIJACK_NONINTERRUPTIBLE_THREADS
// if we're not interruptible right here, we need to determine the
// return address for hijacking.
if (!pES->m_IsInterruptible)
@@ -7087,7 +6621,6 @@ StackWalkAction SWCB_GetExecutionState(CrawlFrame *pCF, VOID *pData)
action = SWA_CONTINUE;
#endif // !WIN64EXCEPTIONS
}
-#endif // HIJACK_NONINTERRUPTIBLE_THREADS
}
// else we are successfully out of here with SWA_ABORT
}
@@ -7162,7 +6695,6 @@ void STDCALL OnHijackWorker(HijackArgs * pArgs)
}
CONTRACTL_END;
-#ifdef HIJACK_NONINTERRUPTIBLE_THREADS
Thread *thread = GetThread();
#ifdef FEATURE_STACK_PROBE
@@ -7205,9 +6737,6 @@ void STDCALL OnHijackWorker(HijackArgs * pArgs)
#endif // _DEBUG
frame.Pop();
-#else
- PORTABILITY_ASSERT("OnHijackWorker not implemented on this platform.");
-#endif // HIJACK_NONINTERRUPTIBLE_THREADS
}
ReturnKind GetReturnKindFromMethodTable(Thread *pThread, EECodeInfo *codeInfo)