diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h index 89999fac659592..f8f003d70bb573 100644 --- a/src/coreclr/debug/ee/debugger.h +++ b/src/coreclr/debug/ee/debugger.h @@ -3835,7 +3835,7 @@ HANDLE OpenWin32EventOrThrow( #define SENDIPCEVENT_RAW_END SENDIPCEVENT_RAW_END_EX // Suspend-aware SENDIPCEVENT macros: -// Check whether __thread has been suspended by the debugger via SetDebugState(). +// Check whether thread has been suspended by the debugger via SetDebugState(). // If this thread has been suspended, it shouldn't send any event to the RS because the // debugger may not be expecting it. Instead, just leave the lock and retry. // When we leave, we'll enter coop mode first and get suspended if a suspension is in progress. diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index a7e3dbd57cf651..157f5ba824615d 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -335,12 +335,6 @@ extern uint64_t g_startupTimelineEvents[NUM_STARTUP_TIMELINE_EVENTS]; #define C_ASSERT(e) static_assert(e, #e) #endif // C_ASSERT -#ifdef _MSC_VER -#define DECLSPEC_THREAD __declspec(thread) -#else // _MSC_VER -#define DECLSPEC_THREAD __thread -#endif // !_MSC_VER - // PAL Numbers // Used to ensure cross-compiler compatibility when declaring large // integer constants. 64-bit integer constants should be wrapped in the diff --git a/src/coreclr/nativeaot/Runtime/GCHelpers.cpp b/src/coreclr/nativeaot/Runtime/GCHelpers.cpp index 6e37321143e541..e7fdf907977b32 100644 --- a/src/coreclr/nativeaot/Runtime/GCHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/GCHelpers.cpp @@ -405,7 +405,7 @@ FCIMPLEND // The MethodTable is remembered in some slow-path allocation paths. This value is used in event tracing. // It may statistically correlate with the most allocated type on the given stack/thread. -DECLSPEC_THREAD +static PLATFORM_THREAD_LOCAL MethodTable* tls_pLastAllocationEEType = NULL; MethodTable* GetLastAllocEEType() diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp index 8d2c4b0e7c68d0..f42f8d524d7b44 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp @@ -50,7 +50,7 @@ ep_rt_aot_walk_managed_stack_for_thread ( EP_ASSERT (thread != NULL); EP_ASSERT (stack_contents != NULL); - StackFrameIterator frameIterator(thread, thread->GetTransitionFrameForSampling()); + StackFrameIterator frameIterator(thread, thread->GetTransitionFrameForSampling()); while (frameIterator.IsValid()) { @@ -223,11 +223,7 @@ ep_rt_aot_diagnostics_command_line_get (void) namespace { - #ifdef TARGET_UNIX - __thread EventPipeThreadHolder* eventpipe_tls_instance; - #else - thread_local EventPipeThreadHolder* eventpipe_tls_instance; - #endif + PLATFORM_THREAD_LOCAL EventPipeThreadHolder* eventpipe_tls_instance; void free_thread_holder () { diff --git a/src/coreclr/nativeaot/Runtime/threadstore.cpp b/src/coreclr/nativeaot/Runtime/threadstore.cpp index 2dc0c1a64d9738..daf745ba0b65ef 100644 --- a/src/coreclr/nativeaot/Runtime/threadstore.cpp +++ b/src/coreclr/nativeaot/Runtime/threadstore.cpp @@ -418,7 +418,7 @@ FCIMPLEND C_ASSERT(sizeof(Thread) == sizeof(RuntimeThreadLocals)); #ifndef _MSC_VER -__thread RuntimeThreadLocals tls_CurrentThread; +PLATFORM_THREAD_LOCAL RuntimeThreadLocals tls_CurrentThread; #endif EXTERN_C RuntimeThreadLocals* RhpGetThread() diff --git a/src/coreclr/nativeaot/Runtime/threadstore.inl b/src/coreclr/nativeaot/Runtime/threadstore.inl index 5b4701249eec4b..4be81a7e60891b 100644 --- a/src/coreclr/nativeaot/Runtime/threadstore.inl +++ b/src/coreclr/nativeaot/Runtime/threadstore.inl @@ -1,12 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +EXTERN_C #ifdef _MSC_VER // a workaround to prevent tls_CurrentThread from becoming dynamically checked/initialized. -EXTERN_C __declspec(selectany) __declspec(thread) RuntimeThreadLocals tls_CurrentThread; -#else -EXTERN_C __thread RuntimeThreadLocals tls_CurrentThread; +__declspec(selectany) #endif +PLATFORM_THREAD_LOCAL RuntimeThreadLocals tls_CurrentThread; // static inline Thread * ThreadStore::RawGetCurrentThread() diff --git a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp index ef025469fb9170..74c709e922b31a 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp @@ -481,7 +481,7 @@ thread_local TlsDestructionMonitor tls_destructionMonitor; #endif // This thread local variable is used for delegate marshalling -DECLSPEC_THREAD intptr_t tls_thunkData; +PLATFORM_THREAD_LOCAL intptr_t tls_thunkData; #ifdef FEATURE_EMULATED_TLS EXTERN_C intptr_t* RhpGetThunkData() @@ -1061,48 +1061,45 @@ int32_t PalGetProcessCpuCount() return g_RhNumberOfProcessors; } -__thread void* pStackHighOut = NULL; -__thread void* pStackLowOut = NULL; - // Retrieves the entire range of memory dedicated to the calling thread's stack. This does // not get the current dynamic bounds of the stack, which can be significantly smaller than // the maximum bounds. bool PalGetMaximumStackBounds(_Out_ void** ppStackLowOut, _Out_ void** ppStackHighOut) { - if (pStackHighOut == NULL) - { + void* pStackHighOut = NULL; + void* pStackLowOut = NULL; + #ifdef __APPLE__ - // This is a Mac specific method - pStackHighOut = pthread_get_stackaddr_np(pthread_self()); - pStackLowOut = ((uint8_t *)pStackHighOut - pthread_get_stacksize_np(pthread_self())); + // This is a Mac specific method + pStackHighOut = pthread_get_stackaddr_np(pthread_self()); + pStackLowOut = ((uint8_t *)pStackHighOut - pthread_get_stacksize_np(pthread_self())); #else // __APPLE__ - pthread_attr_t attr; - size_t stackSize; - int status; + pthread_attr_t attr; + size_t stackSize; + int status; - pthread_t thread = pthread_self(); + pthread_t thread = pthread_self(); - status = pthread_attr_init(&attr); - ASSERT_MSG(status == 0, "pthread_attr_init call failed"); + status = pthread_attr_init(&attr); + ASSERT_MSG(status == 0, "pthread_attr_init call failed"); #if HAVE_PTHREAD_ATTR_GET_NP - status = pthread_attr_get_np(thread, &attr); + status = pthread_attr_get_np(thread, &attr); #elif HAVE_PTHREAD_GETATTR_NP - status = pthread_getattr_np(thread, &attr); + status = pthread_getattr_np(thread, &attr); #else #error Dont know how to get thread attributes on this platform! #endif - ASSERT_MSG(status == 0, "pthread_getattr_np call failed"); + ASSERT_MSG(status == 0, "pthread_getattr_np call failed"); - status = pthread_attr_getstack(&attr, &pStackLowOut, &stackSize); - ASSERT_MSG(status == 0, "pthread_attr_getstack call failed"); + status = pthread_attr_getstack(&attr, &pStackLowOut, &stackSize); + ASSERT_MSG(status == 0, "pthread_attr_getstack call failed"); - status = pthread_attr_destroy(&attr); - ASSERT_MSG(status == 0, "pthread_attr_destroy call failed"); + status = pthread_attr_destroy(&attr); + ASSERT_MSG(status == 0, "pthread_attr_destroy call failed"); - pStackHighOut = (uint8_t*)pStackLowOut + stackSize; + pStackHighOut = (uint8_t*)pStackLowOut + stackSize; #endif // __APPLE__ - } *ppStackLowOut = pStackLowOut; *ppStackHighOut = pStackHighOut; diff --git a/src/coreclr/vm/amd64/AsmMacros.inc b/src/coreclr/vm/amd64/AsmMacros.inc index 8d05620571257d..c6966135fc7ef4 100644 --- a/src/coreclr/vm/amd64/AsmMacros.inc +++ b/src/coreclr/vm/amd64/AsmMacros.inc @@ -467,7 +467,7 @@ OFFSETOF__ee_alloc_context EQU OFFSETOF__RuntimeThreadLocals__ee_alloc_context ; Pushes a TransitionBlock on the stack without saving the argument registers. See ; the PROLOG_WITH_TRANSITION_BLOCK macro for the stack layout. PUSH_COOP_PINVOKE_FRAME macro target - + __PWTB_StackAlloc = SIZEOF_MAX_OUTGOING_ARGUMENT_HOMES + 8 ; alignment to make the stack 16b aligned __PWTB_TransitionBlock = __PWTB_StackAlloc diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index bd00b1c7a5406d..bc776643ff1cb9 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -1664,7 +1664,7 @@ static uint32_t g_flsIndex = FLS_OUT_OF_INDEXES; #define FLS_STATE_ARMED 1 #define FLS_STATE_INVOKED 2 -static thread_local byte t_flsState; +static PLATFORM_THREAD_LOCAL byte t_flsState; // This is called when each *fiber* is destroyed. When the home fiber of a thread is destroyed, // it means that the thread itself is destroyed. diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h index d4be1f1f00d4a6..bb587124cf168f 100644 --- a/src/coreclr/vm/common.h +++ b/src/coreclr/vm/common.h @@ -207,18 +207,6 @@ EXTERN_C AppDomain* STDCALL GetAppDomain(); extern BOOL isMemoryReadable(const TADDR start, unsigned len); -#ifndef memcpyUnsafe_f -#define memcpyUnsafe_f - -// use this when you want to memcpy something that contains GC refs -FORCEINLINE void* memcpyUnsafe(void *dest, const void *src, size_t len) -{ - WRAPPER_NO_CONTRACT; - return memcpy(dest, src, len); -} - -#endif // !memcpyUnsafe_f - FORCEINLINE void* memcpyNoGCRefs(void * dest, const void * src, size_t len) { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 598e68fcc4467e..74f6adc2c8b4a5 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -344,15 +344,11 @@ HCIMPLEND // //======================================================================== -// Define the t_ThreadStatics variable here, so that these helpers can use -// the most optimal TLS access pattern for the platform when inlining the -// GetThreadLocalStaticBaseIfExistsAndInitialized function. // Using compiler specific thread local storage directives due to linkage issues. #ifdef _MSC_VER -__declspec(selectany) __declspec(thread) ThreadLocalData t_ThreadStatics; -#else -__thread ThreadLocalData t_ThreadStatics; +__declspec(selectany) #endif // _MSC_VER +PLATFORM_THREAD_LOCAL ThreadLocalData t_ThreadStatics; extern "C" void QCALLTYPE GetThreadStaticsByMethodTable(QCall::ByteRefOnStack refHandle, MethodTable* pMT, bool gcStatic) { diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index 1834db25e7b421..3bc2038b7d52b2 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -72,7 +72,7 @@ TailCallTls::TailCallTls() } #ifndef _MSC_VER -__thread RuntimeThreadLocals t_runtime_thread_locals; +PLATFORM_THREAD_LOCAL RuntimeThreadLocals t_runtime_thread_locals; #endif Thread* STDCALL GetThreadHelper() @@ -345,7 +345,7 @@ bool Thread::DetectHandleILStubsForDebugger() } #ifndef _MSC_VER -__thread ThreadLocalInfo t_CurrentThreadInfo; +PLATFORM_THREAD_LOCAL ThreadLocalInfo t_CurrentThreadInfo; #endif // _MSC_VER #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index fa3d3342e903e2..9f177c67c8f24c 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -331,13 +331,13 @@ void DestroyThread(Thread *th); DWORD GetRuntimeId(); -#define CREATETHREAD_IF_NULL_FAILFAST(__thread, __msg) \ +#define CREATETHREAD_IF_NULL_FAILFAST(thread__, msg__) \ { \ - HRESULT __ctinffhr; \ - __thread = SetupThreadNoThrow(&__ctinffhr); \ - if (__thread == NULL) \ + HRESULT ctinffhr__; \ + thread__ = SetupThreadNoThrow(&ctinffhr__); \ + if (thread__ == NULL) \ { \ - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(__ctinffhr, __msg); \ + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(ctinffhr__, msg__); \ UNREACHABLE(); \ } \ } @@ -433,11 +433,11 @@ struct RuntimeThreadLocals #ifdef _MSC_VER // use selectany to avoid initialization de-optimization issues in the compiler -__declspec(selectany) thread_local +__declspec(selectany) #else -extern __thread +extern #endif -RuntimeThreadLocals t_runtime_thread_locals; +PLATFORM_THREAD_LOCAL RuntimeThreadLocals t_runtime_thread_locals; typedef DPTR(struct RuntimeThreadLocals) PTR_RuntimeThreadLocals; typedef DPTR(struct gc_alloc_context) PTR_gc_alloc_context; diff --git a/src/coreclr/vm/threads.inl b/src/coreclr/vm/threads.inl index 8b59caaa10437e..1cf28d27c6dc42 100644 --- a/src/coreclr/vm/threads.inl +++ b/src/coreclr/vm/threads.inl @@ -27,11 +27,11 @@ EXTERN_C UINT32 _tls_index; #endif #ifdef _MSC_VER -__declspec(selectany) thread_local +__declspec(selectany) #else -EXTERN_C __thread +EXTERN_C #endif -ThreadLocalInfo t_CurrentThreadInfo; +PLATFORM_THREAD_LOCAL ThreadLocalInfo t_CurrentThreadInfo; inline Thread* GetThreadNULLOk() { diff --git a/src/coreclr/vm/threadstatics.h b/src/coreclr/vm/threadstatics.h index 9bcc4e9a6a5f13..b114555982de46 100644 --- a/src/coreclr/vm/threadstatics.h +++ b/src/coreclr/vm/threadstatics.h @@ -87,11 +87,11 @@ typedef DPTR(ThreadLocalData) PTR_ThreadLocalData; // Using compiler specific thread local storage directives due to linkage issues. #ifndef DACCESS_COMPILE +extern #ifdef _MSC_VER -extern __declspec(selectany) __declspec(thread) ThreadLocalData t_ThreadStatics; -#else -extern __thread ThreadLocalData t_ThreadStatics; +__declspec(selectany) #endif // _MSC_VER +PLATFORM_THREAD_LOCAL ThreadLocalData t_ThreadStatics; #endif // !DACCESS_COMPILE #define NUMBER_OF_TLSOFFSETS_NOT_USED_IN_NONCOLLECTIBLE_ARRAY 2 diff --git a/src/native/minipal/utils.h b/src/native/minipal/utils.h index de25c457341e4f..23a6a643601d1e 100644 --- a/src/native/minipal/utils.h +++ b/src/native/minipal/utils.h @@ -44,6 +44,17 @@ #define LIBC_CALLBACK #endif +// Define a macro to declare TLS variables. There are cases +// where we want to use the platform specific thread-local +// storage mechanism: +// * Better performance characteristics compared to C++'s thread_local keyword. +// * Makes consuming TLS variables from assembly code easier. +#if defined(_MSC_VER) +#define PLATFORM_THREAD_LOCAL __declspec(thread) +#else +#define PLATFORM_THREAD_LOCAL __thread +#endif + #if defined(_MSC_VER) # if defined(__SANITIZE_ADDRESS__) # define HAS_ADDRESS_SANITIZER