@@ -1702,6 +1702,130 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error.
1702
1702
1703
1703
#endif // !defined(CORECLR_EMBEDDED)
1704
1704
1705
+ static void RuntimeThreadShutdown (void * thread)
1706
+ {
1707
+ Thread* pThread = (Thread*)thread;
1708
+ _ASSERTE (pThread == GetThreadNULLOk ());
1709
+
1710
+ if (pThread)
1711
+ {
1712
+ #ifdef FEATURE_COMINTEROP
1713
+ // reset the CoInitialize state
1714
+ // so we don't call CoUninitialize during thread detach
1715
+ pThread->ResetCoInitialized ();
1716
+ #endif // FEATURE_COMINTEROP
1717
+ // For case where thread calls ExitThread directly, we need to reset the
1718
+ // frame pointer. Otherwise stackwalk would AV. We need to do it in cooperative mode.
1719
+ // We need to set m_GCOnTransitionsOK so this thread won't trigger GC when toggle GC mode
1720
+ if (pThread->m_pFrame != FRAME_TOP)
1721
+ {
1722
+ #ifdef _DEBUG
1723
+ pThread->m_GCOnTransitionsOK = FALSE ;
1724
+ #endif
1725
+ GCX_COOP_NO_DTOR ();
1726
+ pThread->m_pFrame = FRAME_TOP;
1727
+ GCX_COOP_NO_DTOR_END ();
1728
+ }
1729
+
1730
+ pThread->DetachThread (TRUE );
1731
+ }
1732
+ else
1733
+ {
1734
+ // Since we don't actually cleanup the TLS data along this path, verify that it is already cleaned up
1735
+ AssertThreadStaticDataFreed ();
1736
+ }
1737
+
1738
+ ThreadDetaching ();
1739
+ }
1740
+
1741
+ #ifdef TARGET_WINDOWS
1742
+
1743
+ // Index for the fiber local storage of the attached thread pointer
1744
+ static uint32_t g_flsIndex = FLS_OUT_OF_INDEXES;
1745
+
1746
+ // This is called when each *fiber* is destroyed. When the home fiber of a thread is destroyed,
1747
+ // it means that the thread itself is destroyed.
1748
+ // Since we receive that notification outside of the Loader Lock, it allows us to safely acquire
1749
+ // the ThreadStore lock in the RuntimeThreadShutdown.
1750
+ static void __stdcall FiberDetachCallback (void * lpFlsData)
1751
+ {
1752
+ ASSERT (g_flsIndex != FLS_OUT_OF_INDEXES);
1753
+ ASSERT (lpFlsData == FlsGetValue (g_flsIndex));
1754
+
1755
+ if (lpFlsData != NULL )
1756
+ {
1757
+ // The current fiber is the home fiber of a thread, so the thread is shutting down
1758
+ RuntimeThreadShutdown (lpFlsData);
1759
+ }
1760
+ }
1761
+
1762
+ bool InitFlsSlot ()
1763
+ {
1764
+ // We use fiber detach callbacks to run our thread shutdown code because the fiber detach
1765
+ // callback is made without the OS loader lock
1766
+ g_flsIndex = FlsAlloc (FiberDetachCallback);
1767
+ if (g_flsIndex == FLS_OUT_OF_INDEXES)
1768
+ {
1769
+ return false ;
1770
+ }
1771
+
1772
+ return true ;
1773
+ }
1774
+
1775
+ // Register the thread with OS to be notified when thread is about to be destroyed
1776
+ // It fails fast if a different thread was already registered with the current fiber.
1777
+ // Parameters:
1778
+ // thread - thread to attach
1779
+ static void OsAttachThread (void * thread)
1780
+ {
1781
+ void * threadFromCurrentFiber = FlsGetValue (g_flsIndex);
1782
+
1783
+ if (threadFromCurrentFiber != NULL )
1784
+ {
1785
+ _ASSERTE (!" Multiple threads encountered from a single fiber" );
1786
+ COMPlusThrowWin32 ();
1787
+ }
1788
+
1789
+ // Associate the current fiber with the current thread. This makes the current fiber the thread's "home"
1790
+ // fiber. This fiber is the only fiber allowed to execute managed code on this thread. When this fiber
1791
+ // is destroyed, we consider the thread to be destroyed.
1792
+ FlsSetValue (g_flsIndex, thread);
1793
+ }
1794
+
1795
+ // Detach thread from OS notifications.
1796
+ // It fails fast if some other thread value was attached to the current fiber.
1797
+ // Parameters:
1798
+ // thread - thread to detach
1799
+ // Return:
1800
+ // true if the thread was detached, false if there was no attached thread
1801
+ bool OsDetachThread (void * thread)
1802
+ {
1803
+ ASSERT (g_flsIndex != FLS_OUT_OF_INDEXES);
1804
+ void * threadFromCurrentFiber = FlsGetValue (g_flsIndex);
1805
+
1806
+ if (threadFromCurrentFiber == NULL )
1807
+ {
1808
+ // we've seen this thread, but not this fiber. It must be a "foreign" fiber that was
1809
+ // borrowing this thread.
1810
+ return false ;
1811
+ }
1812
+
1813
+ if (threadFromCurrentFiber != thread)
1814
+ {
1815
+ _ASSERTE (!" Detaching a thread from the wrong fiber" );
1816
+ COMPlusThrowWin32 ();
1817
+ }
1818
+
1819
+ FlsSetValue (g_flsIndex, NULL );
1820
+ return true ;
1821
+ }
1822
+
1823
+ void EnsureTlsDestructionMonitor ()
1824
+ {
1825
+ OsAttachThread (GetThread ());
1826
+ }
1827
+
1828
+ #else
1705
1829
struct TlsDestructionMonitor
1706
1830
{
1707
1831
bool m_activated = false ;
@@ -1715,36 +1839,7 @@ struct TlsDestructionMonitor
1715
1839
{
1716
1840
if (m_activated)
1717
1841
{
1718
- Thread* thread = GetThreadNULLOk ();
1719
- if (thread)
1720
- {
1721
- #ifdef FEATURE_COMINTEROP
1722
- // reset the CoInitialize state
1723
- // so we don't call CoUninitialize during thread detach
1724
- thread->ResetCoInitialized ();
1725
- #endif // FEATURE_COMINTEROP
1726
- // For case where thread calls ExitThread directly, we need to reset the
1727
- // frame pointer. Otherwise stackwalk would AV. We need to do it in cooperative mode.
1728
- // We need to set m_GCOnTransitionsOK so this thread won't trigger GC when toggle GC mode
1729
- if (thread->m_pFrame != FRAME_TOP)
1730
- {
1731
- #ifdef _DEBUG
1732
- thread->m_GCOnTransitionsOK = FALSE ;
1733
- #endif
1734
- GCX_COOP_NO_DTOR ();
1735
- thread->m_pFrame = FRAME_TOP;
1736
- GCX_COOP_NO_DTOR_END ();
1737
- }
1738
-
1739
- thread->DetachThread (TRUE );
1740
- }
1741
- else
1742
- {
1743
- // Since we don't actually cleanup the TLS data along this path, verify that it is already cleaned up
1744
- AssertThreadStaticDataFreed ();
1745
- }
1746
-
1747
- ThreadDetaching ();
1842
+ RuntimeThreadShutdown (GetThreadNULLOk ());
1748
1843
}
1749
1844
}
1750
1845
};
@@ -1758,6 +1853,8 @@ void EnsureTlsDestructionMonitor()
1758
1853
tls_destructionMonitor.Activate ();
1759
1854
}
1760
1855
1856
+ #endif
1857
+
1761
1858
#ifdef DEBUGGING_SUPPORTED
1762
1859
//
1763
1860
// InitializeDebugger initialized the Runtime-side COM+ Debugging Services
0 commit comments