Inline TLS access. (mono/mono#16882)
authorJay Krell <jaykrell@microsoft.com>
Sat, 21 Sep 2019 16:35:19 +0000 (09:35 -0700)
committerAlexander Köplinger <alex.koeplinger@outlook.com>
Sat, 21 Sep 2019 16:35:19 +0000 (18:35 +0200)
The same functions are referenced by JIT and runtime.
The JIT uses cannot be inlined. The runtime can.
Since I could not get anything else to build and the change is simple and mechanical, now two sets of functions are provided, inline and extern. Extern just calls inline.
This PR appears to change all the uses, but it is only the JIT uses. The runtime ones just work and keep the old names.

We should also consider building desktop with LTO/LTCG, which would do all this automatically, smarter, more generally. A quick experiment shows it grows the runtime size, which is why I say desktop.

Commit migrated from https://github.com/mono/mono/commit/aca55a42aa5117f4406b68b1ac217063cc7ab3ec

src/mono/mono/metadata/jit-icall-reg.h
src/mono/mono/mini/exceptions-amd64.c
src/mono/mono/mini/mini-arm.c
src/mono/mono/mini/mini-ppc.c
src/mono/mono/mini/mini-runtime.c
src/mono/mono/mini/mini-s390x.c
src/mono/mono/utils/mono-tls.c
src/mono/mono/utils/mono-tls.h

index 91c0ce6..5fab43b 100644 (file)
@@ -48,11 +48,11 @@ MONO_JIT_ICALL (generic_trampoline_generic_virtual_remoting)        \
 MONO_JIT_ICALL (generic_trampoline_vcall)      \
        \
 /* These must be ordered like MonoTlsKey (alphabetical). */ \
-MONO_JIT_ICALL (mono_tls_get_domain) \
-MONO_JIT_ICALL (mono_tls_get_jit_tls) \
-MONO_JIT_ICALL (mono_tls_get_lmf_addr) \
-MONO_JIT_ICALL (mono_tls_get_sgen_thread_info) \
-MONO_JIT_ICALL (mono_tls_get_thread) \
+MONO_JIT_ICALL (mono_tls_get_domain_extern) \
+MONO_JIT_ICALL (mono_tls_get_jit_tls_extern) \
+MONO_JIT_ICALL (mono_tls_get_lmf_addr_extern) \
+MONO_JIT_ICALL (mono_tls_get_sgen_thread_info_extern) \
+MONO_JIT_ICALL (mono_tls_get_thread_extern) \
        \
 MONO_JIT_ICALL (__emul_fadd)   \
 MONO_JIT_ICALL (__emul_fcmp_ceq)       \
@@ -341,7 +341,7 @@ MONO_JIT_ICALL (ves_icall_thread_finish_async_abort) \
        \
 MONO_JIT_ICALL (count) \
 
-#define MONO_JIT_ICALL_mono_get_lmf_addr MONO_JIT_ICALL_mono_tls_get_lmf_addr
+#define MONO_JIT_ICALL_mono_get_lmf_addr MONO_JIT_ICALL_mono_tls_get_lmf_addr_extern
 
 #ifdef __cplusplus
 typedef enum MonoJitICallId : gsize // Widen to gsize for use in MonoJumpInfo union.
index b274cc4..186c005 100644 (file)
@@ -97,7 +97,7 @@ get_win32_restore_stack (void)
        amd64_call_reg (code, AMD64_R11);
 
        /* get jit_tls with context to restore */
-       amd64_mov_reg_imm (code, AMD64_R11, mono_tls_get_jit_tls);
+       amd64_mov_reg_imm (code, AMD64_R11, mono_tls_get_jit_tls_extern);
        amd64_call_reg (code, AMD64_R11);
 
        /* move jit_tls from return reg to arg reg */
index c384c46..76c2c73 100644 (file)
@@ -428,7 +428,7 @@ emit_save_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
                code = emit_tls_get (code, ARMREG_R0, mono_tls_get_tls_offset (TLS_KEY_LMF_ADDR));
        } else {
                mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID,
-                                                        GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr));
+                                                        GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr_extern));
                code = emit_call_seq (cfg, code);
        }
        /* we build the MonoLMF structure on the stack - see mini-arm.h */
index fc8851e..12f7d77 100644 (file)
@@ -5156,7 +5156,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL);
                }
                mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID,
-                            GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr));
+                            GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr_extern));
                if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
                        ppc_load_func (code, PPC_CALL_REG, 0);
                        ppc_mtlr (code, PPC_CALL_REG);
index c991aa2..98cea18 100644 (file)
@@ -4646,11 +4646,11 @@ register_icalls (void)
        register_icall (pthread_getspecific, mono_icall_sig_ptr_ptr, TRUE);
 #endif
        /* Register tls icalls */
-       register_icall_no_wrapper (mono_tls_get_thread, mono_icall_sig_ptr);
-       register_icall_no_wrapper (mono_tls_get_jit_tls, mono_icall_sig_ptr);
-       register_icall_no_wrapper (mono_tls_get_domain, mono_icall_sig_ptr);
-       register_icall_no_wrapper (mono_tls_get_sgen_thread_info, mono_icall_sig_ptr);
-       register_icall_no_wrapper (mono_tls_get_lmf_addr, mono_icall_sig_ptr);
+       register_icall_no_wrapper (mono_tls_get_thread_extern, mono_icall_sig_ptr);
+       register_icall_no_wrapper (mono_tls_get_jit_tls_extern, mono_icall_sig_ptr);
+       register_icall_no_wrapper (mono_tls_get_domain_extern, mono_icall_sig_ptr);
+       register_icall_no_wrapper (mono_tls_get_sgen_thread_info_extern, mono_icall_sig_ptr);
+       register_icall_no_wrapper (mono_tls_get_lmf_addr_extern, mono_icall_sig_ptr);
 
        register_icall_no_wrapper (mono_interp_entry_from_trampoline, mono_icall_sig_void_ptr_ptr);
        register_icall_no_wrapper (mono_interp_to_native_trampoline, mono_icall_sig_void_ptr_ptr);
index bef1e45..06f4231 100644 (file)
@@ -5650,7 +5650,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                /*---------------------------------------------------------------*/
                mono_add_patch_info (cfg, code - cfg->native_code, 
                                MONO_PATCH_INFO_JIT_ICALL_ID,
-                               GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr));
+                               GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr_extern));
                S390_CALL_TEMPLATE(code, s390_r1);
 
                /*---------------------------------------------------------------*/     
index 26f6b4c..a73a0a3 100644 (file)
@@ -8,84 +8,10 @@
  * Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
  */
 
-#include <mono/utils/mach-support.h>
-
 #include "mono-tls.h"
 
-/*
- * On all platforms we should be able to use either __thread or __declspec (thread)
- * or pthread/TlsGetValue.
- * Certain platforms will support fast tls only when using one of the thread local
- * storage backends. By default this is __thread if we have MONO_KEYWORD_THREAD defined.
- *
- * By default all platforms will call into these native getters whenever they need
- * to get a tls value. On certain platforms we can try to be faster than this and
- * avoid the call. We call this fast tls and each platform defines its own way to
- * achieve this. For this, a platform has to define MONO_ARCH_HAVE_INLINED_TLS,
- * and provide alternative getters/setters for a MonoTlsKey. In order to have fast
- * getter/setters, the platform has to declare a way to fetch an internal offset
- * (MONO_THREAD_VAR_OFFSET) which is stored here, and in the arch specific file
- * probe the system to see if we can use the offset initialized here. If these
- * run-time checks don't succeed we just use the fallbacks.
- *
- * In case we would wish to provide fast inlined tls for aot code, we would need
- * to be sure that, at run-time, these two platform checks would never fail
- * otherwise the tls getter/setters that we emitted would not work. Normally,
- * there is little incentive to support this since tls access is most common in
- * wrappers and managed allocators, both of which are not aot-ed by default.
- * So far, we never supported inlined fast tls on full-aot systems.
- */
-
 #ifdef MONO_KEYWORD_THREAD
 
-/* tls attribute */
-#if HAVE_TLS_MODEL_ATTR
-
-#if defined(__PIC__) && !defined(PIC)
-/*
- * Must be compiling -fPIE, for executables.  Build PIC
- * but with initial-exec.
- * http://bugs.gentoo.org/show_bug.cgi?id=165547
- */
-#define PIC
-#define PIC_INITIAL_EXEC
-#endif
-
-/*
- * Define this if you want a faster libmono, which cannot be loaded dynamically as a
- * module.
- */
-//#define PIC_INITIAL_EXEC
-
-#if defined(PIC)
-
-#ifdef PIC_INITIAL_EXEC
-#define MONO_TLS_FAST __attribute__ ((__tls_model__("initial-exec")))
-#else
-#if defined (__powerpc__)
-/* local dynamic requires a call to __tls_get_addr to look up the
-   TLS block address via the Dynamic Thread Vector. In this case Thread
-   Pointer relative offsets can't be used as this modules TLS was
-   allocated separately (none contiguoiusly) from the initial TLS
-   block.
-
-   For now we will disable this. */
-#define MONO_TLS_FAST
-#else
-#define MONO_TLS_FAST __attribute__ ((__tls_model__("local-dynamic")))
-#endif
-#endif
-
-#else
-
-#define MONO_TLS_FAST __attribute__ ((__tls_model__("local-exec")))
-
-#endif
-
-#else
-#define MONO_TLS_FAST
-#endif
-
 /* Runtime offset detection */
 #if defined(TARGET_AMD64) && !defined(TARGET_MACH) && !defined(HOST_WIN32) /* __thread likely not tested on mac/win */
 
@@ -191,32 +117,24 @@ MONO_KEYWORD_THREAD MonoLMF           **mono_tls_lmf_addr MONO_TLS_FAST;
 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
 #endif
 
-static MonoNativeTlsKey mono_tls_key_thread;
-static MonoNativeTlsKey mono_tls_key_jit_tls;
-static MonoNativeTlsKey mono_tls_key_domain;
-static MonoNativeTlsKey mono_tls_key_sgen_thread_info;
-static MonoNativeTlsKey mono_tls_key_lmf_addr;
+MonoNativeTlsKey mono_tls_key_thread;
+MonoNativeTlsKey mono_tls_key_jit_tls;
+MonoNativeTlsKey mono_tls_key_domain;
+MonoNativeTlsKey mono_tls_key_sgen_thread_info;
+MonoNativeTlsKey mono_tls_key_lmf_addr;
 
 #endif
 
-static gint32 tls_offsets [TLS_KEY_NUM];
-
-#ifdef MONO_KEYWORD_THREAD
-#define MONO_TLS_GET_VALUE(tls_var,tls_key) (tls_var)
-#define MONO_TLS_SET_VALUE(tls_var,tls_key,value) (tls_var = value)
-#else
-#define MONO_TLS_GET_VALUE(tls_var,tls_key) (mono_native_tls_get_value (tls_key))
-#define MONO_TLS_SET_VALUE(tls_var,tls_key,value) (mono_native_tls_set_value (tls_key, value))
-#endif
+gint32 mono_tls_offsets [TLS_KEY_NUM];
 
 void
 mono_tls_init_gc_keys (void)
 {
 #ifdef MONO_KEYWORD_THREAD
-       MONO_THREAD_VAR_OFFSET (mono_tls_sgen_thread_info, tls_offsets [TLS_KEY_SGEN_THREAD_INFO]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_sgen_thread_info, mono_tls_offsets [TLS_KEY_SGEN_THREAD_INFO]);
 #else
        mono_native_tls_alloc (&mono_tls_key_sgen_thread_info, NULL);
-       MONO_THREAD_VAR_OFFSET (mono_tls_key_sgen_thread_info, tls_offsets [TLS_KEY_SGEN_THREAD_INFO]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_key_sgen_thread_info, mono_tls_offsets [TLS_KEY_SGEN_THREAD_INFO]);
 #endif
 }
 
@@ -224,19 +142,19 @@ void
 mono_tls_init_runtime_keys (void)
 {
 #ifdef MONO_KEYWORD_THREAD
-       MONO_THREAD_VAR_OFFSET (mono_tls_thread, tls_offsets [TLS_KEY_THREAD]);
-       MONO_THREAD_VAR_OFFSET (mono_tls_jit_tls, tls_offsets [TLS_KEY_JIT_TLS]);
-       MONO_THREAD_VAR_OFFSET (mono_tls_domain, tls_offsets [TLS_KEY_DOMAIN]);
-       MONO_THREAD_VAR_OFFSET (mono_tls_lmf_addr, tls_offsets [TLS_KEY_LMF_ADDR]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_thread, mono_tls_offsets [TLS_KEY_THREAD]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_jit_tls, mono_tls_offsets [TLS_KEY_JIT_TLS]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_domain, mono_tls_offsets [TLS_KEY_DOMAIN]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_lmf_addr, mono_tls_offsets [TLS_KEY_LMF_ADDR]);
 #else
        mono_native_tls_alloc (&mono_tls_key_thread, NULL);
-       MONO_THREAD_VAR_OFFSET (mono_tls_key_thread, tls_offsets [TLS_KEY_THREAD]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_key_thread, mono_tls_offsets [TLS_KEY_THREAD]);
        mono_native_tls_alloc (&mono_tls_key_jit_tls, NULL);
-       MONO_THREAD_VAR_OFFSET (mono_tls_key_jit_tls, tls_offsets [TLS_KEY_JIT_TLS]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_key_jit_tls, mono_tls_offsets [TLS_KEY_JIT_TLS]);
        mono_native_tls_alloc (&mono_tls_key_domain, NULL);
-       MONO_THREAD_VAR_OFFSET (mono_tls_key_domain, tls_offsets [TLS_KEY_DOMAIN]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_key_domain, mono_tls_offsets [TLS_KEY_DOMAIN]);
        mono_native_tls_alloc (&mono_tls_key_lmf_addr, NULL);
-       MONO_THREAD_VAR_OFFSET (mono_tls_key_lmf_addr, tls_offsets [TLS_KEY_LMF_ADDR]);
+       MONO_THREAD_VAR_OFFSET (mono_tls_key_lmf_addr, mono_tls_offsets [TLS_KEY_LMF_ADDR]);
 #endif
 }
 
@@ -252,69 +170,29 @@ mono_tls_free_keys (void)
 #endif
 }
 
+// Some references are from AOT and cannot be inlined.
 
-/*
- * Gets the tls offset associated with the key. This offset is set at key
- * initialization (at runtime). Certain targets can implement computing
- * this offset and using it at runtime for fast inlined tls access.
- */
-gint32
-mono_tls_get_tls_offset (MonoTlsKey key)
-{
-       g_assert (tls_offsets [key]);
-       return tls_offsets [key];
-}
-
-// Casts on getters are for the !MONO_KEYWORD_THREAD case.
-
-/* Getters for each tls key */
-MonoInternalThread *mono_tls_get_thread (void)
-{
-       return (MonoInternalThread*)MONO_TLS_GET_VALUE (mono_tls_thread, mono_tls_key_thread);
-}
-
-MonoJitTlsData *mono_tls_get_jit_tls (void)
-{
-       return (MonoJitTlsData*)MONO_TLS_GET_VALUE (mono_tls_jit_tls, mono_tls_key_jit_tls);
-}
-
-MonoDomain *mono_tls_get_domain (void)
-{
-       return (MonoDomain*)MONO_TLS_GET_VALUE (mono_tls_domain, mono_tls_key_domain);
-}
-
-SgenThreadInfo *mono_tls_get_sgen_thread_info (void)
-{
-       return (SgenThreadInfo*)MONO_TLS_GET_VALUE (mono_tls_sgen_thread_info, mono_tls_key_sgen_thread_info);
-}
-
-MonoLMF **mono_tls_get_lmf_addr (void)
-{
-       return (MonoLMF**)MONO_TLS_GET_VALUE (mono_tls_lmf_addr, mono_tls_key_lmf_addr);
-}
-
-/* Setters for each tls key */
-void mono_tls_set_thread (MonoInternalThread *value)
+G_EXTERN_C MonoInternalThread *mono_tls_get_thread_extern (void)
 {
-       MONO_TLS_SET_VALUE (mono_tls_thread, mono_tls_key_thread, value);
+       return mono_tls_get_thread ();
 }
 
-void mono_tls_set_jit_tls (MonoJitTlsData *value)
+G_EXTERN_C MonoJitTlsData *mono_tls_get_jit_tls_extern (void)
 {
-       MONO_TLS_SET_VALUE (mono_tls_jit_tls, mono_tls_key_jit_tls, value);
+       return mono_tls_get_jit_tls ();
 }
 
-void mono_tls_set_domain (MonoDomain *value)
+G_EXTERN_C MonoDomain *mono_tls_get_domain_extern (void)
 {
-       MONO_TLS_SET_VALUE (mono_tls_domain, mono_tls_key_domain, value);
+       return mono_tls_get_domain ();
 }
 
-void mono_tls_set_sgen_thread_info (SgenThreadInfo *value)
+G_EXTERN_C SgenThreadInfo *mono_tls_get_sgen_thread_info_extern (void)
 {
-       MONO_TLS_SET_VALUE (mono_tls_sgen_thread_info, mono_tls_key_sgen_thread_info, value);
+       return mono_tls_get_sgen_thread_info ();
 }
 
-void mono_tls_set_lmf_addr (MonoLMF **value)
+G_EXTERN_C MonoLMF **mono_tls_get_lmf_addr_extern (void)
 {
-       MONO_TLS_SET_VALUE (mono_tls_lmf_addr, mono_tls_key_lmf_addr, value);
+       return mono_tls_get_lmf_addr ();
 }
index cf99376..b61b5b9 100644 (file)
 #include <config.h>
 #include <glib.h>
 #include <mono/utils/mono-forward-internal.h>
+#include <mono/utils/mach-support.h>
+
+#if __cplusplus
+#define MONO_INLINE inline
+#elif _MSC_VER
+#define MONO_INLINE __inline
+#else
+#define MONO_INLINE static inline
+#endif
 
 /* TLS entries used by the runtime */
 // This ordering is mimiced in MONO_JIT_ICALLS (alphabetical).
@@ -32,7 +41,7 @@ typedef enum {
 g_static_assert (TLS_KEY_DOMAIN == 0);
 #endif
 // There are only JIT icalls to get TLS, not set TLS.
-#define mono_get_tls_key_to_jit_icall_id(a)    ((MonoJitICallId)((a) + MONO_JIT_ICALL_mono_tls_get_domain))
+#define mono_get_tls_key_to_jit_icall_id(a)    ((MonoJitICallId)((a) + MONO_JIT_ICALL_mono_tls_get_domain_extern))
 
 #ifdef HOST_WIN32
 
@@ -57,7 +66,7 @@ g_static_assert (TLS_KEY_DOMAIN == 0);
 
 // TlsGetValue always writes 0 to LastError. Which can cause problems. This never changes LastError.
 //
-static inline
+MONO_INLINE
 void*
 mono_native_tls_get_value (unsigned index)
 {
@@ -78,19 +87,19 @@ mono_native_tls_get_value (unsigned index)
 #define MonoNativeTlsKey pthread_key_t
 #define mono_native_tls_get_value pthread_getspecific
 
-static inline int
+MONO_INLINE int
 mono_native_tls_alloc (MonoNativeTlsKey *key, void *destructor)
 {
        return pthread_key_create (key, (void (*)(void*)) destructor) == 0;
 }
 
-static inline void
+MONO_INLINE void
 mono_native_tls_free (MonoNativeTlsKey key)
 {
        pthread_key_delete (key);
 }
 
-static inline int
+MONO_INLINE int
 mono_native_tls_set_value (MonoNativeTlsKey key, gpointer value)
 {
        return !pthread_setspecific (key, value);
@@ -101,18 +110,190 @@ mono_native_tls_set_value (MonoNativeTlsKey key, gpointer value)
 void mono_tls_init_gc_keys (void);
 void mono_tls_init_runtime_keys (void);
 void mono_tls_free_keys (void);
-gint32 mono_tls_get_tls_offset (MonoTlsKey key);
-
-G_EXTERN_C MonoInternalThread *mono_tls_get_thread (void);
-G_EXTERN_C MonoJitTlsData     *mono_tls_get_jit_tls (void);
-G_EXTERN_C MonoDomain *mono_tls_get_domain (void);
-G_EXTERN_C SgenThreadInfo     *mono_tls_get_sgen_thread_info (void);
-G_EXTERN_C MonoLMF           **mono_tls_get_lmf_addr (void);
-
-void mono_tls_set_thread          (MonoInternalThread *value);
-void mono_tls_set_jit_tls         (MonoJitTlsData     *value);
-void mono_tls_set_domain          (MonoDomain         *value);
-void mono_tls_set_sgen_thread_info (SgenThreadInfo     *value);
-void mono_tls_set_lmf_addr        (MonoLMF           **value);
+
+G_EXTERN_C MonoInternalThread *mono_tls_get_thread_extern (void);
+G_EXTERN_C MonoJitTlsData     *mono_tls_get_jit_tls_extern (void);
+G_EXTERN_C MonoDomain *mono_tls_get_domain_extern (void);
+G_EXTERN_C SgenThreadInfo *mono_tls_get_sgen_thread_info_extern (void);
+G_EXTERN_C MonoLMF       **mono_tls_get_lmf_addr_extern (void);
+
+/*
+ * On all platforms we should be able to use either __thread or __declspec (thread)
+ * or pthread/TlsGetValue.
+ * Certain platforms will support fast tls only when using one of the thread local
+ * storage backends. By default this is __thread if we have MONO_KEYWORD_THREAD defined.
+ *
+ * By default all platforms will call into these native getters whenever they need
+ * to get a tls value. On certain platforms we can try to be faster than this and
+ * avoid the call. We call this fast tls and each platform defines its own way to
+ * achieve this. For this, a platform has to define MONO_ARCH_HAVE_INLINED_TLS,
+ * and provide alternative getters/setters for a MonoTlsKey. In order to have fast
+ * getter/setters, the platform has to declare a way to fetch an internal offset
+ * (MONO_THREAD_VAR_OFFSET) which is stored here, and in the arch specific file
+ * probe the system to see if we can use the offset initialized here. If these
+ * run-time checks don't succeed we just use the fallbacks.
+ *
+ * In case we would wish to provide fast inlined tls for aot code, we would need
+ * to be sure that, at run-time, these two platform checks would never fail
+ * otherwise the tls getter/setters that we emitted would not work. Normally,
+ * there is little incentive to support this since tls access is most common in
+ * wrappers and managed allocators, both of which are not aot-ed by default.
+ * So far, we never supported inlined fast tls on full-aot systems.
+ */
+
+#ifdef MONO_KEYWORD_THREAD
+
+/* tls attribute */
+#if HAVE_TLS_MODEL_ATTR
+
+#if defined(__PIC__) && !defined(PIC)
+/*
+ * Must be compiling -fPIE, for executables.  Build PIC
+ * but with initial-exec.
+ * http://bugs.gentoo.org/show_bug.cgi?id=165547
+ */
+#define PIC
+#define PIC_INITIAL_EXEC
+#endif
+
+/*
+ * Define this if you want a faster libmono, which cannot be loaded dynamically as a
+ * module.
+ */
+//#define PIC_INITIAL_EXEC
+
+#if defined(PIC)
+
+#ifdef PIC_INITIAL_EXEC
+#define MONO_TLS_FAST __attribute__ ((__tls_model__("initial-exec")))
+#else
+#if defined (__powerpc__)
+/* local dynamic requires a call to __tls_get_addr to look up the
+   TLS block address via the Dynamic Thread Vector. In this case Thread
+   Pointer relative offsets can't be used as this modules TLS was
+   allocated separately (none contiguoiusly) from the initial TLS
+   block.
+
+   For now we will disable this. */
+#define MONO_TLS_FAST
+#else
+#define MONO_TLS_FAST __attribute__ ((__tls_model__("local-dynamic")))
+#endif
+#endif
+
+#else
+
+#define MONO_TLS_FAST __attribute__ ((__tls_model__("local-exec")))
+
+#endif
+
+#else
+#define MONO_TLS_FAST
+#endif
+
+// Tls variables for each MonoTlsKey.
+//
+extern MONO_KEYWORD_THREAD MonoInternalThread *mono_tls_thread MONO_TLS_FAST;
+extern MONO_KEYWORD_THREAD MonoJitTlsData     *mono_tls_jit_tls MONO_TLS_FAST;
+extern MONO_KEYWORD_THREAD MonoDomain         *mono_tls_domain MONO_TLS_FAST;
+extern MONO_KEYWORD_THREAD SgenThreadInfo     *mono_tls_sgen_thread_info MONO_TLS_FAST;
+extern MONO_KEYWORD_THREAD MonoLMF           **mono_tls_lmf_addr MONO_TLS_FAST;
+
+#else
+
+extern MonoNativeTlsKey mono_tls_key_thread;
+extern MonoNativeTlsKey mono_tls_key_jit_tls;
+extern MonoNativeTlsKey mono_tls_key_domain;
+extern MonoNativeTlsKey mono_tls_key_sgen_thread_info;
+extern MonoNativeTlsKey mono_tls_key_lmf_addr;
+
+#endif
+
+extern gint32 mono_tls_offsets [TLS_KEY_NUM];
+
+#ifdef MONO_KEYWORD_THREAD
+#define MONO_TLS_GET_VALUE(tls_var,tls_key) (tls_var)
+#define MONO_TLS_SET_VALUE(tls_var,tls_key,value) (tls_var = value)
+#else
+#define MONO_TLS_GET_VALUE(tls_var,tls_key) (mono_native_tls_get_value (tls_key))
+#define MONO_TLS_SET_VALUE(tls_var,tls_key,value) (mono_native_tls_set_value (tls_key, value))
+#endif
+
+/*
+ * Gets the tls offset associated with the key. This offset is set at key
+ * initialization (at runtime). Certain targets can implement computing
+ * this offset and using it at runtime for fast inlined tls access.
+ */
+MONO_INLINE
+gint32
+mono_tls_get_tls_offset (MonoTlsKey key)
+{
+       g_assert (mono_tls_offsets [key]);
+       return mono_tls_offsets [key];
+}
+
+// Casts on getters are for the !MONO_KEYWORD_THREAD case.
+
+/* Getters for each tls key */
+MONO_INLINE
+MonoInternalThread *mono_tls_get_thread (void)
+{
+       return (MonoInternalThread*)MONO_TLS_GET_VALUE (mono_tls_thread, mono_tls_key_thread);
+}
+
+MONO_INLINE
+MonoJitTlsData *mono_tls_get_jit_tls (void)
+{
+       return (MonoJitTlsData*)MONO_TLS_GET_VALUE (mono_tls_jit_tls, mono_tls_key_jit_tls);
+}
+
+MONO_INLINE
+MonoDomain *mono_tls_get_domain (void)
+{
+       return (MonoDomain*)MONO_TLS_GET_VALUE (mono_tls_domain, mono_tls_key_domain);
+}
+
+MONO_INLINE
+SgenThreadInfo *mono_tls_get_sgen_thread_info (void)
+{
+       return (SgenThreadInfo*)MONO_TLS_GET_VALUE (mono_tls_sgen_thread_info, mono_tls_key_sgen_thread_info);
+}
+
+MONO_INLINE
+MonoLMF **mono_tls_get_lmf_addr (void)
+{
+       return (MonoLMF**)MONO_TLS_GET_VALUE (mono_tls_lmf_addr, mono_tls_key_lmf_addr);
+}
+
+/* Setters for each tls key */
+MONO_INLINE
+void mono_tls_set_thread (MonoInternalThread *value)
+{
+       MONO_TLS_SET_VALUE (mono_tls_thread, mono_tls_key_thread, value);
+}
+
+MONO_INLINE
+void mono_tls_set_jit_tls (MonoJitTlsData *value)
+{
+       MONO_TLS_SET_VALUE (mono_tls_jit_tls, mono_tls_key_jit_tls, value);
+}
+
+MONO_INLINE
+void mono_tls_set_domain (MonoDomain *value)
+{
+       MONO_TLS_SET_VALUE (mono_tls_domain, mono_tls_key_domain, value);
+}
+
+MONO_INLINE
+void mono_tls_set_sgen_thread_info (SgenThreadInfo *value)
+{
+       MONO_TLS_SET_VALUE (mono_tls_sgen_thread_info, mono_tls_key_sgen_thread_info, value);
+}
+
+MONO_INLINE
+void mono_tls_set_lmf_addr (MonoLMF **value)
+{
+       MONO_TLS_SET_VALUE (mono_tls_lmf_addr, mono_tls_key_lmf_addr, value);
+}
 
 #endif /* __MONO_TLS_H__ */