Fix hijacking for ARM/ARM64/x86 on Unix (#20042)
[platform/upstream/coreclr.git] / src / vm / threadsuspend.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 // 
5 // threadsuspend.CPP
6 // 
7 // This file contains the implementation of thread suspension. The implementation of thread suspension
8 // used to be spread through multiple places. That is why, many methods still live in their own homes 
9 // (class Thread, class ThreadStore, etc.). They should be eventually refactored into class ThreadSuspend.
10 //
11
12 #include "common.h"
13
14 #include "threadsuspend.h"
15
16 #include "finalizerthread.h"
17 #include "dbginterface.h"
18
19 #include "mdaassistants.h"
20
21 // from ntstatus.h
22 #define STATUS_SUSPEND_COUNT_EXCEEDED    ((NTSTATUS)0xC000004AL)
23
24 #define HIJACK_NONINTERRUPTIBLE_THREADS
25
26 bool ThreadSuspend::s_fSuspendRuntimeInProgress = false;
27
28 CLREvent* ThreadSuspend::g_pGCSuspendEvent = NULL;
29
30 ThreadSuspend::SUSPEND_REASON ThreadSuspend::m_suspendReason;
31 Thread* ThreadSuspend::m_pThreadAttemptingSuspendForGC;
32
33 CLREventBase * ThreadSuspend::s_hAbortEvt = NULL;
34 CLREventBase * ThreadSuspend::s_hAbortEvtCache = NULL;
35
36 // If you add any thread redirection function, make sure the debugger can 1) recognize the redirection 
37 // function, and 2) retrieve the original CONTEXT.  See code:Debugger.InitializeHijackFunctionAddress and
38 // code:DacDbiInterfaceImpl.RetrieveHijackedContext. 
39 extern "C" void             RedirectedHandledJITCaseForGCThreadControl_Stub(void);
40 extern "C" void             RedirectedHandledJITCaseForDbgThreadControl_Stub(void);
41 extern "C" void             RedirectedHandledJITCaseForUserSuspend_Stub(void);
42
43 #define GetRedirectHandlerForGCThreadControl()      \
44                 ((PFN_REDIRECTTARGET) GetEEFuncEntryPoint(RedirectedHandledJITCaseForGCThreadControl_Stub))
45 #define GetRedirectHandlerForDbgThreadControl()     \
46                 ((PFN_REDIRECTTARGET) GetEEFuncEntryPoint(RedirectedHandledJITCaseForDbgThreadControl_Stub))
47 #define GetRedirectHandlerForUserSuspend()          \
48                 ((PFN_REDIRECTTARGET) GetEEFuncEntryPoint(RedirectedHandledJITCaseForUserSuspend_Stub))
49
50 #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
51 #if defined(HAVE_GCCOVER) && defined(USE_REDIRECT_FOR_GCSTRESS) // GCCOVER
52 extern "C" void             RedirectedHandledJITCaseForGCStress_Stub(void);
53 #define GetRedirectHandlerForGCStress()             \
54                 ((PFN_REDIRECTTARGET) GetEEFuncEntryPoint(RedirectedHandledJITCaseForGCStress_Stub))
55 #endif // HAVE_GCCOVER && USE_REDIRECT_FOR_GCSTRESS
56 #endif // _TARGET_AMD64_ || _TARGET_ARM_
57
58
59 // Every PING_JIT_TIMEOUT ms, check to see if a thread in JITted code has wandered
60 // into some fully interruptible code (or should have a different hijack to improve
61 // our chances of snagging it at a safe spot).
62 #define PING_JIT_TIMEOUT        10
63
64 // When we find a thread in a spot that's not safe to abort -- how long to wait before
65 // we try again.
66 #define ABORT_POLL_TIMEOUT      10
67 #ifdef _DEBUG
68 #define ABORT_FAIL_TIMEOUT      40000
69 #endif // _DEBUG
70
71 //
72 // CANNOT USE IsBad*Ptr() methods here.  They are *banned* APIs because of various
73 // reasons (see http://winweb/wincet/bannedapis.htm).
74 //
75 #define IS_VALID_WRITE_PTR(addr, size)      _ASSERTE(addr != NULL)
76 #define IS_VALID_CODE_PTR(addr)             _ASSERTE(addr != NULL)
77
78
79 void ThreadSuspend::SetSuspendRuntimeInProgress()
80 {
81     LIMITED_METHOD_CONTRACT;
82     _ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit());
83     _ASSERTE(!s_fSuspendRuntimeInProgress || IsAtProcessExit());
84     s_fSuspendRuntimeInProgress = true;
85 }
86
87 void ThreadSuspend::ResetSuspendRuntimeInProgress()
88 {
89     LIMITED_METHOD_CONTRACT;
90     _ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit());
91     _ASSERTE(s_fSuspendRuntimeInProgress || IsAtProcessExit());
92     s_fSuspendRuntimeInProgress = false;
93 }
94
95
96 // When SuspendThread returns, target thread may still be executing user code.
97 // We can not access data, e.g. m_fPreemptiveGCDisabled, changed by target thread.
98 // But our code depends on reading these data.  To make this operation safe, we
99 // call GetThreadContext which returns only after target thread does not execute
100 // any user code.
101
102 // Message from David Cutler
103 /*
104     After SuspendThread returns, can the suspended thread continue to execute code in user mode?
105
106     [David Cutler] The suspended thread cannot execute any more user code, but it might be currently "running"
107     on a logical processor whose other logical processor is currently actually executing another thread.
108     In this case the target thread will not suspend until the hardware switches back to executing instructions
109     on its logical processor. In this case even the memory barrier would not necessarily work - a better solution
110     would be to use interlocked operations on the variable itself.
111
112     After SuspendThread returns, does the store buffer of the CPU for the suspended thread still need to drain?
113
114     Historically, we've assumed that the answer to both questions is No.  But on one 4/8 hyper-threaded machine
115     running Win2K3 SP1 build 1421, we've seen two stress failures where SuspendThread returns while writes seem to still be in flight.
116
117     Usually after we suspend a thread, we then call GetThreadContext.  This seems to guarantee consistency.
118     But there are places we would like to avoid GetThreadContext, if it's safe and legal.
119
120     [David Cutler] Get context delivers a APC to the target thread and waits on an event that will be set
121     when the target thread has delivered its context.
122
123     Chris.
124 */
125
126 // Message from Neill Clift
127 /*
128     What SuspendThread does is insert an APC block into a target thread and request an inter-processor interrupt to
129     do the APC interrupt. It doesn't wait till the thread actually enters some state or the interrupt has been serviced.
130
131     I took a quick look at the APIC spec in the Intel manuals this morning. Writing to the APIC posts a message on a bus.
132     Processors accept messages and presumably queue the s/w interrupts at this time. We don't wait for this acceptance
133     when we send the IPI so at least on APIC machines when you suspend a thread it continues to execute code for some short time
134     after the routine returns. We use other mechanisms for IPI and so it could work differently on different h/w.
135
136 */
137 BOOL EnsureThreadIsSuspended (HANDLE hThread, Thread* pThread)
138 {
139     STATIC_CONTRACT_NOTHROW;
140     STATIC_CONTRACT_GC_NOTRIGGER;
141
142     WRAPPER_NO_CONTRACT;
143
144     CONTEXT ctx;
145     ctx.ContextFlags = CONTEXT_INTEGER;
146
147     BOOL ret;
148     ret = ::GetThreadContext(hThread, &ctx);
149     return ret;
150 }
151
152 FORCEINLINE VOID MyEnterLogLock()
153 {
154     EnterLogLock();
155 }
156 FORCEINLINE VOID MyLeaveLogLock()
157 {
158     LeaveLogLock();
159 }
160
161 // On non-Windows CORECLR platforms remove Thread::SuspendThread support
162 #ifndef DISABLE_THREADSUSPEND 
163 // SuspendThread
164 //   Attempts to OS-suspend the thread, whichever GC mode it is in.
165 // Arguments:
166 //   fOneTryOnly - If TRUE, report failure if the thread has its
167 //     m_dwForbidSuspendThread flag set.  If FALSE, retry.
168 //   pdwSuspendCount - If non-NULL, will contain the return code
169 //     of the underlying OS SuspendThread call on success,
170 //     undefined on any kind of failure.
171 // Return value:
172 //   A SuspendThreadResult value indicating success or failure.
173 Thread::SuspendThreadResult Thread::SuspendThread(BOOL fOneTryOnly, DWORD *pdwSuspendCount)
174 {
175     CONTRACTL {
176         NOTHROW;
177         GC_NOTRIGGER;
178     }
179     CONTRACTL_END;
180
181 #ifdef STRESS_LOG
182     if (StressLog::StressLogOn((unsigned int)-1, 0))
183     {
184         // Make sure to create the stress log for the current thread
185         // (if needed) before we suspend the target thread.  The target
186         // thread may be holding the stress log lock when we suspend it,
187         // which could cause a deadlock.
188         if (StressLog::CreateThreadStressLog() == NULL)
189         {
190             return STR_NoStressLog;
191         }
192     }
193 #endif
194
195     Volatile<HANDLE> hThread;
196     SuspendThreadResult str = (SuspendThreadResult) -1;
197     DWORD dwSuspendCount = 0;
198     DWORD tries = 1;
199 #if defined(_DEBUG)
200     int nCnt = 0;
201     bool bDiagSuspend = g_pConfig->GetDiagnosticSuspend();
202     ULONGLONG i64TimestampStart = CLRGetTickCount64();
203     ULONGLONG i64TimestampCur = i64TimestampStart;
204     ULONGLONG i64TimestampPrev = i64TimestampStart; 
205
206     // This is the max allowed timestamp ticks to transpire from beginning of
207     // our attempt to suspend the thread, before we'll assert (implying we believe
208     // there might be a deadlock) - (default = 2000).
209     ULONGLONG i64TimestampTicksMax = g_pConfig->SuspendThreadDeadlockTimeoutMs();
210 #endif // _DEBUG
211
212 #if defined(_DEBUG)
213     // Stop the stress log from allocating any new memory while in this function
214     // as that can lead to deadlocks
215     CantAllocHolder hldrCantAlloc;
216 #endif
217
218     DWORD dwSwitchCount = 0;
219
220     while (TRUE) {
221         StateHolder<MyEnterLogLock, MyLeaveLogLock> LogLockHolder(FALSE);
222
223         CounterHolder handleHolder(&m_dwThreadHandleBeingUsed);
224
225         // Whether or not "goto retry" should YieldProcessor and __SwitchToThread
226         BOOL doSwitchToThread = TRUE;
227
228         hThread = GetThreadHandle();
229         if (hThread == INVALID_HANDLE_VALUE) {
230             str = STR_UnstartedOrDead;
231             break;
232         }
233         else if (hThread == SWITCHOUT_HANDLE_VALUE) {
234             str = STR_SwitchedOut;
235             break;
236         }
237
238         {
239             // We do not want to suspend the target thread while it is holding the log lock.
240             // By acquiring the lock ourselves, we know that this is not the case.
241             LogLockHolder.Acquire();
242             
243             // It is important to avoid two threads suspending each other.
244             // Before a thread suspends another, it increments its own m_dwForbidSuspendThread count first,
245             // then it checks the target thread's m_dwForbidSuspendThread.
246             ForbidSuspendThreadHolder forbidSuspend;
247             if ((m_dwForbidSuspendThread != 0))
248             {
249 #if defined(_DEBUG)
250                 // Enable the diagnostic ::SuspendThread() if the 
251                 //     DiagnosticSuspend config setting is set.
252                 // This will interfere with the mutual suspend race but it's
253                 //     here only for diagnostic purposes anyway
254                 if (!bDiagSuspend)
255 #endif // _DEBUG
256                     goto retry;
257             }
258
259             dwSuspendCount = ::SuspendThread(hThread);
260
261             //
262             // Since SuspendThread is asynchronous, we now must wait for the thread to 
263             // actually be suspended before decrementing our own m_dwForbidSuspendThread count. 
264             // Otherwise there would still be a chance for the "suspended" thread to suspend us
265             // before it really stops running.
266             //
267             if ((int)dwSuspendCount >= 0)
268             {
269                 if (!EnsureThreadIsSuspended(hThread, this))
270                 {
271                     ::ResumeThread(hThread);
272                     str = STR_Failure;
273                     break;
274                 }
275             }
276         }
277         if ((int)dwSuspendCount >= 0)
278         {
279             if (hThread == GetThreadHandle())
280             {
281                 if (m_dwForbidSuspendThread != 0)
282                 {
283 #if defined(_DEBUG)
284                     // Log diagnostic below 8 times during the i64TimestampTicksMax period
285                     if (i64TimestampCur-i64TimestampStart >= nCnt*(i64TimestampTicksMax>>3) )
286                     {
287                         CONTEXT ctx; 
288                         SetIP(&ctx, -1);
289                         ctx.ContextFlags = CONTEXT_CONTROL;
290                         this->GetThreadContext(&ctx);
291                         STRESS_LOG7(LF_SYNC, LL_INFO1000, 
292                             "Thread::SuspendThread[%p]:  EIP=%p. nCnt=%d. result=%d.\n"
293                             "\t\t\t\t\t\t\t\t\t     forbidSuspend=%d. coop=%d. state=%x.\n", 
294                             this, GetIP(&ctx), nCnt, dwSuspendCount,
295                             (LONG)this->m_dwForbidSuspendThread, (ULONG)this->m_fPreemptiveGCDisabled, this->GetSnapshotState());
296
297                         // Enable a preemptive assert in diagnostic mode: before we
298                         // resume the target thread to get its current state in the debugger
299                         if (bDiagSuspend)
300                         {
301                             // triggered after 6 * 250msec
302                             _ASSERTE(nCnt < 6 && "Timing out in Thread::SuspendThread");
303                         }
304
305                         ++nCnt;
306                     }
307 #endif // _DEBUG
308                     ::ResumeThread(hThread);
309
310 #if defined(_DEBUG)
311                     // If the suspend diagnostics are enabled we need to spin here in order to avoid
312                     // the case where we Suspend/Resume the target thread without giving it a chance to run.
313                     if ((!fOneTryOnly) && bDiagSuspend)
314                     {
315                         while ( m_dwForbidSuspendThread != 0 && 
316                             CLRGetTickCount64()-i64TimestampStart < nCnt*(i64TimestampTicksMax>>3) )
317                         {
318                             if (g_SystemInfo.dwNumberOfProcessors > 1)
319                             {
320                                 if ((tries++) % 20 != 0) 
321                                 {
322                                     YieldProcessor();           // play nice on hyperthreaded CPUs
323                                 } else {
324                                     __SwitchToThread(0, ++dwSwitchCount);
325                                 }
326                             }
327                             else
328                             {
329                                 __SwitchToThread(0, ++dwSwitchCount); // don't spin on uniproc machines
330                             }
331                         }
332                     }
333 #endif // _DEBUG
334                     goto retry;
335                 }
336                 // We suspend the right thread
337 #ifdef _DEBUG
338                 Thread * pCurThread = GetThread();
339                 if (pCurThread != NULL)
340                 {
341                     pCurThread->dbg_m_cSuspendedThreads ++;
342                     _ASSERTE(pCurThread->dbg_m_cSuspendedThreads > 0);
343                 }
344 #endif
345                 IncCantAllocCount();
346                 
347                 m_ThreadHandleForResume = hThread;
348                 str = STR_Success;
349                 break;
350             }
351             else
352             {
353                 // A thread was switch out but in again.
354                 // We suspend a wrong thread.
355                 ::ResumeThread(hThread);
356                 doSwitchToThread = FALSE;
357                 goto retry;
358             }
359         }
360         else {
361             // We can get here either SuspendThread fails
362             // Or the fiber thread dies after this fiber switched out.
363
364             if ((int)dwSuspendCount != -1) {
365                 STRESS_LOG1(LF_SYNC, LL_INFO1000, "In Thread::SuspendThread ::SuspendThread returned %x\n", dwSuspendCount);
366             }
367             if (GetThreadHandle() == SWITCHOUT_HANDLE_VALUE) {
368                 str = STR_SwitchedOut;
369                 break;
370             }
371             else {
372                 // Our callers generally expect that STR_Failure means that
373                 // the thread has exited.
374 #ifndef FEATURE_PAL                
375                 _ASSERTE(NtCurrentTeb()->LastStatusValue != STATUS_SUSPEND_COUNT_EXCEEDED);
376 #endif // !FEATURE_PAL                
377                 str = STR_Failure;
378                 break;
379             }
380         }
381
382 retry:
383         handleHolder.Release();
384         LogLockHolder.Release();
385
386         if (fOneTryOnly)
387         {
388             str = STR_Forbidden;
389             break;
390         }
391
392 #if defined(_DEBUG)
393         i64TimestampPrev = i64TimestampCur;
394         i64TimestampCur = CLRGetTickCount64();
395         // CLRGetTickCount64() is global per machine (not per CPU, like getTimeStamp()).
396         // Next ASSERT states that CLRGetTickCount64() is increasing, or has wrapped.
397         // If it wrapped, the last iteration should have executed faster then 0.5 seconds.
398         _ASSERTE(i64TimestampCur >= i64TimestampPrev || i64TimestampCur <= 500);
399
400         if (i64TimestampCur - i64TimestampStart >= i64TimestampTicksMax)
401         {
402             dwSuspendCount = ::SuspendThread(hThread);
403             _ASSERTE(!"It takes too long to suspend a thread");
404             if ((int)dwSuspendCount >= 0)
405                 ::ResumeThread(hThread);
406         }
407 #endif // _DEBUG
408
409         if (doSwitchToThread)
410         {
411             // When looking for deadlocks we need to allow the target thread to run in order to make some progress.
412             // On multi processor machines we saw the suspending thread resuming immediately after the __SwitchToThread()
413             // because it has another few processors available.  As a consequence the target thread was being Resumed and
414             // Suspended right away, w/o a real chance to make any progress.
415             if (g_SystemInfo.dwNumberOfProcessors > 1)
416             {
417                 if ((tries++) % 20 != 0) {
418                     YieldProcessor();           // play nice on hyperthreaded CPUs
419                 } else {
420                     __SwitchToThread(0, ++dwSwitchCount);
421                 }
422             }
423             else
424             {
425                 __SwitchToThread(0, ++dwSwitchCount); // don't spin on uniproc machines
426             }
427         }
428
429     }
430
431 #ifdef PROFILING_SUPPORTED
432     {
433         BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
434         if (str == STR_Success)
435         {
436             g_profControlBlock.pProfInterface->RuntimeThreadSuspended((ThreadID)this);
437         }
438         END_PIN_PROFILER();
439     }
440 #endif // PROFILING_SUPPORTED
441
442     if (pdwSuspendCount != NULL)
443     {
444         *pdwSuspendCount = dwSuspendCount;
445     }
446     _ASSERTE(str != (SuspendThreadResult) -1);
447     return str;
448
449 }
450 #endif // DISABLE_THREADSUSPEND
451
452 // On non-Windows CORECLR platforms remove Thread::ResumeThread support
453 #ifndef DISABLE_THREADSUSPEND 
454 DWORD Thread::ResumeThread()
455 {
456     CONTRACTL
457     {
458         NOTHROW;
459         GC_NOTRIGGER;
460         SO_TOLERANT;
461         MODE_ANY;
462     }
463     CONTRACTL_END;
464
465     _ASSERTE (m_ThreadHandleForResume != INVALID_HANDLE_VALUE);
466
467     _ASSERTE (GetThreadHandle() != SWITCHOUT_HANDLE_VALUE);
468
469     //DWORD res = ::ResumeThread(GetThreadHandle());
470     DWORD res = ::ResumeThread(m_ThreadHandleForResume);
471     _ASSERTE (res != 0 && "Thread is not previously suspended");
472 #ifdef _DEBUG_IMPL
473     _ASSERTE (!m_Creater.IsCurrentThread());
474     if ((res != (DWORD)-1) && (res != 0))
475     {
476         Thread * pCurThread = GetThread();
477         if (pCurThread != NULL)
478         {
479             _ASSERTE(pCurThread->dbg_m_cSuspendedThreads > 0);
480             pCurThread->dbg_m_cSuspendedThreads --;
481             _ASSERTE(pCurThread->dbg_m_cSuspendedThreadsWithoutOSLock <= pCurThread->dbg_m_cSuspendedThreads);
482         }
483     }
484 #endif
485     if (res != (DWORD) -1 && res != 0) 
486     {
487         DecCantAllocCount();
488     }
489 #ifdef PROFILING_SUPPORTED    
490     {
491         BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
492         if ((res != 0) && (res != (DWORD)-1))
493         {
494             g_profControlBlock.pProfInterface->RuntimeThreadResumed((ThreadID)this);
495         }
496         END_PIN_PROFILER();
497     }
498 #endif
499     return res;
500
501 }
502 #endif // DISABLE_THREADSUSPEND
503
504 #ifdef _DEBUG
505 void* forceStackA;
506
507 // CheckSuspended
508 //   Checks whether the given thread is currently suspended.
509 //   Note that if we cannot determine the true suspension status
510 //   of the thread, we succeed.  Intended to be used in asserts
511 //   in operations that require the target thread to be suspended.
512 // Arguments:
513 //   pThread - The thread to examine.
514 // Return value:
515 //   FALSE, if the thread is definitely not suspended.
516 //   TRUE, otherwise.
517 static inline BOOL CheckSuspended(Thread *pThread)
518 {
519     CONTRACTL
520     {
521         NOTHROW;
522         GC_NOTRIGGER;
523         DEBUG_ONLY;
524     }
525     CONTRACTL_END;
526
527     _ASSERTE(GetThread() != pThread);
528     _ASSERTE(CheckPointer(pThread));
529
530 #ifndef DISABLE_THREADSUSPEND
531     // Only perform this test if we're allowed to call back into the host.
532     // Thread::SuspendThread contains several potential calls into the host.
533     if (CanThisThreadCallIntoHost())
534     {
535         DWORD dwSuspendCount;
536         Thread::SuspendThreadResult str = pThread->SuspendThread(FALSE, &dwSuspendCount);
537         forceStackA = &dwSuspendCount;
538         if (str == Thread::STR_Success)
539         {
540             pThread->ResumeThread();
541             return dwSuspendCount >= 1;
542         }
543     }
544 #endif // !DISABLE_THREADSUSPEND
545     return TRUE;
546 }
547 #endif //_DEBUG
548
549 BOOL EEGetThreadContext(Thread *pThread, CONTEXT *pContext)
550 {
551     CONTRACTL {
552         NOTHROW;
553         GC_NOTRIGGER;
554     }
555     CONTRACTL_END;
556
557     _ASSERTE(CheckSuspended(pThread));
558
559     BOOL ret =  pThread->GetThreadContext(pContext);
560
561     STRESS_LOG6(LF_SYNC, LL_INFO1000, "Got thread context ret = %d EIP = %p ESP = %p EBP = %p, pThread = %p, ContextFlags = 0x%x\n",
562         ret, GetIP(pContext), GetSP(pContext), GetFP(pContext), pThread, pContext->ContextFlags);
563
564     return ret;
565
566 }
567
568 BOOL EESetThreadContext(Thread *pThread, const CONTEXT *pContext)
569 {
570     CONTRACTL {
571         NOTHROW;
572         GC_NOTRIGGER;
573     }
574     CONTRACTL_END;
575
576 #ifdef _TARGET_X86_
577     _ASSERTE(CheckSuspended(pThread));
578 #endif
579
580     BOOL ret = pThread->SetThreadContext(pContext);
581
582     STRESS_LOG6(LF_SYNC, LL_INFO1000, "Set thread context ret = %d EIP = %p ESP = %p EBP = %p, pThread = %p, ContextFlags = 0x%x\n",
583         ret, GetIP((CONTEXT*)pContext), GetSP((CONTEXT*)pContext), GetFP((CONTEXT*)pContext), pThread, pContext->ContextFlags);
584
585     return ret;
586 }
587
588 // The AbortReason must be cleared at the following times:
589 //
590 //  1.  When the application performs a ResetAbort.
591 //
592 //  2.  When the physical thread stops running.  That's because we must eliminate any
593 //      cycles that would otherwise be uncollectible, between the Reason and the Thread.
594 //      Nobody can retrieve the Reason after the thread stops running anyway.
595 //
596 //  We don't have to do any work when the AppDomain containing the Reason object is unloaded.
597 //  That's because the HANDLE is released as part of the tear-down.  The 'adid' prevents us
598 //  from ever using the trash handle value thereafter.
599
600 void Thread::ClearAbortReason(BOOL pNoLock)
601 {
602     CONTRACTL
603     {
604         GC_NOTRIGGER;
605         MODE_COOPERATIVE;
606         NOTHROW;
607     }
608     CONTRACTL_END;
609
610     OBJECTHANDLE oh;
611     ADID adid;
612
613     if (pNoLock){
614         // Stash the fields so we can destroy the OBJECTHANDLE if appropriate.
615         oh = m_AbortReason;
616         adid = m_AbortReasonDomainID;
617
618         // Clear the fields.
619         m_AbortReason = 0;
620         m_AbortReasonDomainID = ADID(INVALID_APPDOMAIN_ID);
621     }
622     else
623     // Scope the lock to stashing and clearing the two fields on the Thread object.
624     {
625         // Atomically get the OBJECTHANDLE and ADID of the object, and then
626         //  clear them.
627
628         // NOTE: get the lock on this thread object, not on the executing thread.
629         Thread::AbortRequestLockHolder lock(this);
630
631         // Stash the fields so we can destroy the OBJECTHANDLE if appropriate.
632         oh = m_AbortReason;
633         adid = m_AbortReasonDomainID;
634
635         // Clear the fields.
636         m_AbortReason = 0;
637         m_AbortReasonDomainID = ADID(INVALID_APPDOMAIN_ID);
638     }
639
640     // If there is an OBJECTHANDLE, try to clear it.
641     if (oh != 0 && adid.m_dwId != 0)
642     {   // See if the domain is still valid; if so, destroy the ObjectHandle
643         AppDomainFromIDHolder ad(adid, TRUE);
644         if (!ad.IsUnloaded())
645         {   // Still a valid domain, so destroy the handle.
646             DestroyHandle(oh);
647         }
648     }
649 }
650
651
652 // Context passed down through a stack crawl (see code below).
653 struct StackCrawlContext
654 {
655     enum SCCType
656     {
657         SCC_CheckWithinEH   = 0x00000001,
658         SCC_CheckWithinCer  = 0x00000002,
659     };
660     Thread* pAbortee;
661     int         eType;
662     BOOL        fUnprotectedCode;
663     BOOL        fWithinEHClause;
664     BOOL        fWithinCer;
665     BOOL        fHasManagedCodeOnStack;
666     BOOL        fWriteToStressLog;
667
668     BOOL        fHaveLatchedCF;
669     CrawlFrame  LatchedCF;
670 };
671
672 // Crawl the stack looking for Thread Abort related information (whether we're executing inside a CER or an error handling clauses
673 // of some sort).
674 static StackWalkAction TAStackCrawlCallBackWorker(CrawlFrame* pCf, StackCrawlContext *pData)
675 {
676     CONTRACTL {
677         NOTHROW;
678         GC_NOTRIGGER;
679     }
680     CONTRACTL_END;
681
682     _ASSERTE(pData->eType & (StackCrawlContext::SCC_CheckWithinCer | StackCrawlContext::SCC_CheckWithinEH));
683
684     if(pCf->IsFrameless())
685     {
686         IJitManager* pJitManager = pCf->GetJitManager();
687         _ASSERTE(pJitManager);
688         if (pJitManager && !pData->fHasManagedCodeOnStack)
689         {
690             pData->fHasManagedCodeOnStack = TRUE;
691         }
692     }
693
694     // Get the method for this frame if it exists (might not be a managed method, so check the explicit frame if that's what we're
695     // looking at).
696     MethodDesc *pMD = pCf->GetFunction();
697     Frame *pFrame = pCf->GetFrame();
698     if (pMD == NULL && pFrame != NULL)
699         pMD = pFrame->GetFunction();
700
701     // Non-method frames don't interest us.
702     if (pMD == NULL)
703         return SWA_CONTINUE;
704
705     #if defined(_DEBUG)
706     #define METHODNAME(pFunc) (pFunc?pFunc->m_pszDebugMethodName:"<n/a>")
707     #else
708     #define METHODNAME(pFunc) "<n/a>"
709     #endif
710     if (pData->fWriteToStressLog)
711     {
712         STRESS_LOG5(LF_EH, LL_INFO100, "TAStackCrawlCallBack: STACKCRAWL method:%pM ('%s'), offset %x, Frame:%p, FrameVtable = %pV\n",
713             pMD, METHODNAME(pMD), pCf->IsFrameless()?pCf->GetRelOffset():0, pFrame, pCf->IsFrameless()?0:(*(void**)pFrame));
714     }
715     #undef METHODNAME
716
717
718     // If we weren't asked about EH clauses then we can return now (stop the stack trace if we have a definitive answer on the CER
719     // question, move to the next frame otherwise).
720     if ((pData->eType & StackCrawlContext::SCC_CheckWithinEH) == 0)
721         return ((pData->fWithinCer || pData->fUnprotectedCode) && pData->fHasManagedCodeOnStack) ? SWA_ABORT : SWA_CONTINUE;
722
723     // If we already discovered we're within an EH clause but are still processing (presumably to determine whether we're within a
724     // CER), then we can just skip to the next frame straight away. Also terminate here if the current frame is not frameless since
725     // there isn't any useful EH information for non-managed frames.
726     if (pData->fWithinEHClause || !pCf->IsFrameless())
727         return SWA_CONTINUE;
728
729     IJitManager* pJitManager = pCf->GetJitManager();
730     _ASSERTE(pJitManager);
731
732     EH_CLAUSE_ENUMERATOR pEnumState;
733     unsigned EHCount = pJitManager->InitializeEHEnumeration(pCf->GetMethodToken(), &pEnumState);
734     if (EHCount == 0)
735         // We do not have finally clause here.
736         return SWA_CONTINUE;
737
738     DWORD offs = (DWORD)pCf->GetRelOffset();
739
740     if (!pCf->IsActiveFrame())
741     {
742         // If we aren't the topmost method, then our IP is a return address and
743         // we can't use it to directly compare against the EH ranges because we
744         // may be in an cloned finally which has a call as the last instruction.
745
746         offs--;
747     }
748
749     if (pData->fWriteToStressLog)
750     {
751         STRESS_LOG1(LF_EH, LL_INFO100, "TAStackCrawlCallBack: STACKCRAWL Offset 0x%x V\n", offs);
752     }
753     EE_ILEXCEPTION_CLAUSE EHClause;
754
755     StackWalkAction action = SWA_CONTINUE;
756 #ifndef WIN64EXCEPTIONS
757     // On X86, the EH encoding for catch clause is completely mess.
758     // If catch clause is in its own basic block, the end of catch includes everything in the basic block.
759     // For nested catch, the end of catch may include several jmp instructions after JIT_EndCatch call.
760     // To better decide if we are inside a nested catch, we check if offs-1 is in more than one catch clause.
761     DWORD countInCatch = 0;
762     BOOL fAtJitEndCatch = FALSE;
763     if (pData->pAbortee == GetThread() && 
764         pData->pAbortee->ThrewControlForThread() == Thread::InducedThreadRedirectAtEndOfCatch &&
765         GetControlPC(pCf->GetRegisterSet()) == (PCODE)GetIP(pData->pAbortee->GetAbortContext()))
766     {
767         fAtJitEndCatch = TRUE;
768         offs -= 1;
769     }
770 #endif  // !WIN64EXCEPTIONS
771
772     for(ULONG i=0; i < EHCount; i++)
773     {
774         pJitManager->GetNextEHClause(&pEnumState, &EHClause);
775         _ASSERTE(IsValidClause(&EHClause));
776
777         // !!! If this function is called on Aborter thread, we should check for finally only.
778
779         // !!! If this function is called on Aborter thread, we should check for finally only.
780         // !!! Catch and filter clause are skipped.  In UserAbort, the first thing after ReadyForAbort
781         // !!! is to check if the target thread is processing exception.
782         // !!! If exception is in flight, we don't induce ThreadAbort.  Instead at the end of Jit_EndCatch
783         // !!! we will handle abort.
784         if (pData->pAbortee != GetThread() && !IsFaultOrFinally(&EHClause))
785         {
786             continue;
787         }
788         if (offs >= EHClause.HandlerStartPC &&
789             offs < EHClause.HandlerEndPC)
790         {
791 #ifndef WIN64EXCEPTIONS
792             if (fAtJitEndCatch)
793             {
794                 // On X86, JIT's EH info may include the instruction after JIT_EndCatch inside the same catch
795                 // clause if it is in the same basic block.
796                 // So for this case, the offs is in at least one catch handler, but since we are at the end of
797                 // catch, this one should not be counted.
798                 countInCatch ++;
799                 if (countInCatch == 1)
800                 {
801                     continue;
802                 }
803             }
804 #endif // !WIN64EXCEPTIONS
805             pData->fWithinEHClause = true;
806             // We're within an EH clause. If we're asking about CERs too then stop the stack walk if we've reached a conclusive
807             // result or continue looking otherwise. Else we can stop the stackwalk now.
808             if (pData->eType & StackCrawlContext::SCC_CheckWithinCer)
809             {
810                 action = (pData->fWithinCer || pData->fUnprotectedCode) ? SWA_ABORT : SWA_CONTINUE;
811             }
812             else
813             {
814                 action = SWA_ABORT;
815         }
816             break;
817     }
818     }
819
820 #ifndef WIN64EXCEPTIONS
821 #ifdef _DEBUG
822     if (fAtJitEndCatch)
823     {
824         _ASSERTE (countInCatch > 0);
825     }
826 #endif   // _DEBUG
827 #endif   // !WIN64EXCEPTIONS_
828     return action;
829 }
830
831 // Wrapper around code:TAStackCrawlCallBackWorker that abstracts away the differences between the reporting order
832 // of x86 and 64-bit stackwalker implementations, and also deals with interop calls that have an implicit reliability
833 // contract. If a P/Invoke or CLR->COM call returns SafeHandle or CriticalHandle, the IL stub could be aborted
834 // before having a chance to store the native handle into the Safe/CriticalHandle object. Therefore such calls are
835 // treated as unbreakable by convention.
836 StackWalkAction TAStackCrawlCallBack(CrawlFrame* pCf, void* data)
837 {
838     CONTRACTL {
839         NOTHROW;
840         GC_NOTRIGGER;
841     }
842     CONTRACTL_END;
843
844     StackCrawlContext *pData = (StackCrawlContext *)data;
845
846     // We have the current frame in pCf and possibly one latched frame in pData->LatchedCF. This enumeration
847     // describes which of these should be passed to code:TAStackCrawlCallBackWorker and in what order.
848     enum LatchedFrameAction
849     {
850         DiscardLatchedFrame,    // forget the latched frame, report the current one
851         DiscardCurrentFrame,    // ignore the current frame, report the latched one
852         ProcessLatchedInOrder,  // report the latched frame, then report the current frame
853         ProcessLatchedReversed, // report the current frame, then report the latched frame
854         LatchCurrentFrame       // latch the current frame, don't report anything
855     }
856     frameAction = DiscardLatchedFrame;
857
858 #ifdef _TARGET_X86_
859     // On X86 the IL stub method is reported to us before the frame with the actual interop method. We need to
860     // swap the order because if the worker saw the IL stub - which is a CER root - first, it would terminate the
861     // stack walk and wouldn't allow the thread to be aborted, regardless of how the interop method is annotated.
862     if (pData->fHaveLatchedCF)
863     {
864         // Does the current and latched frame represent the same call?
865         if (pCf->pFrame == pData->LatchedCF.pFrame)
866         {
867             if (pData->LatchedCF.GetFunction()->AsDynamicMethodDesc()->IsUnbreakable())
868             {
869                 // Report only the latched IL stub frame which is a CER root.
870                 frameAction = DiscardCurrentFrame;
871             }
872             else
873             {
874                 // Report the interop method (current frame) which may be annotated, then the IL stub.
875                 frameAction = ProcessLatchedReversed;
876             }
877         }
878         else
879         {
880             // The two frames are unrelated - process them in order.
881             frameAction = ProcessLatchedInOrder;
882         }
883         pData->fHaveLatchedCF = FALSE;
884     }
885     else
886     {
887         MethodDesc *pMD = pCf->GetFunction();
888         if (pMD != NULL && pMD->IsILStub() && InlinedCallFrame::FrameHasActiveCall(pCf->pFrame))
889         {
890             // This may be IL stub for an interesting interop call - latch it.
891             frameAction = LatchCurrentFrame;
892         }
893     }
894 #else // _TARGET_X86_
895     // On 64-bit the IL stub method is reported after the actual interop method so we don't have to swap them.
896     // However, we still want to discard the interop method frame if the call is unbreakable by convention.
897     if (pData->fHaveLatchedCF)
898     {
899         MethodDesc *pMD = pCf->GetFunction();
900         if (pMD != NULL && pMD->IsILStub() &&
901             pData->LatchedCF.GetFrame()->GetReturnAddress() == GetControlPC(pCf->GetRegisterSet()) &&
902             pMD->AsDynamicMethodDesc()->IsUnbreakable())
903         {
904             // The current and latched frame represent the same call and the IL stub is marked as unbreakable.
905             // We will discard the interop method and report only the IL stub which is a CER root.
906             frameAction = DiscardLatchedFrame;
907         }
908         else
909         {
910             // Otherwise process the two frames in order.
911             frameAction = ProcessLatchedInOrder;
912         }
913         pData->fHaveLatchedCF = FALSE;
914     }
915     else
916     {
917         MethodDesc *pMD = pCf->GetFunction();
918         if (pCf->GetFrame() != NULL && pMD != NULL && (pMD->IsNDirect() || pMD->IsComPlusCall()))
919         {
920             // This may be interop method of an interesting interop call - latch it.
921             frameAction = LatchCurrentFrame;
922         }
923     }
924 #endif // _TARGET_X86_
925
926     // Execute the "frame action".
927     StackWalkAction action;
928     switch (frameAction)
929     {
930         case DiscardLatchedFrame:
931                 action = TAStackCrawlCallBackWorker(pCf, pData);
932                 break;
933
934         case DiscardCurrentFrame:
935                 action = TAStackCrawlCallBackWorker(&pData->LatchedCF, pData);
936                 break;
937
938         case ProcessLatchedInOrder:
939                 action = TAStackCrawlCallBackWorker(&pData->LatchedCF, pData);
940                 if (action == SWA_CONTINUE)
941                     action = TAStackCrawlCallBackWorker(pCf, pData);
942                 break;
943
944         case ProcessLatchedReversed:
945                 action = TAStackCrawlCallBackWorker(pCf, pData);
946                 if (action == SWA_CONTINUE)
947                     action = TAStackCrawlCallBackWorker(&pData->LatchedCF, pData);
948                 break;
949
950         case LatchCurrentFrame:
951                 pData->LatchedCF = *pCf;
952                 pData->fHaveLatchedCF = TRUE;
953                 action = SWA_CONTINUE;
954                 break;
955                 
956         default:
957             UNREACHABLE();
958     }
959     return action;
960 }
961
962 // Is the current thread currently executing within a constrained execution region?
963 BOOL Thread::IsExecutingWithinCer()
964 {
965     CONTRACTL
966     {
967         NOTHROW;
968         GC_NOTRIGGER;
969     }
970     CONTRACTL_END;
971
972     if (!g_fEEStarted)
973         return FALSE;
974
975     Thread *pThread = GetThread();
976     _ASSERTE (pThread);
977     StackCrawlContext sContext = { pThread,
978                                    StackCrawlContext::SCC_CheckWithinCer,
979         FALSE,
980         FALSE,
981         FALSE,
982         FALSE,
983         FALSE,
984         FALSE};
985
986     pThread->StackWalkFrames(TAStackCrawlCallBack, &sContext);
987
988 #ifdef STRESS_LOG
989     if (sContext.fWithinCer && StressLog::StressLogOn(~0u, 0))
990     {
991         // If stress log is on, write info to stress log
992         StackCrawlContext sContext1 = { pThread,
993                                         StackCrawlContext::SCC_CheckWithinCer,
994             FALSE,
995             FALSE,
996             FALSE,
997             FALSE,
998             TRUE,
999             FALSE};
1000
1001         pThread->StackWalkFrames(TAStackCrawlCallBack, &sContext1);
1002     }
1003 #endif
1004
1005     return sContext.fWithinCer;
1006 }
1007
1008
1009 // Context structure used during stack walks to determine whether a given method is executing within a CER.
1010 struct CerStackCrawlContext
1011 {
1012     MethodDesc *m_pStartMethod;         // First method we crawl (here for debug purposes)
1013     bool        m_fFirstFrame;          // True for first callback only
1014     bool        m_fWithinCer;           // The result
1015 };
1016
1017
1018 // Determine whether the method at the given depth in the thread's execution stack is executing within a CER.
1019 BOOL Thread::IsWithinCer(CrawlFrame *pCf)
1020 {
1021     CONTRACTL
1022     {
1023         NOTHROW;
1024         GC_NOTRIGGER;
1025     }
1026     CONTRACTL_END;
1027
1028     return FALSE;
1029 }
1030
1031 #if defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK)
1032 BOOL Thread::IsSafeToInjectThreadAbort(PTR_CONTEXT pContextToCheck)
1033 {
1034     CONTRACTL
1035     {
1036         NOTHROW;
1037         GC_NOTRIGGER;
1038         MODE_ANY;
1039         PRECONDITION(pContextToCheck != NULL);
1040     }
1041     CONTRACTL_END;
1042
1043     EECodeInfo codeInfo(GetIP(pContextToCheck));
1044     _ASSERTE(codeInfo.IsValid());
1045
1046     // Check if the method uses a frame register. If it does not, then RSP will be used by the OS as the frame register
1047     // and returned as the EstablisherFrame. This is fine at any instruction in the method (including epilog) since there is always a 
1048     // difference of stackslot size between the callerSP and the callee SP due to return address having been pushed on the stack.
1049     if (!codeInfo.HasFrameRegister())
1050     {
1051         return TRUE;
1052     }
1053
1054     BOOL fSafeToInjectThreadAbort = TRUE;
1055
1056     if (IsIPInEpilog(pContextToCheck, &codeInfo, &fSafeToInjectThreadAbort))
1057     {
1058         return fSafeToInjectThreadAbort;
1059     }
1060     else
1061     {
1062         return TRUE;
1063     }
1064 }
1065 #endif // defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK)
1066
1067 #ifdef _TARGET_AMD64_
1068 // CONTEXT_CONTROL does not include any nonvolatile registers that might be the frame pointer.
1069 #define CONTEXT_MIN_STACKWALK (CONTEXT_CONTROL | CONTEXT_INTEGER)
1070 #else
1071 #define CONTEXT_MIN_STACKWALK (CONTEXT_CONTROL)
1072 #endif
1073
1074
1075 BOOL Thread::ReadyForAsyncException()
1076 {
1077     CONTRACTL {
1078         NOTHROW;
1079         GC_NOTRIGGER;
1080         SO_TOLERANT;
1081     }
1082     CONTRACTL_END;
1083
1084     if (!IsAbortRequested())
1085     {
1086         return FALSE;
1087     }
1088
1089     if (IsAbortRequested() && HasThreadStateNC(TSNC_SOWorkNeeded))
1090     {
1091         return TRUE;
1092     }
1093
1094     // This needs the probe with GenerateHardSO
1095     CONTRACT_VIOLATION(SOToleranceViolation);
1096
1097     if (GetThread() == this && HasThreadStateNC (TSNC_PreparingAbort) && !IsRudeAbort() )
1098     {
1099         STRESS_LOG0(LF_APPDOMAIN, LL_INFO10, "in Thread::ReadyForAbort  PreparingAbort\n");
1100         // Avoid recursive call
1101         return FALSE;
1102     }
1103
1104     if (IsAbortPrevented())
1105     {
1106         //
1107         // If the thread is marked to have a FuncEval abort request, then allow that to go through
1108         // since we dont want to block funcEval aborts. Such requests are initiated by the
1109         // right-side when the thread is doing funcEval and the exception would be caught in the 
1110         // left-side's funcEval implementation that will then clear the funcEval-abort-state from the thread.
1111         //
1112         // If another thread also marked this one for a non-FuncEval abort, then the left-side will 
1113         // proceed to [re]throw that exception post funcEval abort. When we come here next, we would follow 
1114         // the usual rules to raise the exception and if raised, to prevent the abort if applicable.
1115         //
1116         if (!IsFuncEvalAbort())
1117         {
1118             STRESS_LOG0(LF_APPDOMAIN, LL_INFO10, "in Thread::ReadyForAbort  prevent abort\n");
1119             return FALSE;
1120         }
1121     }
1122
1123     // The thread requests not to be aborted.  Honor this for safe abort.
1124     if (!IsRudeAbort() && IsAsyncPrevented())
1125     {
1126         STRESS_LOG0(LF_APPDOMAIN, LL_INFO10, "in Thread::ReadyForAbort  AsyncPrevented\n");
1127         return FALSE;
1128     }
1129
1130     // If we are doing safe abort, we can not abort a thread if it has locks.
1131     if (m_AbortType == EEPolicy::TA_Safe && HasLockInCurrentDomain()) {
1132         STRESS_LOG0(LF_APPDOMAIN, LL_INFO10, "in Thread::ReadyForAbort  HasLock\n");
1133         return FALSE;
1134     }
1135
1136     REGDISPLAY rd;
1137
1138     Frame *pStartFrame = NULL;
1139     if (ThrewControlForThread() == Thread::InducedThreadRedirect ||
1140         ThrewControlForThread() == Thread::InducedThreadRedirectAtEndOfCatch)
1141     {
1142         _ASSERTE(GetThread() == this);
1143         _ASSERTE(ExecutionManager::IsManagedCode(GetIP(m_OSContext)));
1144         FillRegDisplay(&rd, m_OSContext);
1145
1146         if (ThrewControlForThread() == Thread::InducedThreadRedirectAtEndOfCatch)
1147         {
1148             // On 64bit, this function may be called from COMPlusCheckForAbort when
1149             // stack has not unwound, but m_OSContext points to the place after unwind.
1150             // 
1151             TADDR sp = GetSP(m_OSContext);
1152             Frame *pFrameAddr = m_pFrame;
1153             while (pFrameAddr < (LPVOID)sp)
1154             {
1155                 pFrameAddr = pFrameAddr->Next();
1156             }
1157             if (pFrameAddr != m_pFrame)
1158             {
1159                 pStartFrame = pFrameAddr;
1160             }
1161         }
1162 #if defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK)
1163         else if (ThrewControlForThread() == Thread::InducedThreadRedirect)
1164         {
1165             if (!IsSafeToInjectThreadAbort(m_OSContext))
1166             {
1167                 STRESS_LOG0(LF_EH, LL_INFO10, "Thread::ReadyForAbort: Not injecting abort since we are at an unsafe instruction.\n");
1168                 return FALSE;
1169             }
1170         }
1171 #endif // defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK)
1172     }
1173     else
1174     {
1175         if (GetFilterContext())
1176         {
1177             FillRegDisplay(&rd, GetFilterContext());
1178         }
1179         else
1180         {
1181              CONTEXT ctx;
1182              SetIP(&ctx, 0);
1183              SetSP(&ctx, 0);
1184              FillRegDisplay(&rd, &ctx);
1185         }
1186     }
1187
1188 #ifdef STRESS_LOG
1189     REGDISPLAY rd1;
1190     if (StressLog::StressLogOn(~0u, 0))
1191     {
1192         CONTEXT ctx1;
1193         CopyRegDisplay(&rd, &rd1, &ctx1);
1194     }
1195 #endif
1196
1197     // Walk the stack to determine if we are running in Constrained Execution Region or finally EH clause (in the non-rude abort
1198     // case). We cannot initiate an abort in these circumstances.
1199     StackCrawlContext TAContext =
1200     {
1201         this,
1202         StackCrawlContext::SCC_CheckWithinCer | (IsRudeAbort() ? 0 : StackCrawlContext::SCC_CheckWithinEH),
1203         FALSE,
1204         FALSE,
1205         FALSE,
1206         FALSE,
1207         FALSE
1208     };
1209
1210     StackWalkFramesEx(&rd, TAStackCrawlCallBack, &TAContext, QUICKUNWIND, pStartFrame);
1211
1212     if (!TAContext.fHasManagedCodeOnStack && IsAbortInitiated() && GetThread() == this)
1213     {
1214         EEResetAbort(TAR_Thread);
1215         return FALSE;
1216     }
1217
1218     if (TAContext.fWithinCer)
1219     {
1220         STRESS_LOG0(LF_APPDOMAIN, LL_INFO10, "in Thread::ReadyForAbort  RunningCer\n");
1221         return FALSE;
1222     }
1223
1224 #ifdef STRESS_LOG
1225     if (StressLog::StressLogOn(~0u, 0) &&
1226         (IsRudeAbort() || !TAContext.fWithinEHClause))
1227     {
1228         //Save into stresslog.
1229         StackCrawlContext TAContext1 =
1230         {
1231             this,
1232             StackCrawlContext::SCC_CheckWithinCer | (IsRudeAbort() ? 0 : StackCrawlContext::SCC_CheckWithinEH),
1233             FALSE,
1234             FALSE,
1235             FALSE,
1236             FALSE,
1237             TRUE
1238         };
1239
1240         StackWalkFramesEx(&rd1, TAStackCrawlCallBack, &TAContext1, QUICKUNWIND, pStartFrame);
1241     }
1242 #endif
1243
1244     if (IsRudeAbort()) {
1245         // If it is rude abort, there is no additional restriction on abort.
1246         STRESS_LOG0(LF_APPDOMAIN, LL_INFO10, "in Thread::ReadyForAbort  RudeAbort\n");
1247         return TRUE;
1248     }
1249
1250     if (TAContext.fWithinEHClause)
1251     {
1252         STRESS_LOG0(LF_APPDOMAIN, LL_INFO10, "in Thread::ReadyForAbort  RunningEHClause\n");
1253     }
1254
1255     //if (m_AbortType == EEPolicy::TA_V1Compatible) {
1256     //    return TRUE;
1257     //}
1258
1259     // If we are running finally, we can not abort for Safe Abort.
1260     return !TAContext.fWithinEHClause;
1261 }
1262
1263 BOOL Thread::IsRudeAbort()
1264 {
1265     CONTRACTL {
1266         NOTHROW;
1267         GC_NOTRIGGER;
1268         SO_TOLERANT;
1269     }
1270     CONTRACTL_END;
1271
1272     return (IsAbortRequested() && (m_AbortType == EEPolicy::TA_Rude));
1273 }
1274
1275 BOOL Thread::IsRudeAbortOnlyForADUnload()
1276 {
1277     CONTRACTL {
1278         NOTHROW;
1279         GC_NOTRIGGER;
1280     }
1281     CONTRACTL_END;
1282
1283     return (IsAbortRequested() &&
1284             (m_AbortInfo & TAI_ADUnloadRudeAbort) &&
1285             !(m_AbortInfo & (TAI_ThreadRudeAbort | TAI_FuncEvalRudeAbort))
1286            );
1287 }
1288
1289 BOOL Thread::IsRudeUnload()
1290 {
1291     CONTRACTL {
1292         NOTHROW;
1293         GC_NOTRIGGER;
1294     }
1295     CONTRACTL_END;
1296
1297     return (IsAbortRequested() && (m_AbortInfo & TAI_ADUnloadRudeAbort));
1298 }
1299
1300 BOOL Thread::IsFuncEvalAbort()
1301 {
1302     CONTRACTL {
1303         NOTHROW;
1304         GC_NOTRIGGER;
1305     }
1306     CONTRACTL_END;
1307
1308     return (IsAbortRequested() && (m_AbortInfo & TAI_AnyFuncEvalAbort));
1309 }
1310
1311 //
1312 // If the OS is down in kernel mode when we do a GetThreadContext,any
1313 // updates we make to the context will not take effect if we try to do
1314 // a SetThreadContext.  As a result, newer OSes expose the idea of
1315 // "trap frame reporting" which will tell us if it is unsafe to modify
1316 // the context and pass it along to SetThreadContext.
1317 //
1318 // On OSes that support trap frame reporting, we will return FALSE if
1319 // we can determine that the OS is not in user mode.  Otherwise, we
1320 // return TRUE.
1321 //
1322 BOOL Thread::IsContextSafeToRedirect(CONTEXT* pContext)
1323 {
1324     CONTRACTL
1325     {
1326         NOTHROW;
1327         GC_NOTRIGGER;
1328         MODE_ANY;
1329     }
1330     CONTRACTL_END;
1331
1332     BOOL isSafeToRedirect = TRUE;
1333
1334 #ifndef FEATURE_PAL
1335     
1336 #if !defined(_TARGET_X86_)
1337     // In some cases (x86 WOW64, ARM32 on ARM64) Windows will not set the CONTEXT_EXCEPTION_REPORTING flag
1338     // if the thread is executing in kernel mode (i.e. in the middle of a syscall or exception handling).
1339     // Therefore, we should treat the absence of the CONTEXT_EXCEPTION_REPORTING flag as an indication that
1340     // it is not safe to manipulate with the current state of the thread context.
1341     // Note: the x86 WOW64 case is already handled in GetSafelyRedirectableThreadContext; in addition, this
1342     // flag is never set on Windows7 x86 WOW64. So this check is valid for non-x86 architectures only.
1343     isSafeToRedirect = (pContext->ContextFlags & CONTEXT_EXCEPTION_REPORTING) != 0;
1344 #endif // !defined(_TARGET_X86_)
1345
1346     if (pContext->ContextFlags & CONTEXT_EXCEPTION_REPORTING)
1347     {
1348         if (pContext->ContextFlags & (CONTEXT_SERVICE_ACTIVE|CONTEXT_EXCEPTION_ACTIVE))
1349         {
1350             // cannot process exception
1351             LOG((LF_ALWAYS, LL_WARNING, "thread [os id=0x08%x id=0x08%x] redirect failed due to ContextFlags of 0x%08x\n", m_OSThreadId, m_ThreadId, pContext->ContextFlags));
1352             isSafeToRedirect = FALSE;
1353         }
1354     }
1355
1356 #endif // !FEATURE_PAL
1357
1358     return isSafeToRedirect;
1359 }
1360
1361 void Thread::SetAbortEndTime(ULONGLONG endTime, BOOL fRudeAbort)
1362 {
1363     LIMITED_METHOD_CONTRACT;
1364
1365     {
1366         AbortRequestLockHolder lh(this);
1367         if (fRudeAbort)
1368         {
1369             if (endTime < m_RudeAbortEndTime)
1370             {
1371                 m_RudeAbortEndTime = endTime;
1372             }
1373         }
1374         else
1375         {
1376             if (endTime < m_AbortEndTime)
1377             {
1378                 m_AbortEndTime = endTime;
1379             }
1380         }
1381     }
1382
1383 }
1384
1385 #ifdef _PREFAST_
1386 #pragma warning(push)
1387 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1388 #endif
1389 HRESULT
1390 Thread::UserAbort(ThreadAbortRequester requester,
1391                   EEPolicy::ThreadAbortTypes abortType,
1392                   DWORD timeout,
1393                   UserAbort_Client client
1394                  )
1395 {
1396     CONTRACTL
1397     {
1398         THROWS;
1399         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
1400     }
1401     CONTRACTL_END;
1402
1403     STRESS_LOG2(LF_SYNC | LF_APPDOMAIN, LL_INFO100, "UserAbort Thread %p Thread Id = %x\n", this, GetThreadId());
1404 #ifdef _DEBUG
1405     AddFiberInfo(ThreadTrackInfo_Abort);
1406 #endif
1407
1408     BOOL fHoldingThreadStoreLock = ThreadStore::HoldingThreadStore();
1409
1410     // For SafeAbort from FuncEval abort, we do not apply escalation policy.  Debugger
1411     // tries SafeAbort first with a short timeout.  The thread will return to debugger.
1412     // After some break, the thread is going to do RudeAbort if abort has not finished.
1413     EClrOperation operation;
1414     if (abortType == EEPolicy::TA_Rude)
1415     {
1416         if (HasLockInCurrentDomain())
1417         {
1418             operation = OPR_ThreadRudeAbortInCriticalRegion;
1419         }
1420         else
1421         {
1422             operation = OPR_ThreadRudeAbortInNonCriticalRegion;
1423         }
1424     }
1425     else
1426     {
1427         operation = OPR_ThreadAbort;
1428     }
1429
1430     // Debugger func-eval aborts (both rude + normal) don't have any escalation policy. They are invoked
1431     // by the debugger and the debugger handles the consequences. 
1432     // Furthermore, in interop-debugging, threads will be hard-suspened in preemptive mode while we try to abort them.
1433     // So any abort strategy that relies on a timeout and the target thread slipping is dangerous. Escalation policy would let a 
1434     // host circumvent the timeout and thus we may wait forever for the target thread to slip. We'd deadlock here. Since the escalation
1435     // policy doesn't let the host break this deadlock (and certianly doesn't let the debugger break the deadlock), it's unsafe
1436     // to have an escalation policy for func-eval aborts at all.
1437     BOOL fEscalation = (requester != TAR_FuncEval);
1438     if (fEscalation)
1439     {
1440         EPolicyAction action = GetEEPolicy()->GetDefaultAction(operation, this);
1441         switch (action)
1442         {
1443         case eAbortThread:
1444             GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
1445             break;
1446         case eRudeAbortThread:
1447             if (abortType != EEPolicy::TA_Rude)
1448             {
1449                 abortType = EEPolicy::TA_Rude;
1450             }
1451             GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
1452             break;
1453         case eUnloadAppDomain:
1454             {
1455                 AppDomain *pDomain = GetDomain();
1456                 if (!pDomain->IsDefaultDomain())
1457                 {
1458                     GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
1459                     pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
1460                 }
1461             }
1462             // AD unload does not abort finalizer thread.
1463             if (this != FinalizerThread::GetFinalizerThread())
1464             {
1465                 if (this == GetThread())
1466                 {
1467                     Join(INFINITE,TRUE);
1468                 }
1469                 return S_OK;
1470             }
1471             break;
1472         case eRudeUnloadAppDomain:
1473             {
1474                 AppDomain *pDomain = GetDomain();
1475                 if (!pDomain->IsDefaultDomain())
1476                 {
1477                     GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
1478                     pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
1479                 }
1480             }
1481             // AD unload does not abort finalizer thread.
1482             if (this != FinalizerThread::GetFinalizerThread())
1483             {
1484                 if (this == GetThread())
1485                 {
1486                     Join(INFINITE,TRUE);
1487                 }
1488                 return S_OK;
1489             }
1490             break;
1491         case eExitProcess:
1492         case eFastExitProcess:
1493         case eRudeExitProcess:
1494         case eDisableRuntime:
1495             GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
1496             EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_THREADABORT);
1497             _ASSERTE (!"Should not reach here");
1498             break;
1499         default:
1500             _ASSERTE (!"unknown policy for thread abort");
1501         }
1502
1503         DWORD timeoutFromPolicy;
1504         if (abortType != EEPolicy::TA_Rude)
1505         {
1506             timeoutFromPolicy = GetEEPolicy()->GetTimeout(OPR_ThreadAbort);
1507         }
1508         else if (!HasLockInCurrentDomain())
1509         {
1510             timeoutFromPolicy = GetEEPolicy()->GetTimeout(OPR_ThreadRudeAbortInNonCriticalRegion);
1511         }
1512         else
1513         {
1514             timeoutFromPolicy = GetEEPolicy()->GetTimeout(OPR_ThreadRudeAbortInCriticalRegion);
1515         }
1516         if (timeout > timeoutFromPolicy)
1517         {
1518             timeout = timeoutFromPolicy;
1519         }
1520     }
1521
1522     AbortControlHolder AbortController(this);
1523
1524     // Swap in timeout
1525     if (timeout != INFINITE)
1526     {
1527         ULONG64 curTime = CLRGetTickCount64();
1528         ULONG64 newEndTime = curTime + timeout;
1529
1530         SetAbortEndTime(newEndTime, abortType == EEPolicy::TA_Rude);
1531     }
1532
1533     // If the abort comes from the thread abort watchdog, proceed with the abort only 
1534     // if the abort is still requested. This handles race between watchdog and UnmarkThreadForAbort.
1535     BOOL fTentative = (requester == Thread::TAR_Thread) && (client == UAC_WatchDog);
1536     MarkThreadForAbort(requester, abortType, fTentative);
1537
1538     Thread *pCurThread = GetThread();
1539
1540     // If aboring self
1541     if (this == pCurThread)
1542     {
1543         SetAbortInitiated();
1544 #ifdef _DEBUG
1545         m_dwAbortPoint = 1;
1546 #endif
1547
1548         if (CLRHosted() && GetAbortEndTime() != MAXULONGLONG)
1549         {
1550             // ToDo: Skip debugger funcval
1551             // Use our helper thread to watch abort.
1552             AppDomain::EnableADUnloadWorkerForThreadAbort();
1553         }
1554
1555         GCX_COOP();
1556
1557         OBJECTREF exceptObj;
1558
1559         if (IsRudeAbort())
1560         {
1561             exceptObj = CLRException::GetPreallocatedRudeThreadAbortException();
1562         }
1563         else
1564         {
1565             EEException eeExcept(kThreadAbortException);
1566             exceptObj = CLRException::GetThrowableFromException(&eeExcept);
1567         }
1568
1569         RaiseTheExceptionInternalOnly(exceptObj, FALSE);
1570     }
1571
1572 #ifdef MDA_SUPPORTED
1573     if (requester != TAR_FuncEval)
1574     {
1575         // FuncEval abort is always aborting another thread.  No need to trigger MDA.
1576         MDA_TRIGGER_ASSISTANT(AsynchronousThreadAbort, ReportViolation(GetThread(), this));
1577     }
1578 #endif
1579
1580     _ASSERTE(this != pCurThread);      // Aborting another thread.
1581
1582     if (client == UAC_Host)
1583     {
1584         // A host may call ICLRTask::Abort on a critical thread.  We don't want to
1585         // block this thread.
1586         AppDomain::EnableADUnloadWorkerForThreadAbort();
1587         return S_OK;
1588     }
1589
1590 #ifdef _DEBUG
1591     DWORD elapsed_time = 0;
1592 #endif
1593
1594     // We do not want this thread to be alerted.
1595     ThreadPreventAsyncHolder preventAsync(pCurThread != NULL);
1596
1597 #ifdef _DEBUG
1598     // If UserAbort times out, put up msgbox once.
1599     BOOL fAlreadyAssert = FALSE;
1600 #endif
1601
1602     BOOL fOneTryOnly = (client == UAC_WatchDog) || (client == UAC_FinalizerTimeout); 
1603     BOOL fFirstRun = TRUE;
1604     BOOL fNeedEscalation;
1605
1606 #if !defined(DISABLE_THREADSUSPEND)
1607     DWORD dwSwitchCount = 0;
1608 #endif // !defined(DISABLE_THREADSUSPEND)
1609
1610 LRetry:
1611     fNeedEscalation = FALSE;
1612     for (;;)
1613     {
1614         if (fOneTryOnly)
1615         {
1616             if (!fFirstRun)
1617             {
1618                 return S_OK;
1619             }
1620             fFirstRun = FALSE;
1621         }
1622         // Lock the thread store
1623         LOG((LF_SYNC, INFO3, "UserAbort obtain lock\n"));
1624
1625         ULONGLONG abortEndTime = GetAbortEndTime();
1626         if (abortEndTime != MAXULONGLONG)
1627         {
1628             ULONGLONG now_time = CLRGetTickCount64();
1629
1630             if (now_time >= abortEndTime)
1631             {
1632                 EPolicyAction action1 = eNoAction;
1633                 DWORD timeout1 = INFINITE;
1634                 if (fEscalation)
1635                 {
1636                     if (!IsRudeAbort())
1637                     {
1638                         action1 = GetEEPolicy()->GetActionOnTimeout(OPR_ThreadAbort, this);
1639                         timeout1 = GetEEPolicy()->GetTimeout(OPR_ThreadAbort);
1640                     }
1641                     else if (HasLockInCurrentDomain())
1642                     {
1643                         action1 = GetEEPolicy()->GetActionOnTimeout(OPR_ThreadRudeAbortInCriticalRegion, this);
1644                         timeout1 = GetEEPolicy()->GetTimeout(OPR_ThreadRudeAbortInCriticalRegion);
1645                     }
1646                     else
1647                     {
1648                         action1 = GetEEPolicy()->GetActionOnTimeout(OPR_ThreadRudeAbortInNonCriticalRegion, this);
1649                         timeout1 = GetEEPolicy()->GetTimeout(OPR_ThreadRudeAbortInNonCriticalRegion);
1650                     }
1651                 }
1652                 if (action1 == eNoAction)
1653                 {
1654                     // timeout, but no action on timeout.
1655                     // Debugger can call this function to about func-eval with a timeout
1656                     return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
1657                 }
1658                 if (timeout1 != INFINITE)
1659                 {
1660                     // There is an escalation policy.
1661                     fNeedEscalation = TRUE;
1662                     break;
1663                 }
1664             }
1665         }
1666
1667         // Thread abort needs to walk stack to decide if thread abort can proceed.
1668         // It is unsafe to crawl a stack of thread if the thread is OS-suspended which we do during
1669         // thread abort.  For example, Thread T1 aborts thread T2.  T2 is suspended by T1. Inside SQL
1670         // this means that no thread sharing the same scheduler with T2 can run.  If T1 needs a lock which
1671         // is owned by one thread on the scheduler, T1 will wait forever.
1672         // Our solution is to move T2 to a safe point, resume it, and then do stack crawl.
1673
1674         // We need to make sure that ThreadStoreLock is released after CheckForAbort.  This makes sure
1675         // that ThreadAbort does not race against GC.
1676         class CheckForAbort
1677         {
1678         private:
1679             Thread *m_pThread;
1680             BOOL m_fHoldingThreadStoreLock;
1681             BOOL m_NeedRelease;
1682         public:
1683             CheckForAbort(Thread *pThread, BOOL fHoldingThreadStoreLock)
1684             : m_pThread(pThread),
1685               m_fHoldingThreadStoreLock(fHoldingThreadStoreLock),
1686               m_NeedRelease(TRUE)
1687             {
1688                 if (!fHoldingThreadStoreLock)
1689                 {
1690                     ThreadSuspend::LockThreadStore(ThreadSuspend::SUSPEND_OTHER);
1691                 }
1692                 ThreadStore::ResetStackCrawlEvent();
1693
1694                 // The thread being aborted may clear the TS_AbortRequested bit and the matching increment
1695                 // of g_TrapReturningThreads behind our back. Increment g_TrapReturningThreads here
1696                 // to ensure that we stop for the stack crawl even if the TS_AbortRequested bit is cleared.
1697                 ThreadStore::TrapReturningThreads(TRUE);
1698             }
1699             void NeedStackCrawl()
1700             {
1701                 m_pThread->SetThreadState(Thread::TS_StackCrawlNeeded);
1702             }
1703             ~CheckForAbort()
1704             {
1705                 Release();
1706             }
1707             void Release()
1708             {
1709                 if (m_NeedRelease)
1710                 {
1711                     m_NeedRelease = FALSE;
1712                     ThreadStore::TrapReturningThreads(FALSE);
1713                     ThreadStore::SetStackCrawlEvent();
1714                     m_pThread->ResetThreadState(TS_StackCrawlNeeded);
1715                     if (!m_fHoldingThreadStoreLock)
1716                     {
1717                         ThreadSuspend::UnlockThreadStore();
1718                     }
1719                 }
1720             }
1721         };
1722         CheckForAbort checkForAbort(this, fHoldingThreadStoreLock);
1723
1724         // We own TS lock.  The state of the Thread can not be changed.
1725         if (m_State & TS_Unstarted)
1726         {
1727             // This thread is not yet started.
1728 #ifdef _DEBUG
1729             m_dwAbortPoint = 2;
1730 #endif
1731             if(requester == Thread::TAR_Thread)
1732                 SetAborted();
1733             return S_OK;
1734         }
1735
1736         if (GetThreadHandle() == INVALID_HANDLE_VALUE &&
1737             (m_State & TS_Unstarted) == 0)
1738         {
1739             // The thread is going to die or is already dead.
1740             UnmarkThreadForAbort(Thread::TAR_ALL);
1741 #ifdef _DEBUG
1742             m_dwAbortPoint = 3;
1743 #endif
1744             if(requester == Thread::TAR_Thread)
1745                 SetAborted();
1746             return S_OK;
1747         }
1748
1749         // What if someone else has this thread suspended already?   It'll depend where the
1750         // thread got suspended.
1751         //
1752         // User Suspend:
1753         //     We'll just set the abort bit and hope for the best on the resume.
1754         //
1755         // GC Suspend:
1756         //    If it's suspended in jitted code, we'll hijack the IP.
1757         //    <REVISIT_TODO> Consider race w/ GC suspension</REVISIT_TODO>
1758         //    If it's suspended but not in jitted code, we'll get suspended for GC, the GC
1759         //    will complete, and then we'll abort the target thread.
1760         //
1761
1762         // It's possible that the thread has completed the abort already.
1763         //
1764         if (!(m_State & TS_AbortRequested))
1765         {
1766 #ifdef _DEBUG
1767             m_dwAbortPoint = 4;
1768 #endif
1769             if(requester == Thread::TAR_Thread)
1770                 SetAborted();
1771             return S_OK;
1772         }
1773
1774         // If a thread is Dead or Detached, abort is a NOP.
1775         //
1776         if (m_State & (TS_Dead | TS_Detached | TS_TaskReset))
1777         {
1778             UnmarkThreadForAbort(Thread::TAR_ALL);
1779             if(requester == Thread::TAR_Thread)
1780                 SetAborted();
1781 #ifdef _DEBUG
1782             m_dwAbortPoint = 5;
1783 #endif
1784             return S_OK;
1785         }
1786
1787         // It's possible that some stub notices the AbortRequested bit -- even though we
1788         // haven't done any real magic yet.  If the thread has already started it's abort, we're
1789         // done.
1790         //
1791         // Two more cases can be folded in here as well.  If the thread is unstarted, it'll
1792         // abort when we start it.
1793         //
1794         // If the thread is user suspended (SyncSuspended) -- we're out of luck.  Set the bit and
1795         // hope for the best on resume.
1796         //
1797         if ((m_State & TS_AbortInitiated) && !IsRudeAbort())
1798         {
1799 #ifdef _DEBUG
1800             m_dwAbortPoint = 6;
1801 #endif
1802             break;
1803         }
1804
1805         BOOL fOutOfRuntime = FALSE;
1806         BOOL fNeedStackCrawl = FALSE;
1807
1808 #ifdef DISABLE_THREADSUSPEND
1809         // On platforms that do not support safe thread suspension we have to 
1810         // rely on the GCPOLL mechanism; the mechanism is activated above by 
1811         // TrapReturningThreads.  However when reading shared state we need 
1812         // to erect appropriate memory barriers. So the interlocked operation 
1813         // below ensures that any future reads on this thread will happen after
1814         // any earlier writes on a different thread have taken effect.
1815         FastInterlockOr((DWORD*)&m_State, 0);
1816
1817 #else // DISABLE_THREADSUSPEND
1818
1819         // Win32 suspend the thread, so it isn't moving under us.
1820         SuspendThreadResult str = SuspendThread();
1821         switch (str)
1822         {
1823         case STR_Success:
1824             break;
1825
1826         case STR_Failure:
1827         case STR_UnstartedOrDead:
1828         case STR_NoStressLog:
1829             checkForAbort.Release();
1830             __SwitchToThread(0, ++dwSwitchCount);
1831             continue;
1832
1833         case STR_SwitchedOut:
1834             // If the thread is in preemptive gc mode, we can erect a barrier to block the
1835             // thread to return to cooperative mode.  Then we can do stack crawl and make decision.
1836             if (!m_fPreemptiveGCDisabled)
1837             {
1838                 checkForAbort.NeedStackCrawl();
1839                 if (GetThreadHandle() != SWITCHOUT_HANDLE_VALUE || m_fPreemptiveGCDisabled)
1840                 {
1841                     checkForAbort.Release();
1842                     __SwitchToThread(0, ++dwSwitchCount);
1843                     continue;
1844                 }
1845                 else
1846                 {
1847                     goto LStackCrawl;
1848                 }
1849             }
1850             else
1851             {
1852                 goto LPrepareRetry;
1853             }
1854
1855         default:
1856             UNREACHABLE();
1857         }
1858
1859         _ASSERTE(str == STR_Success);
1860
1861 #endif // DISABLE_THREADSUSPEND
1862
1863         // It's possible that the thread has completed the abort already.
1864         //
1865         if (!(m_State & TS_AbortRequested))
1866         {
1867 #ifndef DISABLE_THREADSUSPEND
1868             ResumeThread();
1869 #endif
1870             if(requester == Thread::TAR_Thread)
1871                 SetAborted();
1872 #ifdef _DEBUG
1873             m_dwAbortPoint = 63;
1874 #endif
1875             return S_OK;
1876         }
1877
1878         // Check whether some stub noticed the AbortRequested bit in-between our test above
1879         // and us suspending the thread.
1880         if ((m_State & TS_AbortInitiated) && !IsRudeAbort())
1881         {
1882 #ifndef DISABLE_THREADSUSPEND
1883             ResumeThread();
1884 #endif
1885 #ifdef _DEBUG
1886             m_dwAbortPoint = 65;
1887 #endif
1888             break;
1889         }
1890
1891         // If Threads is stopped under a managed debugger, it will have both
1892         // TS_DebugSuspendPending and TS_SyncSuspended, regardless of whether
1893         // the thread is actually suspended or not.
1894         // If it's suspended w/o the debugger (eg, by via Thread.Suspend), it will
1895         // also have TS_UserSuspendPending set.
1896         if (m_State & TS_SyncSuspended)
1897         {
1898 #ifndef DISABLE_THREADSUSPEND
1899             ResumeThread();
1900 #endif
1901             checkForAbort.Release();
1902 #ifdef _DEBUG
1903             m_dwAbortPoint = 7;
1904 #endif
1905
1906             // CoreCLR does not support user-requested thread suspension
1907             _ASSERTE(!(m_State & TS_UserSuspendPending));
1908
1909             //
1910             // If it's stopped by the debugger, we don't want to throw an exception.
1911             // Debugger suspension is to have no effect of the runtime behaviour.
1912             //
1913             if (m_State & TS_DebugSuspendPending)
1914             {
1915                 return S_OK;
1916             }
1917
1918             COMPlusThrow(kThreadStateException, IDS_EE_THREAD_ABORT_WHILE_SUSPEND);
1919         }
1920
1921         // If the thread has no managed code on it's call stack, abort is a NOP.  We're about
1922         // to touch the unmanaged thread's stack -- for this to be safe, we can't be
1923         // Dead/Detached/Unstarted.
1924         //
1925         _ASSERTE(!(m_State & (  TS_Dead
1926                               | TS_Detached
1927                               | TS_Unstarted)));
1928
1929 #if defined(_TARGET_X86_) && !defined(WIN64EXCEPTIONS)
1930         // TODO WIN64: consider this if there is a way to detect of managed code on stack.
1931         if ((m_pFrame == FRAME_TOP)
1932             && (GetFirstCOMPlusSEHRecord(this) == EXCEPTION_CHAIN_END)
1933            )
1934         {
1935 #ifndef DISABLE_THREADSUSPEND
1936             ResumeThread();
1937 #endif
1938 #ifdef _DEBUG
1939             m_dwAbortPoint = 8;
1940 #endif
1941
1942             if(requester == Thread::TAR_Thread)
1943                 SetAborted();
1944             return S_OK;
1945         }
1946 #endif // _TARGET_X86_
1947
1948
1949         if (!m_fPreemptiveGCDisabled)
1950         {
1951             if ((m_pFrame != FRAME_TOP) && m_pFrame->IsTransitionToNativeFrame()
1952 #if defined(_TARGET_X86_) && !defined(WIN64EXCEPTIONS)
1953                 && ((size_t) GetFirstCOMPlusSEHRecord(this) > ((size_t) m_pFrame) - 20)
1954 #endif // _TARGET_X86_
1955                 )
1956             {
1957                 fOutOfRuntime = TRUE;
1958             }
1959         }
1960
1961         checkForAbort.NeedStackCrawl();
1962         if (!m_fPreemptiveGCDisabled)
1963         {
1964             fNeedStackCrawl = TRUE;
1965         }
1966 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
1967         else
1968         {
1969             HandleJITCaseForAbort();
1970         }
1971 #endif // FEATURE_HIJACK && !PLATFORM_UNIX
1972
1973 #ifndef DISABLE_THREADSUSPEND
1974         // The thread is not suspended now.
1975         ResumeThread();
1976 #endif
1977
1978         if (!fNeedStackCrawl)
1979         {
1980             goto LPrepareRetry;
1981         }
1982
1983 #ifndef DISABLE_THREADSUSPEND
1984 LStackCrawl:
1985 #endif // DISABLE_THREADSUSPEND
1986
1987         if (!ReadyForAbort()) {
1988             goto LPrepareRetry;
1989         }
1990
1991         // !!! Check for Exception in flight should happen before induced thread abort.
1992         // !!! ReadyForAbort skips catch and filter clause.
1993
1994         // If an exception is currently being thrown, one of two things will happen.  Either, we'll
1995         // catch, and notice the abort request in our end-catch, or we'll not catch [in which case
1996         // we're leaving managed code anyway.  The top-most handler is responsible for resetting
1997         // the bit.
1998         //
1999         if (HasException() &&
2000             // For rude abort, we will initiated abort
2001             !IsRudeAbort())
2002         {
2003 #ifdef _DEBUG
2004             m_dwAbortPoint = 9;
2005 #endif
2006             break;
2007         }
2008
2009         // If the thread is in sleep, wait, or join interrupt it
2010         // However, we do NOT want to interrupt if the thread is already processing an exception
2011         if (m_State & TS_Interruptible)
2012         {
2013             UserInterrupt(TI_Abort);        // if the user wakes up because of this, it will read the
2014                                             // abort requested bit and initiate the abort
2015 #ifdef _DEBUG
2016             m_dwAbortPoint = 10;
2017 #endif
2018             goto LPrepareRetry;
2019         }
2020
2021         if (fOutOfRuntime)
2022         {
2023             // If the thread is running outside the EE, and is behind a stub that's going
2024             // to catch...
2025 #ifdef _DEBUG
2026             m_dwAbortPoint = 11;
2027 #endif
2028             break;
2029         }
2030
2031         // Ok.  It's not in managed code, nor safely out behind a stub that's going to catch
2032         // it on the way in.  We have to poll.
2033
2034 LPrepareRetry:
2035
2036         checkForAbort.Release();
2037
2038         if (fOneTryOnly)
2039         {
2040             break;
2041         }
2042
2043         // Don't do a Sleep.  It's possible that the thread we are trying to abort is
2044         // stuck in unmanaged code trying to get into the apartment that we are supposed
2045         // to be pumping!  Instead, ping the current thread's handle.  Obviously this
2046         // will time out, but it will pump if we need it to.
2047         if (pCurThread)
2048         {
2049             pCurThread->Join(ABORT_POLL_TIMEOUT, TRUE);
2050         }
2051         else
2052         {
2053             ClrSleepEx(ABORT_POLL_TIMEOUT, FALSE);
2054         }
2055
2056
2057 #ifdef _DEBUG
2058         elapsed_time += ABORT_POLL_TIMEOUT;
2059         if (g_pConfig->GetGCStressLevel() == 0 && !fAlreadyAssert)
2060         {
2061             _ASSERTE(elapsed_time < ABORT_FAIL_TIMEOUT);
2062             fAlreadyAssert = TRUE;
2063         }
2064 #endif
2065
2066     } // for(;;)
2067
2068     if (fOneTryOnly  && !fNeedEscalation)
2069     {
2070         return S_OK;
2071     }
2072
2073     if ((GetAbortEndTime() != MAXULONGLONG)  && IsAbortRequested())
2074     {
2075         while (TRUE)
2076         {
2077             if (!IsAbortRequested())
2078             {
2079                 return S_OK;
2080             }
2081             ULONGLONG curTime = CLRGetTickCount64();
2082             if (curTime >= GetAbortEndTime())
2083             {
2084                 break;
2085             }
2086
2087             if (pCurThread)
2088             {
2089                 pCurThread->Join(100, TRUE);
2090             }
2091             else
2092             {
2093                 ClrSleepEx(100, FALSE);
2094             }
2095
2096         }
2097
2098         if (IsAbortRequested() && fEscalation)
2099         {
2100             EPolicyAction action1;
2101             EClrOperation operation1;
2102             if (!IsRudeAbort())
2103             {
2104                 operation1 = OPR_ThreadAbort;
2105             }
2106             else if (HasLockInCurrentDomain())
2107             {
2108                 operation1 = OPR_ThreadRudeAbortInCriticalRegion;
2109             }
2110             else
2111             {
2112                 operation1 = OPR_ThreadRudeAbortInNonCriticalRegion;
2113             }
2114             action1 = GetEEPolicy()->GetActionOnTimeout(operation1, this);
2115             switch (action1)
2116             {
2117             case eRudeAbortThread:
2118                 GetEEPolicy()->NotifyHostOnTimeout(operation1, action1);
2119                 MarkThreadForAbort(requester, EEPolicy::TA_Rude);
2120                 SetRudeAbortEndTimeFromEEPolicy();
2121                 goto LRetry;
2122             case eUnloadAppDomain:
2123                 {
2124                     AppDomain *pDomain = GetDomain();
2125                     if (!pDomain->IsDefaultDomain())
2126                     {
2127                         GetEEPolicy()->NotifyHostOnTimeout(operation1, action1);
2128                         pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
2129                     }
2130                 }
2131                 // AD unload does not abort finalizer thread.
2132                 if (this == FinalizerThread::GetFinalizerThread())
2133                 {
2134                     GetEEPolicy()->NotifyHostOnTimeout(operation1, action1);
2135                     MarkThreadForAbort(requester, EEPolicy::TA_Rude);
2136                     SetRudeAbortEndTimeFromEEPolicy();
2137                     goto LRetry;
2138                 }
2139                 else
2140                 {
2141                     if (this == GetThread())
2142                     {
2143                         Join(INFINITE,TRUE);
2144                     }
2145                     return S_OK;
2146                 }
2147                 break;
2148             case eRudeUnloadAppDomain:
2149                 {
2150                     AppDomain *pDomain = GetDomain();
2151                     if (!pDomain->IsDefaultDomain())
2152                     {
2153                         GetEEPolicy()->NotifyHostOnTimeout(operation1, action1);
2154                         pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
2155                     }
2156                 }
2157                 // AD unload does not abort finalizer thread.
2158                 if (this == FinalizerThread::GetFinalizerThread())
2159                 {
2160                     MarkThreadForAbort(requester, EEPolicy::TA_Rude);
2161                     SetRudeAbortEndTimeFromEEPolicy();
2162                     goto LRetry;
2163                 }
2164                 else
2165                 {
2166                     if (this == GetThread())
2167                     {
2168                         Join(INFINITE,TRUE);
2169                     }
2170                     return S_OK;
2171                 }
2172                 break;
2173             case eExitProcess:
2174             case eFastExitProcess:
2175             case eRudeExitProcess:
2176             case eDisableRuntime:
2177                 GetEEPolicy()->NotifyHostOnTimeout(operation1, action1);
2178                 EEPolicy::HandleExitProcessFromEscalation(action1, HOST_E_EXITPROCESS_TIMEOUT);
2179                 _ASSERTE (!"Should not reach here");
2180                 break;
2181             default:
2182             break;
2183             }
2184         }
2185
2186         return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
2187     }
2188
2189     if(requester == Thread::TAR_Thread)
2190         SetAborted();
2191     return S_OK;
2192 }
2193 #ifdef _PREFAST_
2194 #pragma warning(pop)
2195 #endif
2196
2197 void Thread::SetRudeAbortEndTimeFromEEPolicy()
2198 {
2199     LIMITED_METHOD_CONTRACT;
2200
2201     DWORD timeout = GetEEPolicy()->GetTimeout(OPR_ThreadRudeAbortInCriticalRegion);
2202
2203     ULONGLONG newEndTime;
2204     if (timeout == INFINITE)
2205     {
2206         newEndTime = MAXULONGLONG;
2207     }
2208     else
2209     {
2210         newEndTime = CLRGetTickCount64() + timeout;
2211     }
2212
2213     SetAbortEndTime(newEndTime, TRUE);
2214 }
2215
2216 ULONGLONG Thread::s_NextSelfAbortEndTime = MAXULONGLONG;
2217
2218 void Thread::ThreadAbortWatchDogAbort(Thread *pThread)
2219 {
2220     CONTRACTL
2221     {
2222         NOTHROW;
2223         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
2224     }
2225     CONTRACTL_END;
2226
2227         EEPolicy::ThreadAbortTypes abortType = EEPolicy::TA_Safe;
2228         if (pThread->m_AbortInfo & TAI_ThreadRudeAbort)
2229         {
2230             abortType = EEPolicy::TA_Rude;
2231         }
2232         else if (pThread->m_AbortInfo & TAI_ThreadV1Abort)
2233         {
2234             abortType = EEPolicy::TA_V1Compatible;
2235         }
2236         else if (pThread->m_AbortInfo & TAI_ThreadAbort)
2237         {
2238             abortType = EEPolicy::TA_Safe;
2239         }
2240         else
2241         {
2242             return;
2243         }
2244
2245         EX_TRY
2246         {
2247             pThread->UserAbort(Thread::TAR_Thread, abortType, INFINITE, Thread::UAC_WatchDog);            
2248         }
2249         EX_CATCH
2250         {
2251         }
2252         EX_END_CATCH(SwallowAllExceptions);
2253 }
2254
2255 void Thread::ThreadAbortWatchDogEscalate(Thread *pThread)
2256 {
2257     CONTRACTL
2258     {
2259         NOTHROW;
2260         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
2261     }
2262     CONTRACTL_END;
2263
2264     EPolicyAction action = eNoAction;
2265     EClrOperation operation = OPR_ThreadRudeAbortInNonCriticalRegion;
2266     if (!pThread->IsRudeAbort())
2267     {
2268         operation = OPR_ThreadAbort;
2269     }
2270     else if (pThread->HasLockInCurrentDomain())
2271     {
2272         operation = OPR_ThreadRudeAbortInCriticalRegion;
2273     }
2274     else
2275     {
2276         operation = OPR_ThreadRudeAbortInNonCriticalRegion;
2277     }
2278     action = GetEEPolicy()->GetActionOnTimeout(operation, pThread);
2279     // We only support escalation to rude abort
2280
2281     EX_TRY {
2282         switch (action)
2283         {
2284         case eRudeAbortThread:
2285             GetEEPolicy()->NotifyHostOnTimeout(operation,action);
2286             pThread->UserAbort(Thread::TAR_Thread, EEPolicy::TA_Rude, INFINITE, Thread::UAC_WatchDog);
2287             break;
2288         case eUnloadAppDomain:
2289             {
2290                 AppDomain *pDomain = pThread->GetDomain();
2291                 if (!pDomain->IsDefaultDomain())
2292                 {
2293                     GetEEPolicy()->NotifyHostOnTimeout(operation,action);
2294                     pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
2295                 }
2296             }
2297             break;
2298         case eRudeUnloadAppDomain:
2299             {
2300                 AppDomain *pDomain = pThread->GetDomain();
2301                 if (!pDomain->IsDefaultDomain())
2302                 {
2303                     GetEEPolicy()->NotifyHostOnTimeout(operation,action);
2304                     pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
2305                 }
2306             }
2307             break;
2308         case eExitProcess:
2309         case eFastExitProcess:
2310         case eRudeExitProcess:
2311         case eDisableRuntime:
2312             // HandleExitProcessFromEscalation will try to grab ThreadStore again.
2313             _ASSERTE (ThreadStore::HoldingThreadStore());
2314             ThreadStore::UnlockThreadStore();
2315             GetEEPolicy()->NotifyHostOnTimeout(operation,action);
2316             EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_THREADABORT);
2317             _ASSERTE (!"Should not reach here");
2318             break;
2319         case eNoAction:
2320             break;
2321         default:
2322             _ASSERTE (!"unknown policy for thread abort");
2323         }
2324     }
2325     EX_CATCH {
2326     }
2327     EX_END_CATCH(SwallowAllExceptions);
2328 }
2329
2330 // If a thread is self-aborted and has a timeout, we need to watch the thread
2331 void Thread::ThreadAbortWatchDog()
2332 {
2333     CONTRACTL
2334     {
2335         NOTHROW;
2336         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
2337     }
2338     CONTRACTL_END;
2339
2340     if (CLRHosted())
2341     {
2342         ThreadStoreLockHolder tsLock;
2343
2344         ULONGLONG curTime = CLRGetTickCount64();
2345
2346         s_NextSelfAbortEndTime = MAXULONGLONG;
2347
2348         Thread *thread = NULL;
2349             while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
2350             {
2351                 if (!thread->IsAbortRequested())
2352                 {
2353                     continue;
2354                 }
2355
2356                 if (thread == FinalizerThread::GetFinalizerThread() && !g_FinalizerIsRunning)
2357                 {
2358                     // if finalizer method is not running, don't try to abort the finalizer thread
2359                     continue;
2360                 }
2361                 
2362             BOOL fNeedsToInitiateAbort = !thread->IsAbortInitiated() || thread->IsRudeAbort();
2363             ULONGLONG endTime = thread->GetAbortEndTime();
2364             if (fNeedsToInitiateAbort)
2365                 {
2366                 s_NextSelfAbortEndTime = 0;
2367             }
2368             else if (endTime < s_NextSelfAbortEndTime)
2369             {
2370                 s_NextSelfAbortEndTime = endTime;
2371                 }
2372
2373             if (thread->m_AbortController == 0)
2374                 {
2375                     STRESS_LOG3(LF_ALWAYS, LL_ALWAYS, "ThreadAbortWatchDog for Thread %p Thread Id = %x with timeout %x\n",
2376                                 thread, thread->GetThreadId(), endTime);
2377
2378                 if (endTime != MAXULONGLONG && curTime >= endTime)
2379                     {
2380                     ThreadAbortWatchDogEscalate(thread);
2381                     }
2382                 else if (fNeedsToInitiateAbort)
2383                     {
2384                     ThreadAbortWatchDogAbort(thread);
2385                 }
2386             }
2387         }
2388     }
2389 }
2390
2391 void Thread::LockAbortRequest(Thread* pThread)
2392 {
2393     WRAPPER_NO_CONTRACT;
2394
2395     DWORD dwSwitchCount = 0;
2396
2397     while (TRUE) {
2398         for (unsigned i = 0; i < 10000; i ++) {
2399             if (VolatileLoad(&(pThread->m_AbortRequestLock)) == 0) {
2400                 break;
2401             }
2402             YieldProcessor();               // indicate to the processor that we are spinning
2403         }
2404         if (FastInterlockCompareExchange(&(pThread->m_AbortRequestLock),1,0) == 0) {
2405             return;
2406         }
2407         __SwitchToThread(0, ++dwSwitchCount);
2408     }
2409 }
2410
2411 void Thread::UnlockAbortRequest(Thread *pThread)
2412 {
2413     LIMITED_METHOD_CONTRACT;
2414
2415     _ASSERTE (pThread->m_AbortRequestLock == 1);
2416     FastInterlockExchange(&pThread->m_AbortRequestLock, 0);
2417 }
2418
2419 void Thread::MarkThreadForAbort(ThreadAbortRequester requester, EEPolicy::ThreadAbortTypes abortType, BOOL fTentative /*=FALSE*/)
2420 {
2421     CONTRACTL
2422     {
2423         NOTHROW;
2424         GC_NOTRIGGER;
2425     }
2426     CONTRACTL_END;
2427
2428     _ASSERTE ((requester & TAR_StackOverflow) == 0 || (requester & TAR_Thread) == TAR_Thread);
2429
2430     AbortRequestLockHolder lh(this);
2431
2432     if (fTentative)
2433     {
2434         if (!IsAbortRequested())
2435         {
2436             STRESS_LOG0(LF_SYNC, LL_INFO1000, "Tentative thread abort abandoned\n");
2437             return;
2438         }
2439     }
2440
2441 #ifdef _DEBUG
2442     if (abortType == EEPolicy::TA_Rude)
2443     {
2444         m_fRudeAborted = TRUE;
2445     }
2446 #endif
2447
2448     DWORD abortInfo = 0;
2449
2450     if (requester & TAR_Thread)
2451     {
2452         if (abortType == EEPolicy::TA_Safe)
2453         {
2454             abortInfo |= TAI_ThreadAbort;
2455         }
2456         else if (abortType == EEPolicy::TA_Rude)
2457         {
2458             abortInfo |= TAI_ThreadRudeAbort;
2459         }
2460         else if (abortType == EEPolicy::TA_V1Compatible)
2461         {
2462             abortInfo |= TAI_ThreadV1Abort;
2463         }
2464     }
2465
2466     if (requester & TAR_ADUnload)
2467     {
2468         if (abortType == EEPolicy::TA_Safe)
2469         {
2470             abortInfo |= TAI_ADUnloadAbort;
2471         }
2472         else if (abortType == EEPolicy::TA_Rude)
2473         {
2474             abortInfo |= TAI_ADUnloadRudeAbort;
2475         }
2476         else if (abortType == EEPolicy::TA_V1Compatible)
2477         {
2478             abortInfo |= TAI_ADUnloadV1Abort;
2479         }
2480         if (IsADUnloadHelperThread())
2481         {
2482             abortInfo |= TAI_ForADUnloadThread;
2483         }
2484     }
2485
2486     if (requester & TAR_FuncEval)
2487     {
2488         if (abortType == EEPolicy::TA_Safe)
2489         {
2490             abortInfo |= TAI_FuncEvalAbort;
2491         }
2492         else if (abortType == EEPolicy::TA_Rude)
2493         {
2494             abortInfo |= TAI_FuncEvalRudeAbort;
2495         }
2496         else if (abortType == EEPolicy::TA_V1Compatible)
2497         {
2498             abortInfo |= TAI_FuncEvalV1Abort;
2499         }
2500     }
2501
2502     if (abortInfo == 0)
2503     {
2504         ASSERT(!"Invalid abort information");
2505         return;
2506     }
2507
2508     if (requester == TAR_Thread)
2509     {
2510         DWORD timeoutFromPolicy;
2511         if (abortType != EEPolicy::TA_Rude)
2512         {
2513             timeoutFromPolicy = GetEEPolicy()->GetTimeout(OPR_ThreadAbort);
2514         }
2515         else if (!HasLockInCurrentDomain())
2516         {
2517             timeoutFromPolicy = GetEEPolicy()->GetTimeout(OPR_ThreadRudeAbortInNonCriticalRegion);
2518         }
2519         else
2520         {
2521             timeoutFromPolicy = GetEEPolicy()->GetTimeout(OPR_ThreadRudeAbortInCriticalRegion);
2522         }
2523         if (timeoutFromPolicy != INFINITE)
2524         {
2525             ULONGLONG endTime = CLRGetTickCount64() + timeoutFromPolicy;
2526             if (abortType != EEPolicy::TA_Rude)
2527             {
2528                 if (endTime < m_AbortEndTime)
2529                 {
2530                     m_AbortEndTime = endTime;
2531                 }
2532             }
2533             else if (endTime < m_RudeAbortEndTime)
2534             {
2535                 m_RudeAbortEndTime = endTime;
2536             }
2537             // We can not call into host if we are in the middle of stack overflow.
2538             // And we don't need to wake up our watchdog if there is no timeout.
2539             if (GetThread() == this && (requester & TAR_StackOverflow) == 0)
2540         {
2541             AppDomain::EnableADUnloadWorkerForThreadAbort();
2542         }
2543     }
2544     }
2545
2546     if (abortInfo == (m_AbortInfo & abortInfo))
2547     {
2548         //
2549         // We are already doing this kind of abort.
2550         //
2551         return;
2552     }
2553
2554     m_AbortInfo |= abortInfo;
2555
2556     if (m_AbortType >= (DWORD)abortType)
2557     {
2558         // another thread is aborting at a higher level
2559         return;
2560     }
2561
2562     m_AbortType = abortType;
2563
2564     if (!IsAbortRequested())
2565     {
2566         // We must set this before we start flipping thread bits to avoid races where
2567         // trap returning threads is already high due to other reasons.
2568
2569         // The thread is asked for abort the first time
2570         SetAbortRequestBit();
2571
2572 #ifdef _DEBUG
2573         AddFiberInfo(ThreadTrackInfo_Abort);
2574 #endif
2575     }
2576     STRESS_LOG4(LF_APPDOMAIN, LL_ALWAYS, "Mark Thread %p Thread Id = %x for abort from requester %d (type %d)\n", this, GetThreadId(), requester, abortType);
2577 }
2578
2579 void Thread::SetAbortRequestBit()
2580 {
2581     WRAPPER_NO_CONTRACT;
2582     while (TRUE)
2583     {
2584         Volatile<LONG> curValue = (LONG)m_State;
2585         if ((curValue & TS_AbortRequested) != 0)
2586         {
2587             break;
2588         }
2589         if (FastInterlockCompareExchange((LONG*)&m_State, curValue|TS_AbortRequested, curValue) == curValue)
2590         {
2591             ThreadStore::TrapReturningThreads(TRUE);
2592
2593             break;
2594         }
2595     }
2596 }
2597
2598 void Thread::RemoveAbortRequestBit()
2599 {
2600     CONTRACTL {
2601         NOTHROW;
2602         GC_NOTRIGGER;
2603     } CONTRACTL_END;
2604
2605 #ifdef _DEBUG
2606     // There's a race between removing the TS_AbortRequested bit and decrementing g_TrapReturningThreads
2607     // We may remove the bit, but before we have a chance to call ThreadStore::TrapReturningThreads(FALSE)
2608     // DbgFindThread() may execute, and find too few threads with the bit set.
2609     // To ensure the assert in DbgFindThread does not fire under such a race we set the ChgInFlight before hand.
2610     CounterHolder trtHolder(&g_trtChgInFlight);
2611 #endif
2612     while (TRUE)
2613     {
2614         Volatile<LONG> curValue = (LONG)m_State;
2615         if ((curValue & TS_AbortRequested) == 0)
2616         {
2617             break;
2618         }
2619         if (FastInterlockCompareExchange((LONG*)&m_State, curValue&(~TS_AbortRequested), curValue) == curValue)
2620         {
2621             ThreadStore::TrapReturningThreads(FALSE);
2622
2623             break;
2624         }
2625     }
2626 }
2627
2628 // Make sure that when AbortRequest bit is cleared, we also dec TrapReturningThreads count.
2629 void Thread::UnmarkThreadForAbort(ThreadAbortRequester requester, BOOL fForce)
2630 {
2631     CONTRACTL
2632     {
2633         NOTHROW;
2634         GC_NOTRIGGER;
2635     }
2636     CONTRACTL_END;
2637
2638     // Switch to COOP (for ClearAbortReason) before acquiring AbortRequestLock 
2639     GCX_COOP();
2640
2641     AbortRequestLockHolder lh(this);
2642
2643     //
2644     // Unmark the bits that are being turned off
2645     //
2646     if (requester & TAR_Thread)
2647     {
2648         if ((m_AbortInfo != TAI_ThreadRudeAbort) || fForce)
2649         {
2650             m_AbortInfo &= ~(TAI_ThreadAbort   |
2651                              TAI_ThreadV1Abort |
2652                              TAI_ThreadRudeAbort );
2653         }
2654
2655         if (m_AbortReason)
2656         {
2657             ClearAbortReason(TRUE);
2658         }
2659     }
2660
2661     if (requester & TAR_ADUnload)
2662     {
2663         m_AbortInfo &= ~(TAI_ADUnloadAbort   |
2664                          TAI_ADUnloadV1Abort |
2665                          TAI_ADUnloadRudeAbort);
2666     }
2667
2668     if (requester & TAR_FuncEval)
2669     {
2670         m_AbortInfo &= ~(TAI_FuncEvalAbort   |
2671                          TAI_FuncEvalV1Abort |
2672                          TAI_FuncEvalRudeAbort);
2673     }
2674
2675     //
2676     // Decide which type of abort to do based on the new bit field.
2677     //
2678     if (m_AbortInfo & TAI_AnyRudeAbort)
2679     {
2680         m_AbortType = EEPolicy::TA_Rude;
2681     }
2682     else if (m_AbortInfo & TAI_AnyV1Abort)
2683     {
2684         m_AbortType = EEPolicy::TA_V1Compatible;
2685         }
2686     else if (m_AbortInfo & TAI_AnySafeAbort)
2687     {
2688         m_AbortType = EEPolicy::TA_Safe;
2689     }
2690     else
2691     {
2692         m_AbortType = EEPolicy::TA_None;
2693     }
2694
2695     //
2696     // If still aborting, do nothing
2697     //
2698     if (m_AbortType != EEPolicy::TA_None)
2699     {
2700         return;
2701     }
2702
2703     m_AbortEndTime = MAXULONGLONG;
2704     m_RudeAbortEndTime = MAXULONGLONG;
2705
2706     if (IsAbortRequested())
2707     {
2708         RemoveAbortRequestBit();
2709         FastInterlockAnd((DWORD*)&m_State,~(TS_AbortInitiated));
2710         m_fRudeAbortInitiated = FALSE;
2711         ResetUserInterrupted();
2712
2713 #ifdef _DEBUG
2714         AddFiberInfo(ThreadTrackInfo_Abort);
2715 #endif
2716     }
2717
2718     STRESS_LOG3(LF_APPDOMAIN, LL_ALWAYS, "Unmark Thread %p Thread Id = %x for abort from requester %d\n", this, GetThreadId(), requester);
2719 }
2720
2721 // Make sure that when AbortRequest bit is cleared, we also dec TrapReturningThreads count.
2722 void Thread::ResetBeginAbortedForADUnload()
2723 {
2724     CONTRACTL
2725     {
2726         NOTHROW;
2727         GC_NOTRIGGER;
2728     }
2729     CONTRACTL_END;
2730
2731     AbortRequestLockHolder lh(this);
2732
2733     m_AbortInfo &= ~TAI_ForADUnloadThread;
2734 }
2735
2736 void Thread::InternalResetAbort(ThreadAbortRequester requester, BOOL fResetRudeAbort)
2737 {
2738     CONTRACTL {
2739         NOTHROW;
2740         GC_NOTRIGGER;
2741     }
2742     CONTRACTL_END;
2743
2744     _ASSERTE(this == GetThread());
2745     _ASSERTE(!IsDead());
2746
2747     // managed code can not reset Rude thread abort
2748     UnmarkThreadForAbort(requester, fResetRudeAbort);
2749 #ifdef _DEBUG
2750     AddFiberInfo(ThreadTrackInfo_Abort);
2751 #endif
2752 }
2753
2754
2755 // Throw a thread abort request when a suspended thread is resumed. Make sure you know what you
2756 // are doing when you call this routine.
2757 void Thread::SetAbortRequest(EEPolicy::ThreadAbortTypes abortType)
2758 {
2759     CONTRACTL {
2760         NOTHROW;
2761         GC_NOTRIGGER;
2762     }
2763     CONTRACTL_END;
2764
2765     MarkThreadForAbort(TAR_ADUnload, abortType);
2766
2767     if (m_State & TS_Interruptible)
2768     {
2769         UserInterrupt(TI_Abort);
2770     }
2771 }
2772
2773
2774 void ThreadSuspend::LockThreadStore(ThreadSuspend::SUSPEND_REASON reason)
2775 {
2776     CONTRACTL {
2777         NOTHROW;
2778         if ((GetThread() != NULL) && GetThread()->PreemptiveGCDisabled()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
2779     }
2780     CONTRACTL_END;
2781
2782     // There's a nasty problem here.  Once we start shutting down because of a
2783     // process detach notification, threads are disappearing from under us.  There
2784     // are a surprising number of cases where the dying thread holds the ThreadStore
2785     // lock.  For example, the finalizer thread holds this during startup in about
2786     // 10 of our COM BVTs.
2787     if (!IsAtProcessExit())
2788     {
2789         BOOL gcOnTransitions;
2790
2791         Thread *pCurThread = GetThread();
2792
2793         gcOnTransitions = GC_ON_TRANSITIONS(FALSE);                // dont do GC for GCStress 3
2794
2795         BOOL toggleGC = (   pCurThread != NULL
2796                          && pCurThread->PreemptiveGCDisabled()
2797                          && reason != ThreadSuspend::SUSPEND_FOR_GC);
2798
2799         // Note: there is logic in gc.cpp surrounding suspending all
2800         // runtime threads for a GC that depends on the fact that we
2801         // do an EnablePreemptiveGC and a DisablePreemptiveGC around
2802         // taking this lock.
2803         if (toggleGC)
2804             pCurThread->EnablePreemptiveGC();
2805
2806         LOG((LF_SYNC, INFO3, "Locking thread store\n"));
2807
2808         // Any thread that holds the thread store lock cannot be stopped by unmanaged breakpoints and exceptions when
2809         // we're doing managed/unmanaged debugging. Calling SetDebugCantStop(true) on the current thread helps us
2810         // remember that.
2811         if (pCurThread)
2812             pCurThread->SetDebugCantStop(true);
2813
2814         // This is used to avoid thread starvation if non-GC threads are competing for
2815         // the thread store lock when there is a real GC-thread waiting to get in.
2816         // This is initialized lazily when the first non-GC thread backs out because of
2817         // a waiting GC thread.
2818         if (s_hAbortEvt != NULL &&
2819             !(reason == ThreadSuspend::SUSPEND_FOR_GC || 
2820               reason == ThreadSuspend::SUSPEND_FOR_GC_PREP ||
2821               reason == ThreadSuspend::SUSPEND_FOR_DEBUGGER_SWEEP) &&
2822             m_pThreadAttemptingSuspendForGC != NULL &&
2823             m_pThreadAttemptingSuspendForGC != pCurThread)
2824         {
2825             CLREventBase * hAbortEvt = s_hAbortEvt;
2826
2827             if (hAbortEvt != NULL)
2828             {
2829                 LOG((LF_SYNC, INFO3, "Performing suspend abort wait.\n"));
2830                 hAbortEvt->Wait(INFINITE, FALSE);
2831                 LOG((LF_SYNC, INFO3, "Release from suspend abort wait.\n"));
2832             }
2833         }
2834
2835         // This is shutdown aware. If we're in shutdown, and not helper/finalizer/shutdown
2836         // then this will not take the lock and just block forever.
2837         ThreadStore::s_pThreadStore->Enter();
2838
2839
2840         _ASSERTE(ThreadStore::s_pThreadStore->m_holderthreadid.IsUnknown());
2841         ThreadStore::s_pThreadStore->m_holderthreadid.SetToCurrentThread();
2842
2843         LOG((LF_SYNC, INFO3, "Locked thread store\n"));
2844
2845         // Established after we obtain the lock, so only useful for synchronous tests.
2846         // A thread attempting to suspend us asynchronously already holds this lock.
2847         ThreadStore::s_pThreadStore->m_HoldingThread = pCurThread;
2848
2849 #ifndef _PREFAST_
2850         if (toggleGC)
2851             pCurThread->DisablePreemptiveGC();
2852 #endif
2853
2854         GC_ON_TRANSITIONS(gcOnTransitions);
2855     }
2856 #ifdef _DEBUG
2857     else
2858         LOG((LF_SYNC, INFO3, "Locking thread store skipped upon detach\n"));
2859 #endif
2860 }
2861
2862 void ThreadSuspend::UnlockThreadStore(BOOL bThreadDestroyed, ThreadSuspend::SUSPEND_REASON reason)
2863 {
2864     CONTRACTL {
2865         NOTHROW;
2866         GC_NOTRIGGER;
2867     }
2868     CONTRACTL_END;
2869
2870     // There's a nasty problem here.  Once we start shutting down because of a
2871     // process detach notification, threads are disappearing from under us.  There
2872     // are a surprising number of cases where the dying thread holds the ThreadStore
2873     // lock.  For example, the finalizer thread holds this during startup in about
2874     // 10 of our COM BVTs.
2875     if (!IsAtProcessExit())
2876     {
2877         Thread *pCurThread = GetThread();
2878
2879         LOG((LF_SYNC, INFO3, "Unlocking thread store\n"));
2880         _ASSERTE(GetThread() == NULL || ThreadStore::s_pThreadStore->m_HoldingThread == GetThread());
2881
2882 #ifdef _DEBUG
2883         // If Thread object has been destroyed, we need to reset the ownership info in Crst.
2884         _ASSERTE(!bThreadDestroyed || GetThread() == NULL);
2885         if (bThreadDestroyed) {
2886             ThreadStore::s_pThreadStore->m_Crst.m_holderthreadid.SetToCurrentThread();
2887         }
2888 #endif
2889
2890         ThreadStore::s_pThreadStore->m_HoldingThread = NULL;
2891         ThreadStore::s_pThreadStore->m_holderthreadid.Clear();
2892         ThreadStore::s_pThreadStore->Leave();
2893
2894         // We're out of the critical area for managed/unmanaged debugging.
2895         if (!bThreadDestroyed && pCurThread)
2896             pCurThread->SetDebugCantStop(false);
2897     }
2898 #ifdef _DEBUG
2899     else
2900         LOG((LF_SYNC, INFO3, "Unlocking thread store skipped upon detach\n"));
2901 #endif
2902 }
2903
2904
2905 void ThreadStore::AllocateOSContext()
2906 {
2907     LIMITED_METHOD_CONTRACT;
2908     _ASSERTE(HoldingThreadStore());
2909     if (s_pOSContext == NULL
2910 #ifdef _DEBUG
2911         || s_pOSContext == (CONTEXT*)0x1
2912 #endif
2913        )
2914     {
2915         s_pOSContext = new (nothrow) CONTEXT();
2916     }
2917 #ifdef _DEBUG
2918     if (s_pOSContext == NULL)
2919     {
2920         s_pOSContext = (CONTEXT*)0x1;
2921     }
2922 #endif
2923 }
2924
2925 CONTEXT *ThreadStore::GrabOSContext()
2926 {
2927     LIMITED_METHOD_CONTRACT;
2928     _ASSERTE(HoldingThreadStore());
2929     CONTEXT *pContext = s_pOSContext;
2930     s_pOSContext = NULL;
2931 #ifdef _DEBUG
2932     if (pContext == (CONTEXT*)0x1)
2933     {
2934         pContext = NULL;
2935     }
2936 #endif
2937     return pContext;
2938 }
2939
2940 extern void WaitForEndOfShutdown();
2941
2942 //----------------------------------------------------------------------------
2943 //
2944 // Suspending threads, rendezvousing with threads that reach safe places, etc.
2945 //
2946 //----------------------------------------------------------------------------
2947
2948 // A note on SUSPENSIONS.
2949 //
2950 // We must not suspend a thread while it is holding the ThreadStore lock, or
2951 // the lock on the thread.  Why?  Because we need those locks to resume the
2952 // thread (and to perform a GC, use the debugger, spawn or kill threads, etc.)
2953 //
2954 // There are two types of suspension we must consider to enforce the above
2955 // rule.  Synchronous suspensions are where we persuade the thread to suspend
2956 // itself.  This is CommonTripThread and its cousins.  In other words, the
2957 // thread toggles the GC mode, or it hits a hijack, or certain opcodes in the
2958 // interpreter, etc.  In these cases, the thread can simply check whether it
2959 // is holding these locks before it suspends itself.
2960 //
2961 // The other style is an asynchronous suspension.  This is where another
2962 // thread looks to see where we are.  If we are in a fully interruptible region
2963 // of JIT code, we will be left suspended.  In this case, the thread performing
2964 // the suspension must hold the locks on the thread and the threadstore.  This
2965 // ensures that we aren't suspended while we are holding these locks.
2966 //
2967 // Note that in the asynchronous case it's not enough to just inspect the thread
2968 // to see if it's holding these locks.  Since the thread must be in preemptive
2969 // mode to block to acquire these locks, and since there will be a few inst-
2970 // ructions between acquiring the lock and noting in our state that we've
2971 // acquired it, then there would be a window where we would seem eligible for
2972 // suspension -- but in fact would not be.
2973
2974 //----------------------------------------------------------------------------
2975
2976 // We can't leave preemptive mode and enter cooperative mode, if a GC is
2977 // currently in progress.  This is the situation when returning back into
2978 // the EE from outside.  See the comments in DisablePreemptiveGC() to understand
2979 // why we Enable GC here!
2980 void Thread::RareDisablePreemptiveGC()
2981 {
2982     BEGIN_PRESERVE_LAST_ERROR;
2983
2984     CONTRACTL {
2985         NOTHROW;
2986         SO_TOLERANT;
2987         DISABLED(GC_TRIGGERS);  // I think this is actually wrong: prevents a p->c->p mode switch inside a NOTRIGGER region.
2988     }
2989     CONTRACTL_END;
2990
2991     CONTRACT_VIOLATION(SOToleranceViolation);
2992
2993     if (IsAtProcessExit())
2994     {
2995         goto Exit;
2996     }
2997
2998
2999 #ifdef _DEBUG
3000     AddFiberInfo(ThreadTrackInfo_GCMode);
3001 #endif
3002
3003     // This should NEVER be called if the TSNC_UnsafeSkipEnterCooperative bit is set!
3004     _ASSERTE(!(m_StateNC & TSNC_UnsafeSkipEnterCooperative) && "DisablePreemptiveGC called while the TSNC_UnsafeSkipEnterCooperative bit is set");
3005
3006     // Holding a spin lock in preemp mode and switch to coop mode could cause other threads spinning
3007     // waiting for GC
3008     _ASSERTE ((m_StateNC & Thread::TSNC_OwnsSpinLock) == 0);
3009
3010     if (!GCHeapUtilities::IsGCHeapInitialized())
3011     {
3012         goto Exit;
3013     }
3014
3015     // CoreCLR does not support user-requested thread suspension
3016     _ASSERTE(!(m_State & TS_UserSuspendPending));
3017
3018     // Note IsGCInProgress is also true for say Pause (anywhere SuspendEE happens) and GCThread is the 
3019     // thread that did the Pause. While in Pause if another thread attempts Rev/Pinvoke it should get inside the following and 
3020     // block until resume
3021     if (((GCHeapUtilities::IsGCInProgress()  && (this != ThreadSuspend::GetSuspensionThread())) ||
3022         (m_State & (TS_UserSuspendPending | TS_DebugSuspendPending | TS_StackCrawlNeeded))) &&
3023         (!g_fSuspendOnShutdown || IsFinalizerThread() || IsShutdownSpecialThread()))
3024     {
3025         if (!ThreadStore::HoldingThreadStore(this))
3026         {
3027             STRESS_LOG1(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: entering. Thread state = %x\n", m_State.Load());
3028
3029             DWORD dwSwitchCount = 0;
3030
3031             do
3032             {
3033                 // CoreCLR does not support user-requested thread suspension
3034                 _ASSERTE(!(m_State & TS_UserSuspendPending));
3035
3036                 EnablePreemptiveGC();
3037
3038                 // Cannot use GCX_PREEMP_NO_DTOR here because we're inside of the thread
3039                 // PREEMP->COOP switch mechanism and GCX_PREEMP's assert's will fire.
3040                 // Instead we use BEGIN_GCX_ASSERT_PREEMP to inform Scan of the mode
3041                 // change here.
3042                 BEGIN_GCX_ASSERT_PREEMP;
3043
3044                 // just wait until the GC is over.
3045                 if (this != ThreadSuspend::GetSuspensionThread())
3046                 {
3047 #ifdef PROFILING_SUPPORTED
3048                     // If profiler desires GC events, notify it that this thread is waiting until the GC is over
3049                     // Do not send suspend notifications for debugger suspensions
3050                     {
3051                         BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
3052                         if (!(m_State & TS_DebugSuspendPending))
3053                         {
3054                             g_profControlBlock.pProfInterface->RuntimeThreadSuspended((ThreadID)this);
3055                         }
3056                         END_PIN_PROFILER();
3057                     }
3058 #endif // PROFILING_SUPPORTED
3059
3060
3061
3062                     DWORD status = S_OK;
3063                     SetThreadStateNC(TSNC_WaitUntilGCFinished);
3064                     status = GCHeapUtilities::GetGCHeap()->WaitUntilGCComplete();
3065                     ResetThreadStateNC(TSNC_WaitUntilGCFinished);
3066
3067                     if (status == (DWORD)COR_E_STACKOVERFLOW)
3068                     {
3069                         // One of two things can happen here:
3070                         // 1. GC is suspending the process.  GC needs to wait.
3071                         // 2. GC is proceeding after suspension.  The current thread needs to spin.
3072                         SetThreadState(TS_BlockGCForSO);
3073                         while (GCHeapUtilities::IsGCInProgress() && m_fPreemptiveGCDisabled.Load() == 0)
3074                         {
3075 #undef Sleep
3076                             // We can not go to a host for blocking operation due ot lack of stack.
3077                             // Instead we will spin here until
3078                             // 1. GC is finished; Or
3079                             // 2. GC lets this thread to run and will wait for it
3080                             Sleep(10);
3081 #define Sleep(a) Dont_Use_Sleep(a)
3082                         }
3083                         ResetThreadState(TS_BlockGCForSO);
3084                         if (m_fPreemptiveGCDisabled.Load() == 1)
3085                         {
3086                             // GC suspension has allowed this thread to switch back to cooperative mode.
3087                             break;
3088                         }
3089                     }
3090                     if (!GCHeapUtilities::IsGCInProgress())
3091                     {
3092                         if (HasThreadState(TS_StackCrawlNeeded))
3093                         {
3094                             SetThreadStateNC(TSNC_WaitUntilGCFinished);
3095                             ThreadStore::WaitForStackCrawlEvent();
3096                             ResetThreadStateNC(TSNC_WaitUntilGCFinished);
3097                         }
3098                         else
3099                         {
3100                             __SwitchToThread(0, ++dwSwitchCount);
3101                         }
3102                     }
3103
3104 #ifdef PROFILING_SUPPORTED
3105                     // Let the profiler know that this thread is resuming
3106                     {
3107                         BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
3108                         g_profControlBlock.pProfInterface->RuntimeThreadResumed((ThreadID)this);
3109                         END_PIN_PROFILER();
3110                     }
3111 #endif // PROFILING_SUPPORTED
3112                 }
3113
3114                 END_GCX_ASSERT_PREEMP;
3115
3116                 // disable preemptive gc.
3117                 FastInterlockOr(&m_fPreemptiveGCDisabled, 1);
3118
3119                 // The fact that we check whether 'this' is the GC thread may seem
3120                 // strange.  After all, we determined this before entering the method.
3121                 // However, it is possible for the current thread to become the GC
3122                 // thread while in this loop.  This happens if you use the COM+
3123                 // debugger to suspend this thread and then release it.
3124
3125             } while ((GCHeapUtilities::IsGCInProgress()  && (this != ThreadSuspend::GetSuspensionThread())) ||
3126                      (m_State & (TS_UserSuspendPending | TS_DebugSuspendPending | TS_StackCrawlNeeded)));
3127         }
3128         STRESS_LOG0(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: leaving\n");
3129     }
3130
3131     // Block all threads except finalizer and shutdown thread during shutdown.
3132     // If g_fSuspendFinalizerOnShutdown is set, block the finalizer too.
3133     if ((g_fSuspendOnShutdown && !IsFinalizerThread() && !IsShutdownSpecialThread()) ||
3134         (g_fSuspendFinalizerOnShutdown && IsFinalizerThread()))
3135     {
3136         STRESS_LOG1(LF_SYNC, LL_INFO1000, "RareDisablePreemptiveGC: entering. Thread state = %x\n", m_State.Load());
3137
3138         EnablePreemptiveGC();
3139
3140         // Cannot use GCX_PREEMP_NO_DTOR here because we're inside of the thread
3141         // PREEMP->COOP switch mechanism and GCX_PREEMP's assert's will fire.
3142         // Instead we use BEGIN_GCX_ASSERT_PREEMP to inform Scan of the mode
3143         // change here.
3144         BEGIN_GCX_ASSERT_PREEMP;
3145
3146 #ifdef PROFILING_SUPPORTED
3147         // If profiler desires GC events, notify it that this thread is waiting until the GC is over
3148         // Do not send suspend notifications for debugger suspensions
3149         {
3150             BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
3151             if (!(m_State & TS_DebugSuspendPending))
3152             {
3153                 g_profControlBlock.pProfInterface->RuntimeThreadSuspended((ThreadID)this);
3154             }
3155             END_PIN_PROFILER();
3156         }
3157 #endif // PROFILING_SUPPORTED
3158
3159
3160
3161         // The thread is blocked for shutdown.  We do not concern for GC violation.
3162         CONTRACT_VIOLATION(GCViolation);
3163
3164         WaitForEndOfShutdown();
3165
3166         END_GCX_ASSERT_PREEMP;
3167
3168         __SwitchToThread(INFINITE, CALLER_LIMITS_SPINNING);
3169         _ASSERTE(!"Cannot reach here");
3170     }
3171
3172 Exit: ;
3173     END_PRESERVE_LAST_ERROR;
3174 }
3175
3176 void Thread::HandleThreadAbortTimeout()
3177 {
3178     WRAPPER_NO_CONTRACT;
3179
3180     EPolicyAction action = eNoAction;
3181     EClrOperation operation = OPR_ThreadRudeAbortInNonCriticalRegion;
3182
3183     if (IsFuncEvalAbort())
3184     {   
3185         // There can't be escalation policy for FuncEvalAbort timeout.
3186         // The debugger should retain control of the policy.  For example, if a RudeAbort times out, it's
3187         // probably because the debugger had some other thread frozen.  When the thread is thawed, things might
3188         // be fine, so we don't want to escelate the FuncEvalRudeAbort (which will be swalled by FuncEvalHijackWorker)
3189         // into a user RudeThreadAbort (which will at least rip the entire thread).
3190         return;
3191     }        
3192
3193     if (!IsRudeAbort())
3194     {
3195         operation = OPR_ThreadAbort;
3196     }
3197     else if (HasLockInCurrentDomain())
3198     {
3199         operation = OPR_ThreadRudeAbortInCriticalRegion;
3200     }
3201     else
3202     {
3203         operation = OPR_ThreadRudeAbortInNonCriticalRegion;
3204     }
3205     action = GetEEPolicy()->GetActionOnTimeout(operation, this);
3206     // We only support escalation to rude abort
3207
3208     EX_TRY {
3209         switch (action)
3210         {
3211         case eRudeAbortThread:
3212             GetEEPolicy()->NotifyHostOnTimeout(operation,action);
3213             MarkThreadForAbort(TAR_Thread, EEPolicy::TA_Rude);
3214             break;
3215         case eUnloadAppDomain:
3216             {
3217                 AppDomain *pDomain = GetDomain();
3218                 if (!pDomain->IsDefaultDomain())
3219                 {
3220                     GetEEPolicy()->NotifyHostOnTimeout(operation,action);
3221                     pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
3222                 }
3223             }
3224             break;
3225         case eRudeUnloadAppDomain:
3226             {
3227                 AppDomain *pDomain = GetDomain();
3228                 if (!pDomain->IsDefaultDomain())
3229                 {
3230                     GetEEPolicy()->NotifyHostOnTimeout(operation,action);
3231                     pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
3232                 }
3233             }
3234             break;
3235         case eExitProcess:
3236         case eFastExitProcess:
3237         case eRudeExitProcess:
3238         case eDisableRuntime:
3239             GetEEPolicy()->NotifyHostOnTimeout(operation,action);
3240             EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_THREADABORT);
3241             _ASSERTE (!"Should not reach here");
3242             break;
3243         case eNoAction:
3244             break;
3245         default:
3246             _ASSERTE (!"unknown policy for thread abort");
3247         }
3248     }
3249     EX_CATCH {
3250     }
3251     EX_END_CATCH(SwallowAllExceptions);
3252 }
3253
3254 void Thread::HandleThreadAbort (BOOL fForce)
3255 {
3256     BEGIN_PRESERVE_LAST_ERROR;
3257
3258     STATIC_CONTRACT_THROWS;
3259     STATIC_CONTRACT_GC_TRIGGERS;
3260     STATIC_CONTRACT_SO_TOLERANT;
3261
3262     BEGIN_SO_INTOLERANT_CODE(this);
3263     TESTHOOKCALL(AppDomainCanBeUnloaded(GetDomain()->GetId().m_dwId,FALSE));
3264
3265     // It's possible we could go through here if we hit a hard SO and MC++ has called back
3266     // into the runtime on this thread
3267
3268     FinishSOWork();
3269   
3270     if (IsAbortRequested() && GetAbortEndTime() < CLRGetTickCount64())
3271     {
3272         HandleThreadAbortTimeout();
3273     }
3274
3275     // @TODO: we should consider treating this function as an FCALL or HCALL and use FCThrow instead of COMPlusThrow
3276
3277     // Sometimes we call this without any CLR SEH in place.  An example is UMThunkStubRareDisableWorker.
3278     // That's okay since COMPlusThrow will eventually erect SEH around the RaiseException. It prevents
3279     // us from stating CONTRACT here.
3280
3281     if (fForce || ReadyForAbort())
3282     {
3283         ResetThreadState ((ThreadState)(TS_Interrupted | TS_Interruptible));
3284         // We are going to abort.  Abort satisfies Thread.Interrupt requirement.
3285         FastInterlockExchange (&m_UserInterrupt, 0);
3286
3287         // generate either a ThreadAbort exception
3288         STRESS_LOG1(LF_APPDOMAIN, LL_INFO100, "Thread::HandleThreadAbort throwing abort for %x\n", GetThreadId());
3289
3290         GCX_COOP_NO_DTOR();
3291
3292         // Can not use holder.  GCX_COOP forces the thread back to the original state during
3293         // exception unwinding, which may put the thread back to cooperative mode.
3294         // GCX_COOP();
3295
3296         if (!IsAbortInitiated() ||
3297             (IsRudeAbort() && !IsRudeAbortInitiated()))
3298         {
3299             PreWorkForThreadAbort();
3300         }
3301
3302         PreparingAbortHolder paHolder;
3303
3304         OBJECTREF exceptObj;
3305
3306         if (IsRudeAbort())
3307         {
3308             exceptObj = CLRException::GetPreallocatedRudeThreadAbortException();
3309         }
3310         else
3311         {
3312             EEException eeExcept(kThreadAbortException);
3313             exceptObj = CLRException::GetThrowableFromException(&eeExcept);
3314         }
3315
3316 #ifdef _DEBUG
3317         AddFiberInfo(ThreadTrackInfo_Abort);
3318 #endif
3319         RaiseTheExceptionInternalOnly(exceptObj, FALSE);
3320     }
3321     END_SO_INTOLERANT_CODE;
3322
3323     END_PRESERVE_LAST_ERROR;
3324 }
3325
3326 void Thread::PreWorkForThreadAbort()
3327 {
3328     WRAPPER_NO_CONTRACT;
3329
3330     SetAbortInitiated();
3331     // if an abort and interrupt happen at the same time (e.g. on a sleeping thread),
3332     // the abort is favored. But we do need to reset the interrupt bits.
3333     FastInterlockAnd((ULONG *) &m_State, ~(TS_Interruptible | TS_Interrupted));
3334     ResetUserInterrupted();
3335
3336     if (IsRudeAbort() && !(m_AbortInfo & (TAI_ADUnloadAbort |
3337                                           TAI_ADUnloadRudeAbort |
3338                                           TAI_ADUnloadV1Abort)
3339                           )) {
3340         if (HasLockInCurrentDomain()) {
3341             AppDomain *pDomain = GetAppDomain();
3342             // Cannot enable the following assertion.
3343             // We may take the lock, but the lock will be released during exception backout.
3344             //_ASSERTE(!pDomain->IsDefaultDomain());
3345             EPolicyAction action = GetEEPolicy()->GetDefaultAction(OPR_ThreadRudeAbortInCriticalRegion, this);
3346             switch (action)
3347             {
3348             case eRudeUnloadAppDomain:
3349                 if (!pDomain->IsDefaultDomain())
3350                 {
3351                     GetEEPolicy()->NotifyHostOnDefaultAction(OPR_ThreadRudeAbortInCriticalRegion,action);
3352                     pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
3353                 }
3354                 break;
3355             case eExitProcess:
3356             case eFastExitProcess:
3357             case eRudeExitProcess:
3358             case eDisableRuntime:
3359                     {
3360                         // We're about to exit the process, if we take an SO here we'll just exit faster right???
3361                         CONTRACT_VIOLATION(SOToleranceViolation);
3362
3363                 GetEEPolicy()->NotifyHostOnDefaultAction(OPR_ThreadRudeAbortInCriticalRegion,action);
3364                 GetEEPolicy()->HandleExitProcessFromEscalation(action,HOST_E_EXITPROCESS_ADUNLOAD);
3365                     }
3366                 break;
3367             default:
3368                 break;
3369             }
3370         }
3371     }
3372 }
3373
3374 #if defined(STRESS_HEAP) && defined(_DEBUG)
3375
3376 // This function is for GC stress testing.  Before we enable preemptive GC, let us do a GC
3377 // because GC may happen while the thread is in preemptive GC mode.
3378 void Thread::PerformPreemptiveGC()
3379 {
3380     CONTRACTL {
3381         NOTHROW;
3382         DISABLED(GC_TRIGGERS);  // I think this is actually wrong: prevents a p->c->p mode switch inside a NOTRIGGER region.
3383         DEBUG_ONLY;
3384     }
3385     CONTRACTL_END;
3386
3387     if (IsAtProcessExit())
3388         return;
3389
3390     if (!GCStressPolicy::IsEnabled() || !GCStress<cfg_transition>::IsEnabled())
3391         return;
3392
3393     if (!GCHeapUtilities::IsGCHeapInitialized())
3394         return;
3395
3396     if (!m_GCOnTransitionsOK
3397 #ifdef ENABLE_CONTRACTS
3398         || RawGCNoTrigger()
3399 #endif
3400         || g_fEEShutDown
3401         || GCHeapUtilities::IsGCInProgress(TRUE)
3402         || GCHeapUtilities::GetGCHeap()->GetGcCount() == 0    // Need something that works for isolated heap.
3403         || ThreadStore::HoldingThreadStore())
3404         return;
3405
3406     if (Thread::ThreadsAtUnsafePlaces())
3407         return;
3408
3409 #ifdef DEBUGGING_SUPPORTED
3410     // Don't collect if the debugger is attach and either 1) there
3411     // are any threads held at unsafe places or 2) this thread is
3412     // under the control of the debugger's dispatch logic (as
3413     // evidenced by having a non-NULL filter context.)
3414     if ((CORDebuggerAttached() &&
3415         (g_pDebugInterface->ThreadsAtUnsafePlaces() ||
3416         (GetFilterContext() != NULL))))
3417         return;
3418 #endif // DEBUGGING_SUPPORTED
3419
3420     _ASSERTE(m_fPreemptiveGCDisabled.Load() == 0);     // we are in preemptive mode when we call this
3421
3422     m_GCOnTransitionsOK = FALSE;
3423     {
3424         GCX_COOP();
3425         m_bGCStressing = TRUE;
3426
3427         // BUG(github #10318) - when not using allocation contexts, the alloc lock
3428         // must be acquired here. Until fixed, this assert prevents random heap corruption.
3429         _ASSERTE(GCHeapUtilities::UseThreadAllocationContexts());
3430         GCHeapUtilities::GetGCHeap()->StressHeap(GetThread()->GetAllocContext());
3431         m_bGCStressing = FALSE;
3432     }
3433     m_GCOnTransitionsOK = TRUE;
3434 }
3435 #endif  // STRESS_HEAP && DEBUG
3436
3437 // To leave cooperative mode and enter preemptive mode, if a GC is in progress, we
3438 // no longer care to suspend this thread.  But if we are trying to suspend the thread
3439 // for other reasons (e.g. Thread.Suspend()), now is a good time.
3440 //
3441 // Note that it is possible for an N/Direct call to leave the EE without explicitly
3442 // enabling preemptive GC.
3443 void Thread::RareEnablePreemptiveGC()
3444 {
3445     CONTRACTL {
3446         NOTHROW;
3447         DISABLED(GC_TRIGGERS); // I think this is actually wrong: prevents a p->c->p mode switch inside a NOTRIGGER region.
3448         SO_TOLERANT;
3449     }
3450     CONTRACTL_END;
3451
3452     // @todo -  Needs a hard SO probe
3453     CONTRACT_VIOLATION(GCViolation|FaultViolation|SOToleranceViolation);
3454
3455     // If we have already received our PROCESS_DETACH during shutdown, there is only one thread in the
3456     // process and no coordination is necessary.
3457     if (IsAtProcessExit())
3458         return;
3459
3460 #ifdef _DEBUG
3461     AddFiberInfo(ThreadTrackInfo_GCMode);
3462 #endif
3463
3464     // EnablePreemptiveGC already set us to preemptive mode before triggering the Rare path.
3465     // Force other threads to see this update, since the Rare path implies that someone else
3466     // is observing us (e.g. SuspendRuntime).
3467
3468     _ASSERTE (!m_fPreemptiveGCDisabled);
3469
3470     // holding a spin lock in coop mode and transit to preemp mode will cause deadlock on GC
3471     _ASSERTE ((m_StateNC & Thread::TSNC_OwnsSpinLock) == 0);
3472
3473     FastInterlockOr (&m_fPreemptiveGCDisabled, 0);
3474
3475 #if defined(STRESS_HEAP) && defined(_DEBUG)
3476     if (!IsDetached())
3477         PerformPreemptiveGC();
3478 #endif
3479
3480     STRESS_LOG1(LF_SYNC, LL_INFO100000, "RareEnablePreemptiveGC: entering. Thread state = %x\n", m_State.Load());
3481     if (!ThreadStore::HoldingThreadStore(this))
3482     {
3483 #ifdef FEATURE_HIJACK
3484         // Remove any hijacks we might have.
3485         UnhijackThread();
3486 #endif // FEATURE_HIJACK
3487
3488         // wake up any threads waiting to suspend us, like the GC thread.
3489         ThreadSuspend::g_pGCSuspendEvent->Set();
3490
3491         // for GC, the fact that we are leaving the EE means that it no longer needs to
3492         // suspend us.  But if we are doing a non-GC suspend, we need to block now.
3493         // Give the debugger precedence over user suspensions:
3494         while (m_State & (TS_DebugSuspendPending | TS_UserSuspendPending))
3495         {
3496             // CoreCLR does not support user-requested thread suspension
3497             _ASSERTE(!(m_State & TS_UserSuspendPending));
3498
3499 #ifdef DEBUGGING_SUPPORTED
3500             // We don't notify the debugger that this thread is now suspended. We'll just
3501             // let the debugger's helper thread sweep and pick it up.
3502             // We also never take the TSL in here either.
3503             // Life's much simpler this way...
3504
3505
3506 #endif // DEBUGGING_SUPPORTED
3507
3508 #ifdef LOGGING
3509             {
3510                 LOG((LF_CORDB, LL_INFO1000, "[0x%x] SUSPEND: suspended while enabling gc.\n", GetThreadId()));
3511             }
3512 #endif
3513
3514             WaitSuspendEvents(); // sets bits, too
3515
3516         }
3517     }
3518     STRESS_LOG0(LF_SYNC, LL_INFO100000, " RareEnablePreemptiveGC: leaving.\n");
3519 }
3520
3521 // Called when we are passing through a safe point in CommonTripThread or 
3522 // HandleGCSuspensionForInterruptedThread. Do the right thing with this thread,
3523 // which can either mean waiting for the GC to complete, or performing a 
3524 // pending suspension.
3525 void Thread::PulseGCMode()
3526 {
3527     CONTRACTL {
3528         NOTHROW;
3529         GC_TRIGGERS;
3530     }
3531     CONTRACTL_END;
3532
3533     _ASSERTE(this == GetThread());
3534
3535     if (PreemptiveGCDisabled() && CatchAtSafePoint())
3536     {
3537         EnablePreemptiveGC();
3538         DisablePreemptiveGC();
3539     }
3540 }
3541
3542 // Indicate whether threads should be trapped when returning to the EE (i.e. disabling
3543 // preemptive GC mode)
3544 Volatile<LONG> g_fTrapReturningThreadsLock;
3545 void ThreadStore::TrapReturningThreads(BOOL yes)
3546 {
3547     CONTRACTL {
3548         NOTHROW;
3549         GC_NOTRIGGER;
3550     } CONTRACTL_END;
3551
3552     // make sure that a thread doesn't get suspended holding g_fTrapReturningThreadsLock
3553     // if a suspended thread held this lock and then the suspending thread called in
3554     // here (which it does) the suspending thread would deadlock causing the suspension
3555     // as a whole to deadlock
3556     ForbidSuspendThreadHolder suspend;
3557     
3558     DWORD dwSwitchCount = 0;
3559     while (1 == FastInterlockExchange(&g_fTrapReturningThreadsLock, 1))
3560     {
3561         // we can't forbid suspension while we are sleeping and don't hold the lock
3562         // this will trigger an assert on SQLCLR but is a general issue
3563         suspend.Release();
3564         __SwitchToThread(0, ++dwSwitchCount);
3565         suspend.Acquire();
3566     }
3567
3568     if (yes)
3569     {
3570 #ifdef _DEBUG
3571         CounterHolder trtHolder(&g_trtChgInFlight);
3572         FastInterlockIncrement(&g_trtChgStamp);
3573 #endif
3574
3575         GCHeapUtilities::GetGCHeap()->SetSuspensionPending(true);
3576         FastInterlockIncrement (&g_TrapReturningThreads);
3577 #ifdef ENABLE_FAST_GCPOLL_HELPER
3578         EnableJitGCPoll();
3579 #endif
3580         _ASSERTE(g_TrapReturningThreads > 0);
3581
3582 #ifdef _DEBUG
3583         trtHolder.Release();
3584 #endif
3585     }
3586     else
3587     {
3588         FastInterlockDecrement (&g_TrapReturningThreads);
3589         GCHeapUtilities::GetGCHeap()->SetSuspensionPending(false);
3590
3591 #ifdef ENABLE_FAST_GCPOLL_HELPER
3592         if (0 == g_TrapReturningThreads)
3593         {
3594             DisableJitGCPoll();
3595         }
3596 #endif
3597
3598         _ASSERTE(g_TrapReturningThreads >= 0);
3599     }
3600 #ifdef ENABLE_FAST_GCPOLL_HELPER
3601     //Ensure that we flush the cache line containing the GC Poll Helper.
3602     MemoryBarrier();
3603 #endif //ENABLE_FAST_GCPOLL_HELPER
3604     g_fTrapReturningThreadsLock = 0;
3605
3606 }
3607
3608 #ifdef FEATURE_HIJACK
3609
3610 void RedirectedThreadFrame::ExceptionUnwind()
3611 {
3612     CONTRACTL
3613     {
3614         NOTHROW;
3615         GC_NOTRIGGER;
3616         SO_TOLERANT;
3617         MODE_ANY;
3618     }
3619     CONTRACTL_END;
3620
3621     STRESS_LOG1(LF_SYNC, LL_INFO1000, "In RedirectedThreadFrame::ExceptionUnwind pFrame = %p\n", this);
3622
3623     Thread* pThread = GetThread();
3624
3625     if (pThread->GetSavedRedirectContext())
3626     {
3627         delete m_Regs;
3628     }
3629     else
3630     {
3631         // Save it for future use to avoid repeatedly new'ing
3632         pThread->SetSavedRedirectContext(m_Regs);
3633     }
3634
3635     m_Regs = NULL;
3636 }
3637
3638 #ifndef PLATFORM_UNIX
3639
3640 #ifdef _TARGET_X86_
3641 //****************************************************************************************
3642 // This will check who caused the exception.  If it was caused by the the redirect function,
3643 // the reason is to resume the thread back at the point it was redirected in the first
3644 // place.  If the exception was not caused by the function, then it was caused by the call
3645 // out to the I[GC|Debugger]ThreadControl client and we need to determine if it's an
3646 // exception that we can just eat and let the runtime resume the thread, or if it's an
3647 // uncatchable exception that we need to pass on to the runtime.
3648 //
3649 int RedirectedHandledJITCaseExceptionFilter(
3650     PEXCEPTION_POINTERS pExcepPtrs,     // Exception data
3651     RedirectedThreadFrame *pFrame,      // Frame on stack
3652     BOOL fDone,                         // Whether redirect completed without exception
3653     CONTEXT *pCtx)                      // Saved context
3654 {
3655     // !!! Do not use a non-static contract here.
3656     // !!! Contract may insert an exception handling record.
3657     // !!! This function assumes that GetCurrentSEHRecord() returns the exception record set up in
3658     // !!! Thread::RedirectedHandledJITCase
3659     //
3660     // !!! Do not use an object with dtor, since it injects a fs:0 entry.
3661     STATIC_CONTRACT_NOTHROW;
3662     STATIC_CONTRACT_GC_TRIGGERS;
3663     STATIC_CONTRACT_MODE_ANY;
3664
3665     if (pExcepPtrs->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
3666     {
3667         return EXCEPTION_CONTINUE_SEARCH;
3668     }
3669
3670     // Get the thread handle
3671     Thread *pThread = GetThread();
3672     _ASSERTE(pThread);
3673
3674
3675     STRESS_LOG2(LF_SYNC, LL_INFO100, "In RedirectedHandledJITCaseExceptionFilter fDone = %d pFrame = %p\n", fDone, pFrame);
3676
3677     // If we get here via COM+ exception, gc-mode is unknown.  We need it to
3678     // be cooperative for this function.
3679     GCX_COOP_NO_DTOR();
3680
3681     // If the exception was due to the called client, then we need to figure out if it
3682     // is an exception that can be eaten or if it needs to be handled elsewhere.
3683     if (!fDone)
3684     {
3685         if (pExcepPtrs->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
3686         {
3687             return (EXCEPTION_CONTINUE_SEARCH);
3688         }
3689
3690         // Get the latest thrown object
3691         OBJECTREF throwable = CLRException::GetThrowableFromExceptionRecord(pExcepPtrs->ExceptionRecord);
3692
3693         // If this is an uncatchable exception, then let the exception be handled elsewhere
3694         if (IsUncatchable(&throwable))
3695         {
3696             pThread->EnablePreemptiveGC();
3697             return (EXCEPTION_CONTINUE_SEARCH);
3698         }
3699     }
3700 #ifdef _DEBUG
3701     else
3702     {
3703         _ASSERTE(pExcepPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_HIJACK);
3704     }
3705 #endif
3706
3707     // Unlink the frame in preparation for resuming in managed code
3708     pFrame->Pop();
3709
3710     // Copy the saved context record into the EH context;
3711     ReplaceExceptionContextRecord(pExcepPtrs->ContextRecord, pCtx);
3712
3713     DWORD espValue = pCtx->Esp;
3714     if (pThread->GetSavedRedirectContext())
3715     {
3716         delete pCtx;
3717     }
3718     else
3719     {
3720         // Save it for future use to avoid repeatedly new'ing
3721         pThread->SetSavedRedirectContext(pCtx);
3722     }
3723
3724     /////////////////////////////////////////////////////////////////////////////
3725     // NOTE: Ugly, ugly workaround.
3726     // We need to resume the thread into the managed code where it was redirected,
3727     // and the corresponding ESP is below the current one.  But C++ expects that
3728     // on an EXCEPTION_CONTINUE_EXECUTION that the ESP will be above where it has
3729     // installed the SEH handler.  To solve this, we need to remove all handlers
3730     // that reside above the resumed ESP, but we must leave the OS-installed
3731     // handler at the top, so we grab the top SEH handler, call
3732     // PopSEHRecords which will remove all SEH handlers above the target ESP and
3733     // then link the OS handler back in with SetCurrentSEHRecord.
3734
3735     // Get the special OS handler and save it until PopSEHRecords is done
3736     EXCEPTION_REGISTRATION_RECORD *pCurSEH = GetCurrentSEHRecord();
3737
3738     // Unlink all records above the target resume ESP
3739     PopSEHRecords((LPVOID)(size_t)espValue);
3740
3741     // Link the special OS handler back in to the top
3742     pCurSEH->Next = GetCurrentSEHRecord();
3743
3744     // Register the special OS handler as the top handler with the OS
3745     SetCurrentSEHRecord(pCurSEH);
3746
3747     // Resume execution at point where thread was originally redirected
3748     return (EXCEPTION_CONTINUE_EXECUTION);
3749 }
3750 #endif // _TARGET_X86_
3751
3752 void NotifyHostOnGCSuspension()
3753 {
3754     CONTRACTL
3755     {
3756         NOTHROW;
3757         GC_NOTRIGGER;
3758         MODE_ANY;
3759         SO_TOLERANT;
3760     }
3761     CONTRACTL_END;
3762
3763 }
3764
3765 // This function is called from the assembly functions used to redirect a thread.  It must not cause
3766 // an exception (except SO).
3767 extern "C" PCONTEXT __stdcall GetCurrentSavedRedirectContext()
3768 {
3769     LIMITED_METHOD_CONTRACT;
3770
3771     DWORD dwLastError = GetLastError();
3772     PCONTEXT pContext = GetThread()->GetSavedRedirectContext();
3773     SetLastError(dwLastError);
3774
3775     return pContext;
3776 }
3777
3778 void __stdcall Thread::RedirectedHandledJITCase(RedirectReason reason)
3779 {
3780     STATIC_CONTRACT_THROWS;
3781     STATIC_CONTRACT_GC_TRIGGERS;
3782     STATIC_CONTRACT_MODE_COOPERATIVE;
3783
3784     // We must preserve this in case we've interrupted an IL pinvoke stub before it
3785     // was able to save the error.
3786     DWORD dwLastError = GetLastError();
3787
3788     Thread *pThread = GetThread();
3789     _ASSERTE(pThread);
3790
3791 #ifdef FEATURE_STACK_PROBE
3792     if (GetEEPolicy()->GetActionOnFailure(FAIL_StackOverflow) == eRudeUnloadAppDomain)
3793     {
3794         RetailStackProbe(ADJUST_PROBE(DEFAULT_ENTRY_PROBE_AMOUNT), pThread);
3795     }
3796 #endif
3797
3798     BEGIN_CONTRACT_VIOLATION(SOToleranceViolation);
3799
3800     // Get the saved context
3801     CONTEXT *pCtx = pThread->GetSavedRedirectContext();
3802     _ASSERTE(pCtx);
3803
3804     INDEBUG(Thread::ObjectRefFlush(pThread));
3805
3806     // Create a frame on the stack
3807     FrameWithCookie<RedirectedThreadFrame> frame(pCtx);
3808
3809     STRESS_LOG5(LF_SYNC, LL_INFO1000, "In RedirectedHandledJITcase reason 0x%x pFrame = %p pc = %p sp = %p fp = %p", reason, &frame, GetIP(pCtx), GetSP(pCtx), GetFP(pCtx));
3810
3811 #ifdef _TARGET_X86_
3812     // This will indicate to the exception filter whether or not the exception is caused
3813     // by us or the client.
3814     BOOL fDone = FALSE;
3815     int filter_count = 0;       // A counter to avoid a nasty case where an
3816                                 // up-stack filter throws another exception
3817                                 // causing our filter to be run again for
3818                                 // some unrelated exception.
3819
3820     __try
3821 #endif // _TARGET_X86_
3822     {
3823         // Make sure this thread doesn't reuse the context memory in re-entrancy cases
3824         _ASSERTE(pThread->GetSavedRedirectContext() != NULL);
3825         pThread->SetSavedRedirectContext(NULL);
3826
3827         // Link in the frame
3828         frame.Push();
3829
3830 #if defined(HAVE_GCCOVER) && defined(USE_REDIRECT_FOR_GCSTRESS) // GCCOVER
3831         if (reason == RedirectReason_GCStress)
3832         {
3833             _ASSERTE(pThread->PreemptiveGCDisabledOther());
3834             DoGcStress(frame.GetContext(), NULL);
3835         }
3836         else
3837 #endif // HAVE_GCCOVER && USE_REDIRECT_FOR_GCSTRESS
3838         {
3839             // Enable PGC before calling out to the client to allow runtime suspend to finish
3840             GCX_PREEMP_NO_DTOR();
3841
3842             // Notify the interface of the pending suspension
3843             switch (reason) {
3844             case RedirectReason_GCSuspension:
3845                 break;
3846             case RedirectReason_DebugSuspension:
3847                 break;
3848             case RedirectReason_UserSuspension:
3849                 // Do nothing;
3850                 break;
3851             default:
3852                 _ASSERTE(!"Invalid redirect reason");
3853                 break;
3854             }
3855
3856             // Disable preemptive GC so we can unlink the frame
3857             GCX_PREEMP_NO_DTOR_END();
3858         }
3859
3860 #ifdef _TARGET_X86_
3861         pThread->HandleThreadAbort();        // Might throw an exception.
3862
3863         // Indicate that the call to the service went without an exception, and that
3864         // we're raising our own exception to resume the thread to where it was
3865         // redirected from
3866         fDone = TRUE;
3867
3868         // Save the instruction pointer where we redirected last.  This does not race with the check
3869         // against this variable in HandledJitCase because the GC will not attempt to redirect the
3870         // thread until the instruction pointer of this thread is back in managed code.
3871         pThread->m_LastRedirectIP = GetIP(pCtx);
3872         pThread->m_SpinCount = 0;
3873
3874         RaiseException(EXCEPTION_HIJACK, 0, 0, NULL);
3875
3876 #else // _TARGET_X86_
3877
3878 #if defined(HAVE_GCCOVER) && defined(USE_REDIRECT_FOR_GCSTRESS) // GCCOVER
3879         //
3880         // If GCStress interrupts an IL stub or inlined p/invoke while it's running in preemptive mode, it switches the mode to 
3881         // cooperative - but we will resume to preemptive below.  We should not trigger an abort in that case, as it will fail 
3882         // due to the GC mode.
3883         //
3884         if (!pThread->m_fPreemptiveGCDisabledForGCStress)
3885 #endif 
3886         {
3887
3888             UINT_PTR uAbortAddr;
3889             UINT_PTR uResumePC = (UINT_PTR)GetIP(pCtx);
3890             CopyOSContext(pThread->m_OSContext, pCtx);
3891             uAbortAddr = (UINT_PTR)COMPlusCheckForAbort();
3892             if (uAbortAddr)
3893             {
3894                 LOG((LF_EH, LL_INFO100, "thread abort in progress, resuming thread under control... (handled jit case)\n"));
3895
3896                 CONSISTENCY_CHECK(CheckPointer(pCtx));
3897
3898                 STRESS_LOG1(LF_EH, LL_INFO10, "resume under control: ip: %p (handled jit case)\n", uResumePC);
3899
3900                 SetIP(pThread->m_OSContext, uResumePC);
3901
3902 #if defined(_TARGET_ARM_)
3903                 // Save the original resume PC in Lr
3904                 pCtx->Lr = uResumePC;
3905
3906                 // Since we have set a new IP, we have to clear conditional execution flags too.
3907                 ClearITState(pThread->m_OSContext);
3908 #endif // _TARGET_ARM_
3909
3910                 SetIP(pCtx, uAbortAddr);
3911             }
3912         }
3913
3914         // Unlink the frame in preparation for resuming in managed code
3915         frame.Pop();
3916
3917         {
3918             // Free the context struct if we already have one cached
3919             if (pThread->GetSavedRedirectContext())
3920             {
3921                 CONTEXT* pCtxTemp = (CONTEXT*)_alloca(sizeof(CONTEXT));
3922                 memcpy(pCtxTemp, pCtx, sizeof(CONTEXT));
3923                 delete pCtx;
3924                 pCtx = pCtxTemp;
3925             }
3926             else
3927             {
3928                 // Save it for future use to avoid repeatedly new'ing
3929                 pThread->SetSavedRedirectContext(pCtx);
3930             }
3931
3932 #if defined(HAVE_GCCOVER) && defined(USE_REDIRECT_FOR_GCSTRESS) // GCCOVER
3933             if (pThread->m_fPreemptiveGCDisabledForGCStress)
3934             {
3935                 pThread->EnablePreemptiveGC();
3936                 pThread->m_fPreemptiveGCDisabledForGCStress = false;
3937             }
3938 #endif
3939
3940             LOG((LF_SYNC, LL_INFO1000, "Resuming execution with RtlRestoreContext\n"));
3941
3942             SetLastError(dwLastError);
3943
3944             RtlRestoreContext(pCtx, NULL);
3945         }
3946 #endif // _TARGET_X86_
3947     }
3948 #ifdef _TARGET_X86_
3949     __except (++filter_count == 1
3950         ? RedirectedHandledJITCaseExceptionFilter(GetExceptionInformation(), &frame, fDone, pCtx)
3951         : EXCEPTION_CONTINUE_SEARCH)
3952     {
3953         _ASSERTE(!"Reached body of __except in Thread::RedirectedHandledJITCase");
3954     }
3955
3956 #endif // _TARGET_X86_
3957
3958     END_CONTRACT_VIOLATION;
3959
3960 }
3961
3962 //****************************************************************************************
3963 // This helper is called when a thread suspended in managed code at a sequence point while
3964 // suspending the runtime and there is a client interested in re-assigning the thread to
3965 // do interesting work while the runtime is suspended.  This will call into the client
3966 // notifying it that the thread will be suspended for a runtime suspension.
3967 //
3968 void __stdcall Thread::RedirectedHandledJITCaseForDbgThreadControl()
3969 {
3970     WRAPPER_NO_CONTRACT;
3971     RedirectedHandledJITCase(RedirectReason_DebugSuspension);
3972 }
3973
3974 //****************************************************************************************
3975 // This helper is called when a thread suspended in managed code at a sequence point when
3976 // suspending the runtime.
3977 //
3978 // We do this because the obvious code sequence:
3979 //
3980 //      SuspendThread(t1);
3981 //      GetContext(t1, &ctx);
3982 //      ctx.Ecx = <some new value>;
3983 //      SetContext(t1, &ctx);
3984 //      ResumeThread(t1);
3985 //
3986 // simply does not work due to a nasty race with exception handling in the OS.  If the
3987 // thread that is suspended has just faulted, then the update can disappear without ever
3988 // modifying the real thread ... and there is no way to tell.
3989 //
3990 // Updating the EIP may not work ... but when it doesn't, we're ok ... an exception ends
3991 // up getting dispatched anyway.
3992 //
3993 // If the host is interested in getting control, then we give control to the host.  If the
3994 // host is not interested in getting control, then we call out to the host.  After that,
3995 // we raise an exception and will end up waiting for the GC to finish inside the filter.
3996 //
3997 void __stdcall Thread::RedirectedHandledJITCaseForGCThreadControl()
3998 {
3999     WRAPPER_NO_CONTRACT;
4000     RedirectedHandledJITCase(RedirectReason_GCSuspension);
4001 }
4002
4003 //***********************
4004 // Like the above, but called for a UserSuspend.
4005 //
4006 void __stdcall Thread::RedirectedHandledJITCaseForUserSuspend()
4007 {
4008     WRAPPER_NO_CONTRACT;
4009     RedirectedHandledJITCase(RedirectReason_UserSuspension);
4010 }
4011
4012 #if defined(HAVE_GCCOVER) && defined(USE_REDIRECT_FOR_GCSTRESS) // GCCOVER
4013
4014 //***********************
4015 // Like the above, but called for GC stress.
4016 //
4017 void __stdcall Thread::RedirectedHandledJITCaseForGCStress()
4018 {
4019     WRAPPER_NO_CONTRACT;
4020     RedirectedHandledJITCase(RedirectReason_GCStress);
4021 }
4022
4023 #endif // HAVE_GCCOVER && _DEBUG && USE_REDIRECT_FOR_GCSTRESS
4024
4025 //****************************************************************************************
4026 // This will take a thread that's been suspended in managed code at a sequence point and
4027 // will Redirect the thread. It will save all register information, build a frame on the
4028 // thread's stack, put a pointer to the frame at the top of the stack and set the IP of
4029 // the thread to pTgt.  pTgt is then responsible for unlinking the thread,
4030 //
4031 // NOTE: Cannot play with a suspended thread's stack memory, since the OS will use the
4032 // top of the stack to store information.  The thread must be resumed and play with it's
4033 // own stack.
4034 //
4035
4036 #ifdef _TARGET_X86_
4037 #define CONTEXT_COMPLETE (CONTEXT_FULL | CONTEXT_FLOATING_POINT |       \
4038                           CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS | CONTEXT_EXCEPTION_REQUEST)
4039 #else
4040 #define CONTEXT_COMPLETE (CONTEXT_FULL | CONTEXT_EXCEPTION_REQUEST)
4041 #endif
4042
4043 BOOL Thread::RedirectThreadAtHandledJITCase(PFN_REDIRECTTARGET pTgt)
4044 {
4045     CONTRACTL {
4046         NOTHROW;
4047         GC_NOTRIGGER;
4048     }
4049     CONTRACTL_END;
4050
4051     _ASSERTE(HandledJITCase());
4052     _ASSERTE(GetThread() != this);
4053
4054     ////////////////////////////////////////////////////////////////
4055     // Acquire a context structure to save the thread state into
4056
4057     // We need to distinguish between two types of callers:
4058     // - Most callers, including GC, operate while holding the ThreadStore
4059     //   lock.  This means that we can pre-allocate a context structure
4060     //   globally in the ThreadStore and use it in this function.
4061     // - Some callers (currently only YieldTask) cannot take the ThreadStore
4062     //   lock.  Therefore we always allocate a SavedRedirectContext in the
4063     //   Thread constructor.  (Since YieldTask currently is the only caller
4064     //   that does not hold the ThreadStore lock, we only do this when
4065     //   we're hosted.)
4066
4067     // Check whether we have a SavedRedirectContext we can reuse:
4068     CONTEXT *pCtx = GetSavedRedirectContext();
4069
4070     // If we've never allocated a context for this thread, do so now
4071     if (!pCtx)
4072     {
4073         // If our caller took the ThreadStore lock, then it pre-allocated
4074         // a context in the ThreadStore:
4075         if (ThreadStore::HoldingThreadStore())
4076         {
4077             pCtx = ThreadStore::GrabOSContext();
4078         }
4079
4080         if (!pCtx)
4081         {
4082             // Even when our caller is YieldTask, we can find a NULL
4083             // SavedRedirectContext in this function:  Consider the scenario
4084             // where GC is in progress and has already redirected a thread.
4085             // That thread will set its SavedRedirectContext to NULL to enable
4086             // reentrancy.  Now assume that the host calls YieldTask for the
4087             // redirected thread.  In this case, this function will simply
4088             // fail, but that is fine:  The redirected thread will check,
4089             // before it resumes execution, whether it should yield.
4090             return (FALSE);
4091         }
4092
4093         // Save the pointer for the redirect function
4094         _ASSERTE(GetSavedRedirectContext() == NULL);
4095         SetSavedRedirectContext(pCtx);
4096     }
4097
4098     //////////////////////////////////////
4099     // Get and save the thread's context
4100
4101     // Always get complete context
4102     pCtx->ContextFlags = CONTEXT_COMPLETE;
4103     BOOL bRes = EEGetThreadContext(this, pCtx);
4104     _ASSERTE(bRes && "Failed to GetThreadContext in RedirectThreadAtHandledJITCase - aborting redirect.");
4105
4106     if (!bRes)
4107         return (FALSE);
4108
4109     if (!IsContextSafeToRedirect(pCtx))
4110         return (FALSE);
4111
4112     ////////////////////////////////////////////////////
4113     // Now redirect the thread to the helper function
4114
4115     // Temporarily set the IP of the context to the target for SetThreadContext
4116     PCODE dwOrigEip = GetIP(pCtx);
4117 #ifdef _TARGET_ARM_
4118     // Redirection can be required when in IT Block.
4119     // In that case must reset the IT state before redirection.
4120     DWORD dwOrigCpsr = pCtx->Cpsr;
4121     ClearITState(pCtx);
4122 #endif
4123     _ASSERTE(ExecutionManager::IsManagedCode(dwOrigEip));
4124     SetIP(pCtx, (PCODE)pTgt);
4125
4126
4127     STRESS_LOG4(LF_SYNC, LL_INFO10000, "Redirecting thread %p(tid=%x) from address 0x%08x to address 0x%p\n",
4128         this, this->GetThreadId(), dwOrigEip, pTgt);
4129
4130     bRes = EESetThreadContext(this, pCtx);
4131     _ASSERTE(bRes && "Failed to SetThreadContext in RedirectThreadAtHandledJITCase - aborting redirect.");
4132
4133     // Restore original IP
4134     SetIP(pCtx, dwOrigEip);
4135 #ifdef _TARGET_ARM_
4136     // restore IT State in the context
4137     pCtx->Cpsr = dwOrigCpsr;
4138 #endif
4139
4140
4141     //////////////////////////////////////////////////
4142     // Indicate whether or not the redirect succeeded
4143
4144     return (bRes);
4145 }
4146
4147 BOOL Thread::CheckForAndDoRedirect(PFN_REDIRECTTARGET pRedirectTarget)
4148 {
4149     CONTRACTL
4150     {
4151         NOTHROW;
4152         GC_NOTRIGGER;
4153         MODE_ANY;
4154     }
4155     CONTRACTL_END;
4156
4157     _ASSERTE(this != GetThread());
4158     _ASSERTE(PreemptiveGCDisabledOther());
4159     _ASSERTE(IsAddrOfRedirectFunc(pRedirectTarget));
4160
4161     BOOL fRes = FALSE;
4162     fRes = RedirectThreadAtHandledJITCase(pRedirectTarget);
4163     LOG((LF_GC, LL_INFO1000, "RedirectThreadAtHandledJITCase %s.\n", fRes ? "SUCCEEDED" : "FAILED"));
4164
4165     return (fRes);
4166 }
4167
4168 BOOL Thread::RedirectCurrentThreadAtHandledJITCase(PFN_REDIRECTTARGET pTgt, CONTEXT *pCurrentThreadCtx)
4169 {
4170     CONTRACTL {
4171         NOTHROW;
4172         GC_NOTRIGGER;
4173     }
4174     CONTRACTL_END;
4175
4176     // REVISIT_TODO need equivalent of this for the current thread
4177     //_ASSERTE(HandledJITCase());
4178
4179     _ASSERTE(GetThread() == this);
4180     _ASSERTE(PreemptiveGCDisabledOther());
4181     _ASSERTE(IsAddrOfRedirectFunc(pTgt));
4182     _ASSERTE(pCurrentThreadCtx);
4183     _ASSERTE((pCurrentThreadCtx->ContextFlags & (CONTEXT_COMPLETE - CONTEXT_EXCEPTION_REQUEST))
4184                                              == (CONTEXT_COMPLETE - CONTEXT_EXCEPTION_REQUEST));
4185     _ASSERTE(ExecutionManager::IsManagedCode(GetIP(pCurrentThreadCtx)));
4186
4187     ////////////////////////////////////////////////////////////////
4188     // Allocate a context structure to save the thread state into
4189
4190     // Check to see if we've already got memory allocated for this purpose.
4191     CONTEXT *pCtx = GetSavedRedirectContext();
4192
4193     // If we've never allocated a context for this thread, do so now
4194     if (!pCtx)
4195     {
4196         pCtx = new (nothrow) CONTEXT();
4197
4198         if (!pCtx)
4199             return (FALSE);
4200
4201         // Save the pointer for the redirect function
4202         _ASSERTE(GetSavedRedirectContext() == NULL);
4203         SetSavedRedirectContext(pCtx);
4204     }
4205
4206     //////////////////////////////////////
4207     // Get and save the thread's context
4208
4209     CopyMemory(pCtx, pCurrentThreadCtx, sizeof(CONTEXT));
4210
4211     // Clear any new bits we don't understand (like XSAVE) in case we pass
4212     // this context to RtlRestoreContext (like for gcstress)
4213     pCtx->ContextFlags &= CONTEXT_ALL;
4214
4215     // Ensure that this flag is set for the next time through the normal path,
4216     // RedirectThreadAtHandledJITCase.
4217     pCtx->ContextFlags |= CONTEXT_EXCEPTION_REQUEST;
4218
4219     ////////////////////////////////////////////////////
4220     // Now redirect the thread to the helper function
4221
4222     SetIP(pCurrentThreadCtx, (PCODE)pTgt);
4223
4224 #ifdef _TARGET_ARM_
4225     // Redirection can be required when in IT Block
4226     // Clear the IT State before redirecting
4227     ClearITState(pCurrentThreadCtx);
4228 #endif
4229
4230     //////////////////////////////////////////////////
4231     // Indicate whether or not the redirect succeeded
4232
4233     return TRUE;
4234 }
4235
4236 //************************************************************************
4237 // Exception handling needs to special case the redirection. So provide
4238 // a helper to identify redirection targets and keep the exception
4239 // checks in sync with the redirection here.
4240 // See CPFH_AdjustContextForThreadSuspensionRace for details.
4241 BOOL Thread::IsAddrOfRedirectFunc(void * pFuncAddr)
4242 {
4243     WRAPPER_NO_CONTRACT;
4244
4245 #if defined(HAVE_GCCOVER) && defined(USE_REDIRECT_FOR_GCSTRESS) // GCCOVER
4246     if (pFuncAddr == GetRedirectHandlerForGCStress())
4247         return TRUE;
4248 #endif // HAVE_GCCOVER && USE_REDIRECT_FOR_GCSTRESS
4249
4250     return
4251         (pFuncAddr == GetRedirectHandlerForGCThreadControl()) ||
4252         (pFuncAddr == GetRedirectHandlerForDbgThreadControl()) ||
4253         (pFuncAddr == GetRedirectHandlerForUserSuspend());
4254 }
4255
4256 //************************************************************************
4257 // Redirect thread at a GC suspension.
4258 BOOL Thread::CheckForAndDoRedirectForGC()
4259 {
4260     CONTRACTL
4261     {
4262         NOTHROW;
4263         GC_NOTRIGGER;
4264         MODE_ANY;
4265     }
4266     CONTRACTL_END;
4267
4268     LOG((LF_GC, LL_INFO1000, "Redirecting thread %08x for GCThreadSuspension", GetThreadId()));
4269     return CheckForAndDoRedirect(GetRedirectHandlerForGCThreadControl());
4270 }
4271
4272 //************************************************************************
4273 // Redirect thread at a debug suspension.
4274 BOOL Thread::CheckForAndDoRedirectForDbg()
4275 {
4276     CONTRACTL
4277     {
4278         NOTHROW;
4279         GC_NOTRIGGER;
4280         MODE_ANY;
4281     }
4282     CONTRACTL_END;
4283
4284     LOG((LF_CORDB, LL_INFO1000, "Redirecting thread %08x for DebugSuspension", GetThreadId()));
4285     return CheckForAndDoRedirect(GetRedirectHandlerForDbgThreadControl());
4286 }
4287
4288 //*************************************************************************
4289 // Redirect thread at a user suspend.
4290 BOOL Thread::CheckForAndDoRedirectForUserSuspend()
4291 {
4292     CONTRACTL
4293     {
4294         NOTHROW;
4295         GC_NOTRIGGER;
4296         MODE_ANY;
4297     }
4298     CONTRACTL_END;
4299
4300     LOG((LF_SYNC, LL_INFO1000, "Redirecting thread %08x for UserSuspension", GetThreadId()));
4301     return CheckForAndDoRedirect(GetRedirectHandlerForUserSuspend());
4302 }
4303
4304 #if defined(HAVE_GCCOVER) && defined(USE_REDIRECT_FOR_GCSTRESS) // GCCOVER
4305 //*************************************************************************
4306 // Redirect thread at a GC stress point.
4307 BOOL Thread::CheckForAndDoRedirectForGCStress (CONTEXT *pCurrentThreadCtx)
4308 {
4309     WRAPPER_NO_CONTRACT;
4310
4311     LOG((LF_CORDB, LL_INFO1000, "Redirecting thread %08x for GCStress", GetThreadId()));
4312
4313     m_fPreemptiveGCDisabledForGCStress = !PreemptiveGCDisabled();
4314     GCX_COOP_NO_DTOR();
4315
4316     BOOL fSuccess = RedirectCurrentThreadAtHandledJITCase(GetRedirectHandlerForGCStress(), pCurrentThreadCtx);
4317
4318     if (!fSuccess)
4319     {
4320         GCX_COOP_NO_DTOR_END();
4321         m_fPreemptiveGCDisabledForGCStress = false;
4322     }
4323
4324     return fSuccess;
4325 }
4326 #endif // HAVE_GCCOVER && USE_REDIRECT_FOR_GCSTRESS
4327
4328 #endif // !PLATFORM_UNIX
4329 #endif // FEATURE_HIJACK
4330
4331
4332 #ifdef PROFILING_SUPPORTED
4333 // Simple helper to convert the GC's SUSPEND_REASON enum to the profiling API's public
4334 // COR_PRF_SUSPEND_REASON enum.  Used in code:Thread::SuspendRuntime to help with
4335 // sending the suspension event to the profiler.
4336 COR_PRF_SUSPEND_REASON GCSuspendReasonToProfSuspendReason(ThreadSuspend::SUSPEND_REASON gcReason)
4337 {
4338     LIMITED_METHOD_CONTRACT;
4339
4340     switch(gcReason)
4341     {
4342     default:
4343         return COR_PRF_SUSPEND_OTHER;
4344     case ThreadSuspend::SUSPEND_FOR_GC:
4345         return COR_PRF_SUSPEND_FOR_GC;
4346     case ThreadSuspend::SUSPEND_FOR_APPDOMAIN_SHUTDOWN:
4347         return COR_PRF_SUSPEND_FOR_APPDOMAIN_SHUTDOWN;
4348     case ThreadSuspend::SUSPEND_FOR_REJIT:
4349         return COR_PRF_SUSPEND_FOR_REJIT;
4350     case ThreadSuspend::SUSPEND_FOR_SHUTDOWN:
4351         return COR_PRF_SUSPEND_FOR_SHUTDOWN;
4352     case ThreadSuspend::SUSPEND_FOR_DEBUGGER:
4353         return COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER;
4354     case ThreadSuspend::SUSPEND_FOR_GC_PREP:
4355         return COR_PRF_SUSPEND_FOR_GC_PREP;
4356     }
4357 }
4358 #endif // PROFILING_SUPPORTED
4359
4360 //************************************************************************************
4361 // To support fast application switch (FAS), one requirement is that the CPU 
4362 // consumption during the time the CLR is paused should be 0. Given that the process
4363 // will be anyway suspended this should've been an NOP for CLR. However, in Mango
4364 // we ensured that no handle timed out or no other such context switch happens
4365 // during the pause time. To match that and also to ensure that in-between the 
4366 // pause and when the process is suspended (~60 sec) no context switch happens due to 
4367 // CLR handles (like Waits/sleeps due to calls from BCL) we call APC on these
4368 // Threads and make them wait on the resume handle
4369 void __stdcall PauseAPC(__in ULONG_PTR dwParam)
4370 {
4371     CONTRACTL
4372     {
4373         NOTHROW;
4374         GC_NOTRIGGER;
4375         MODE_ANY;
4376     }
4377     CONTRACTL_END;
4378     
4379     if(g_IsPaused && (GetThread()->m_State & Thread::TS_Interruptible))
4380     {
4381         _ASSERTE(g_ClrResumeEvent.IsValid());
4382         EX_TRY {
4383             g_ClrResumeEvent.Wait(INFINITE, FALSE);
4384         }
4385         EX_CATCH {
4386             // Assert on debug builds 
4387             _ASSERTE(FALSE);
4388         }
4389         EX_END_CATCH(SwallowAllExceptions);
4390     }
4391 }
4392
4393
4394 //************************************************************************************
4395 //
4396 // SuspendRuntime is responsible for ensuring that all managed threads reach a
4397 // "safe point."  It returns when all threads are known to be in "preemptive" mode.
4398 // This is *only* called by ThreadSuspend::SuspendEE; these two methods should really
4399 // be refactored into a separate "managed execution lock."
4400 //
4401 // Note that we use this method for more than just GC suspension.  We also suspend
4402 // for debugging, etc.
4403 //
4404 // The basic algorithm is this:
4405 //
4406 //    while there are threads in cooperative mode:
4407 //        for each thread in cooprative mode:
4408 //           suspend the native thread.
4409 //           if it's still in cooperative mode, and it's running JIT'd code:
4410 //               Redirect/hijack the thread
4411 //
4412 // Redirection vs. Hijacking:
4413 //
4414 // JIT'd code does not generally poll to see if a GC wants to run.  Instead, the JIT
4415 // records "GC info" describing where the "safe points" are in the code.  While we
4416 // have a native thread suspended in JIT'd code, we can see which instruction it
4417 // is currently executing.  If that instruction is a safe point, then the GC may proceed.
4418 // Returning from a managed method is *always* a safe point, so if the thread is not
4419 // currently at a safe point we can "hijack" its return address.  Once that it done,
4420 // if/when the method tried to return the thread will be sent to a hijack routine
4421 // that will leave cooperative mode and wait for the GC to complete.
4422 //
4423 // If the thread is already at a safe point, you might think we could simply leave it
4424 // suspended and proceed with the GC.  In principle, this should be what we do.
4425 // However, various historical OS bugs prevent this from working.  The problem is that
4426 // we are not guaranteed to capture an accurate CONTEXT (register state) for a suspended
4427 // thread.  So instead, we "redirect" the thread, by overwriting its instruction pointer.
4428 // We then resume the thread, and it immediately starts executing our "redirect" routine,
4429 // which leaves cooperative mode and waits for the GC to complete.
4430 //           
4431 // See code:Thread#SuspendingTheRuntime for more 
4432 HRESULT ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason)
4433 {
4434     CONTRACTL {
4435         NOTHROW;
4436         if (GetThread())
4437         {
4438             GC_TRIGGERS;            // CLREvent::Wait is GC_TRIGGERS
4439         }
4440         else
4441         {
4442             DISABLED(GC_TRIGGERS);
4443         }
4444     }
4445     CONTRACTL_END;
4446
4447     // This thread
4448     Thread  *pCurThread = GetThread();
4449
4450     // The thread we're working on (suspending, etc.) right now.
4451     Thread  *thread = NULL;
4452
4453     // The number of threads we found in COOP mode.
4454     LONG     countThreads = 0;
4455
4456     DWORD    res;
4457
4458     // Caller is expected to be holding the ThreadStore lock.  Also, caller must
4459     // have set GcInProgress before coming here, or things will break;
4460     _ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit());
4461     _ASSERTE(GCHeapUtilities::IsGCInProgress() );
4462
4463     STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime(reason=0x%x)\n", reason);
4464
4465
4466 #ifdef PROFILING_SUPPORTED
4467     // If the profiler desires information about GCs, then let it know that one
4468     // is starting.
4469     {
4470         BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
4471         _ASSERTE(reason != ThreadSuspend::SUSPEND_FOR_DEBUGGER);
4472         _ASSERTE(reason != ThreadSuspend::SUSPEND_FOR_DEBUGGER_SWEEP);
4473
4474         {
4475             g_profControlBlock.pProfInterface->RuntimeSuspendStarted(
4476                 GCSuspendReasonToProfSuspendReason(reason));
4477         }
4478         if (pCurThread)
4479         {
4480             // Notify the profiler that the thread that is actually doing the GC is 'suspended',
4481             // meaning that it is doing stuff other than run the managed code it was before the
4482             // GC started.
4483             g_profControlBlock.pProfInterface->RuntimeThreadSuspended((ThreadID)pCurThread);
4484         }
4485         END_PIN_PROFILER();
4486     }
4487 #endif // PROFILING_SUPPORTED
4488
4489     //
4490     // If this thread is running at low priority, boost its priority.  We remember the old 
4491     // priority so that we can restore it in ResumeRuntime.
4492     //
4493     if (pCurThread)     // concurrent GC occurs on threads we don't know about
4494     {
4495         _ASSERTE(pCurThread->m_Priority == INVALID_THREAD_PRIORITY);
4496         int priority = pCurThread->GetThreadPriority();
4497         if (priority < THREAD_PRIORITY_NORMAL)
4498         {
4499             pCurThread->m_Priority = priority;
4500             pCurThread->SetThreadPriority(THREAD_PRIORITY_NORMAL);
4501         }
4502     }
4503
4504     // From this point until the end of the function, consider all active thread
4505     // suspension to be in progress.  This is mainly to give the profiler API a hint
4506     // that trying to suspend a thread (in order to walk its stack) could delay the
4507     // overall EE suspension.  So the profiler API would early-abort the stackwalk
4508     // in such a case.
4509     SuspendRuntimeInProgressHolder hldSuspendRuntimeInProgress;
4510
4511
4512     // Flush the store buffers on all CPUs, to ensure two things:
4513     // - we get a reliable reading of the threads' m_fPreemptiveGCDisabled state
4514     // - other threads see that g_TrapReturningThreads is set
4515     // See VSW 475315 and 488918 for details.
4516
4517     ::FlushProcessWriteBuffers();
4518
4519     //
4520     // Make a pass through all threads.  We do a couple of things here:
4521     // 1) we count the number of threads that are observed to be in cooperative mode.
4522     // 2) for threads currently running managed code, we try to redirect/jihack them.
4523     //
4524     // Later we will make more passes where we do roughly the same thing.  We should combine the two loops.
4525     //
4526     
4527     while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
4528     {
4529         if (thread->HasThreadState(Thread::TS_GCSuspendPending))
4530         {
4531             thread->ResetThreadState(Thread::TS_GCSuspendPending);
4532         }
4533
4534         if (thread == pCurThread)
4535             continue;
4536
4537         STRESS_LOG3(LF_SYNC, LL_INFO10000, "    Inspecting thread 0x%x ID 0x%x coop mode = %d\n",
4538             thread, thread->GetThreadId(), thread->m_fPreemptiveGCDisabled.Load());
4539
4540         // Nothing confusing left over from last time.
4541         _ASSERTE((thread->m_State & Thread::TS_GCSuspendPending) == 0);
4542
4543         // Threads can be in Preemptive or Cooperative GC mode.  Threads cannot switch
4544         // to Cooperative mode without special treatment when a GC is happening.
4545         if (thread->m_fPreemptiveGCDisabled)
4546         {
4547             // Check a little more carefully.  Threads might sneak out without telling
4548             // us, because of inlined PInvoke which doesn't go through RareEnablePreemptiveGC.
4549
4550 #ifdef DISABLE_THREADSUSPEND
4551             // On platforms that do not support safe thread suspension, we do one of two things:
4552             //
4553             //     - If we're on a Unix platform where hijacking is enabled, we attempt
4554             //       to inject a GC suspension which will try to redirect or hijack the
4555             //       thread to get it to a safe point.
4556             //
4557             //     - Otherwise, we rely on the GCPOLL mechanism enabled by 
4558             //       TrapReturningThreads.
4559
4560             // When reading shared state we need to erect appropriate memory barriers.
4561             // The interlocked operation below ensures that any future reads on this
4562             // thread will happen after any earlier writes on a different thread.
4563             //
4564             // <TODO> Need more careful review of this </TODO>
4565             //
4566             FastInterlockOr(&thread->m_fPreemptiveGCDisabled, 0);
4567
4568             if (thread->m_fPreemptiveGCDisabled)
4569             {
4570                 FastInterlockOr((ULONG *) &thread->m_State, Thread::TS_GCSuspendPending);
4571                 countThreads++;
4572
4573 #if defined(FEATURE_HIJACK) && defined(PLATFORM_UNIX)
4574                 bool gcSuspensionSignalSuccess = thread->InjectGcSuspension();
4575                 if (!gcSuspensionSignalSuccess)
4576                 {
4577                     STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime() -   Failed to raise GC suspension signal for thread %p.\n", thread);
4578                 }
4579 #endif // FEATURE_HIJACK && PLATFORM_UNIX
4580             }
4581
4582 #else // DISABLE_THREADSUSPEND
4583
4584 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
4585             DWORD dwSwitchCount = 0;
4586     RetrySuspension:
4587 #endif
4588
4589             // We can not allocate memory after we suspend a thread.
4590             // Otherwise, we may deadlock the process, because the thread we just suspended
4591             // might hold locks we would need to acquire while allocating.
4592             ThreadStore::AllocateOSContext();
4593
4594 #ifdef TIME_SUSPEND
4595             DWORD startSuspend = g_SuspendStatistics.GetTime();
4596 #endif
4597
4598             //
4599             // Suspend the native thread.
4600             //
4601             Thread::SuspendThreadResult str = thread->SuspendThread();
4602
4603             // We should just always build with this TIME_SUSPEND stuff, and report the results via ETW.
4604 #ifdef TIME_SUSPEND
4605             g_SuspendStatistics.osSuspend.Accumulate(
4606                     SuspendStatistics::GetElapsed(startSuspend,
4607                                                   g_SuspendStatistics.GetTime()));
4608
4609             if (str == Thread::STR_Success)
4610                 g_SuspendStatistics.cntOSSuspendResume++;
4611             else
4612                 g_SuspendStatistics.cntFailedSuspends++;
4613 #endif
4614
4615             if (str == Thread::STR_NoStressLog)
4616             {
4617                 STRESS_LOG2(LF_SYNC, LL_ERROR, "    ERROR: Could not suspend thread 0x%x, result = %d\n", thread, str);
4618             }
4619             else
4620             if (thread->m_fPreemptiveGCDisabled)
4621             {
4622                 // We now know for sure that the thread is still in cooperative mode.  If it's in JIT'd code, here
4623                 // is where we try to hijack/redirect the thread.  If it's in VM code, we have to just let the VM
4624                 // finish what it's doing.
4625
4626 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
4627                 // Only check for HandledJITCase if we actually suspended the thread.
4628                 if (str == Thread::STR_Success)
4629                 {
4630                     Thread::WorkingOnThreadContextHolder workingOnThreadContext(thread);
4631
4632                     //
4633                     // Note that thread->HandledJITCase is not a simple predicate - it actually will hijack the thread if that's possible.
4634                     // So HandledJITCase can do one of these:
4635                     //
4636                     //   - Return TRUE, in which case it's our responsibility to redirect the thread
4637                     //   - Return FALSE after hijacking the thread - we shouldn't try to redirect
4638                     //   - Return FALSE but not hijack the thread - there's nothing we can do either
4639                     //
4640                     // Here is another great opportunity for refactoring :)
4641                     //
4642                     if (workingOnThreadContext.Acquired() && thread->HandledJITCase())
4643                     {
4644                         // Redirect thread so we can capture a good thread context
4645                         // (GetThreadContext is not sufficient, due to an OS bug).
4646                         if (!thread->CheckForAndDoRedirectForGC())
4647                         {
4648 #ifdef TIME_SUSPEND
4649                             g_SuspendStatistics.cntFailedRedirections++;
4650 #endif
4651                             STRESS_LOG1(LF_SYNC, LL_INFO1000, "Failed to CheckForAndDoRedirectForGC(). Retry suspension for thread %p\n", thread);
4652                             thread->ResumeThread();
4653                             __SwitchToThread(0, ++dwSwitchCount);
4654                             goto RetrySuspension;
4655                         }
4656 #ifdef TIME_SUSPEND
4657                         else
4658                             g_SuspendStatistics.cntRedirections++;
4659 #endif
4660                         STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime() -   Thread %p redirected().\n", thread);
4661                     }
4662                 }
4663 #endif // FEATURE_HIJACK && !PLATFORM_UNIX
4664
4665                 FastInterlockOr((ULONG *) &thread->m_State, Thread::TS_GCSuspendPending);
4666
4667                 countThreads++;
4668
4669                 // Only resume if we actually suspended the thread above.
4670                 if (str == Thread::STR_Success)
4671                     thread->ResumeThread();
4672
4673                 STRESS_LOG1(LF_SYNC, LL_INFO1000, "    Thread 0x%x is in cooperative needs to rendezvous\n", thread);
4674             }
4675             else
4676             if (str == Thread::STR_Success)
4677             {
4678                 STRESS_LOG1(LF_SYNC, LL_WARNING, "    Inspecting thread 0x%x was in cooperative, but now is not\n", thread);
4679                 // Oops.
4680                 thread->ResumeThread();
4681             }
4682             else
4683             if (str == Thread::STR_SwitchedOut) {
4684                 STRESS_LOG1(LF_SYNC, LL_WARNING, "    Inspecting thread 0x%x was in cooperative, but now is switched out\n", thread);
4685             }
4686             else {
4687                 _ASSERTE(str == Thread::STR_Failure || str == Thread::STR_UnstartedOrDead);
4688                 STRESS_LOG3(LF_SYNC, LL_ERROR, "    ERROR: Could not suspend thread 0x%x, result = %d, lastError = 0x%x\n", thread, str, GetLastError());
4689             }
4690
4691 #endif // DISABLE_THREADSUSPEND
4692
4693         }
4694         else
4695         {
4696             // To ensure 0 CPU utilization for FAS (see implementation of PauseAPC)
4697             // we queue the APC to all interruptable threads. 
4698             if(g_IsPaused && (thread->m_State & Thread::TS_Interruptible))
4699             {
4700                 HANDLE handle = thread->GetThreadHandle();
4701                 QueueUserAPC((PAPCFUNC)PauseAPC, handle, APC_Code);
4702             }
4703         }
4704     }
4705
4706 #ifdef _DEBUG
4707
4708     {
4709         int     countCheck = 0;
4710         Thread *InnerThread = NULL;
4711
4712         while ((InnerThread = ThreadStore::GetThreadList(InnerThread)) != NULL)
4713         {
4714             if (InnerThread != pCurThread &&
4715                 (InnerThread->m_State & Thread::TS_GCSuspendPending) != 0)
4716             {
4717                 countCheck++;
4718             }
4719         }
4720         _ASSERTE(countCheck == countThreads);
4721     }
4722
4723 #endif
4724
4725     //
4726     // Now we keep retrying until we find that no threads are in cooperative mode.  This should be merged into 
4727     // the first loop.
4728     //
4729     while (countThreads)
4730     {
4731         _ASSERTE (thread == NULL);
4732         STRESS_LOG1(LF_SYNC, LL_INFO1000, "    A total of %d threads need to rendezvous\n", countThreads);
4733         while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
4734         {
4735             if (thread == pCurThread)
4736                 continue;
4737
4738             if (thread->HasThreadState(Thread::TS_BlockGCForSO))
4739             {
4740                 // The thread is trying to block for GC.  But we don't have enough stack to do
4741                 // this operation.
4742                 // We will let the thread switch back to cooperative mode, and continue running.
4743                 if (thread->m_fPreemptiveGCDisabled.Load() == 0)
4744                 {
4745                     if (!thread->HasThreadState(Thread::TS_GCSuspendPending))
4746                     {
4747                         thread->SetThreadState(Thread::TS_GCSuspendPending);
4748                         countThreads ++;
4749                     }
4750                     thread->ResetThreadState(Thread::TS_BlockGCForSO);
4751                     FastInterlockOr (&thread->m_fPreemptiveGCDisabled, 1);
4752                 }
4753                 continue;
4754             }
4755             if ((thread->m_State & Thread::TS_GCSuspendPending) == 0)
4756                 continue;
4757
4758             if (!thread->m_fPreemptiveGCDisabled)
4759             {
4760                 // Inlined N/Direct can sneak out to preemptive without actually checking.
4761                 // If we find one, we can consider it suspended (since it can't get back in).
4762                 STRESS_LOG1(LF_SYNC, LL_INFO1000, "    Thread %x went preemptive it is at a GC safe point\n", thread);
4763                 countThreads--;
4764                 thread->ResetThreadState(Thread::TS_GCSuspendPending);
4765
4766                 // To ensure 0 CPU utilization for FAS (see implementation of PauseAPC)
4767                 // we queue the APC to all interruptable threads.
4768                 if(g_IsPaused && (thread->m_State & Thread::TS_Interruptible))
4769                 {
4770                     HANDLE handle = thread->GetThreadHandle();
4771                     QueueUserAPC((PAPCFUNC)PauseAPC, handle, APC_Code);
4772                 }
4773             }
4774         }
4775
4776         if (countThreads == 0)
4777         {
4778             break;
4779         }
4780
4781 #ifdef _DEBUG
4782         DWORD dbgStartTimeout = GetTickCount();
4783 #endif
4784
4785         // If another thread is trying to do a GC, there is a chance of deadlock
4786         // because this thread holds the threadstore lock and the GC thread is stuck
4787         // trying to get it, so this thread must bail and do a retry after the GC completes.
4788         //
4789         // <REVISIT> Shouldn't we do this only if *this* thread isn't attempting a GC?  We're mostly 
4790         //  done suspending the EE at this point - why give up just because another thread wants
4791         //  to do exactly the same thing?  Note that GetGCThreadAttemptingSuspend will never (AFAIK)
4792         //  return the current thread here, because we NULL it out after obtaining the thread store lock. </REVISIT>
4793         //
4794         if (m_pThreadAttemptingSuspendForGC != NULL && m_pThreadAttemptingSuspendForGC != pCurThread)
4795         {
4796 #ifdef PROFILING_SUPPORTED
4797             // Must let the profiler know that this thread is aborting its attempt at suspending
4798             {
4799                 BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
4800                 g_profControlBlock.pProfInterface->RuntimeSuspendAborted();
4801                 END_PIN_PROFILER();
4802             }
4803 #endif // PROFILING_SUPPORTED
4804
4805             STRESS_LOG0(LF_SYNC, LL_ALWAYS, "Thread::SuspendRuntime() - Timing out.\n");
4806             return (ERROR_TIMEOUT);
4807         }
4808
4809 #ifdef TIME_SUSPEND
4810         DWORD startWait = g_SuspendStatistics.GetTime();
4811 #endif
4812
4813         // 
4814         // Wait for at least one thread to tell us it's left cooperative mode.  
4815         // we do this by waiting on g_pGCSuspendEvent.  We cannot simply wait forever, because we
4816         // might have done return-address hijacking on a thread, and that thread might not
4817         // return from the method we hijacked (maybe it calls into some other managed code that
4818         // executes a long loop, for example).  We we wait with a timeout, and retry hijacking/redirection.
4819         //
4820         // This is unfortunate, because it means that in some cases we wait for PING_JIT_TIMEOUT
4821         // milliseconds, causing long GC pause times.
4822         //
4823         // We should fix this, by calling SwitchToThread/Sleep(0) a few times before waiting on the event.
4824         // This will not fix it 100% of the time (we may still have to wait on the event), but 
4825         // the event is needed to work around limitations of SwitchToThread/Sleep(0).  
4826         //
4827         // For now, we simply wait.
4828         //
4829
4830         res = g_pGCSuspendEvent->Wait(PING_JIT_TIMEOUT, FALSE);
4831
4832
4833 #ifdef TIME_SUSPEND
4834         g_SuspendStatistics.wait.Accumulate(
4835                 SuspendStatistics::GetElapsed(startWait,
4836                                               g_SuspendStatistics.GetTime()));
4837
4838         g_SuspendStatistics.cntWaits++;
4839         if (res == WAIT_TIMEOUT)
4840             g_SuspendStatistics.cntWaitTimeouts++;
4841 #endif
4842
4843         if (res == WAIT_TIMEOUT || res == WAIT_IO_COMPLETION)
4844         {
4845             STRESS_LOG1(LF_SYNC, LL_INFO1000, "    Timed out waiting for rendezvous event %d threads remaining\n", countThreads);
4846 #ifdef _DEBUG
4847             DWORD dbgEndTimeout = GetTickCount();
4848
4849             if ((dbgEndTimeout > dbgStartTimeout) &&
4850                 (dbgEndTimeout - dbgStartTimeout > g_pConfig->SuspendDeadlockTimeout()))
4851             {
4852                 // Do not change this to _ASSERTE.
4853                 // We want to catch the state of the machine at the
4854                 // time when we can not suspend some threads.
4855                 // It takes too long for _ASSERTE to stop the process.
4856                 DebugBreak();
4857                 _ASSERTE(!"Timed out trying to suspend EE due to thread");
4858                 char message[256];
4859                 _ASSERTE (thread == NULL);
4860                 while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
4861                 {
4862                     if (thread == pCurThread)
4863                         continue;
4864
4865                     if ((thread->m_State & Thread::TS_GCSuspendPending) == 0)
4866                         continue;
4867
4868                     if (thread->m_fPreemptiveGCDisabled)
4869                     {
4870                         DWORD id = thread->m_OSThreadId;
4871                         if (id == 0xbaadf00d)
4872                         {
4873                             sprintf_s (message, COUNTOF(message), "Thread CLR ID=%x cannot be suspended",
4874                                      thread->GetThreadId());
4875                         }
4876                         else
4877                         {
4878                             sprintf_s (message, COUNTOF(message), "Thread OS ID=%x cannot be suspended",
4879                                      id);
4880                         }
4881                         DbgAssertDialog(__FILE__, __LINE__, message);
4882                     }
4883                 }
4884                 // if we continue from the assert we'll reset the time
4885                 dbgStartTimeout = GetTickCount();
4886             }
4887 #endif
4888
4889 #if defined(FEATURE_HIJACK) && defined(PLATFORM_UNIX)
4890             _ASSERTE (thread == NULL);
4891             while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
4892             {
4893                 if (thread == pCurThread)
4894                     continue;
4895
4896                 if ((thread->m_State & Thread::TS_GCSuspendPending) == 0)
4897                     continue;
4898
4899                 if (!thread->m_fPreemptiveGCDisabled)
4900                     continue;
4901
4902                 // When we tried to inject the suspension before, we may have been in a place
4903                 // where it wasn't possible. Try one more time.
4904                 bool gcSuspensionSignalSuccess = thread->InjectGcSuspension();
4905                 if (!gcSuspensionSignalSuccess)
4906                 {
4907                     // If we failed to raise the signal for some reason, just log it and move on.
4908                     STRESS_LOG1(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime() -   Failed to raise GC suspension signal for thread %p.\n", thread);
4909                 }
4910             }
4911 #endif
4912
4913 #ifndef DISABLE_THREADSUSPEND
4914             // all these threads should be in cooperative mode unless they have
4915             // set their SafeEvent on the way out.  But there's a race between
4916             // when we time out and when they toggle their mode, so sometimes
4917             // we will suspend a thread that has just left.
4918             _ASSERTE (thread == NULL);
4919             while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
4920             {
4921                 if (thread == pCurThread)
4922                     continue;
4923
4924                 if ((thread->m_State & Thread::TS_GCSuspendPending) == 0)
4925                     continue;
4926
4927                 if (!thread->m_fPreemptiveGCDisabled)
4928                     continue;
4929
4930 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
4931             RetrySuspension2:
4932 #endif
4933                 // We can not allocate memory after we suspend a thread.
4934                 // Otherwise, we may deadlock the process when CLR is hosted.
4935                 ThreadStore::AllocateOSContext();
4936
4937 #ifdef TIME_SUSPEND
4938                 DWORD startSuspend = g_SuspendStatistics.GetTime();
4939 #endif
4940
4941                 Thread::SuspendThreadResult str = thread->SuspendThread();
4942
4943 #ifdef TIME_SUSPEND
4944                 g_SuspendStatistics.osSuspend.Accumulate(
4945                     SuspendStatistics::GetElapsed(startSuspend,
4946                                                   g_SuspendStatistics.GetTime()));
4947
4948                 if (str == Thread::STR_Success)
4949                     g_SuspendStatistics.cntOSSuspendResume++;
4950                 else
4951                     g_SuspendStatistics.cntFailedSuspends++;
4952 #endif
4953
4954 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
4955                 // Only check HandledJITCase if we actually suspended the thread, and
4956                 // the thread is in cooperative mode.
4957                 // See comment at the previous invocation of HandledJITCase - it does
4958                 // more than you think!
4959                 if (str == Thread::STR_Success && thread->m_fPreemptiveGCDisabled)
4960                 {
4961                     Thread::WorkingOnThreadContextHolder workingOnThreadContext(thread);
4962                     if (workingOnThreadContext.Acquired() && thread->HandledJITCase())
4963                     {
4964                         // Redirect thread so we can capture a good thread context
4965                         // (GetThreadContext is not sufficient, due to an OS bug).
4966                         if (!thread->CheckForAndDoRedirectForGC())
4967                         {
4968 #ifdef TIME_SUSPEND
4969                             g_SuspendStatistics.cntFailedRedirections++;
4970 #endif
4971                             STRESS_LOG1(LF_SYNC, LL_INFO1000, "Failed to CheckForAndDoRedirectForGC(). Retry suspension 2 for thread %p\n", thread);
4972                             thread->ResumeThread();
4973                             goto RetrySuspension2;
4974                         }
4975 #ifdef TIME_SUSPEND
4976                         else
4977                             g_SuspendStatistics.cntRedirections++;
4978 #endif
4979                     }
4980                 }
4981 #endif // FEATURE_HIJACK && !PLATFORM_UNIX
4982
4983                 if (str == Thread::STR_Success)
4984                     thread->ResumeThread();
4985             }
4986 #endif // DISABLE_THREADSUSPEND
4987         }
4988         else
4989         if (res == WAIT_OBJECT_0)
4990         {
4991             g_pGCSuspendEvent->Reset();
4992             continue;
4993         }
4994         else
4995         {
4996             // No WAIT_FAILED, WAIT_ABANDONED, etc.
4997             _ASSERTE(!"unexpected wait termination during gc suspension");
4998         }
4999     }
5000
5001 #ifdef PROFILING_SUPPORTED
5002     // If a profiler is keeping track of GC events, notify it
5003     {
5004         BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
5005         g_profControlBlock.pProfInterface->RuntimeSuspendFinished();
5006         END_PIN_PROFILER();
5007     }
5008 #endif // PROFILING_SUPPORTED
5009
5010 #ifdef _DEBUG
5011     if (reason == ThreadSuspend::SUSPEND_FOR_GC) {
5012         thread = NULL;
5013         while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
5014         {
5015             thread->DisableStressHeap();
5016             _ASSERTE (!thread->HasThreadState(Thread::TS_GCSuspendPending));
5017         }
5018     }
5019 #endif
5020
5021     // We know all threads are in preemptive mode, so go ahead and reset the event.  
5022     g_pGCSuspendEvent->Reset();
5023
5024 #ifdef HAVE_GCCOVER
5025     //
5026     // Now that the EE has been suspended, let's see if any oustanding
5027     // gcstress instruction updates need to occur.  Each thread can
5028     // have only one pending at a time.
5029     //
5030     thread = NULL;
5031     while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
5032     {
5033         thread->CommitGCStressInstructionUpdate();
5034     }
5035 #endif // HAVE_GCCOVER
5036
5037     STRESS_LOG0(LF_SYNC, LL_INFO1000, "Thread::SuspendRuntime() - Success\n");
5038     return S_OK;
5039 }
5040
5041 #ifdef HAVE_GCCOVER
5042
5043 void Thread::CommitGCStressInstructionUpdate()
5044 {
5045     CONTRACTL
5046     {
5047         NOTHROW;
5048         GC_NOTRIGGER;
5049         MODE_ANY;
5050     }
5051     CONTRACTL_END;
5052
5053     if (HasPendingGCStressInstructionUpdate())
5054     {
5055 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
5056
5057         *m_pbDestCode = *m_pbSrcCode;
5058
5059 #elif defined(_TARGET_ARM_)
5060
5061         if (GetARMInstructionLength(m_pbDestCode) == 2)
5062             *(WORD*)m_pbDestCode  = *(WORD*)m_pbSrcCode;
5063         else
5064             *(DWORD*)m_pbDestCode = *(DWORD*)m_pbSrcCode;
5065
5066 #elif defined(_TARGET_ARM64_)
5067
5068         *(DWORD*)m_pbDestCode = *(DWORD*)m_pbSrcCode;
5069
5070 #else
5071
5072         *m_pbDestCode = *m_pbSrcCode;
5073
5074 #endif
5075
5076         ClearGCStressInstructionUpdate();
5077     }
5078 }
5079
5080 #endif // HAVE_GCCOVER
5081
5082
5083 #ifdef _DEBUG
5084 void EnableStressHeapHelper()
5085 {
5086     WRAPPER_NO_CONTRACT;
5087     ENABLESTRESSHEAP();
5088 }
5089 #endif
5090
5091 // We're done with our GC.  Let all the threads run again.
5092 // By this point we've already unblocked most threads.  This just releases the ThreadStore lock.
5093 void ThreadSuspend::ResumeRuntime(BOOL bFinishedGC, BOOL SuspendSucceded)
5094 {
5095     CONTRACTL {
5096         NOTHROW;
5097         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
5098     }
5099     CONTRACTL_END;
5100
5101     Thread  *pCurThread = GetThread();
5102
5103     // Caller is expected to be holding the ThreadStore lock.  But they must have
5104     // reset GcInProgress, or threads will continue to suspend themselves and won't
5105     // be resumed until the next GC.
5106     _ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore());
5107     _ASSERTE(!GCHeapUtilities::IsGCInProgress() );
5108
5109     STRESS_LOG2(LF_SYNC, LL_INFO1000, "Thread::ResumeRuntime(finishedGC=%d, SuspendSucceeded=%d) - Start\n", bFinishedGC, SuspendSucceded);
5110
5111     //
5112     // Notify everyone who cares, that this suspension is over, and this thread is going to go do other things.
5113     //
5114
5115
5116 #ifdef PROFILING_SUPPORTED
5117     // Need to give resume event for the GC thread
5118     {
5119         BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
5120         if (pCurThread)
5121         {
5122             g_profControlBlock.pProfInterface->RuntimeThreadResumed((ThreadID)pCurThread);
5123         }
5124         END_PIN_PROFILER();
5125     }
5126 #endif // PROFILING_SUPPORTED
5127
5128 #ifdef TIME_SUSPEND
5129     DWORD startRelease = g_SuspendStatistics.GetTime();
5130 #endif
5131
5132     //
5133     // Unlock the thread store.  At this point, all threads should be allowed to run.
5134     //
5135     ThreadSuspend::UnlockThreadStore();
5136
5137 #ifdef TIME_SUSPEND
5138     g_SuspendStatistics.releaseTSL.Accumulate(SuspendStatistics::GetElapsed(startRelease,
5139                                                                             g_SuspendStatistics.GetTime()));
5140 #endif
5141
5142 #ifdef PROFILING_SUPPORTED
5143     //
5144     // This thread is logically "resuming" from a GC now.  Tell the profiler.
5145     //
5146     {
5147         BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
5148         GCX_PREEMP();
5149         g_profControlBlock.pProfInterface->RuntimeResumeFinished();
5150         END_PIN_PROFILER();
5151     }
5152 #endif // PROFILING_SUPPORTED
5153
5154     //
5155     // If we raised this thread's priority in SuspendRuntime, we restore it here.
5156     //
5157     if (pCurThread)
5158     {
5159         if (pCurThread->m_Priority != INVALID_THREAD_PRIORITY)
5160         {
5161             pCurThread->SetThreadPriority(pCurThread->m_Priority);
5162             pCurThread->m_Priority = INVALID_THREAD_PRIORITY;
5163         }
5164     }
5165
5166     STRESS_LOG0(LF_SYNC, LL_INFO1000, "Thread::ResumeRuntime() - End\n");
5167 }
5168
5169 #ifndef FEATURE_PAL
5170 #ifdef _TARGET_X86_
5171 //****************************************************************************************
5172 // This will resume the thread at the location of redirection.
5173 //
5174 int RedirectedThrowControlExceptionFilter(
5175     PEXCEPTION_POINTERS pExcepPtrs     // Exception data
5176     )
5177 {
5178     // !!! Do not use a non-static contract here.
5179     // !!! Contract may insert an exception handling record.
5180     // !!! This function assumes that GetCurrentSEHRecord() returns the exception record set up in
5181     // !!! ThrowControlForThread
5182     STATIC_CONTRACT_NOTHROW;
5183     STATIC_CONTRACT_GC_NOTRIGGER;
5184     STATIC_CONTRACT_MODE_ANY;
5185
5186     if (pExcepPtrs->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
5187     {
5188         return EXCEPTION_CONTINUE_SEARCH;
5189     }
5190
5191     // Get the thread handle
5192     Thread *pThread = GetThread();
5193     _ASSERTE(pThread);
5194
5195
5196     STRESS_LOG0(LF_SYNC, LL_INFO100, "In RedirectedThrowControlExceptionFilter\n");
5197
5198     // If we get here via COM+ exception, gc-mode is unknown.  We need it to
5199     // be cooperative for this function.
5200     _ASSERTE (pThread->PreemptiveGCDisabled());
5201
5202     _ASSERTE(pExcepPtrs->ExceptionRecord->ExceptionCode == BOOTUP_EXCEPTION_COMPLUS);
5203
5204     // Copy the saved context record into the EH context;
5205     CONTEXT *pCtx = pThread->m_OSContext;
5206     ReplaceExceptionContextRecord(pExcepPtrs->ContextRecord, pCtx);
5207
5208     /////////////////////////////////////////////////////////////////////////////
5209     // NOTE: Ugly, ugly workaround.
5210     // We need to resume the thread into the managed code where it was redirected,
5211     // and the corresponding ESP is below the current one.  But C++ expects that
5212     // on an EXCEPTION_CONTINUE_EXECUTION that the ESP will be above where it has
5213     // installed the SEH handler.  To solve this, we need to remove all handlers
5214     // that reside above the resumed ESP, but we must leave the OS-installed
5215     // handler at the top, so we grab the top SEH handler, call
5216     // PopSEHRecords which will remove all SEH handlers above the target ESP and
5217     // then link the OS handler back in with SetCurrentSEHRecord.
5218
5219     // Get the special OS handler and save it until PopSEHRecords is done
5220     EXCEPTION_REGISTRATION_RECORD *pCurSEH = GetCurrentSEHRecord();
5221
5222     // Unlink all records above the target resume ESP
5223     PopSEHRecords((LPVOID)(size_t)pCtx->Esp);
5224
5225     // Link the special OS handler back in to the top
5226     pCurSEH->Next = GetCurrentSEHRecord();
5227
5228     // Register the special OS handler as the top handler with the OS
5229     SetCurrentSEHRecord(pCurSEH);
5230
5231     // Resume execution at point where thread was originally redirected
5232     return (EXCEPTION_CONTINUE_EXECUTION);
5233 }
5234 #endif
5235 #endif // !FEATURE_PAL
5236
5237 // Resume a thread at this location, to persuade it to throw a ThreadStop.  The
5238 // exception handler needs a reasonable idea of how large this method is, so don't
5239 // add lots of arbitrary code here.
5240 void
5241 ThrowControlForThread(
5242 #ifdef WIN64EXCEPTIONS
5243         FaultingExceptionFrame *pfef
5244 #endif // WIN64EXCEPTIONS
5245         )
5246 {
5247     STATIC_CONTRACT_THROWS;
5248     STATIC_CONTRACT_GC_NOTRIGGER;
5249
5250     Thread *pThread = GetThread();
5251     _ASSERTE(pThread);
5252     _ASSERTE(pThread->m_OSContext);
5253
5254     _ASSERTE(pThread->PreemptiveGCDisabled());
5255
5256 #ifdef FEATURE_STACK_PROBE
5257     if (GetEEPolicy()->GetActionOnFailure(FAIL_StackOverflow) == eRudeUnloadAppDomain)
5258     {
5259         RetailStackProbe(ADJUST_PROBE(DEFAULT_ENTRY_PROBE_AMOUNT), pThread);
5260     }
5261 #endif
5262
5263     // Check if we can start abort
5264     // We use InducedThreadRedirect as a marker to tell stackwalker that a thread is redirected from JIT code.
5265     // This is to distinguish a thread is in Preemptive mode and in JIT code.
5266     // After stackcrawl, we change to InducedThreadStop.
5267     if (pThread->ThrewControlForThread() == Thread::InducedThreadRedirect ||
5268         pThread->ThrewControlForThread() == Thread::InducedThreadRedirectAtEndOfCatch)
5269     {
5270         _ASSERTE((pThread->m_OSContext->ContextFlags & CONTEXT_ALL) == CONTEXT_ALL);
5271         if (!pThread->ReadyForAbort())
5272         {
5273             STRESS_LOG0(LF_SYNC, LL_INFO100, "ThrowControlForThread resume\n");
5274             pThread->ResetThrowControlForThread();
5275             // Thread abort is not allowed at this point
5276 #ifndef WIN64EXCEPTIONS
5277             __try{
5278                 RaiseException(BOOTUP_EXCEPTION_COMPLUS,0,0,NULL);
5279             }
5280             __except(RedirectedThrowControlExceptionFilter(GetExceptionInformation()))
5281             {
5282                 _ASSERTE(!"Should not reach here");
5283             }
5284 #else // WIN64EXCEPTIONS
5285             RtlRestoreContext(pThread->m_OSContext, NULL);
5286 #endif // !WIN64EXCEPTIONS
5287             _ASSERTE(!"Should not reach here");
5288         }
5289         pThread->SetThrowControlForThread(Thread::InducedThreadStop);
5290     }
5291
5292 #if defined(WIN64EXCEPTIONS)
5293     *(TADDR*)pfef = FaultingExceptionFrame::GetMethodFrameVPtr();
5294     *pfef->GetGSCookiePtr() = GetProcessGSCookie();
5295 #else // WIN64EXCEPTIONS
5296     FrameWithCookie<FaultingExceptionFrame> fef;
5297     FaultingExceptionFrame *pfef = &fef;
5298 #endif // WIN64EXCEPTIONS
5299     pfef->InitAndLink(pThread->m_OSContext);
5300
5301     // !!! Can not assert here.  Sometimes our EHInfo for catch clause extends beyond
5302     // !!! Jit_EndCatch.  Not sure if we have guarantee on catch clause.
5303     //_ASSERTE (pThread->ReadyForAbort());
5304
5305     STRESS_LOG0(LF_SYNC, LL_INFO100, "ThrowControlForThread Aborting\n");
5306
5307     // Here we raise an exception.
5308     RaiseComPlusException();
5309 }
5310
5311 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
5312 // This function is called by UserAbort and StopEEAndUnwindThreads.
5313 // It forces a thread to abort if allowed and the thread is running managed code.
5314 BOOL Thread::HandleJITCaseForAbort()
5315 {
5316     CONTRACTL {
5317         NOTHROW;
5318         GC_NOTRIGGER;
5319     }
5320     CONTRACTL_END;
5321
5322     _ASSERTE(ThreadStore::HoldingThreadStore());
5323
5324     WorkingOnThreadContextHolder workingOnThreadContext(this);
5325     if (!workingOnThreadContext.Acquired())
5326     {
5327         return FALSE;
5328     }
5329
5330     _ASSERTE (m_fPreemptiveGCDisabled);
5331
5332     CONTEXT ctx;
5333     ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
5334     BOOL success     = EEGetThreadContext(this, &ctx);
5335     _ASSERTE(success && "Thread::HandleJITCaseForAbort : Failed to get thread context");
5336
5337     if (success)
5338     {
5339         success = IsContextSafeToRedirect(&ctx);
5340     }
5341
5342     if (success)
5343     {
5344         PCODE curIP = GetIP(&ctx);
5345
5346         // check if this is code managed by the code manager (ie. in the code heap)
5347         if (ExecutionManager::IsManagedCode(curIP))
5348         {
5349             return ResumeUnderControl(&ctx);
5350         }
5351     }
5352
5353     return FALSE;
5354 }
5355
5356 // Threads suspended by the Win32 ::SuspendThread() are resumed in two ways.  If we
5357 // suspended them in error, they are resumed via the Win32 ::ResumeThread().  But if
5358 // this is the HandledJIT() case and the thread is in fully interruptible code, we
5359 // can resume them under special control.  ResumeRuntime and UserResume are cases
5360 // of this.
5361 //
5362 // The suspension has done its work (e.g. GC or user thread suspension).  But during
5363 // the resumption we may have more that we want to do with this thread.  For example,
5364 // there may be a pending ThreadAbort request.  Instead of resuming the thread at its
5365 // current EIP, we tweak its resumption point via the thread context.  Then it starts
5366 // executing at a new spot where we can have our way with it.
5367
5368 BOOL Thread::ResumeUnderControl(CONTEXT *pCtx)
5369 {
5370     CONTRACTL {
5371         NOTHROW;
5372         GC_NOTRIGGER;
5373     }
5374     CONTRACTL_END;
5375
5376     BOOL fSuccess = FALSE;
5377
5378     LOG((LF_APPDOMAIN, LL_INFO100, "ResumeUnderControl %x\n", GetThreadId()));
5379
5380     BOOL fSucceeded;
5381
5382     m_OSContext->ContextFlags = CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST;
5383     fSucceeded = EEGetThreadContext(this, m_OSContext);
5384
5385     if (fSucceeded)
5386     {
5387         if (GetIP(pCtx) != GetIP(m_OSContext))
5388         {
5389             return FALSE;
5390         }
5391         fSucceeded = IsContextSafeToRedirect(m_OSContext);
5392     }
5393
5394     if (fSucceeded)
5395     {
5396         PCODE resumePC = GetIP(m_OSContext);
5397         SetIP(m_OSContext, GetEEFuncEntryPoint(THROW_CONTROL_FOR_THREAD_FUNCTION));
5398         SetThrowControlForThread(InducedThreadRedirect);
5399         STRESS_LOG1(LF_SYNC, LL_INFO100, "ResumeUnderControl for Thread %p\n", this);
5400
5401 #ifdef _TARGET_AMD64_
5402         // We need to establish the return value on the stack in the redirection stub, to
5403         // achieve crawlability.  We use 'rcx' as the way to communicate the return value.
5404         // However, we are going to crawl in ReadyForAbort and we are going to resume in
5405         // ThrowControlForThread using m_OSContext.  It's vital that the original correct
5406         // Rcx is present at those times, or we will have corrupted Rcx at the point of
5407         // resumption.
5408         UINT_PTR    keepRcx = m_OSContext->Rcx;
5409
5410         m_OSContext->Rcx = (UINT_PTR)resumePC;
5411 #endif // _TARGET_AMD64_
5412
5413 #if defined(_TARGET_ARM_)
5414         // We save the original ControlPC in LR on ARM.
5415         UINT_PTR originalLR = m_OSContext->Lr;
5416         m_OSContext->Lr = (UINT_PTR)resumePC;
5417
5418         // Since we have set a new IP, we have to clear conditional execution flags too.
5419         UINT_PTR originalCpsr = m_OSContext->Cpsr;
5420         ClearITState(m_OSContext);
5421 #endif // _TARGET_ARM_
5422
5423         EESetThreadContext(this, m_OSContext);
5424
5425 #ifdef _TARGET_ARM_
5426         // Restore the original LR now that the OS context has been updated to resume @ redirection function.
5427         m_OSContext->Lr = originalLR;
5428         m_OSContext->Cpsr = originalCpsr;
5429 #endif // _TARGET_ARM_
5430
5431 #ifdef _TARGET_AMD64_
5432         // and restore.
5433         m_OSContext->Rcx = keepRcx;
5434 #endif // _TARGET_AMD64_
5435
5436         SetIP(m_OSContext, resumePC);
5437
5438         fSuccess = TRUE;
5439     }
5440 #if _DEBUG
5441     else
5442         _ASSERTE(!"Couldn't obtain thread context -- StopRequest delayed");
5443 #endif
5444     return fSuccess;
5445 }
5446
5447 #endif // FEATURE_HIJACK && !PLATFORM_UNIX
5448
5449
5450 PCONTEXT Thread::GetAbortContext ()
5451 {
5452     LIMITED_METHOD_CONTRACT;
5453
5454     LOG((LF_EH, LL_INFO100, "Returning abort context: %p\n", m_OSContext));
5455     return m_OSContext;
5456 }
5457
5458
5459 //****************************************************************************
5460 // Return true if we've Suspended the runtime,
5461 // False if we still need to sweep.
5462 //****************************************************************************
5463 bool Thread::SysStartSuspendForDebug(AppDomain *pAppDomain)
5464 {
5465     CONTRACTL {
5466         NOTHROW;
5467         GC_NOTRIGGER;
5468     }
5469     CONTRACTL_END;
5470
5471     Thread  *pCurThread = GetThread();
5472     Thread  *thread = NULL;
5473
5474     if (IsAtProcessExit())
5475     {
5476         LOG((LF_CORDB, LL_INFO1000,
5477              "SUSPEND: skipping suspend due to process detach.\n"));
5478         return true;
5479     }
5480
5481     LOG((LF_CORDB, LL_INFO1000, "[0x%x] SUSPEND: starting suspend.  Trap count: %d\n",
5482          pCurThread ? pCurThread->GetThreadId() : (DWORD) -1, g_TrapReturningThreads.Load()));
5483
5484     // Caller is expected to be holding the ThreadStore lock
5485     _ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit());
5486
5487
5488     // NOTE::NOTE::NOTE::NOTE::NOTE
5489     // This function has parallel logic in SuspendRuntime.  Please make
5490     // sure to make appropriate changes there as well.
5491
5492     _ASSERTE(m_DebugWillSyncCount == -1);
5493     m_DebugWillSyncCount++;
5494
5495     // From this point until the end of the function, consider all active thread
5496     // suspension to be in progress.  This is mainly to give the profiler API a hint
5497     // that trying to suspend a thread (in order to walk its stack) could delay the
5498     // overall EE suspension.  So the profiler API would early-abort the stackwalk
5499     // in such a case.
5500     ThreadSuspend::SuspendRuntimeInProgressHolder hldSuspendRuntimeInProgress;
5501
5502     while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
5503     {
5504 #if 0
5505 //<REVISIT_TODO>  @todo APPD This needs to be finished, replaced, or yanked --MiPanitz</REVISIT_TODO>
5506         if (m_DebugAppDomainTarget != NULL &&
5507             thread->GetDomain() != m_DebugAppDomainTarget)
5508         {
5509             continue;
5510         }
5511 #endif
5512
5513         // Don't try to suspend threads that you've left suspended.
5514         if (thread->m_StateNC & TSNC_DebuggerUserSuspend)
5515             continue;
5516
5517         if (thread == pCurThread)
5518         {
5519             LOG((LF_CORDB, LL_INFO1000,
5520                  "[0x%x] SUSPEND: marking current thread.\n",
5521                  thread->GetThreadId()));
5522
5523             _ASSERTE(!thread->m_fPreemptiveGCDisabled);
5524
5525             // Mark this thread so it trips when it tries to re-enter
5526             // after completing this call.
5527             thread->SetupForSuspension(TS_DebugSuspendPending);
5528             thread->MarkForSuspension(TS_DebugSuspendPending);
5529             continue;
5530         }
5531
5532         thread->SetupForSuspension(TS_DebugSuspendPending);
5533
5534         // Threads can be in Preemptive or Cooperative GC mode.
5535         // Threads cannot switch to Cooperative mode without special
5536         // treatment when a GC is happening.  But they can certainly
5537         // switch back and forth during a debug suspension -- until we
5538         // can get their Pending bit set.
5539
5540 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
5541         DWORD dwSwitchCount = 0;
5542     RetrySuspension:
5543 #endif // FEATURE_HIJACK && !PLATFORM_UNIX
5544
5545         // We can not allocate memory after we suspend a thread.
5546         // Otherwise, we may deadlock the process when CLR is hosted.
5547         ThreadStore::AllocateOSContext();
5548
5549 #ifdef DISABLE_THREADSUSPEND
5550         // On platforms that do not support safe thread suspension we have
5551         // to rely on the GCPOLL mechanism.
5552         
5553         // When we do not suspend the target thread we rely on the GCPOLL
5554         // mechanism enabled by TrapReturningThreads.  However when reading
5555         // shared state we need to erect appropriate memory barriers. So
5556         // the interlocked operation below ensures that any future reads on 
5557         // this thread will happen after any earlier writes on a different 
5558         // thread.
5559         SuspendThreadResult str = STR_Success;
5560         FastInterlockOr(&thread->m_fPreemptiveGCDisabled, 0);
5561 #else
5562         SuspendThreadResult str = thread->SuspendThread();
5563 #endif // DISABLE_THREADSUSPEND
5564
5565         if (thread->m_fPreemptiveGCDisabled && str == STR_Success)
5566         {
5567
5568 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
5569             WorkingOnThreadContextHolder workingOnThreadContext(thread);
5570             if (workingOnThreadContext.Acquired() && thread->HandledJITCase())
5571             {
5572                 // Redirect thread so we can capture a good thread context
5573                 // (GetThreadContext is not sufficient, due to an OS bug).
5574                 // If we don't succeed (should only happen on Win9X, due to
5575                 // a different OS bug), we must resume the thread and try
5576                 // again.
5577                 if (!thread->CheckForAndDoRedirectForDbg())
5578                 {
5579                     thread->ResumeThread();
5580                     __SwitchToThread(0, ++dwSwitchCount);
5581                     goto RetrySuspension;
5582                 }
5583             }
5584 #endif // FEATURE_HIJACK && !PLATFORM_UNIX
5585
5586             // Remember that this thread will be running to a safe point
5587             FastInterlockIncrement(&m_DebugWillSyncCount);
5588
5589             // When the thread reaches a safe place, it will wait
5590             // on the DebugSuspendEvent which clients can set when they
5591             // want to release us.
5592             thread->MarkForSuspension(TS_DebugSuspendPending |
5593                                        TS_DebugWillSync
5594                       );
5595
5596 #ifdef DISABLE_THREADSUSPEND
5597             // There'a a race above between the moment we first check m_fPreemptiveGCDisabled
5598             // and the moment we enable TrapReturningThreads in MarkForSuspension.  However, 
5599             // nothing bad happens if the thread has transitioned to preemptive before marking 
5600             // the thread for suspension; the thread will later be identified as Synced in
5601             // SysSweepThreadsForDebug
5602 #else  // DISABLE_THREADSUSPEND
5603             // Resume the thread and let it run to a safe point
5604             thread->ResumeThread();
5605 #endif // DISABLE_THREADSUSPEND
5606
5607             LOG((LF_CORDB, LL_INFO1000,
5608                  "[0x%x] SUSPEND: gc disabled - will sync.\n",
5609                  thread->GetThreadId()));
5610         }
5611         else if (!thread->m_fPreemptiveGCDisabled)
5612         {
5613             // Mark threads that are outside the Runtime so that if
5614             // they attempt to re-enter they will trip.
5615             thread->MarkForSuspension(TS_DebugSuspendPending);
5616
5617 #ifdef DISABLE_THREADSUSPEND
5618             // There'a a race above between the moment we first check m_fPreemptiveGCDisabled
5619             // and the moment we enable TrapReturningThreads in MarkForSuspension.  To account 
5620             // for that we check whether the thread moved into cooperative mode, and if it had
5621             // we mark it as a DebugWillSync thread, that will be handled later in 
5622             // SysSweepThreadsForDebug
5623             if (thread->m_fPreemptiveGCDisabled)
5624             {
5625                 // Remember that this thread will be running to a safe point
5626                 FastInterlockIncrement(&m_DebugWillSyncCount);
5627                 thread->SetThreadState(TS_DebugWillSync);
5628             }
5629 #else  // DISABLE_THREADSUSPEND
5630             if (str == STR_Success) {
5631                 thread->ResumeThread();
5632             }
5633 #endif // DISABLE_THREADSUSPEND
5634
5635             LOG((LF_CORDB, LL_INFO1000,
5636                  "[0x%x] SUSPEND: gc enabled.\n", thread->GetThreadId()));
5637         }
5638     }
5639
5640     //
5641     // Return true if all threads are synchronized now, otherwise the
5642     // debugge must wait for the SuspendComplete, called from the last
5643     // thread to sync.
5644     //
5645
5646     if (FastInterlockDecrement(&m_DebugWillSyncCount) < 0)
5647     {
5648         LOG((LF_CORDB, LL_INFO1000,
5649              "SUSPEND: all threads sync before return.\n"));
5650         return true;
5651     }
5652     else
5653         return false;
5654 }
5655
5656 //
5657 // This method is called by the debugger helper thread when it times out waiting for a set of threads to
5658 // synchronize. Its used to chase down threads that are not syncronizing quickly. It returns true if all the threads are
5659 // now synchronized. This also means that we own the thread store lock.
5660 //
5661 // This can be safely called if we're already suspended.
5662 bool Thread::SysSweepThreadsForDebug(bool forceSync)
5663 {
5664     CONTRACT(bool) {
5665         NOTHROW;
5666         DISABLED(GC_TRIGGERS); // WaitUntilConcurrentGCComplete toggle GC mode, disabled because called by unmanaged thread
5667
5668         // We assume that only the "real" helper thread ever calls this (not somebody doing helper thread duty).
5669         PRECONDITION(IsDbgHelperSpecialThread());
5670         PRECONDITION(GetThread() == NULL);
5671
5672         // Iff we return true, then we have the TSL (or the aux lock used in workarounds).
5673         POSTCONDITION(RETVAL == !!ThreadStore::HoldingThreadStore());
5674     }
5675     CONTRACT_END;
5676
5677     _ASSERTE(!forceSync); // deprecated parameter
5678
5679     Thread *thread = NULL;
5680
5681     // NOTE::NOTE::NOTE::NOTE::NOTE
5682     // This function has parallel logic in SuspendRuntime.  Please make
5683     // sure to make appropriate changes there as well.
5684
5685     // We use ThreadSuspend::SUSPEND_FOR_DEBUGGER_SWEEP here to avoid a deadlock which
5686     // can occur due to the s_hAbortEvt event.  This event causes any thread trying
5687     // to take the ThreadStore lock to wait for a GC to complete.  If a thread is
5688     // in SuspendEE for a GC and suspends for the debugger, then this thread will
5689     // deadlock if we do not pass in SUSPEND_FOR_DEBUGGER_SWEEP here.
5690     ThreadSuspend::LockThreadStore(ThreadSuspend::SUSPEND_FOR_DEBUGGER_SWEEP);
5691
5692     // From this point until the end of the function, consider all active thread
5693     // suspension to be in progress.  This is mainly to give the profiler API a hint
5694     // that trying to suspend a thread (in order to walk its stack) could delay the
5695     // overall EE suspension.  So the profiler API would early-abort the stackwalk
5696     // in such a case.
5697     ThreadSuspend::SuspendRuntimeInProgressHolder hldSuspendRuntimeInProgress;
5698
5699     // Loop over the threads...
5700     while (((thread = ThreadStore::GetThreadList(thread)) != NULL) && (m_DebugWillSyncCount >= 0))
5701     {
5702         // Skip threads that we aren't waiting for to sync.
5703         if ((thread->m_State & TS_DebugWillSync) == 0)
5704             continue;
5705
5706 #ifdef DISABLE_THREADSUSPEND
5707
5708         // On platforms that do not support safe thread suspension we have
5709         // to rely on the GCPOLL mechanism.
5710         
5711         // When we do not suspend the target thread we rely on the GCPOLL
5712         // mechanism enabled by TrapReturningThreads.  However when reading
5713         // shared state we need to erect appropriate memory barriers. So
5714         // the interlocked operation below ensures that any future reads on 
5715         // this thread will happen after any earlier writes on a different 
5716         // thread.
5717         FastInterlockOr(&thread->m_fPreemptiveGCDisabled, 0);
5718         if (!thread->m_fPreemptiveGCDisabled)
5719         {
5720             // If the thread toggled to preemptive mode, then it's synced.
5721             goto Label_MarkThreadAsSynced;
5722         }
5723         else
5724         {
5725             continue;
5726         }
5727
5728 #else // DISABLE_THREADSUSPEND
5729         // Suspend the thread
5730
5731 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
5732         DWORD dwSwitchCount = 0;
5733 #endif
5734
5735 RetrySuspension:
5736         // We can not allocate memory after we suspend a thread.
5737         // Otherwise, we may deadlock the process when CLR is hosted.
5738         ThreadStore::AllocateOSContext();
5739
5740         SuspendThreadResult str = thread->SuspendThread();
5741
5742         if (str == STR_Failure || str == STR_UnstartedOrDead)
5743         {
5744             // The thread cannot actually be unstarted - if it was, we would not
5745             // have marked it with TS_DebugWillSync in the first phase.
5746             _ASSERTE(!(thread->m_State & TS_Unstarted));
5747
5748             // If the thread has gone, we can't wait on it.
5749             goto Label_MarkThreadAsSynced;
5750         }
5751         else if (str == STR_SwitchedOut)
5752         {
5753             // The thread was switched b/c of fiber-mode stuff.
5754             if (!thread->m_fPreemptiveGCDisabled)
5755             {
5756                 goto Label_MarkThreadAsSynced;
5757             }
5758             else
5759             {
5760                 goto RetrySuspension;
5761             }
5762         }
5763         else if (str == STR_NoStressLog)
5764         {
5765             goto RetrySuspension;
5766         }
5767         else if (!thread->m_fPreemptiveGCDisabled)
5768         {
5769             // If the thread toggled to preemptive mode, then it's synced.
5770
5771             // We can safely resume the thread here b/c it's in PreemptiveMode and the
5772             // EE will trap anybody trying to re-enter cooperative. So letting it run free
5773             // won't hurt the runtime.
5774             _ASSERTE(str == STR_Success);
5775             thread->ResumeThread();
5776
5777             goto Label_MarkThreadAsSynced;
5778         }
5779 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
5780         // If the thread is in jitted code, HandledJitCase will try to hijack it; and the hijack
5781         // will toggle the GC.
5782         else
5783         {
5784             _ASSERTE(str == STR_Success);
5785             WorkingOnThreadContextHolder workingOnThreadContext(thread);
5786             if (workingOnThreadContext.Acquired() && thread->HandledJITCase())
5787             {
5788                 // Redirect thread so we can capture a good thread context
5789                 // (GetThreadContext is not sufficient, due to an OS bug).
5790                 // If we don't succeed (should only happen on Win9X, due to
5791                 // a different OS bug), we must resume the thread and try
5792                 // again.
5793                 if (!thread->CheckForAndDoRedirectForDbg())
5794                 {
5795                     thread->ResumeThread();
5796                     __SwitchToThread(0, ++dwSwitchCount);
5797                     goto RetrySuspension;
5798                 }
5799
5800                 // The hijack will toggle our GC mode, and thus we could wait for the next sweep,
5801                 // and the GC-mode check above would catch and sync us. But there's no reason to wait,
5802                 // if the thread is hijacked, it's as good as synced, so mark it now.
5803                 thread->ResumeThread();
5804                 goto Label_MarkThreadAsSynced;
5805             }
5806         }
5807 #endif // FEATURE_HIJACK && !PLATFORM_UNIX
5808
5809         // If we didn't take the thread out of the set, then resume it and give it another chance to reach a safe
5810         // point.
5811         thread->ResumeThread();
5812         continue;
5813
5814 #endif // DISABLE_THREADSUSPEND
5815
5816         // The thread is synced. Remove the sync bits and dec the sync count.
5817 Label_MarkThreadAsSynced:
5818         FastInterlockAnd((ULONG *) &thread->m_State, ~TS_DebugWillSync);
5819         if (FastInterlockDecrement(&m_DebugWillSyncCount) < 0)
5820         {
5821             // If that was the last thread, then the CLR is synced.
5822             // We return while own the thread store lock. We return true now, which indicates this to the caller.
5823             RETURN true;
5824         }
5825         continue;
5826
5827     } // end looping through Thread Store
5828
5829     if (m_DebugWillSyncCount < 0)
5830     {
5831         RETURN true;
5832     }
5833
5834     // The CLR is not yet synced. We release the threadstore lock and return false.
5835     hldSuspendRuntimeInProgress.Release();
5836     ThreadSuspend::UnlockThreadStore();
5837
5838     RETURN false;
5839 }
5840
5841 void Thread::SysResumeFromDebug(AppDomain *pAppDomain)
5842 {
5843     CONTRACTL {
5844         NOTHROW;
5845         GC_NOTRIGGER;
5846     }
5847     CONTRACTL_END;
5848
5849     Thread  *thread = NULL;
5850
5851     if (IsAtProcessExit())
5852     {
5853         LOG((LF_CORDB, LL_INFO1000,
5854              "RESUME: skipping resume due to process detach.\n"));
5855         return;
5856     }
5857
5858     LOG((LF_CORDB, LL_INFO1000, "RESUME: starting resume AD:0x%x.\n", pAppDomain));
5859
5860
5861     // Make sure we completed the previous sync
5862     _ASSERTE(m_DebugWillSyncCount == -1);
5863
5864     // Caller is expected to be holding the ThreadStore lock
5865     _ASSERTE(ThreadStore::HoldingThreadStore() || IsAtProcessExit());
5866
5867     while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
5868     {
5869         // Only consider resuming threads if they're in the correct appdomain
5870         if (pAppDomain != NULL && thread->GetDomain() != pAppDomain)
5871         {
5872             LOG((LF_CORDB, LL_INFO1000, "RESUME: Not resuming thread 0x%x, since it's "
5873                 "in appdomain 0x%x.\n", thread, pAppDomain));
5874             continue;
5875         }
5876
5877         // If the user wants to keep the thread suspended, then
5878         // don't release the thread.
5879         if (!(thread->m_StateNC & TSNC_DebuggerUserSuspend))
5880         {
5881             // If we are still trying to suspend this thread, forget about it.
5882             if (thread->m_State & TS_DebugSuspendPending)
5883             {
5884                 LOG((LF_CORDB, LL_INFO1000,
5885                      "[0x%x] RESUME: TS_DebugSuspendPending was set, but will be removed\n",
5886                      thread->GetThreadId()));
5887
5888 #ifdef _TARGET_ARM_
5889                 if (thread->IsSingleStepEnabled())
5890                 {
5891                     if (ISREDIRECTEDTHREAD(thread))
5892                         thread->ApplySingleStep(GETREDIRECTEDCONTEXT(thread));
5893                 }
5894 #endif
5895                 // Note: we unmark for suspension _then_ set the suspend event.
5896                 thread->ReleaseFromSuspension(TS_DebugSuspendPending);
5897             }
5898
5899         }
5900         else
5901         {
5902             // Thread will remain suspended due to a request from the debugger.
5903
5904             LOG((LF_CORDB,LL_INFO10000,"Didn't unsuspend thread 0x%x"
5905                 "(ID:0x%x)\n", thread, thread->GetThreadId()));
5906             LOG((LF_CORDB,LL_INFO10000,"Suspending:0x%x\n",
5907                 thread->m_State & TS_DebugSuspendPending));
5908             _ASSERTE((thread->m_State & TS_DebugWillSync) == 0);
5909
5910         }
5911     }
5912
5913     LOG((LF_CORDB, LL_INFO1000, "RESUME: resume complete. Trap count: %d\n", g_TrapReturningThreads.Load()));
5914 }
5915
5916 /*
5917  *
5918  * WaitSuspendEventsHelper
5919  *
5920  * This function is a simple helper function for WaitSuspendEvents.  It is needed
5921  * because of the EX_TRY macro.  This macro does an alloca(), which allocates space
5922  * off the stack, not free'ing it.  Thus, doing a EX_TRY in a loop can easily result
5923  * in a stack overflow error.  By factoring out the EX_TRY into a separate function,
5924  * we recover that stack space.
5925  *
5926  * Parameters:
5927  *   None.
5928  *
5929  * Return:
5930  *   true if meant to continue, else false.
5931  *
5932  */
5933 BOOL Thread::WaitSuspendEventsHelper(void)
5934 {
5935     STATIC_CONTRACT_NOTHROW;
5936     STATIC_CONTRACT_GC_NOTRIGGER;
5937
5938     DWORD result = WAIT_FAILED;
5939
5940     EX_TRY {
5941
5942         // CoreCLR does not support user-requested thread suspension
5943         _ASSERTE(!(m_State & TS_UserSuspendPending));
5944
5945         if (m_State & TS_DebugSuspendPending) {
5946
5947             ThreadState oldState = m_State;
5948
5949             while (oldState & TS_DebugSuspendPending) {
5950
5951                 ThreadState newState = (ThreadState)(oldState | TS_SyncSuspended);
5952                 if (FastInterlockCompareExchange((LONG *)&m_State, newState, oldState) == (LONG)oldState)
5953                 {
5954                     result = m_DebugSuspendEvent.Wait(INFINITE,FALSE);
5955 #if _DEBUG
5956                     newState = m_State;
5957                     _ASSERTE(!(newState & TS_SyncSuspended) || (newState & TS_UserSuspendPending));
5958 #endif
5959                     break;
5960                 }
5961
5962                 oldState = m_State;
5963             }
5964         }
5965     }
5966     EX_CATCH {
5967     }
5968     EX_END_CATCH(SwallowAllExceptions)
5969
5970     return result != WAIT_OBJECT_0;
5971 }
5972
5973
5974 // There's a bit of a workaround here
5975 void Thread::WaitSuspendEvents(BOOL fDoWait)
5976 {
5977     STATIC_CONTRACT_NOTHROW;
5978     STATIC_CONTRACT_GC_NOTRIGGER;
5979
5980     _ASSERTE(!PreemptiveGCDisabled());
5981     _ASSERTE((m_State & TS_SyncSuspended) == 0);
5982
5983     // Let us do some useful work before suspending ourselves.
5984
5985     // If we're required to perform a wait, do so.  Typically, this is
5986     // skipped if this thread is a Debugger Special Thread.
5987     if (fDoWait)
5988     {
5989         while (TRUE)
5990         {
5991             WaitSuspendEventsHelper();
5992
5993             ThreadState oldState = m_State;
5994
5995             // CoreCLR does not support user-requested thread suspension
5996             _ASSERTE(!(oldState & TS_UserSuspendPending));
5997
5998             //
5999             // If all reasons to suspend are off, we think we can exit
6000             // this loop, but we need to check atomically.
6001             //
6002             if ((oldState & (TS_UserSuspendPending | TS_DebugSuspendPending)) == 0)
6003             {
6004                 //
6005                 // Construct the destination state we desire - all suspension bits turned off.
6006                 //
6007                 ThreadState newState = (ThreadState)(oldState & ~(TS_UserSuspendPending |
6008                                                                   TS_DebugSuspendPending |
6009                                                                   TS_SyncSuspended));
6010
6011                 if (FastInterlockCompareExchange((LONG *)&m_State, newState, oldState) == (LONG)oldState)
6012                 {
6013                     //
6014                     // We are done.
6015                     //
6016                     break;
6017                 }
6018             }
6019         }
6020     }
6021 }
6022
6023 #ifdef FEATURE_HIJACK
6024 //                      Hijacking JITted calls
6025 //                      ======================
6026
6027 // State of execution when we suspend a thread
6028 struct ExecutionState
6029 {
6030     BOOL            m_FirstPass;
6031     BOOL            m_IsJIT;            // are we executing JITted code?
6032     MethodDesc     *m_pFD;              // current function/method we're executing
6033     VOID          **m_ppvRetAddrPtr;    // pointer to return address in frame
6034     DWORD           m_RelOffset;        // relative offset at which we're currently executing in this fcn
6035     IJitManager    *m_pJitManager;
6036     METHODTOKEN     m_MethodToken;
6037     BOOL            m_IsInterruptible;  // is this code interruptible?
6038
6039     ExecutionState() : m_FirstPass(TRUE) {LIMITED_METHOD_CONTRACT;  }
6040 };
6041
6042 // Client is responsible for suspending the thread before calling
6043 void Thread::HijackThread(VOID *pvHijackAddr, ExecutionState *esb)
6044 {
6045     CONTRACTL {
6046         NOTHROW;
6047         GC_NOTRIGGER;
6048     }
6049     CONTRACTL_END;
6050
6051     // Don't hijack if are in the first level of running a filter/finally/catch.
6052     // This is because they share ebp with their containing function further down the
6053     // stack and we will hijack their containing function incorrectly
6054     if (IsInFirstFrameOfHandler(this, esb->m_pJitManager, esb->m_MethodToken, esb->m_RelOffset))
6055     {
6056         STRESS_LOG3(LF_SYNC, LL_INFO100, "Thread::HijackThread(%p to %p): Early out - IsInFirstFrameOfHandler. State=%x.\n", this, pvHijackAddr, (ThreadState)m_State);
6057         return;
6058     }
6059
6060     // Don't hijack if a profiler stackwalk is in progress
6061     HijackLockHolder hijackLockHolder(this);
6062     if (!hijackLockHolder.Acquired())
6063     {
6064         STRESS_LOG3(LF_SYNC, LL_INFO100, "Thread::HijackThread(%p to %p): Early out - !hijackLockHolder.Acquired. State=%x.\n", this, pvHijackAddr, (ThreadState)m_State);
6065         return;
6066     }
6067
6068     IS_VALID_CODE_PTR((FARPROC) pvHijackAddr);
6069
6070     if (m_State & TS_Hijacked)
6071         UnhijackThread();
6072
6073     // Make sure that the location of the return address is on the stack
6074     _ASSERTE(IsAddressInStack(esb->m_ppvRetAddrPtr));
6075
6076     // Obtain the location of the return address in the currently executing stack frame
6077     m_ppvHJRetAddrPtr = esb->m_ppvRetAddrPtr;
6078
6079     // Remember the place that the return would have gone
6080     m_pvHJRetAddr = *esb->m_ppvRetAddrPtr;
6081
6082     IS_VALID_CODE_PTR((FARPROC) (TADDR)m_pvHJRetAddr);
6083     // TODO [DAVBR]: For the full fix for VsWhidbey 450273, the below
6084     // may be uncommented once isLegalManagedCodeCaller works properly
6085     // with non-return address inputs, and with non-DEBUG builds
6086     //_ASSERTE(isLegalManagedCodeCaller((TADDR)m_pvHJRetAddr));
6087     STRESS_LOG2(LF_SYNC, LL_INFO100, "Hijacking return address 0x%p for thread %p\n", m_pvHJRetAddr, this);
6088
6089     // Remember the method we're executing
6090     m_HijackedFunction = esb->m_pFD;
6091
6092     // Bash the stack to return to one of our stubs
6093     *esb->m_ppvRetAddrPtr = pvHijackAddr;
6094     FastInterlockOr((ULONG *) &m_State, TS_Hijacked);
6095 }
6096
6097 // If we are unhijacking another thread (not the current thread), then the caller is responsible for
6098 // suspending that thread.
6099 // It's legal to unhijack the current thread without special treatment.
6100 void Thread::UnhijackThread()
6101 {
6102     CONTRACTL {
6103         NOTHROW;
6104         GC_NOTRIGGER;
6105         SO_TOLERANT;
6106         CANNOT_TAKE_LOCK;
6107     }
6108     CONTRACTL_END;
6109
6110     if (m_State & TS_Hijacked)
6111     {
6112         IS_VALID_WRITE_PTR(m_ppvHJRetAddrPtr, sizeof(void*));
6113         IS_VALID_CODE_PTR((FARPROC) m_pvHJRetAddr);
6114
6115         // Can't make the following assertion, because sometimes we unhijack after
6116         // the hijack has tripped (i.e. in the case we actually got some value from
6117         // it.
6118 //       _ASSERTE(*m_ppvHJRetAddrPtr == OnHijackTripThread);
6119
6120         STRESS_LOG2(LF_SYNC, LL_INFO100, "Unhijacking return address 0x%p for thread %p\n", m_pvHJRetAddr, this);
6121         // restore the return address and clear the flag
6122         *m_ppvHJRetAddrPtr = m_pvHJRetAddr;
6123         FastInterlockAnd((ULONG *) &m_State, ~TS_Hijacked);
6124
6125         // But don't touch m_pvHJRetAddr.  We may need that to resume a thread that
6126         // is currently hijacked!
6127     }
6128 }
6129
6130 // Get the ExecutionState for the specified *SUSPENDED* thread.  Note that this is
6131 // a 'StackWalk' call back (PSTACKWALKFRAMESCALLBACK).
6132 StackWalkAction SWCB_GetExecutionState(CrawlFrame *pCF, VOID *pData)
6133 {
6134     CONTRACTL {
6135         NOTHROW;
6136         GC_NOTRIGGER;
6137     }
6138     CONTRACTL_END;
6139
6140     ExecutionState  *pES = (ExecutionState *) pData;
6141     StackWalkAction  action = SWA_ABORT;
6142
6143     if (pES->m_FirstPass)
6144     {
6145         // This will help factor out some repeated code.
6146         bool notJittedCase = false;
6147
6148         // If we're jitted code at the top of the stack, grab everything
6149         if (pCF->IsFrameless() && pCF->IsActiveFunc())
6150         {
6151             pES->m_IsJIT = TRUE;
6152             pES->m_pFD = pCF->GetFunction();
6153             pES->m_MethodToken = pCF->GetMethodToken();
6154             pES->m_ppvRetAddrPtr = 0;
6155             pES->m_IsInterruptible = pCF->IsGcSafe();
6156             pES->m_RelOffset = pCF->GetRelOffset();
6157             pES->m_pJitManager = pCF->GetJitManager();
6158
6159             STRESS_LOG3(LF_SYNC, LL_INFO1000, "Stopped in Jitted code at pc = %p sp = %p fullyInt=%d\n",
6160                 GetControlPC(pCF->GetRegisterSet()), GetRegdisplaySP(pCF->GetRegisterSet()), pES->m_IsInterruptible);
6161
6162 #if defined(FEATURE_CONSERVATIVE_GC) && !defined(USE_GC_INFO_DECODER)
6163             if (g_pConfig->GetGCConservative())
6164             {
6165                 // Conservative GC enabled; behave as if HIJACK_NONINTERRUPTIBLE_THREADS had not been
6166                 // set above:
6167                 // 
6168                 notJittedCase = true;
6169             }
6170             else
6171 #endif // FEATURE_CONSERVATIVE_GC
6172             {
6173 #ifndef HIJACK_NONINTERRUPTIBLE_THREADS
6174                 if (!pES->m_IsInterruptible)
6175                 {
6176                     notJittedCase = true;
6177                 }
6178 #else // HIJACK_NONINTERRUPTIBLE_THREADS
6179                 // if we're not interruptible right here, we need to determine the
6180                 // return address for hijacking.
6181                 if (!pES->m_IsInterruptible)
6182                 {
6183 #ifdef WIN64EXCEPTIONS
6184                     PREGDISPLAY pRDT = pCF->GetRegisterSet();
6185                     _ASSERTE(pRDT != NULL);
6186
6187                     // For simplicity, don't hijack in funclets
6188                     bool fIsFunclet = pCF->IsFunclet();
6189                     if (fIsFunclet)
6190                     {
6191                         notJittedCase = true;
6192                     }
6193                     else
6194                     {
6195                          // We already have the caller context available at this point
6196                         _ASSERTE(pRDT->IsCallerContextValid);
6197 #if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
6198
6199                         // Why do we use CallerContextPointers below?
6200                         //
6201                         // Assume the following callstack, growing from left->right:
6202                         // 
6203                         // C -> B -> A
6204                         // 
6205                         // Assuming A is non-interruptible function and pushes LR on stack, 
6206                         // when we get the stackwalk callback for A, the CallerContext would 
6207                         // contain non-volatile register state for B and CallerContextPtrs would 
6208                         // contain the location where the caller's (B's) non-volatiles where restored 
6209                         // from. This would be the stack location in A where they were pushed. Thus, 
6210                         // CallerContextPtrs->Lr would contain the stack location in A where LR (representing an address in B) 
6211                         // was pushed and thus, contains the return address in B.
6212
6213                         // Note that the JIT always pushes LR even for leaf methods to make hijacking
6214                         // work for them. See comment in code:Compiler::genPushCalleeSavedRegisters.
6215
6216                         if(pRDT->pCallerContextPointers->Lr == &pRDT->pContext->Lr)
6217                         {
6218                             // This is the case when we are either:
6219                             //
6220                             // 1) In a leaf method that does not push LR on stack, OR
6221                             // 2) In the prolog/epilog of a non-leaf method that has not yet pushed LR on stack
6222                             //    or has LR already popped off.
6223                             //
6224                             // The remaining case of non-leaf method is that of IP being in the body of the
6225                             // function. In such a case, LR would be have been pushed on the stack and thus,
6226                             // we wouldnt be here but in the "else" clause below.
6227                             //
6228                             // For (1) we can use CallerContext->ControlPC to be used as the return address
6229                             // since we know that leaf frames will return back to their caller.
6230                             // For this, we may need JIT support to do so.
6231                             notJittedCase = true;
6232                         }
6233                         else if (pCF->HasTailCalls())
6234                         {
6235                             // Do not hijack functions that have tail calls, since there are two problems:
6236                             // 1. When a function that tail calls another one is hijacked, the LR may be
6237                             //    stored at a different location in the stack frame of the tail call target.
6238                             //    So just by performing tail call, the hijacked location becomes invalid and
6239                             //    unhijacking would corrupt stack by writing to that location.
6240                             // 2. There is a small window after the caller pops LR from the stack in its
6241                             //    epilog and before the tail called function pushes LR in its prolog when
6242                             //    the hijacked return address would not be not on the stack and so we would
6243                             //    not be able to unhijack.
6244                             notJittedCase = true;
6245                         }
6246                         else
6247                         {
6248                             // This is the case of IP being inside the method body and LR is 
6249                             // pushed on the stack. We get it to determine the return address
6250                             // in the caller of the current non-interruptible frame.
6251                             pES->m_ppvRetAddrPtr = (void **) pRDT->pCallerContextPointers->Lr;
6252                         }
6253 #elif defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
6254                         pES->m_ppvRetAddrPtr = (void **) (EECodeManager::GetCallerSp(pRDT) - sizeof(void*));
6255 #else // _TARGET_X86_ || _TARGET_AMD64_
6256                         PORTABILITY_ASSERT("Platform NYI");
6257 #endif // _TARGET_???_
6258                     }
6259 #else // WIN64EXCEPTIONS
6260                     // peel off the next frame to expose the return address on the stack
6261                     pES->m_FirstPass = FALSE;
6262                     action = SWA_CONTINUE;
6263 #endif // !WIN64EXCEPTIONS
6264                 }
6265 #endif // HIJACK_NONINTERRUPTIBLE_THREADS
6266             }
6267             // else we are successfully out of here with SWA_ABORT
6268         }
6269         else
6270         {
6271 #ifdef _TARGET_X86_
6272             STRESS_LOG2(LF_SYNC, LL_INFO1000, "Not in Jitted code at EIP = %p, &EIP = %p\n", GetControlPC(pCF->GetRegisterSet()), pCF->GetRegisterSet()->PCTAddr);
6273 #else
6274             STRESS_LOG1(LF_SYNC, LL_INFO1000, "Not in Jitted code at pc = %p\n", GetControlPC(pCF->GetRegisterSet()));
6275 #endif
6276             notJittedCase = true;
6277         }
6278
6279         // Cases above may have set "notJITtedCase", which we handle as follows:
6280         if (notJittedCase)
6281         {
6282             pES->m_IsJIT = FALSE;
6283 #ifdef _DEBUG
6284             pES->m_pFD = (MethodDesc *)POISONC;
6285             pES->m_ppvRetAddrPtr = (void **)POISONC;
6286             pES->m_IsInterruptible = FALSE;
6287 #endif
6288         }
6289     }
6290     else
6291     {
6292 #if defined(_TARGET_X86_) && !defined(WIN64EXCEPTIONS)
6293         // Second pass, looking for the address of the return address so we can
6294         // hijack:
6295
6296         PREGDISPLAY     pRDT = pCF->GetRegisterSet();
6297
6298         if (pRDT != NULL)
6299         {
6300             // pPC points to the return address sitting on the stack, as our
6301             // current EIP for the penultimate stack frame.
6302             pES->m_ppvRetAddrPtr = (void **) pRDT->PCTAddr;
6303
6304             STRESS_LOG2(LF_SYNC, LL_INFO1000, "Partially Int case hijack address = 0x%x val = 0x%x\n", pES->m_ppvRetAddrPtr, *pES->m_ppvRetAddrPtr);
6305         }
6306 #else
6307         PORTABILITY_ASSERT("Platform NYI");
6308 #endif
6309     }
6310
6311     return action;
6312 }
6313
6314 HijackFrame::HijackFrame(LPVOID returnAddress, Thread *thread, HijackArgs *args)
6315            : m_ReturnAddress((TADDR)returnAddress),
6316              m_Thread(thread),
6317              m_Args(args)
6318 {
6319     CONTRACTL {
6320         NOTHROW;
6321         GC_NOTRIGGER;
6322     }
6323     CONTRACTL_END;
6324
6325     _ASSERTE(m_Thread == GetThread());
6326
6327     m_Next = m_Thread->GetFrame();
6328     m_Thread->SetFrame(this);
6329 }
6330
6331 void STDCALL OnHijackWorker(HijackArgs * pArgs)
6332 {
6333     CONTRACTL{
6334         THROWS;
6335         GC_TRIGGERS;
6336         SO_TOLERANT;
6337     }
6338     CONTRACTL_END;
6339
6340 #ifdef HIJACK_NONINTERRUPTIBLE_THREADS
6341     Thread         *thread = GetThread();
6342
6343 #ifdef FEATURE_STACK_PROBE
6344     if (GetEEPolicy()->GetActionOnFailure(FAIL_StackOverflow) == eRudeUnloadAppDomain)
6345     {
6346         // Make sure default domain does not see SO.
6347         // probe for our entry point amount and throw if not enough stack
6348         RetailStackProbe(ADJUST_PROBE(DEFAULT_ENTRY_PROBE_AMOUNT), thread);
6349     }
6350 #endif // FEATURE_STACK_PROBE
6351
6352     CONTRACT_VIOLATION(SOToleranceViolation);
6353
6354     thread->ResetThreadState(Thread::TS_Hijacked);
6355
6356     // Fix up our caller's stack, so it can resume from the hijack correctly
6357     pArgs->ReturnAddress = (size_t)thread->m_pvHJRetAddr;
6358
6359     // Build a frame so that stack crawling can proceed from here back to where
6360     // we will resume execution.
6361     FrameWithCookie<HijackFrame> frame((void *)pArgs->ReturnAddress, thread, pArgs);
6362
6363 #ifdef _DEBUG
6364     BOOL GCOnTransition = FALSE;
6365     if (g_pConfig->FastGCStressLevel()) {
6366         GCOnTransition = GC_ON_TRANSITIONS(FALSE);
6367     }
6368 #endif // _DEBUG
6369
6370 #ifdef TIME_SUSPEND
6371     g_SuspendStatistics.cntHijackTrap++;
6372 #endif // TIME_SUSPEND
6373
6374     CommonTripThread();
6375
6376 #ifdef _DEBUG
6377     if (g_pConfig->FastGCStressLevel()) {
6378         GC_ON_TRANSITIONS(GCOnTransition);
6379     }
6380 #endif // _DEBUG
6381
6382     frame.Pop();
6383 #else
6384     PORTABILITY_ASSERT("OnHijackWorker not implemented on this platform.");
6385 #endif // HIJACK_NONINTERRUPTIBLE_THREADS
6386 }
6387
6388 ReturnKind GetReturnKindFromMethodTable(Thread *pThread, EECodeInfo *codeInfo)
6389 {
6390 #ifdef _WIN64
6391     // For simplicity, we don't hijack in funclets, but if you ever change that, 
6392     // be sure to choose the OnHijack... callback type to match that of the FUNCLET
6393     // not the main method (it would probably be Scalar).
6394 #endif // _WIN64
6395
6396     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
6397     // Mark that we are performing a stackwalker like operation on the current thread.
6398     // This is necessary to allow the signature parsing functions to work without triggering any loads
6399     ClrFlsValueSwitch threadStackWalking(TlsIdx_StackWalkerWalkingThread, pThread);
6400
6401     MethodDesc *methodDesc = codeInfo->GetMethodDesc();
6402     _ASSERTE(methodDesc != nullptr);
6403
6404 #ifdef _TARGET_X86_
6405     MetaSig msig(methodDesc);
6406     if (msig.HasFPReturn())
6407     {
6408         // Figuring out whether the function returns FP or not is hard to do
6409         // on-the-fly, so we use a different callback helper on x86 where this
6410         // piece of information is needed in order to perform the right save &
6411         // restore of the return value around the call to OnHijackScalarWorker.
6412         return RT_Float;
6413     }
6414 #endif // _TARGET_X86_
6415
6416     MethodTable* pMT = NULL;
6417     MetaSig::RETURNTYPE type = methodDesc->ReturnsObject(INDEBUG_COMMA(false) &pMT);
6418     if (type == MetaSig::RETOBJ)
6419     {
6420         return RT_Object;
6421     }
6422
6423     if (type == MetaSig::RETBYREF)
6424     {
6425         return RT_ByRef;
6426     }
6427
6428 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
6429     // The Multi-reg return case using the classhandle is only implemented for AMD64 SystemV ABI.
6430     // On other platforms, multi-reg return is not supported with GcInfo v1.
6431     // So, the relevant information must be obtained from the GcInfo tables (which requires version2).
6432     if (type == MetaSig::RETVALUETYPE)
6433     {
6434         EEClass *eeClass = pMT->GetClass();
6435         ReturnKind regKinds[2] = { RT_Unset, RT_Unset };
6436         int orefCount = 0;
6437         for (int i = 0; i < 2; i++)
6438         {
6439             if (eeClass->GetEightByteClassification(i) == SystemVClassificationTypeIntegerReference)
6440             {
6441                 regKinds[i] = RT_Object;
6442             }
6443             else if (eeClass->GetEightByteClassification(i) == SystemVClassificationTypeIntegerByRef)
6444             {
6445                 regKinds[i] = RT_ByRef;
6446             }
6447             else
6448             {
6449                 regKinds[i] = RT_Scalar;
6450             }
6451         }
6452         ReturnKind structReturnKind = GetStructReturnKind(regKinds[0], regKinds[1]);
6453         return structReturnKind;
6454     }
6455 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
6456
6457     return RT_Scalar;
6458 }
6459
6460 ReturnKind GetReturnKind(Thread *pThread, EECodeInfo *codeInfo)
6461 {
6462     GCInfoToken gcInfoToken = codeInfo->GetGCInfoToken();
6463     ReturnKind returnKind = codeInfo->GetCodeManager()->GetReturnKind(gcInfoToken);
6464
6465     if (!IsValidReturnKind(returnKind))
6466     {
6467         returnKind = GetReturnKindFromMethodTable(pThread, codeInfo);
6468     }
6469     else
6470     {
6471 #if !defined(FEATURE_MULTIREG_RETURN) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
6472          // For ARM64 struct-return, GetReturnKindFromMethodTable() is not supported
6473         _ASSERTE(returnKind == GetReturnKindFromMethodTable(pThread, codeInfo));
6474 #endif // !FEATURE_MULTIREG_RETURN || FEATURE_UNIX_AMD64_STRUCT_PASSING
6475     }
6476
6477     _ASSERTE(IsValidReturnKind(returnKind));
6478     return returnKind;
6479 }
6480
6481 VOID * GetHijackAddr(Thread *pThread, EECodeInfo *codeInfo)
6482 {
6483     ReturnKind returnKind = GetReturnKind(pThread, codeInfo);
6484     pThread->SetHijackReturnKind(returnKind);
6485
6486 #ifdef _TARGET_X86_
6487     if (returnKind == RT_Float)
6488     {
6489         return reinterpret_cast<VOID *>(OnHijackFPTripThread);
6490     }
6491 #endif // _TARGET_X86_
6492
6493     return reinterpret_cast<VOID *>(OnHijackTripThread);
6494 }
6495
6496 #ifndef PLATFORM_UNIX
6497
6498 // Get the ExecutionState for the specified SwitchIn thread.  Note that this is
6499 // a 'StackWalk' call back (PSTACKWALKFRAMESCALLBACK).
6500 StackWalkAction SWCB_GetExecutionStateForSwitchIn(CrawlFrame *pCF, VOID *pData)
6501 {
6502     CONTRACTL {
6503         NOTHROW;
6504         GC_NOTRIGGER;
6505     }
6506     CONTRACTL_END;
6507
6508     ExecutionState  *pES = (ExecutionState *) pData;
6509     StackWalkAction  action = SWA_CONTINUE;
6510
6511     if (pES->m_FirstPass) {
6512         if (pCF->IsFrameless()) {
6513 #ifdef _TARGET_X86_
6514             pES->m_FirstPass = FALSE;
6515 #else
6516             _ASSERTE(!"Platform NYI");
6517 #endif
6518
6519             pES->m_IsJIT = TRUE;
6520             pES->m_pFD = pCF->GetFunction();
6521             pES->m_MethodToken = pCF->GetMethodToken();
6522             // We do not care if the code is interruptible
6523             pES->m_IsInterruptible = FALSE;
6524             pES->m_RelOffset = pCF->GetRelOffset();
6525             pES->m_pJitManager = pCF->GetJitManager();
6526         }
6527     }
6528     else {
6529 #ifdef _TARGET_X86_
6530         if (pCF->IsFrameless()) {
6531             PREGDISPLAY     pRDT = pCF->GetRegisterSet();
6532             if (pRDT) {
6533                 // pPC points to the return address sitting on the stack, as our
6534                 // current EIP for the penultimate stack frame.
6535                 pES->m_ppvRetAddrPtr = (void **) pRDT->PCTAddr;
6536                 action = SWA_ABORT;
6537             }
6538         }
6539 #else
6540         _ASSERTE(!"Platform NYI");
6541 #endif
6542     }
6543     return action;
6544 }
6545
6546 //
6547 // The function below, ThreadCaughtInKernelModeExceptionHandling, exists to detect and work around a very subtle
6548 // race that we have when we suspend a thread while that thread is in the kernel handling an exception.
6549 //
6550 // When a user-mode thread takes an exception, the OS must get involved to handle that exception before user-mode
6551 // exception handling takes place. The exception causes the thread to enter kernel-mode. To handle the exception,
6552 // the kernel does the following: 1) pushes a CONTEXT, then an EXCEPTION_RECORD, and finally an EXCEPTION_POINTERS
6553 // struct onto the thread's user-mode stack. 2) the Esp value in the thread's user-mode context is updated to
6554 // reflect the fact that these structures have just been pushed. 3) some segment registers in the user-mode context
6555 // are modified. 4) the Eip value in the user-mode context is changed to point to the user-mode exception dispatch
6556 // routine. 5) the kernel resumes user-mode execution with the altered context.
6557 //
6558 // Note that during this entire process: 1) the thread can be suspeded by another user-mode thread, and 2)
6559 // Get/SetThreadContext all operate on the user-mode context.
6560 //
6561 // There are two important races to consider here: a race with attempting to hijack the thread in HandledJITCase,
6562 // and a race attempting to trace the thread's stack in HandledJITCase.
6563 //
6564 //
6565 // Race #1: failure to hijack a thread in HandledJITCase.
6566 //
6567 // In HandledJITCase, if we see that a thread's Eip is in managed code at an interruptable point, we will attempt
6568 // to move the thread to a hijack in order to stop it's execution for a variety of reasons (GC, debugger, user-mode
6569 // supension, etc.) We do this by suspending the thread, inspecting Eip, changing Eip to the address of the hijack
6570 // routine, and resuming the thread.
6571 //
6572 // The problem here is that in step #4 above, the kernel is going to change Eip in the thread's context to point to
6573 // the user-mode exception dispatch routine. If we suspend a thread when it has taken an exception in managed code,
6574 // we may see Eip pointing to managed code and attempt to hijack the thread. When we resume the thread, step #4
6575 // will eventually execute and the thread will go to the user-mode exception dispatch routine instead of to our
6576 // hijack.
6577 //
6578 // We tollerate this by recgonizing that this has happened when we arrive in our exception handler
6579 // (COMPlusFrameHandler), and we fix up the IP in the context passed to the handler.
6580 //
6581 //
6582 // Race #2: inability to trace a managed call stack
6583 //
6584 // If we suspend a thread after step #2 above, but before step #4, then we will see an Eip pointing to managed
6585 // code, but an Esp that points to the newly pushed exception structures. If we are in a managed function that does
6586 // not have an Ebp frame, the return address will be relative to Esp and we will not be able to resolve the return
6587 // address properly. Since we will attempt to place a return address hijack (as part of our heroic efforts to trap
6588 // the thread quickly), we may end up writing over random memory with our hijack. This is obviously extremely
6589 // bad. Realistically, any attempt to trace a thread's stack in this case is suspect, even if the mangaed function
6590 // has a EBP frame.
6591 //
6592 // The solution is to attempt to detect this race and abandon the hijack attempt. We have developed the following
6593 // heuristic to detect this case. Basically, we look to see if Esp points to an EXCEPTION_POINTERS structure, and
6594 // that this structure points to valid EXCEPTION_RECORD and CONTEXT structures. They must be ordered on the stack,
6595 // and the faulting address in the EXCEPTION_RECORD should be the thread's current Eip, and the Eip in the CONTEXT
6596 // should be the thread's current Eip.
6597 //
6598 // This is the heuristic codified. Given Eip and Esp from the thread's current context:
6599 //
6600 // 1. if Eip points to a managed function, and...
6601 // 2. the pointer at Esp is equal to Esp + sizeof(EXCEPTION_POINTERS), and...
6602 // 3. the faulting address in the EXCEPTION_RECORD at that location is equal to the current Eip, and...
6603 // 4. the NumberParameters field in the EXCEPTION_RECORD is valid (between 0 and EXCEPTION_MAXIMUM_PARAMETERS), and...
6604 // 5. the pointer at Esp + 4 is equal to Esp + sizeof(EXCEPTION_POINTERS) + the dynamic size of the EXCEPTION_RECORD, and...
6605 // 6. the Eip value of the CONTEXT at that location is equal to the current Eip, then we have recgonized the race.
6606 //
6607 // The validation of Eip in both places, combined with ensuring that the pointer values are on the thread's stack
6608 // make this a safe heuristic to evaluate. Even if one could end up in a function with the stack looking exactly
6609 // like this, and even if we are trying to suspend such a thread and we catch it at the Eip that matches the values
6610 // at the proper places on the stack, then the worst that will happen is we won't attempt to hijack the thread at
6611 // that point. We'll resume it and try again later. There will be at least one other instruction in the function
6612 // that is not at the Eip value on the stack, and we'll be able to trace the thread's stack from that instruction
6613 // and place the return address hijack.
6614 //
6615 // As races go, race #1 above is very, very easy to hit. We hit it in the wild before we shipped V1, and a simple
6616 // test program with one thread constantly AV'ing and another thread attempting to suspend the first thread every
6617 // half second hit's the race almost instantly.
6618 //
6619 // Race #2 is extremely rare in comparison. The same program properly instrumented only hits the race about 5 times
6620 // every 2000 attempts or so. We did not hit this even in very stressful exception tests and
6621 // it's never been seen in the wild.
6622 //
6623 // Note: a new feature has been added in recent OS's that allows us to detect both of these races with a simple
6624 // call to GetThreadContext. This feature exists on all Win64 platforms, so this change is only for 32-bit
6625 // platforms. We've asked for this fix to be applied to future 32-bit OS's, so we can remove this on those
6626 // platforms when that happens. Furthermore, once we stop supporting the older 32-bit OS versions that don't have
6627 // the new feature, we can remove these alltogether.
6628 //
6629 // WARNING: Interrupts (int 3) immediately increment the IP whereas traps (AVs) do not.
6630 // So this heuristic only works for trap, but not for interrupts. As a result, the race
6631 // is still a problem for interrupts. This means that the race can cause a process crash
6632 // if the managed debugger puts an "int 3" in order to do a stepping operation,
6633 // and GC or a sampling profiler tries to suspend the thread. This can be handled
6634 // by modifying the code below to additionally check if the instruction just before
6635 // the IP is an "int 3".
6636 //
6637
6638 #ifdef _TARGET_X86_
6639
6640 #ifndef FEATURE_PAL
6641 #define WORKAROUND_RACES_WITH_KERNEL_MODE_EXCEPTION_HANDLING
6642 #endif // !FEATURE_PAL
6643
6644 #ifdef WORKAROUND_RACES_WITH_KERNEL_MODE_EXCEPTION_HANDLING
6645 BOOL ThreadCaughtInKernelModeExceptionHandling(Thread *pThread, CONTEXT *ctx)
6646 {
6647     CONTRACTL
6648     {
6649         NOTHROW;
6650         GC_NOTRIGGER;
6651         MODE_ANY;
6652         PRECONDITION(pThread != NULL);
6653         PRECONDITION(ctx != NULL);
6654     }
6655     CONTRACTL_END;
6656
6657     // Validate that Esp plus all of our maximum structure sizes is on the thread's stack. We use the cached bounds
6658     // on the Thread object. If we're that close to the top of the thread's stack, then we can't possibly have hit
6659     // the race. If we pass this test, we can assume all memory accesses below are legal, since they're all on the
6660     // thread's stack.
6661     if ((ctx->Esp + sizeof(EXCEPTION_POINTERS) + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)) >=
6662         (UINT_PTR)pThread->GetCachedStackBase())
6663     {
6664         return FALSE;
6665     }
6666
6667     // The calculations below assume that a DWORD is the same size as a pointer. Since this is only needed on
6668     // 32-bit platforms, this should be fine.
6669     _ASSERTE(sizeof(DWORD) == sizeof(void*));
6670
6671     // There are cases where the ESP is just decremented but the page is not touched, thus the page is not commited or
6672     // still has page guard bit set. We can't hit the race in such case so we just leave. Besides, we can't access the
6673     // memory with page guard flag or not committed.
6674     MEMORY_BASIC_INFORMATION mbi;
6675 #undef VirtualQuery
6676     // This code can run below YieldTask, which means that it must not call back into the host.
6677     // The reason is that YieldTask is invoked by the host, and the host needs not be reentrant.
6678     if (VirtualQuery((LPCVOID)(UINT_PTR)ctx->Esp, &mbi, sizeof(mbi)) == sizeof(mbi))
6679     {
6680         if (!(mbi.State & MEM_COMMIT) || (mbi.Protect & PAGE_GUARD))
6681             return FALSE;
6682     }
6683     else
6684         STRESS_LOG0 (LF_SYNC, ERROR, "VirtualQuery failed!");
6685 #define VirtualQuery(lpAddress, lpBuffer, dwLength) Dont_Use_VirtualQuery(lpAddress, lpBuffer, dwLength)
6686
6687     // The first two values on the stack should be a pointer to the EXCEPTION_RECORD and a pointer to the CONTEXT.
6688     UINT_PTR Esp = (UINT_PTR)ctx->Esp;
6689     UINT_PTR ER = *((UINT_PTR*)Esp);
6690     UINT_PTR CTX = *((UINT_PTR*)(Esp + sizeof(EXCEPTION_RECORD*)));
6691
6692     // The EXCEPTION_RECORD should be at Esp + sizeof(EXCEPTION_POINTERS)... if it's not, then we haven't hit the race.
6693     if (ER != (Esp + sizeof(EXCEPTION_POINTERS)))
6694     {
6695         return FALSE;
6696     }
6697
6698     // Assume we have an EXCEPTION_RECORD at Esp + sizeof(EXCEPTION_POINTERS) and look at values within that.
6699     EXCEPTION_RECORD *pER = (EXCEPTION_RECORD*)ER;
6700
6701     // Make sure the faulting address in the EXCEPTION_RECORD matches the thread's current Eip.
6702     if ((UINT_PTR)pER->ExceptionAddress != ctx->Eip)
6703     {
6704         return FALSE;
6705     }
6706
6707     // Validate the number of exception parameters.
6708     if ((pER->NumberParameters > EXCEPTION_MAXIMUM_PARAMETERS))
6709     {
6710         return FALSE;
6711     }
6712
6713     // We have a plausable number of exception parameters, so compute the exact size of this exception
6714     // record. Remember, an EXCEPTION_RECORD has a variable sized array of optional information at the end called
6715     // the ExceptionInformation. It's an array of pointers up to EXCEPTION_MAXIMUM_PARAMETERS in length.
6716     DWORD exceptionRecordSize = sizeof(EXCEPTION_RECORD) -
6717         ((EXCEPTION_MAXIMUM_PARAMETERS - pER->NumberParameters) * sizeof(pER->ExceptionInformation[0]));
6718
6719     // On Vista WOW on X64, the OS pushes the maximum number of parameters onto the stack.
6720     DWORD exceptionRecordMaxSize = sizeof(EXCEPTION_RECORD);
6721
6722     // The CONTEXT pointer should be pointing right after the EXCEPTION_RECORD.
6723     if ((CTX != (ER + exceptionRecordSize)) &&
6724         (CTX != (ER + exceptionRecordMaxSize)))
6725     {
6726         return FALSE;
6727     }
6728
6729     // Assume we have a CONTEXT at Esp + 8 + exceptionRecordSize and look at values within that.
6730     CONTEXT *pCTX = (CONTEXT*)CTX;
6731
6732     // Make sure the Eip in the CONTEXT on the stack matches the current Eip value.
6733     if (pCTX->Eip != ctx->Eip)
6734     {
6735         return FALSE;
6736     }
6737
6738     // If all the tests above fail, then it means that we've hit race #2 described in the text before this function.
6739     STRESS_LOG3(LF_SYNC, LL_INFO100,
6740                 "ThreadCaughtInKernelModeExceptionHandling returning TRUE. Eip=%p, Esp=%p, ExceptionCode=%p\n",
6741                 ctx->Eip, ctx->Esp, pER->ExceptionCode);
6742
6743     return TRUE;
6744 }
6745 #endif //WORKAROUND_RACES_WITH_KERNEL_MODE_EXCEPTION_HANDLING
6746 #endif //_TARGET_X86_
6747
6748 //---------------------------------------------------------------------------------------
6749 //
6750 // Helper used by HandledJITCase and others (like the profiling API) who need an
6751 // absolutely reliable register context.
6752 //
6753 // Arguments:
6754 //     * dwOptions - [in] Combination of flags from enum
6755 //         GetSafelyRedirectableThreadContextOptions to customize the checks performed by
6756 //         this function.
6757 //     * pCtx - [out] This Thread's current context. Callers may rely on this only if nonzero
6758 //         is returned
6759 //     * pRD - [out] Matching REGDISPLAY filled from the pCtx found by this function.
6760 //         Callers may rely on this only if nonzero is returned
6761 //
6762 // Return Value:
6763 //      Nonzero iff all requested checks have succeeded, which would imply that it is
6764 //      a reliable time to use this Thread's context.
6765 //      
6766 BOOL Thread::GetSafelyRedirectableThreadContext(DWORD dwOptions, CONTEXT * pCtx, REGDISPLAY * pRD)
6767 {
6768     CONTRACTL {
6769         NOTHROW;
6770         GC_NOTRIGGER;
6771     }
6772     CONTRACTL_END;
6773
6774     _ASSERTE(pCtx != NULL);
6775     _ASSERTE(pRD != NULL);
6776
6777     // We are never in interruptible code if there if a filter context put in place by the debugger.
6778     if (GetFilterContext() != NULL)
6779         return FALSE;
6780
6781 #ifdef DEBUGGING_SUPPORTED
6782     if ((dwOptions & kCheckDebuggerBreakpoints) != 0)
6783     {
6784         // If we are running under the control of a managed debugger that may have placed breakpoints in the code stream,
6785         // then there is a special case that we need to check. See the comments in debugger.cpp for more information.
6786         if (CORDebuggerAttached() && (g_pDebugInterface->IsThreadContextInvalid(this)))
6787             return FALSE;
6788     }
6789 #endif // DEBUGGING_SUPPORTED
6790
6791     // Make sure we specify CONTEXT_EXCEPTION_REQUEST to detect "trap frame reporting".
6792     _ASSERTE(GetFilterContext() == NULL);
6793
6794     ZeroMemory(pCtx, sizeof(*pCtx));
6795     pCtx->ContextFlags = CONTEXT_FULL | CONTEXT_EXCEPTION_REQUEST;
6796     if (!EEGetThreadContext(this, pCtx))
6797     {
6798         return FALSE;
6799     }
6800
6801     //
6802     // workaround around WOW64 problems.  Only do this workaround if a) this is x86, and b) the OS does not support trap frame reporting,
6803     // If the OS *does* support trap frame reporting, then the call to IsContextSafeToRedirect below will return FALSE if we run
6804     // into this race.
6805     //
6806 #ifdef _TARGET_X86_
6807     if (!(pCtx->ContextFlags & CONTEXT_EXCEPTION_REPORTING) && 
6808         ((dwOptions & kPerfomLastRedirectIPCheck) != 0))
6809     {
6810         // This code fixes a race between GetThreadContext and NtContinue.  If we redirect managed code
6811         // at the same place twice in a row, we run the risk of reading a bogus CONTEXT when we redirect
6812         // the second time.  This leads to access violations on x86 machines.  To fix the problem, we
6813         // never redirect at the same instruction pointer that we redirected at on the previous GC.
6814         if (GetIP(pCtx) == m_LastRedirectIP)
6815         {
6816             // We need to test for an infinite loop in assembly, as this will break the heuristic we
6817             // are using.
6818             const BYTE short_jmp = 0xeb;    // Machine code for a short jump.
6819             const BYTE self = 0xfe;         // -2.  Short jumps are calculated as [ip]+2+[second_byte].
6820
6821             // If we find that we are in an infinite loop, we'll set the last redirected IP to 0 so that we will
6822             // redirect the next time we attempt it.  Delaying one interation allows us to narrow the window of
6823             // the race we are working around in this corner case.
6824             BYTE *ip = (BYTE *)m_LastRedirectIP;
6825             if (ip[0] == short_jmp && ip[1] == self)
6826                 m_LastRedirectIP = 0;
6827
6828             // We set a hard limit of 5 times we will spin on this to avoid any tricky race which we have not
6829             // accounted for.
6830             m_SpinCount++;
6831             if (m_SpinCount >= 5)
6832                 m_LastRedirectIP = 0;
6833                 
6834             STRESS_LOG0(LF_GC, LL_INFO10000, "GetSafelyRedirectableThreadContext() - Cannot redirect at the same IP as the last redirection.\n");
6835             return FALSE;
6836         }
6837     }
6838 #endif
6839
6840     if (!IsContextSafeToRedirect(pCtx))
6841     {
6842         STRESS_LOG0(LF_GC, LL_INFO10000, "GetSafelyRedirectableThreadContext() - trap frame reporting an invalid CONTEXT\n");
6843         return FALSE;
6844     }
6845
6846     ZeroMemory(pRD, sizeof(*pRD));
6847     if (!InitRegDisplay(pRD, pCtx, true))
6848         return FALSE;
6849
6850     return TRUE;
6851 }
6852
6853 // Called while the thread is suspended.  If we aren't in JITted code, this isn't
6854 // a JITCase and we return FALSE.  If it is a JIT case and we are in interruptible
6855 // code, then we are handled.  Our caller has found a good spot and can keep us
6856 // suspended.  If we aren't in interruptible code, then we aren't handled.  So we
6857 // pick a spot to hijack the return address and our caller will wait to get us
6858 // somewhere safe.
6859 BOOL Thread::HandledJITCase(BOOL ForTaskSwitchIn)
6860 {
6861     CONTRACTL {
6862         NOTHROW;
6863         GC_NOTRIGGER;
6864     }
6865     CONTRACTL_END;
6866
6867     BOOL            ret = FALSE;
6868     ExecutionState  esb;
6869     StackWalkAction action;
6870
6871     CONTEXT ctx;
6872     REGDISPLAY rd;
6873     if (!GetSafelyRedirectableThreadContext(
6874         kPerfomLastRedirectIPCheck | kCheckDebuggerBreakpoints,
6875         &ctx,
6876         &rd))
6877     {
6878         STRESS_LOG0(LF_GC, LL_INFO10000, "HandledJITCase() - GetSafelyRedirectableThreadContext() returned FALSE\n");
6879         return FALSE;
6880     }
6881
6882     PCODE ip = GetIP(&ctx);
6883     if (!ExecutionManager::IsManagedCode(ip))
6884     {
6885         return FALSE;
6886     }
6887
6888 #ifdef WORKAROUND_RACES_WITH_KERNEL_MODE_EXCEPTION_HANDLING
6889     if (ThreadCaughtInKernelModeExceptionHandling(this, &ctx))
6890     {
6891         return FALSE;
6892     }
6893 #endif //WORKAROUND_RACES_WITH_KERNEL_MODE_EXCEPTION_HANDLING
6894     
6895 #ifdef _DEBUG
6896     // We know IP is in managed code, mark current thread as safe for calls into host
6897     Thread * pCurThread = GetThread();
6898     if (pCurThread != NULL)
6899     {
6900         pCurThread->dbg_m_cSuspendedThreadsWithoutOSLock ++;
6901         _ASSERTE(pCurThread->dbg_m_cSuspendedThreadsWithoutOSLock <= pCurThread->dbg_m_cSuspendedThreads);
6902     }
6903 #endif //_DEBUG
6904     
6905     // Walk one or two frames of the stack...
6906     if (ForTaskSwitchIn) {
6907         action = StackWalkFramesEx(&rd,SWCB_GetExecutionStateForSwitchIn, &esb, QUICKUNWIND | DISABLE_MISSING_FRAME_DETECTION | THREAD_IS_SUSPENDED | ALLOW_ASYNC_STACK_WALK, NULL);
6908     }
6909     else {
6910 #ifdef TIME_SUSPEND
6911         DWORD startCrawl = g_SuspendStatistics.GetTime();
6912 #endif
6913         action = StackWalkFramesEx(&rd,SWCB_GetExecutionState, &esb,
6914                                    QUICKUNWIND | DISABLE_MISSING_FRAME_DETECTION |
6915                                    THREAD_IS_SUSPENDED | ALLOW_ASYNC_STACK_WALK, NULL);
6916
6917 #ifdef TIME_SUSPEND
6918         g_SuspendStatistics.crawl.Accumulate(
6919                 SuspendStatistics::GetElapsed(startCrawl,
6920                                               g_SuspendStatistics.GetTime()));
6921
6922         g_SuspendStatistics.cntHijackCrawl++;
6923 #endif
6924     }
6925
6926     //
6927     // action should either be SWA_ABORT, in which case we properly walked
6928     // the stack frame and found out whether this is a JIT case, or
6929     // SWA_FAILED, in which case the walk couldn't even be started because
6930     // there are no stack frames, which also isn't a JIT case.
6931     //
6932     if (action == SWA_ABORT && esb.m_IsJIT)
6933     {
6934         // If we are interruptible and we are in cooperative mode, our caller can
6935         // just leave us suspended.
6936         if (esb.m_IsInterruptible && m_fPreemptiveGCDisabled)
6937         {
6938             _ASSERTE(!ThreadStore::HoldingThreadStore(this));
6939             ret = TRUE;
6940         }
6941         else
6942         if (esb.m_ppvRetAddrPtr)
6943         {
6944             // we need to hijack the return address.  Base this on whether or not
6945             // the method returns an object reference, so we know whether to protect
6946             // it or not.
6947             EECodeInfo codeInfo(ip);
6948             VOID *pvHijackAddr = GetHijackAddr(this, &codeInfo);
6949
6950 #ifdef FEATURE_ENABLE_GCPOLL
6951             // On platforms that support both hijacking and GC polling
6952             // decide whether to hijack based on a configuration value.  
6953             // COMPlus_GCPollType = 1 is the setting that enables hijacking
6954             // in GCPOLL enabled builds.
6955             EEConfig::GCPollType pollType = g_pConfig->GetGCPollType();
6956             if (EEConfig::GCPOLL_TYPE_HIJACK == pollType || EEConfig::GCPOLL_TYPE_DEFAULT == pollType)
6957 #endif // FEATURE_ENABLE_GCPOLL
6958             {
6959                 HijackThread(pvHijackAddr, &esb);
6960             }
6961         }
6962     }
6963     // else it's not even a JIT case
6964
6965 #ifdef _DEBUG
6966     // Restore back the number of threads without OS lock
6967     if (pCurThread != NULL)
6968     {
6969         pCurThread->dbg_m_cSuspendedThreadsWithoutOSLock--;
6970     }
6971 #endif //_DEBUG
6972
6973     STRESS_LOG1(LF_SYNC, LL_INFO10000, "    HandledJitCase returning %d\n", ret);
6974     return ret;
6975 }
6976
6977 #endif // !PLATFORM_UNIX
6978
6979 #endif // FEATURE_HIJACK
6980
6981 // Some simple helpers to keep track of the threads we are waiting for
6982 void Thread::MarkForSuspension(ULONG bit)
6983 {
6984     CONTRACTL {
6985         NOTHROW;
6986         GC_NOTRIGGER;
6987     }
6988     CONTRACTL_END;
6989
6990     // CoreCLR does not support user-requested thread suspension
6991     _ASSERTE(bit == TS_DebugSuspendPending ||
6992              bit == (TS_DebugSuspendPending | TS_DebugWillSync));
6993
6994     _ASSERTE(IsAtProcessExit() || ThreadStore::HoldingThreadStore());
6995
6996     _ASSERTE((m_State & bit) == 0);
6997
6998     FastInterlockOr((ULONG *) &m_State, bit);
6999     ThreadStore::TrapReturningThreads(TRUE);
7000 }
7001
7002 void Thread::UnmarkForSuspension(ULONG mask)
7003 {
7004     CONTRACTL {
7005         NOTHROW;
7006         GC_NOTRIGGER;
7007     }
7008     CONTRACTL_END;
7009
7010     // CoreCLR does not support user-requested thread suspension
7011     _ASSERTE(mask == ~TS_DebugSuspendPending);
7012
7013     _ASSERTE(IsAtProcessExit() || ThreadStore::HoldingThreadStore());
7014
7015     _ASSERTE((m_State & ~mask) != 0);
7016
7017     // we decrement the global first to be able to satisfy the assert from DbgFindThread
7018     ThreadStore::TrapReturningThreads(FALSE);
7019     FastInterlockAnd((ULONG *) &m_State, mask);
7020 }
7021
7022 //----------------------------------------------------------------------------
7023
7024 void ThreadSuspend::RestartEE(BOOL bFinishedGC, BOOL SuspendSucceded)
7025 {
7026 #ifdef TIME_SUSPEND
7027     g_SuspendStatistics.StartRestart();
7028 #endif //TIME_SUSPEND
7029
7030     FireEtwGCRestartEEBegin_V1(GetClrInstanceId());
7031
7032     //
7033     // SyncClean holds a list of things to be cleaned up when it's possible.
7034     // SyncClean uses the GC mode to synchronize access to this list.  Threads must be
7035     // in COOP mode to add things to the list, and the list can only be cleaned up
7036     // while no threads are adding things.
7037     // Since we know that no threads are in COOP mode at this point (because the EE is
7038     // suspended), we clean up the list here.
7039     //
7040     SyncClean::CleanUp();
7041
7042 #ifdef PROFILING_SUPPORTED
7043     // If a profiler is keeping track suspend events, notify it.  This notification
7044     // must happen before we set TrapReturning threads to FALSE because as soon as
7045     // we remove the return trap threads can start "running" managed code again as
7046     // they return from unmanaged.  (Whidbey Bug #7505)
7047     // Also must notify before setting GcInProgress = FALSE.
7048     //
7049     // It's very odd that we do this here, in ThreadSuspend::RestartEE, while the 
7050     // corresponding call to RuntimeSuspendStarted is done at a lower architectural layer,
7051     // in ThreadSuspend::SuspendRuntime.
7052     {
7053         BEGIN_PIN_PROFILER(CORProfilerTrackSuspends());
7054         g_profControlBlock.pProfInterface->RuntimeResumeStarted();
7055         END_PIN_PROFILER();
7056     }
7057 #endif // PROFILING_SUPPORTED
7058
7059     //
7060     // Unhijack all threads, and reset their "suspend pending" flags.  Why isn't this in
7061     // Thread::ResumeRuntime?
7062     //
7063     Thread  *thread = NULL;
7064     while ((thread = ThreadStore::GetThreadList(thread)) != NULL)
7065     {
7066         thread->PrepareForEERestart(SuspendSucceded);
7067     }
7068
7069     //
7070     // Revert to being a normal thread
7071     // 
7072     ClrFlsClearThreadType (ThreadType_DynamicSuspendEE);
7073     GCHeapUtilities::GetGCHeap()->SetGCInProgress(false);
7074
7075     //
7076     // Allow threads to enter COOP mode (though we still need to wake the ones
7077     // that we hijacked).
7078     //
7079     // Note: this is the last barrier that keeps managed threads
7080     // from entering cooperative mode. If the sequence changes,
7081     // you may have to change routine GCHeapUtilities::SafeToRestartManagedThreads
7082     // as well.
7083     //
7084     ThreadStore::TrapReturningThreads(FALSE);
7085     g_pSuspensionThread    = 0;
7086
7087     // 
7088     // Any threads that are waiting in WaitUntilGCComplete will continue now.
7089     //
7090     GCHeapUtilities::GetGCHeap()->SetWaitForGCEvent();
7091     _ASSERTE(IsGCSpecialThread() || ThreadStore::HoldingThreadStore());
7092
7093     ResumeRuntime(bFinishedGC, SuspendSucceded);
7094
7095     FireEtwGCRestartEEEnd_V1(GetClrInstanceId());
7096
7097 #ifdef TIME_SUSPEND
7098     g_SuspendStatistics.EndRestart();
7099 #endif //TIME_SUSPEND
7100 }
7101
7102 // The contract between GC and the EE, for starting and finishing a GC is as follows:
7103 //
7104 //  SuspendEE:
7105 //      LockThreadStore
7106 //      SetGCInProgress
7107 //      SuspendRuntime
7108 //
7109 //      ... perform the GC ...
7110 //
7111 // RestartEE:
7112 //      SetGCDone
7113 //      ResumeRuntime
7114 //         calls UnlockThreadStore
7115 //
7116 // Note that this is intentionally *not* symmetrical.  The EE will assert that the
7117 // GC does most of this stuff in the correct sequence.
7118
7119 //
7120 // This is the only way to call ThreadSuspend::SuspendRuntime, and that method is
7121 // so tightly coupled to this one, with intermingled responsibilities, that we don't
7122 // understand why we have a separation at all.  At some point we should refactor all of
7123 // the suspension code into a separate abstraction, which we would like to call the 
7124 // "managed execution lock."  The current "layering" of this stuff has it mixed
7125 // randomly into the Thread and GC code, and split into almost completely arbitrary
7126 // layers.
7127 //
7128 void ThreadSuspend::SuspendEE(SUSPEND_REASON reason)
7129 {
7130 #ifdef TIME_SUSPEND
7131     g_SuspendStatistics.StartSuspend();
7132 #endif //TIME_SUSPEND
7133
7134     BOOL gcOnTransitions;
7135
7136     ETW::GCLog::ETW_GC_INFO Info;
7137     Info.SuspendEE.Reason = reason;
7138     Info.SuspendEE.GcCount = (((reason == SUSPEND_FOR_GC) || (reason == SUSPEND_FOR_GC_PREP)) ? 
7139                               (ULONG)GCHeapUtilities::GetGCHeap()->GetGcCount() : (ULONG)-1);
7140
7141     FireEtwGCSuspendEEBegin_V1(Info.SuspendEE.Reason, Info.SuspendEE.GcCount, GetClrInstanceId());
7142
7143     LOG((LF_SYNC, INFO3, "Suspending the runtime for reason %d\n", reason));
7144
7145     gcOnTransitions = GC_ON_TRANSITIONS(FALSE);        // dont do GC for GCStress 3
7146
7147     Thread* pCurThread = GetThread();
7148
7149     DWORD dwSwitchCount = 0;
7150
7151     // Note: we need to make sure to re-set m_pThreadAttemptingSuspendForGC when we retry
7152     // due to the debugger case below!
7153 retry_for_debugger:
7154
7155     //
7156     // Set variable to indicate that this thread is preforming a true GC
7157     // This gives this thread priority over other threads that are trying to acquire the ThreadStore Lock
7158     // for other reasons.
7159     //
7160     if (reason == ThreadSuspend::SUSPEND_FOR_GC || reason == ThreadSuspend::SUSPEND_FOR_GC_PREP)
7161     {
7162         m_pThreadAttemptingSuspendForGC = pCurThread;
7163
7164         //
7165         // also unblock any thread waiting around for this thread to suspend. This prevents us from completely
7166         // starving other suspension clients, such as the debugger, which we otherwise would do because of
7167         // the priority we just established.
7168         //
7169         g_pGCSuspendEvent->Set();
7170     }
7171
7172 #ifdef TIME_SUSPEND
7173     DWORD startAcquire = g_SuspendStatistics.GetTime();
7174 #endif
7175
7176     //
7177     // Acquire the TSL.  We will hold this until the we restart the EE.
7178     //
7179     ThreadSuspend::LockThreadStore(reason);
7180
7181 #ifdef TIME_SUSPEND
7182     g_SuspendStatistics.acquireTSL.Accumulate(SuspendStatistics::GetElapsed(startAcquire,
7183                                                                             g_SuspendStatistics.GetTime()));
7184 #endif
7185
7186     //
7187     // If we've blocked other threads that are waiting for the ThreadStore lock, unblock them now
7188     // (since we already got it).  This allows them to get the TSL after we release it.
7189     //
7190     if ( s_hAbortEvtCache != NULL &&
7191         (reason == ThreadSuspend::SUSPEND_FOR_GC || reason == ThreadSuspend::SUSPEND_FOR_GC_PREP))
7192     {
7193         LOG((LF_SYNC, INFO3, "GC thread is backing out the suspend abort event.\n"));
7194         s_hAbortEvt = NULL;
7195
7196         LOG((LF_SYNC, INFO3, "GC thread is signalling the suspend abort event.\n"));
7197         s_hAbortEvtCache->Set();
7198     }
7199
7200     //
7201     // Also null-out m_pThreadAttemptingSuspendForGC since it should only matter if s_hAbortEvt is 
7202     // in play.
7203     //
7204     if (reason == ThreadSuspend::SUSPEND_FOR_GC || reason == ThreadSuspend::SUSPEND_FOR_GC_PREP)
7205     {
7206         m_pThreadAttemptingSuspendForGC = NULL;
7207     }
7208
7209     {
7210         //
7211         // Now we're going to acquire an exclusive lock on managed code execution (including
7212         // "maunally managed" code in GCX_COOP regions).
7213         //
7214         // First, we reset the event that we're about to tell other threads to wait for.
7215         //
7216         GCHeapUtilities::GetGCHeap()->ResetWaitForGCEvent();
7217
7218         //
7219         // Remember that we're the one doing the GC.  Actually, maybe we're not doing a GC -
7220         // what this really indicates is that we are trying to acquire the "managed execution lock."
7221         //
7222         {
7223             g_pSuspensionThread = pCurThread;
7224
7225             //
7226             // Tell all threads, globally, to wait for WaitForGCEvent.
7227             //
7228             ThreadStore::TrapReturningThreads(TRUE);
7229
7230             //
7231             // Remember why we're doing this.
7232             //
7233             m_suspendReason = reason;
7234
7235             //
7236             // There's a GC in progress.  (again, not necessarily - we suspend the EE for other reasons.
7237             // I wonder how much confusion this has caused....)
7238             // It seems like much of the above is redundant.  We should investigate reducing the number
7239             // of mechanisms we use to indicate that a suspension is in progress.
7240             //
7241             GCHeapUtilities::GetGCHeap()->SetGCInProgress(true);
7242
7243             //
7244             // Gratuitous memory barrier.  (may be needed - but I'm not sure why.)
7245             //
7246             MemoryBarrier();
7247
7248             ClrFlsSetThreadType (ThreadType_DynamicSuspendEE);
7249         }
7250
7251         HRESULT hr;
7252         {
7253             _ASSERTE(ThreadStore::HoldingThreadStore() || g_fProcessDetach);
7254
7255             //
7256             // Now that we've instructed all threads to please stop, 
7257             // go interrupt the ones that are running managed code and force them to stop.
7258             // This does not return successfully until all threads have acknowledged that they
7259             // will not run managed code.
7260             //
7261             hr = SuspendRuntime(reason);
7262             ASSERT( hr == S_OK || hr == ERROR_TIMEOUT);
7263
7264 #ifdef TIME_SUSPEND
7265             if (hr == ERROR_TIMEOUT)
7266                 g_SuspendStatistics.cntCollideRetry++;
7267 #endif
7268         }
7269
7270         if (hr == ERROR_TIMEOUT)
7271             STRESS_LOG0(LF_SYNC, LL_INFO1000, "SysSuspension colission");
7272
7273         // If the debugging services are attached, then its possible
7274         // that there is a thread which appears to be stopped at a gc
7275         // safe point, but which really is not. If that is the case,
7276         // back off and try again.
7277
7278         // If this is not the GC thread and another thread has triggered
7279         // a GC, then we may have bailed out of SuspendRuntime, so we
7280         // must resume all of the threads and tell the GC that we are
7281         // at a safepoint - since this is the exact same behaviour
7282         // that the debugger needs, just use it's code.
7283         if ((hr == ERROR_TIMEOUT)
7284             || Thread::ThreadsAtUnsafePlaces()
7285 #ifdef DEBUGGING_SUPPORTED  // seriously?  When would we want to disable debugging support? :)
7286              || (CORDebuggerAttached() && 
7287                  g_pDebugInterface->ThreadsAtUnsafePlaces())
7288 #endif // DEBUGGING_SUPPORTED
7289             )
7290         {
7291             // In this case, the debugger has stopped at least one
7292             // thread at an unsafe place.  The debugger will usually
7293             // have already requested that we stop.  If not, it will 
7294             // usually either do so shortly, or resume the thread that is
7295             // at the unsafe place. Either way, we have to wait for the 
7296             // debugger to decide what it wants to do.
7297             // 
7298             // In some rare cases, the end-user debugger may have frozen
7299             // a thread at a gc-unsafe place, and so we'll loop forever
7300             // here and never resolve the deadlock.  Unfortunately we can't
7301             // easily abort a GC 
7302             // and so for now we just wait for the debugger to timeout and 
7303             // hopefully thaw that thread.  Maybe instead we should try to 
7304             // detect this situation sooner (when thread abort is possible)
7305             // and notify the debugger with NotifyOfCrossThreadDependency, giving
7306             // it the chance to thaw other threads or abort us before getting
7307             // wedged in the GC.
7308             //
7309             // Note: we've still got the ThreadStore lock held.
7310             //
7311             // <REVISIT>The below manipulation of two static variables (s_hAbortEvtCache and s_hAbortEvt)
7312             // is protected by the ThreadStore lock, which we are still holding.  But we access these
7313             // in ThreadSuspend::LockThreadStore, prior to obtaining the lock. </REVISIT>
7314             //
7315             LOG((LF_GCROOTS | LF_GC | LF_CORDB,
7316                  LL_INFO10,
7317                  "***** Giving up on current GC suspension due "
7318                  "to debugger or timeout *****\n"));            
7319
7320             if (s_hAbortEvtCache == NULL)
7321             {
7322                 LOG((LF_SYNC, INFO3, "Creating suspend abort event.\n"));
7323
7324                 CLREvent * pEvent = NULL;
7325
7326                 EX_TRY 
7327                 {
7328                     pEvent = new CLREvent();
7329                     pEvent->CreateManualEvent(FALSE);
7330                     s_hAbortEvtCache = pEvent;
7331                 }
7332                 EX_CATCH
7333                 {
7334                     // Bummer... couldn't init the abort event. Its a shame, but not fatal. We'll simply not use it
7335                     // on this iteration and try again next time.
7336                     if (pEvent) {
7337                         _ASSERTE(!pEvent->IsValid());
7338                         pEvent->CloseEvent();
7339                         delete pEvent;
7340                     }
7341                 }
7342                 EX_END_CATCH(SwallowAllExceptions)
7343             }
7344
7345             if (s_hAbortEvtCache != NULL)
7346             {
7347                 LOG((LF_SYNC, INFO3, "Using suspend abort event.\n"));
7348                 s_hAbortEvt = s_hAbortEvtCache;
7349                 s_hAbortEvt->Reset();
7350             }
7351             
7352             // Mark that we're done with the gc, so that the debugger can proceed.
7353             RestartEE(FALSE, FALSE);            
7354             
7355             LOG((LF_GCROOTS | LF_GC | LF_CORDB,
7356                  LL_INFO10, "The EE is free now...\n"));
7357             
7358             // If someone's trying to suspent *this* thread, this is a good opportunity.
7359             // <REVIST>This call to CatchAtSafePoint is redundant - PulseGCMode already checks this.</REVISIT>
7360             if (pCurThread && pCurThread->CatchAtSafePoint())
7361             {
7362                 //  <REVISIT> This assert is fired on BGC thread 'cause we
7363                 // got timeout.</REVISIT>
7364                 //_ASSERTE((pCurThread->PreemptiveGCDisabled()) || IsGCSpecialThread());
7365                 pCurThread->PulseGCMode();  // Go suspend myself.
7366             }
7367             else
7368             {
7369                 // otherwise, just yield so the debugger can finish what it's doing.
7370                 __SwitchToThread (0, ++dwSwitchCount); 
7371             }
7372
7373             goto retry_for_debugger;
7374         }
7375     }
7376     GC_ON_TRANSITIONS(gcOnTransitions);
7377
7378     FireEtwGCSuspendEEEnd_V1(GetClrInstanceId());
7379
7380 #ifdef TIME_SUSPEND
7381     g_SuspendStatistics.EndSuspend(reason == SUSPEND_FOR_GC || reason == SUSPEND_FOR_GC_PREP);
7382 #endif //TIME_SUSPEND
7383 }
7384
7385 #if defined(FEATURE_HIJACK) && defined(PLATFORM_UNIX)
7386
7387 // This function is called by PAL to check if the specified instruction pointer
7388 // is in a function where we can safely inject activation. 
7389 BOOL CheckActivationSafePoint(SIZE_T ip, BOOL checkingCurrentThread)
7390 {
7391     Thread *pThread = GetThread();
7392     // It is safe to call the ExecutionManager::IsManagedCode only if we are making the check for
7393     // a thread different from the current one or if the current thread is in the cooperative mode.
7394     // Otherwise ExecutionManager::IsManagedCode could deadlock if the activation happened when the
7395     // thread was holding the ExecutionManager's writer lock.
7396     // When the thread is in preemptive mode, we know for sure that it is not executing managed code.
7397     BOOL checkForManagedCode = !checkingCurrentThread || (pThread != NULL && pThread->PreemptiveGCDisabled());
7398     return checkForManagedCode && ExecutionManager::IsManagedCode(ip);
7399 }
7400
7401 // This function is called when a GC is pending. It tries to ensure that the current
7402 // thread is taken to a GC-safe place as quickly as possible. It does this by doing 
7403 // one of the following:
7404 //
7405 //     - If the thread is in native code or preemptive GC is not disabled, there's
7406 //       nothing to do, so we return.
7407 //
7408 //     - If the thread is in interruptible managed code, we will push a frame that
7409 //       has information about the context that was interrupted and then switch to
7410 //       preemptive GC mode so that the pending GC can proceed, and then switch back.
7411 //
7412 //     - If the thread is in uninterruptible managed code, we will patch the return
7413 //       address to take the thread to the appropriate stub (based on the return 
7414 //       type of the method) which will then handle preparing the thread for GC.
7415 //
7416 void HandleGCSuspensionForInterruptedThread(CONTEXT *interruptedContext)
7417 {
7418     Thread *pThread = GetThread();
7419
7420     if (pThread->PreemptiveGCDisabled() != TRUE)
7421         return;
7422
7423 #ifdef FEATURE_PERFTRACING
7424     // Mark that the thread is currently in managed code.
7425     pThread->SaveGCModeOnSuspension();
7426 #endif // FEATURE_PERFTRACING
7427
7428     PCODE ip = GetIP(interruptedContext);
7429
7430     // This function can only be called when the interrupted thread is in 
7431     // an activation safe point.
7432     _ASSERTE(CheckActivationSafePoint(ip, /* checkingCurrentThread */ TRUE));
7433
7434     Thread::WorkingOnThreadContextHolder workingOnThreadContext(pThread);
7435     if (!workingOnThreadContext.Acquired())
7436         return;
7437
7438     EECodeInfo codeInfo(ip);
7439     if (!codeInfo.IsValid())
7440         return;
7441
7442     DWORD addrOffset = codeInfo.GetRelOffset();
7443
7444     ICodeManager *pEECM = codeInfo.GetCodeManager();
7445     _ASSERTE(pEECM != NULL);
7446
7447     bool isAtSafePoint = pEECM->IsGcSafe(&codeInfo, addrOffset);
7448     if (isAtSafePoint)
7449     {
7450         // If the thread is at a GC safe point, push a RedirectedThreadFrame with
7451         // the interrupted context and pulse the GC mode so that GC can proceed.
7452         FrameWithCookie<RedirectedThreadFrame> frame(interruptedContext);
7453         pThread->SetSavedRedirectContext(NULL);
7454
7455         frame.Push(pThread);
7456
7457         pThread->PulseGCMode();
7458
7459         frame.Pop(pThread);
7460     }
7461     else
7462     {
7463         // The thread is in non-interruptible code.
7464         ExecutionState executionState;
7465         StackWalkAction action;
7466         REGDISPLAY regDisplay;
7467         pThread->InitRegDisplay(&regDisplay, interruptedContext, true /* validContext */);
7468
7469         BOOL unused;
7470
7471         if (IsIPInEpilog(interruptedContext, &codeInfo, &unused))
7472             return;
7473
7474         // Use StackWalkFramesEx to find the location of the return address. This will locate the
7475         // return address by checking relative to the caller frame's SP, which is preferable to
7476         // checking next to the current RBP because we may have interrupted the function prior to
7477         // the point where RBP is updated.
7478         action = pThread->StackWalkFramesEx(
7479             &regDisplay,
7480             SWCB_GetExecutionState,
7481             &executionState,
7482             QUICKUNWIND | DISABLE_MISSING_FRAME_DETECTION | ALLOW_ASYNC_STACK_WALK);
7483
7484         if (action != SWA_ABORT || !executionState.m_IsJIT)
7485             return;
7486
7487         if (executionState.m_ppvRetAddrPtr == NULL)
7488             return;
7489
7490
7491         // Calling this turns off the GC_TRIGGERS/THROWS/INJECT_FAULT contract in LoadTypeHandle.
7492         // We should not trigger any loads for unresolved types.
7493         ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
7494
7495         // Mark that we are performing a stackwalker like operation on the current thread.
7496         // This is necessary to allow the signature parsing functions to work without triggering any loads.
7497         ClrFlsValueSwitch threadStackWalking(TlsIdx_StackWalkerWalkingThread, pThread);
7498
7499         // Hijack the return address to point to the appropriate routine based on the method's return type.
7500         void *pvHijackAddr = GetHijackAddr(pThread, &codeInfo);
7501         pThread->HijackThread(pvHijackAddr, &executionState);
7502     }
7503 }
7504
7505 bool Thread::InjectGcSuspension()
7506 {
7507     static ConfigDWORD injectionEnabled;
7508     if (injectionEnabled.val(CLRConfig::INTERNAL_ThreadSuspendInjection) == 0)
7509         return false;
7510
7511     Volatile<HANDLE> hThread;
7512     hThread = GetThreadHandle();
7513     if (hThread != INVALID_HANDLE_VALUE && hThread != SWITCHOUT_HANDLE_VALUE)
7514     {
7515         ::PAL_InjectActivation(hThread);
7516         return true;
7517     }
7518
7519     return false;
7520 }
7521
7522 #endif // FEATURE_HIJACK && PLATFORM_UNIX
7523
7524 // Initialize thread suspension support
7525 void ThreadSuspend::Initialize()
7526 {
7527 #if defined(FEATURE_HIJACK) && defined(PLATFORM_UNIX)
7528     ::PAL_SetActivationFunction(HandleGCSuspensionForInterruptedThread, CheckActivationSafePoint);
7529 #endif
7530 }
7531
7532 #ifdef _DEBUG
7533 BOOL Debug_IsLockedViaThreadSuspension()
7534 {
7535     LIMITED_METHOD_CONTRACT;
7536     return GCHeapUtilities::IsGCInProgress() && 
7537                     (dbgOnly_IsSpecialEEThread() || 
7538                     IsGCSpecialThread() || 
7539                     GetThread() == ThreadSuspend::GetSuspensionThread());
7540 }
7541 #endif
7542
7543 #if defined(TIME_SUSPEND) || defined(GC_STATS)
7544
7545 DWORD StatisticsBase::secondsToDisplay = 0;
7546
7547 DWORD StatisticsBase::GetTime()
7548 {
7549     LIMITED_METHOD_CONTRACT;
7550     LARGE_INTEGER large;
7551
7552     if (divisor == 0)
7553     {
7554         if (QueryPerformanceFrequency(&large) && (large.QuadPart != 0))
7555             divisor = (DWORD)(large.QuadPart / (1000 * 1000));        // microseconds
7556         else
7557             divisor = 1;
7558     }
7559
7560     if (QueryPerformanceCounter(&large))
7561         return (DWORD) (large.QuadPart / divisor);
7562     else
7563         return 0;
7564 }
7565
7566 DWORD StatisticsBase::GetElapsed(DWORD start, DWORD stop)
7567 {
7568     LIMITED_METHOD_CONTRACT;
7569     if (stop > start)
7570         return stop - start;
7571
7572     INT64 bigStop = stop;
7573     bigStop += 0x100000000ULL;
7574     bigStop -= start;
7575
7576     // The assert below was seen firing in stress, so comment it out for now
7577     //_ASSERTE(((INT64)(DWORD)bigStop) == bigStop);
7578
7579     if (((INT64)(DWORD)bigStop) == bigStop)
7580         return (DWORD) bigStop;
7581     else
7582         return 0;
7583 }
7584
7585 void StatisticsBase::RollOverIfNeeded()
7586 {
7587     LIMITED_METHOD_CONTRACT;
7588
7589     // Our counters are 32 bits and can count to 4 GB in microseconds or 4K in seconds.
7590     // Reset when we get close to overflowing
7591     const DWORD RolloverInterval = 3900;
7592
7593     // every so often, print a summary of our statistics
7594     DWORD ticksNow = GetTickCount();
7595
7596     if (secondsToDisplay == 0)
7597     {
7598         secondsToDisplay = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_StatsUpdatePeriod);
7599         if (secondsToDisplay == 0)
7600             secondsToDisplay = 1;
7601         else if (secondsToDisplay > RolloverInterval)
7602             secondsToDisplay = RolloverInterval;
7603     }
7604
7605     if (ticksNow - startTick > secondsToDisplay * 1000)
7606     {
7607         DisplayAndUpdate();
7608
7609         startTick = GetTickCount();
7610
7611         // Our counters are 32 bits and can count to 4 GB in microseconds or 4K in seconds.
7612         // Reset when we get close to overflowing
7613         if (++cntDisplay >= (int)(RolloverInterval / secondsToDisplay))
7614             Initialize();
7615     }
7616 }
7617
7618 #endif // defined(TIME_SUSPEND) || defined(GC_STATS)
7619
7620
7621 #ifdef TIME_SUSPEND
7622
7623 // There is a current and a prior copy of the statistics.  This allows us to display deltas per reporting
7624 // interval, as well as running totals.  The 'min' and 'max' values require special treatment.  They are
7625 // Reset (zeroed) in the current statistics when we begin a new interval and they are updated via a
7626 // comparison with the global min/max.
7627 SuspendStatistics g_SuspendStatistics;
7628 SuspendStatistics g_LastSuspendStatistics;
7629
7630 WCHAR* SuspendStatistics::logFileName = NULL;
7631
7632 // Called whenever our timers start to overflow
7633 void SuspendStatistics::Initialize()
7634 {
7635     LIMITED_METHOD_CONTRACT;
7636     // for efficiency sake we're taking a dependency on the layout of a C++ object
7637     // with a vtable. protect against violations of our premise:
7638     static_assert(offsetof(SuspendStatistics, cntDisplay) == sizeof(void*),
7639             "The first field of SuspendStatistics follows the pointer sized vtable");
7640
7641     int podOffs = offsetof(SuspendStatistics, cntDisplay);  // offset of the first POD field
7642     memset((BYTE*)(&g_SuspendStatistics)+podOffs, 0, sizeof(g_SuspendStatistics)-podOffs);
7643     memset((BYTE*)(&g_LastSuspendStatistics)+podOffs, 0, sizeof(g_LastSuspendStatistics)-podOffs);
7644 }
7645
7646 // Top of SuspendEE
7647 void SuspendStatistics::StartSuspend()
7648 {
7649     LIMITED_METHOD_CONTRACT;
7650     startSuspend = GetTime();
7651 }
7652
7653 // Bottom of SuspendEE
7654 void SuspendStatistics::EndSuspend(BOOL bForGC)
7655 {
7656     LIMITED_METHOD_CONTRACT;
7657     DWORD time = GetElapsed(startSuspend, GetTime());
7658
7659     suspend.Accumulate(time);
7660     cntSuspends++;
7661     // details on suspends...
7662     if (!bForGC)
7663         cntNonGCSuspends++;
7664     if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress())
7665     {
7666         cntSuspendsInBGC++;
7667         if (!bForGC)
7668             cntNonGCSuspendsInBGC++;
7669     }
7670 }
7671
7672 // Time spent in the current suspend (for pro-active debugging)
7673 DWORD SuspendStatistics::CurrentSuspend()
7674 {
7675     LIMITED_METHOD_CONTRACT;
7676     return GetElapsed(startSuspend, GetTime());
7677 }
7678
7679 // Top of RestartEE
7680 void SuspendStatistics::StartRestart()
7681 {
7682     LIMITED_METHOD_CONTRACT;
7683     startRestart = GetTime();
7684 }
7685
7686 // Bottom of RestartEE
7687 void SuspendStatistics::EndRestart()
7688 {
7689     LIMITED_METHOD_CONTRACT;
7690     DWORD timeNow = GetTime();
7691
7692     restart.Accumulate(GetElapsed(startRestart, timeNow));
7693     cntRestarts++;
7694
7695     paused.Accumulate(SuspendStatistics::GetElapsed(startSuspend, timeNow));
7696
7697     RollOverIfNeeded();
7698 }
7699
7700 // Time spent in the current restart
7701 DWORD SuspendStatistics::CurrentRestart()
7702 {
7703     LIMITED_METHOD_CONTRACT;
7704     return GetElapsed(startRestart, GetTime());
7705 }
7706
7707 void SuspendStatistics::DisplayAndUpdate()
7708 {
7709     LIMITED_METHOD_CONTRACT;
7710
7711     // TODO: this fires at times...
7712     // _ASSERTE(cntSuspends == cntRestarts);
7713
7714     if (logFileName == NULL)
7715     {
7716         logFileName = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_SuspendTimeLog);
7717     }
7718
7719     FILE* logFile;
7720
7721     if (logFileName != NULL && (logFile = _wfopen((LPCWSTR)logFileName, W("a"))) != NULL)
7722     {
7723     if (cntDisplay == 0)
7724         fprintf(logFile, "\nSUSP **** Initialize *****\n\n");
7725         
7726     fprintf(logFile, "SUSP **** Summary ***** %d\n", cntDisplay);
7727
7728     paused.DisplayAndUpdate    (logFile, "Paused ", &g_LastSuspendStatistics.paused,     cntSuspends, g_LastSuspendStatistics.cntSuspends);
7729     suspend.DisplayAndUpdate   (logFile, "Suspend", &g_LastSuspendStatistics.suspend,    cntSuspends, g_LastSuspendStatistics.cntSuspends);
7730     restart.DisplayAndUpdate   (logFile, "Restart", &g_LastSuspendStatistics.restart,    cntRestarts, g_LastSuspendStatistics.cntSuspends);
7731     acquireTSL.DisplayAndUpdate(logFile, "LockTSL", &g_LastSuspendStatistics.acquireTSL, cntSuspends, g_LastSuspendStatistics.cntSuspends);
7732     releaseTSL.DisplayAndUpdate(logFile, "Unlock ", &g_LastSuspendStatistics.releaseTSL, cntSuspends, g_LastSuspendStatistics.cntSuspends);
7733     osSuspend.DisplayAndUpdate (logFile, "OS Susp", &g_LastSuspendStatistics.osSuspend,  cntOSSuspendResume, g_LastSuspendStatistics.cntOSSuspendResume);
7734     crawl.DisplayAndUpdate     (logFile, "Crawl",   &g_LastSuspendStatistics.crawl,      cntHijackCrawl, g_LastSuspendStatistics.cntHijackCrawl);
7735     wait.DisplayAndUpdate      (logFile, "Wait",    &g_LastSuspendStatistics.wait,       cntWaits,    g_LastSuspendStatistics.cntWaits);
7736
7737     fprintf(logFile, "OS Suspend Failures %d (%d), Wait Timeouts %d (%d), Hijack traps %d (%d)\n",
7738            cntFailedSuspends - g_LastSuspendStatistics.cntFailedSuspends, cntFailedSuspends,
7739            cntWaitTimeouts - g_LastSuspendStatistics.cntWaitTimeouts, cntWaitTimeouts,
7740            cntHijackTrap - g_LastSuspendStatistics.cntHijackTrap, cntHijackTrap);
7741
7742     fprintf(logFile, "Redirected EIP Failures %d (%d), Collided GC/Debugger/ADUnload %d (%d)\n",
7743            cntFailedRedirections - g_LastSuspendStatistics.cntFailedRedirections, cntFailedRedirections,
7744            cntCollideRetry - g_LastSuspendStatistics.cntCollideRetry, cntCollideRetry);
7745
7746     fprintf(logFile, "Suspend: All %d (%d). NonGC: %d (%d). InBGC: %d (%d). NonGCInBGC: %d (%d)\n\n",
7747             cntSuspends - g_LastSuspendStatistics.cntSuspends, cntSuspends,
7748             cntNonGCSuspends - g_LastSuspendStatistics.cntNonGCSuspends, cntNonGCSuspends, 
7749             cntSuspendsInBGC - g_LastSuspendStatistics.cntSuspendsInBGC, cntSuspendsInBGC,
7750             cntNonGCSuspendsInBGC - g_LastSuspendStatistics.cntNonGCSuspendsInBGC, cntNonGCSuspendsInBGC);
7751
7752     // close the log file...
7753     fclose(logFile);
7754     }
7755
7756     memcpy(&g_LastSuspendStatistics, this, sizeof(g_LastSuspendStatistics));
7757
7758     suspend.Reset();
7759     restart.Reset();
7760     paused.Reset();
7761     acquireTSL.Reset();
7762     releaseTSL.Reset();
7763     osSuspend.Reset();
7764     crawl.Reset();
7765     wait.Reset();
7766 }
7767
7768 #endif // TIME_SUSPEND
7769
7770 #if defined(TIME_SUSPEND) || defined(GC_STATS)
7771
7772 const char* const str_timeUnit[]   = { "usec", "msec", "sec" };
7773 const int         timeUnitFactor[] = { 1, 1000, 1000000 };
7774
7775 void MinMaxTot::DisplayAndUpdate(FILE* logFile, __in_z const char *pName, MinMaxTot *pLastOne, int fullCount, int priorCount, timeUnit unit /* = usec */)
7776 {
7777     LIMITED_METHOD_CONTRACT;
7778
7779     int tuf = timeUnitFactor[unit];
7780     int delta = fullCount - priorCount;
7781
7782     fprintf(logFile, "%s  %u (%u) times for %u (%u) %s. Min %u (%u), Max %u (%u), Avg %u (%u)\n",
7783            pName,
7784            delta, fullCount,
7785            (totVal - pLastOne->totVal) / tuf, totVal / tuf,
7786            str_timeUnit[(int)unit],
7787            minVal / tuf, pLastOne->minVal / tuf,
7788            maxVal / tuf, pLastOne->maxVal / tuf,
7789            (delta == 0 ? 0 : (totVal - pLastOne->totVal) / delta) / tuf,
7790            (fullCount == 0 ? 0 : totVal / fullCount) / tuf);
7791
7792     if (minVal > pLastOne->minVal && pLastOne->minVal != 0)
7793         minVal = pLastOne->minVal;
7794
7795     if (maxVal < pLastOne->maxVal)
7796         maxVal = pLastOne->maxVal;
7797 }
7798
7799 #endif // defined(TIME_SUSPEND) || defined(GC_STATS)