@@ -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