@@ -33,7 +33,6 @@ static TLSIndexToMethodTableMap *g_pThreadStaticCollectibleTypeIndices;
3333static  TLSIndexToMethodTableMap *g_pThreadStaticNonCollectibleTypeIndices;
3434static  PTR_MethodTable g_pMethodTablesForDirectThreadLocalData[offsetof(ThreadLocalData, ExtendedDirectThreadLocalTLSData) - offsetof(ThreadLocalData, ThreadBlockingInfo_First) + EXTENDED_DIRECT_THREAD_LOCAL_SIZE];
3535
36- static  Volatile<uint8_t > s_GCsWhichDoRelocateAndCanEmptyOutTheTLSIndices = 0 ;
3736static  uint32_t  g_NextTLSSlot = 1 ;
3837static  uint32_t  g_NextNonCollectibleTlsSlot = NUMBER_OF_TLSOFFSETS_NOT_USED_IN_NONCOLLECTIBLE_ARRAY;
3938static  uint32_t  g_directThreadLocalTLSBytesAvailable = EXTENDED_DIRECT_THREAD_LOCAL_SIZE;
@@ -277,7 +276,7 @@ void TLSIndexToMethodTableMap::Clear(TLSIndex index, uint8_t whenCleared)
277276    _ASSERTE (IsClearedValue (pMap[index.GetIndexOffset ()]));
278277}
279278
280- bool  TLSIndexToMethodTableMap::FindClearedIndex (uint8_t  whenClearedMarkerToAvoid,  TLSIndex* pIndex)
279+ bool  TLSIndexToMethodTableMap::FindClearedIndex (TLSIndex* pIndex)
281280{
282281    CONTRACTL
283282    {
@@ -291,15 +290,6 @@ bool TLSIndexToMethodTableMap::FindClearedIndex(uint8_t whenClearedMarkerToAvoid
291290    {
292291        if  (entry.IsClearedValue )
293292        {
294-             uint8_t  whenClearedMarker = entry.ClearedMarker ;
295-             if  ((whenClearedMarker == whenClearedMarkerToAvoid) ||
296-                 (whenClearedMarker == (whenClearedMarkerToAvoid - 1 )) ||
297-                 (whenClearedMarker == (whenClearedMarkerToAvoid - 2 )))
298-             {
299-                 //  Make sure we are not within 2 of the marker we are trying to avoid
300-                 //  Use multiple compares instead of trying to fuss around with the overflow style comparisons
301-                 continue ;
302-             }
303293            *pIndex = entry.TlsIndex ;
304294            return  true ;
305295        }
@@ -317,7 +307,7 @@ void InitializeThreadStaticData()
317307    }
318308    CONTRACTL_END;
319309
320-     g_pThreadStaticCollectibleTypeIndices = new  TLSIndexToMethodTableMap (TLSIndexType::NonCollectible );
310+     g_pThreadStaticCollectibleTypeIndices = new  TLSIndexToMethodTableMap (TLSIndexType::Collectible );
321311    g_pThreadStaticNonCollectibleTypeIndices = new  TLSIndexToMethodTableMap (TLSIndexType::NonCollectible);
322312    g_TLSCrst.Init (CrstThreadLocalStorageLock, CRST_UNSAFE_ANYMODE);
323313}
@@ -387,7 +377,7 @@ void FreeLoaderAllocatorHandlesForTLSData(Thread *pThread)
387377#endif 
388378        for  (const  auto & entry : g_pThreadStaticCollectibleTypeIndices->CollectibleEntries ())
389379        {
390-             _ASSERTE ((entry.TlsIndex .GetIndexOffset () < pThread->cLoaderHandles ) || allRemainingIndicesAreNotValid);
380+             _ASSERTE ((entry.TlsIndex .GetIndexOffset () <=  pThread->cLoaderHandles ) || allRemainingIndicesAreNotValid);
391381            if  (entry.TlsIndex .GetIndexOffset () >= pThread->cLoaderHandles )
392382            {
393383#ifndef  _DEBUG
@@ -405,6 +395,13 @@ void FreeLoaderAllocatorHandlesForTLSData(Thread *pThread)
405395                }
406396            }
407397        }
398+ 
399+         pThread->cLoaderHandles  = -1 ; //  Sentinel value indicating that there are no LoaderHandles and the thread is permanently dead.
400+         if  (pThread->pLoaderHandles  != NULL )
401+         {
402+             delete[]  pThread->pLoaderHandles ;
403+             pThread->pLoaderHandles  = NULL ;
404+         }
408405    }
409406}
410407
@@ -431,34 +428,46 @@ void FreeThreadStaticData(Thread* pThread)
431428    }
432429    CONTRACTL_END;
433430
434-     SpinLockHolder  spinLock (&pThread-> m_TlsSpinLock ) ;
431+     InFlightTLSData* pOldInFlightData =  nullptr ;
435432
436-     ThreadLocalData *pThreadLocalData = &t_ThreadStatics;
433+     int32_t  oldCollectibleTlsDataCount = 0 ;
434+     DPTR (OBJECTHANDLE) pOldCollectibleTlsArrayData = nullptr ;
437435
438-     for  (int32_t  iTlsSlot = 0 ; iTlsSlot < pThreadLocalData->cCollectibleTlsData ; ++iTlsSlot)
439436    {
440-         if  (!IsHandleNullUnchecked (pThreadLocalData->pCollectibleTlsArrayData [iTlsSlot]))
437+         SpinLockHolder spinLock (&pThread->m_TlsSpinLock );
438+ 
439+         ThreadLocalData *pThreadLocalData = &t_ThreadStatics;
440+ 
441+         pOldCollectibleTlsArrayData = pThreadLocalData->pCollectibleTlsArrayData ;
442+         oldCollectibleTlsDataCount = pThreadLocalData->cCollectibleTlsData ;
443+ 
444+         pThreadLocalData->pCollectibleTlsArrayData  = NULL ;
445+         pThreadLocalData->cCollectibleTlsData  = 0 ;
446+         pThreadLocalData->pNonCollectibleTlsArrayData  = NULL ;
447+         pThreadLocalData->cNonCollectibleTlsData  = 0 ;
448+ 
449+         pOldInFlightData = pThreadLocalData->pInFlightData ;
450+         pThreadLocalData->pInFlightData  = NULL ;
451+         _ASSERTE (pThreadLocalData->pThread  == pThread);
452+         pThreadLocalData->pThread  = NULL ;
453+     }
454+ 
455+     for  (int32_t  iTlsSlot = 0 ; iTlsSlot < oldCollectibleTlsDataCount; ++iTlsSlot)
456+     {
457+         if  (!IsHandleNullUnchecked (pOldCollectibleTlsArrayData[iTlsSlot]))
441458        {
442-             DestroyLongWeakHandle (pThreadLocalData-> pCollectibleTlsArrayData [iTlsSlot]);
459+             DestroyLongWeakHandle (pOldCollectibleTlsArrayData [iTlsSlot]);
443460        }
444461    }
445462
446-     delete[]  (uint8_t *)pThreadLocalData->pCollectibleTlsArrayData ;
447- 
448-     pThreadLocalData->pCollectibleTlsArrayData  = 0 ;
449-     pThreadLocalData->cCollectibleTlsData  = 0 ;
450-     pThreadLocalData->pNonCollectibleTlsArrayData  = 0 ;
451-     pThreadLocalData->cNonCollectibleTlsData  = 0 ;
463+     delete[]  (uint8_t *)pOldCollectibleTlsArrayData;
452464
453-     while  (pThreadLocalData-> pInFlightData  != NULL )
465+     while  (pOldInFlightData  != NULL )
454466    {
455-         InFlightTLSData* pInFlightData = pThreadLocalData-> pInFlightData ;
456-         pThreadLocalData-> pInFlightData  = pInFlightData->pNext ;
467+         InFlightTLSData* pInFlightData = pOldInFlightData ;
468+         pOldInFlightData  = pInFlightData->pNext ;
457469        delete  pInFlightData;
458470    }
459- 
460-     _ASSERTE (pThreadLocalData->pThread  == pThread);
461-     pThreadLocalData->pThread  = NULL ;
462471}
463472
464473void  SetTLSBaseValue (TADDR *ppTLSBaseAddress, TADDR pTLSBaseAddress, bool  useGCBarrierInsteadOfHandleStore)
@@ -553,6 +562,8 @@ void* GetThreadLocalStaticBase(TLSIndex index)
553562            delete[]  pOldArray;
554563        }
555564
565+         _ASSERTE (t_ThreadStatics.pThread ->cLoaderHandles  != -1 ); //  Check sentinel value indicating that there are no LoaderHandles, the thread has gone through termination and is permanently dead.
566+ 
556567        if  (isCollectible && t_ThreadStatics.pThread ->cLoaderHandles  <= index.GetIndexOffset ())
557568        {
558569            //  Grow the underlying TLS array
@@ -594,9 +605,11 @@ void* GetThreadLocalStaticBase(TLSIndex index)
594605                gcBaseAddresses.pTLSBaseAddress  = dac_cast<TADDR>(OBJECTREFToObject (ObjectFromHandle (pInFlightData->hTLSData )));
595606                if  (pMT->IsClassInited ())
596607                {
597-                     SpinLockHolder spinLock (&t_ThreadStatics.pThread ->m_TlsSpinLock );
598-                     SetTLSBaseValue (gcBaseAddresses.ppTLSBaseAddress , gcBaseAddresses.pTLSBaseAddress , staticIsNonCollectible);
599-                     *ppOldNextPtr = pInFlightData->pNext ;
608+                     {
609+                         SpinLockHolder spinLock (&t_ThreadStatics.pThread ->m_TlsSpinLock );
610+                         SetTLSBaseValue (gcBaseAddresses.ppTLSBaseAddress , gcBaseAddresses.pTLSBaseAddress , staticIsNonCollectible);
611+                         *ppOldNextPtr = pInFlightData->pNext ;
612+                     }
600613                    delete  pInFlightData;
601614                }
602615                break ;
@@ -744,7 +757,7 @@ void GetTLSIndexForThreadStatic(MethodTable* pMT, bool gcStatic, TLSIndex* pInde
744757    }
745758    else 
746759    {
747-         if  (!g_pThreadStaticCollectibleTypeIndices->FindClearedIndex (s_GCsWhichDoRelocateAndCanEmptyOutTheTLSIndices,  &newTLSIndex))
760+         if  (!g_pThreadStaticCollectibleTypeIndices->FindClearedIndex (&newTLSIndex))
748761        {
749762            uint32_t  tlsRawIndex = g_NextTLSSlot;
750763            newTLSIndex = TLSIndex (TLSIndexType::Collectible, tlsRawIndex);
@@ -777,7 +790,7 @@ void FreeTLSIndicesForLoaderAllocator(LoaderAllocator *pLoaderAllocator)
777790
778791    while  (current != end)
779792    {
780-         g_pThreadStaticCollectibleTypeIndices->Clear (tlsIndicesToCleanup[current], s_GCsWhichDoRelocateAndCanEmptyOutTheTLSIndices );
793+         g_pThreadStaticCollectibleTypeIndices->Clear (tlsIndicesToCleanup[current], 0 );
781794        ++current;
782795    }
783796}
0 commit comments