Skip to content

Commit

Permalink
Delete !FEATURE_IMPLICIT_TLS (dotnet#14398)
Browse files Browse the repository at this point in the history
Linux and Windows arm64 are using the regular C/C++ thread local statics. This change unifies the remaining Windows architectures to be on the same plan.
  • Loading branch information
jkotas authored Oct 11, 2017
1 parent d07f1b2 commit 27a25bd
Show file tree
Hide file tree
Showing 59 changed files with 177 additions and 3,357 deletions.
4 changes: 0 additions & 4 deletions clrdefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,6 @@ add_definitions(-DFEATURE_ICASTABLE)
if (WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386))
add_definitions(-DFEATURE_INTEROP_DEBUGGING)
endif (WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386))
if (CLR_CMAKE_PLATFORM_UNIX OR CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-DFEATURE_IMPLICIT_TLS)
set(FEATURE_IMPLICIT_TLS 1)
endif(CLR_CMAKE_PLATFORM_UNIX OR CLR_CMAKE_TARGET_ARCH_ARM64)
if(FEATURE_INTERPRETER)
add_definitions(-DFEATURE_INTERPRETER)
endif(FEATURE_INTERPRETER)
Expand Down
28 changes: 2 additions & 26 deletions src/ToolBox/SOS/Strike/strike.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5778,7 +5778,6 @@ HRESULT PrintSpecialThreads()

TADDR CLRTLSDataAddr = 0;

#ifdef FEATURE_IMPLICIT_TLS
TADDR tlsArrayAddr = NULL;
if (!SafeReadMemory (TO_TADDR(cdaTeb) + WINNT_OFFSETOF__TEB__ThreadLocalStoragePointer , &tlsArrayAddr, sizeof (void**), NULL))
{
Expand All @@ -5788,36 +5787,13 @@ HRESULT PrintSpecialThreads()

TADDR moduleTlsDataAddr = 0;

if (!SafeReadMemory (tlsArrayAddr + sizeof (void*) * dwCLRTLSDataIndex, &moduleTlsDataAddr, sizeof (void**), NULL))
if (!SafeReadMemory (tlsArrayAddr + sizeof (void*) * (dwCLRTLSDataIndex & 0xFFFF), &moduleTlsDataAddr, sizeof (void**), NULL))
{
PrintLn("Failed to get Tls expansion slots for thread ", ThreadID(SysId));
continue;
}

CLRTLSDataAddr = moduleTlsDataAddr + OFFSETOF__TLS__tls_EETlsData;
#else
if (dwCLRTLSDataIndex < TLS_MINIMUM_AVAILABLE)
{
CLRTLSDataAddr = TO_TADDR(cdaTeb) + offsetof(TEB, TlsSlots) + sizeof (void*) * dwCLRTLSDataIndex;
}
else
{
//if TLS index is bigger than TLS_MINIMUM_AVAILABLE, the TLS slot lives in ExpansionSlots
TADDR TebExpsionAddr = NULL;
if (!SafeReadMemory (TO_TADDR(cdaTeb) + offsetof(TEB, TlsExpansionSlots) , &TebExpsionAddr, sizeof (void**), NULL))
{
PrintLn("Failed to get Tls expansion slots for thread ", ThreadID(SysId));
continue;
}

if (TebExpsionAddr == NULL)
{
continue;
}

CLRTLSDataAddr = TebExpsionAddr + sizeof (void*) * (dwCLRTLSDataIndex - TLS_MINIMUM_AVAILABLE);
}
#endif // FEATURE_IMPLICIT_TLS
CLRTLSDataAddr = moduleTlsDataAddr + ((dwCLRTLSDataIndex & 0x7FFF0000) >> 16) + OFFSETOF__TLS__tls_EETlsData;

TADDR CLRTLSData = NULL;
if (!SafeReadMemory (CLRTLSDataAddr, &CLRTLSData, sizeof (TADDR), NULL))
Expand Down
5 changes: 0 additions & 5 deletions src/debug/daccess/enummem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,6 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags)
// see synblk.cpp, the pointer is pointed to a static byte[]
SyncBlockCache::s_pSyncBlockCache.EnumMem();

#ifndef FEATURE_IMPLICIT_TLS
ReportMem(m_globalBase + g_dacGlobals.dac__gThreadTLSIndex, sizeof(DWORD));
ReportMem(m_globalBase + g_dacGlobals.dac__gAppDomainTLSIndex, sizeof(DWORD));
#endif

ReportMem(m_globalBase + g_dacGlobals.dac__g_FCDynamicallyAssignedImplementations,
sizeof(TADDR)*ECall::NUM_DYNAMICALLY_ASSIGNED_FCALL_IMPLEMENTATIONS);

Expand Down
4 changes: 2 additions & 2 deletions src/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4041,14 +4041,14 @@ HRESULT ClrDataAccess::GetTLSIndex(ULONG *pIndex)
return E_INVALIDARG;

SOSDacEnter();
if (CExecutionEngine::GetTlsIndex() == TLS_OUT_OF_INDEXES)
if (g_TlsIndex == TLS_OUT_OF_INDEXES)
{
*pIndex = 0;
hr = S_FALSE;
}
else
{
*pIndex = CExecutionEngine::GetTlsIndex();
*pIndex = g_TlsIndex;
}

SOSDacLeave();
Expand Down
3 changes: 1 addition & 2 deletions src/debug/di/rspriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -10609,11 +10609,10 @@ class CordbUnmanagedThread : public CordbBase

void CacheEEDebuggerWord();
HRESULT SetEEThreadValue(REMOTE_PTR EETlsValue);
#ifdef FEATURE_IMPLICIT_TLS

DWORD_PTR GetEEThreadValue();
REMOTE_PTR GetClrModuleTlsDataAddress();
REMOTE_PTR GetEETlsDataBlock();
#endif

public:
HRESULT GetEEDebuggerWord(REMOTE_PTR *pValue);
Expand Down
173 changes: 2 additions & 171 deletions src/debug/di/rsthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2996,12 +2996,7 @@ HRESULT CordbUnmanagedThread::RestoreLeafSeh()
// return value == 0 (assumed default, *pRead = false
REMOTE_PTR CordbUnmanagedThread::GetPreDefTlsSlot(SIZE_T slot, bool * pRead)
{
#ifdef FEATURE_IMPLICIT_TLS
REMOTE_PTR pBlock = (REMOTE_PTR) GetEETlsDataBlock();
#else
DebuggerIPCRuntimeOffsets *pRO = &(GetProcess()->m_runtimeOffsets);
REMOTE_PTR pBlock = (REMOTE_PTR) GetTlsSlot(pRO->m_TLSIndexOfPredefs);
#endif

REMOTE_PTR data = 0;

Expand Down Expand Up @@ -3036,164 +3031,6 @@ REMOTE_PTR CordbUnmanagedThread::GetPreDefTlsSlot(SIZE_T slot, bool * pRead)
return 0;
}

#ifndef FEATURE_IMPLICIT_TLS

// Read the contents from a LS threads's TLS slot.
DWORD_PTR CordbUnmanagedThread::GetTlsSlot(SIZE_T slot)
{
DWORD_PTR ret = 0;

// Compute the address of the necessary TLS value.
if (FAILED(LoadTLSArrayPtr()))
{
return NULL;
}


void * pBase = NULL;
SIZE_T slotAdjusted = slot;

if (slot < TLS_MINIMUM_AVAILABLE)
{
pBase = m_pTLSArray;
}
else if (slot < TLS_MINIMUM_AVAILABLE + TLS_EXPANSION_SLOTS)
{
pBase = m_pTLSExtendedArray;
slotAdjusted -= TLS_MINIMUM_AVAILABLE;

// Expansion slot is lazily allocated. If we're trying to read from it, but hasn't been allocated,
// then the TLS slot is still the default value, which is 0 (NULL).
if (pBase == NULL)
{
return NULL;
}
}
else
{
// Slot is out of range. Shouldn't happen unless debuggee is corrupted.
_ASSERTE(!"Invalid TLS slot");
return NULL;
}

void *pEEThreadTLS = (BYTE*) pBase + (slotAdjusted * sizeof(void*));


// Read the thread's TLS value.
HRESULT hr = GetProcess()->SafeReadStruct(PTR_TO_CORDB_ADDRESS(pEEThreadTLS), &ret);
if (FAILED(hr))
{
LOG((LF_CORDB, LL_INFO1000, "CUT::GEETV: failed to read TLS value: computed addr=0x%p index=%d, err=%x\n",
pEEThreadTLS, slot, hr));

return NULL;
}

LOG((LF_CORDB, LL_INFO1000000, "CUT::GEETV: EE Thread TLS value is 0x%p for thread 0x%x, slot 0x%x\n", ret, m_id, slot));

return ret;
}

// This does a WriteProcessMemory to write to the debuggee's TLS slot allotted to EEThread
//
// Arguments:
// EETlsValue - the value to write to the remote TLS slot.
//
// Notes:
// The TLS slot is m_TLSIndex.
//
// This is very brittle because the OS can lazily allocates storage for TLS slots.
// In order to gaurantee the storage is available, it must have been written to by the debuggee.
// For managed threads, that's easy because the Thread* is already written to the slot.
// But for pure native threads where GetThread() == NULL, the storage may not yet be allocated.
//
// The saving grace is that the debuggee's hijack filters will force the TLS to be allocated before it
// sends a flare.
//
// Therefore, this function can only be called:
// 1) on a managed thread
// 2) on a native thread after that thread has been hijacked and sent a flare.
//
// This is brittle reasoning, but so is the rest of interop-debugging.
//
HRESULT CordbUnmanagedThread::SetEEThreadValue(REMOTE_PTR EETlsValue)
{
FAIL_IF_NEUTERED(this);

// Compute the address of the necessary TLS value.
DebuggerIPCRuntimeOffsets *pRO = &(GetProcess()->m_runtimeOffsets);

// Compute the address of the necessary TLS value.
HRESULT hr = LoadTLSArrayPtr();
if (FAILED(hr))
{
return hr;
}


DWORD slot = (DWORD) pRO->m_TLSIndex;

void * pBase = NULL;
SIZE_T slotAdjusted = slot;
if (slot < TLS_MINIMUM_AVAILABLE)
{
pBase = m_pTLSArray;
}
else if (slot < TLS_MINIMUM_AVAILABLE+TLS_EXPANSION_SLOTS)
{
pBase = m_pTLSExtendedArray;
slotAdjusted -= TLS_MINIMUM_AVAILABLE;

// Expansion slot is lazily allocated. If we're trying to read from it, but hasn't been allocated,
// then the TLS slot is still the default value, which is 0.
if (pBase == NULL)
{
// See reasoning in header for why this should succeed.
_ASSERTE(!"Can't set to expansion slots because they haven't been allocated");
return E_FAIL;
}
}
else
{
// Slot is out of range. Shouldn't happen unless debuggee is corrupted.
_ASSERTE(!"Invalid TLS slot");
return E_INVALIDARG;
}


void *pEEThreadTLS = (BYTE*) pBase + (slotAdjusted * sizeof(void*));


// Write the thread's TLS value.
hr = GetProcess()->SafeWriteStruct(PTR_TO_CORDB_ADDRESS(pEEThreadTLS), &EETlsValue);

if (FAILED(hr))
{
LOG((LF_CORDB, LL_INFO1000, "CUT::SEETV: failed to set TLS value: "
"computed addr=0x%p index=%d, err=%x\n",
pEEThreadTLS, pRO->m_TLSIndex, hr));

return hr;
}

LOG((LF_CORDB, LL_INFO1000000,
"CUT::SEETV: EE Thread TLS value is now 0x%p for thread 0x%x\n",
EETlsValue, m_id));

return S_OK;
}
#else // FEATURE_IMPLICIT_TLS

#ifdef DBG_TARGET_X86
#define WINNT_OFFSETOF__TEB__ThreadLocalStoragePointer 0x2c
#elif defined(DBG_TARGET_AMD64)
#define WINNT_OFFSETOF__TEB__ThreadLocalStoragePointer 0x58
#elif defined(DBG_TARGET_ARM)
#define WINNT_OFFSETOF__TEB__ThreadLocalStoragePointer 0x2c
#elif defined(DBG_TARGET_ARM64)
#define WINNT_OFFSETOF__TEB__ThreadLocalStoragePointer 0x58
#endif

// sets the value of gCurrentThreadInfo.m_pThread
HRESULT CordbUnmanagedThread::SetEEThreadValue(REMOTE_PTR EETlsValue)
{
Expand Down Expand Up @@ -3275,7 +3112,7 @@ REMOTE_PTR CordbUnmanagedThread::GetClrModuleTlsDataAddress()
DWORD slot = (DWORD)(GetProcess()->m_runtimeOffsets.m_TLSIndex);

REMOTE_PTR clrModuleTlsDataAddr;
hr = GetProcess()->SafeReadStruct(PTR_TO_CORDB_ADDRESS((BYTE*)tlsArrayAddr + slot * sizeof(void*)), &clrModuleTlsDataAddr);
hr = GetProcess()->SafeReadStruct(PTR_TO_CORDB_ADDRESS((BYTE*)tlsArrayAddr + (slot & 0xFFFF) * sizeof(void*)), &clrModuleTlsDataAddr);
if (FAILED(hr))
{
return NULL;
Expand All @@ -3287,7 +3124,7 @@ REMOTE_PTR CordbUnmanagedThread::GetClrModuleTlsDataAddress()
return NULL;
}

return clrModuleTlsDataAddr;
return (BYTE*) clrModuleTlsDataAddr + ((slot & 0x7FFF0000) >> 16);
}

// gets the value of gCurrentThreadInfo.m_EETlsData
Expand All @@ -3312,8 +3149,6 @@ REMOTE_PTR CordbUnmanagedThread::GetEETlsDataBlock()
return ret;
}

#endif // FEATURE_IMPLICIT_TLS

/*
* CacheEEDebuggerWord
*
Expand All @@ -3337,11 +3172,7 @@ void CordbUnmanagedThread::CacheEEDebuggerWord()
{
LOG((LF_CORDB, LL_INFO1000, "CacheEEDW: Entered\n"));

#ifdef FEATURE_IMPLICIT_TLS
REMOTE_PTR value = (REMOTE_PTR)GetEEThreadValue();
#else
REMOTE_PTR value = (REMOTE_PTR)GetTlsSlot(GetProcess()->m_runtimeOffsets.m_TLSIndex);
#endif

if ((((DWORD)value) & 0x1) == 1)
{
Expand Down
5 changes: 0 additions & 5 deletions src/debug/ee/rcthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,6 @@ HRESULT DebuggerRCThread::SetupRuntimeOffsets(DebuggerIPCControlBlock * pDebugge
g_pEEInterface->GetRuntimeOffsets(&pDebuggerRuntimeOffsets->m_TLSIndex,
&pDebuggerRuntimeOffsets->m_TLSIsSpecialIndex,
&pDebuggerRuntimeOffsets->m_TLSCantStopIndex,
&pDebuggerRuntimeOffsets->m_TLSIndexOfPredefs,
&pDebuggerRuntimeOffsets->m_EEThreadStateOffset,
&pDebuggerRuntimeOffsets->m_EEThreadStateNCOffset,
&pDebuggerRuntimeOffsets->m_EEThreadPGCDisabledOffset,
Expand All @@ -778,10 +777,6 @@ HRESULT DebuggerRCThread::SetupRuntimeOffsets(DebuggerIPCControlBlock * pDebugge
&pDebuggerRuntimeOffsets->m_EEFrameNextOffset,
&pDebuggerRuntimeOffsets->m_EEIsManagedExceptionStateMask);

#ifndef FEATURE_IMPLICIT_TLS
_ASSERTE((pDebuggerRuntimeOffsets->m_TLSIndexOfPredefs != 0) || !"CExecutionEngine::TlsIndex is not initialized yet");
#endif

// Remember the struct in the control block.
pDebuggerIPCControlBlock->m_pRuntimeOffsets = pDebuggerRuntimeOffsets;

Expand Down
1 change: 0 additions & 1 deletion src/debug/inc/dbgipcevents.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ struct MSLAYOUT DebuggerIPCRuntimeOffsets
SIZE_T m_TLSIndex; // The TLS index the CLR is using to hold Thread objects
SIZE_T m_TLSIsSpecialIndex; // The index into the Predef block of the the "IsSpecial" status for a thread.
SIZE_T m_TLSCantStopIndex; // The index into the Predef block of the the Can't-Stop count.
SIZE_T m_TLSIndexOfPredefs; // The TLS index of the Predef block.
SIZE_T m_EEThreadStateOffset; // Offset of m_state in a Thread
SIZE_T m_EEThreadStateNCOffset; // Offset of m_stateNC in a Thread
SIZE_T m_EEThreadPGCDisabledOffset; // Offset of the bit for whether PGC is disabled or not in a Thread
Expand Down
1 change: 0 additions & 1 deletion src/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_ConditionalContracts, W("ConditionalCon
CONFIG_DWORD_INFO(INTERNAL_ConsistencyCheck, W("ConsistencyCheck"), 0, "")
CONFIG_DWORD_INFO_EX(INTERNAL_ContinueOnAssert, W("ContinueOnAssert"), 0, "If set, doesn't break on asserts.", CLRConfig::REGUTIL_default)
RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_disableStackOverflowProbing, W("disableStackOverflowProbing"), 0, "", CLRConfig::FavorConfigFile)
CONFIG_DWORD_INFO(INTERNAL_EnforceEEThreadNotRequiredContracts, W("EnforceEEThreadNotRequiredContracts"), 0, "Indicates whether to enforce EE_THREAD_NOT_REQUIRED contracts (not enforced by default for perf reasons). Only applicable in dbg/chk builds--EE_THREAD_NOT_REQUIRED contracts never enforced in ret builds.")
CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_InjectFatalError, W("InjectFatalError"), "")
CONFIG_DWORD_INFO_EX(INTERNAL_InjectFault, W("InjectFault"), 0, "", CLRConfig::REGUTIL_default)
CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_SuppressChecks, W("SuppressChecks"), "")
Expand Down
7 changes: 1 addition & 6 deletions src/inc/dacvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ DEFINE_DACVAR(ULONG, BOOL, SystemDomain__s_fForceInstrument, SystemDomain::s_fFo
DEFINE_DACVAR(ULONG, PTR_SharedDomain, SharedDomain__m_pSharedDomain, SharedDomain::m_pSharedDomain)


DEFINE_DACVAR(ULONG, DWORD, CExecutionEngine__TlsIndex, CExecutionEngine::TlsIndex)
DEFINE_DACVAR(ULONG, DWORD, dac__g_TlsIndex, g_TlsIndex)

#if defined(FEATURE_WINDOWSPHONE)
DEFINE_DACVAR(ULONG, int, CCLRErrorReportingManager__g_ECustomDumpFlavor, CCLRErrorReportingManager::g_ECustomDumpFlavor)
Expand All @@ -150,11 +150,6 @@ DEFINE_DACVAR(ULONG, PTR_JITNotification, dac__g_pNotificationTable, ::g_pNotifi
DEFINE_DACVAR(ULONG, ULONG32, dac__g_dacNotificationFlags, ::g_dacNotificationFlags)
DEFINE_DACVAR(ULONG, PTR_GcNotification, dac__g_pGcNotificationTable, ::g_pGcNotificationTable)

#ifndef FEATURE_IMPLICIT_TLS
DEFINE_DACVAR(ULONG, DWORD, dac__gThreadTLSIndex, ::gThreadTLSIndex)
DEFINE_DACVAR(ULONG, DWORD, dac__gAppDomainTLSIndex, ::gAppDomainTLSIndex)
#endif

DEFINE_DACVAR(ULONG, PTR_EEConfig, dac__g_pConfig, ::g_pConfig)

DEFINE_DACVAR(ULONG, MscorlibBinder, dac__g_Mscorlib, ::g_Mscorlib)
Expand Down
7 changes: 0 additions & 7 deletions src/inc/switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,6 @@
#define GC_STATS
#endif


#if defined(_DEBUG) && !defined(DACCESS_COMPILE) && (defined(_TARGET_X86_) || defined(_TARGET_AMD64_))
// On x86/x64 Windows debug builds, respect the COMPlus_EnforceEEThreadNotRequiredContracts
// runtime switch. See code:InitThreadManager and code:GetThreadGenericFullCheck
#define ENABLE_GET_THREAD_GENERIC_FULL_CHECK
#endif

#if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
#define USE_UPPER_ADDRESS 0

Expand Down
Loading

0 comments on commit 27a25bd

Please sign in to comment.