3 * Low-level TLS support
6 * Rodrigo Kumpera (kumpera@gmail.com)
8 * Copyright 2011 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13 #ifndef __MONO_TLS_H__
14 #define __MONO_TLS_H__
18 #include <mono/utils/mono-forward-internal.h>
19 #include <mono/utils/mach-support.h>
21 // FIXME: Make this more visible.
23 #define MONO_INLINE inline
25 #define MONO_INLINE __inline
27 #define MONO_INLINE static inline
30 /* TLS entries used by the runtime */
31 // This ordering is mimiced in MONO_JIT_ICALLS (alphabetical).
33 TLS_KEY_DOMAIN
= 0, // mono_domain_get ()
36 TLS_KEY_SGEN_THREAD_INFO
= 3,
37 TLS_KEY_THREAD
= 4, // mono_thread_internal_current ()
42 g_static_assert (TLS_KEY_DOMAIN
== 0);
44 // There are only JIT icalls to get TLS, not set TLS.
45 #define mono_get_tls_key_to_jit_icall_id(a) ((MonoJitICallId)((a) + MONO_JIT_ICALL_mono_tls_get_domain_extern))
51 // Some Windows SDKs define TLS to be FLS.
52 // That is presumably catastrophic when combined with mono_amd64_emit_tls_get / mono_x86_emit_tls_get.
53 // It also is not consistent.
54 // FLS is a reasonable idea perhaps, but we would need to be consistent and to adjust JIT.
55 // And there is __declspec(fiber).
61 #define MonoNativeTlsKey DWORD
62 #define mono_native_tls_alloc(key,destructor) ((*(key) = TlsAlloc ()) != TLS_OUT_OF_INDEXES && destructor == NULL)
63 #define mono_native_tls_free TlsFree
64 #define mono_native_tls_set_value TlsSetValue
66 #ifdef HAVE_WINTERNL_H
71 PVOID ProcessEnvironmentBlock
;
79 PVOID TlsExpansionSlots
;
83 // TlsGetValue always writes 0 to LastError. Which can cause problems. This never changes LastError.
87 mono_native_tls_get_value (unsigned index
)
89 PTEB
const teb
= NtCurrentTeb ();
91 if (index
< TLS_MINIMUM_AVAILABLE
)
92 return teb
->TlsSlots
[index
];
94 void** const p
= (void**)teb
->TlsExpansionSlots
;
96 return p
? p
[index
- TLS_MINIMUM_AVAILABLE
] : NULL
;
103 #define MonoNativeTlsKey pthread_key_t
104 #define mono_native_tls_get_value pthread_getspecific
107 mono_native_tls_alloc (MonoNativeTlsKey
*key
, void *destructor
)
109 return pthread_key_create (key
, (void (*)(void*)) destructor
) == 0;
113 mono_native_tls_free (MonoNativeTlsKey key
)
115 pthread_key_delete (key
);
119 mono_native_tls_set_value (MonoNativeTlsKey key
, gpointer value
)
121 return !pthread_setspecific (key
, value
);
124 #endif /* HOST_WIN32 */
126 void mono_tls_init_gc_keys (void);
127 void mono_tls_init_runtime_keys (void);
128 void mono_tls_free_keys (void);
130 G_EXTERN_C MonoInternalThread
*mono_tls_get_thread_extern (void);
131 G_EXTERN_C MonoJitTlsData
*mono_tls_get_jit_tls_extern (void);
132 G_EXTERN_C MonoDomain
*mono_tls_get_domain_extern (void);
133 G_EXTERN_C SgenThreadInfo
*mono_tls_get_sgen_thread_info_extern (void);
134 G_EXTERN_C MonoLMF
**mono_tls_get_lmf_addr_extern (void);
137 * On all platforms we should be able to use either __thread or __declspec (thread)
138 * or pthread/TlsGetValue.
139 * Certain platforms will support fast tls only when using one of the thread local
140 * storage backends. By default this is __thread if we have MONO_KEYWORD_THREAD defined.
142 * By default all platforms will call into these native getters whenever they need
143 * to get a tls value. On certain platforms we can try to be faster than this and
144 * avoid the call. We call this fast tls and each platform defines its own way to
145 * achieve this. For this, a platform has to define MONO_ARCH_HAVE_INLINED_TLS,
146 * and provide alternative getters/setters for a MonoTlsKey. In order to have fast
147 * getter/setters, the platform has to declare a way to fetch an internal offset
148 * (MONO_THREAD_VAR_OFFSET) which is stored here, and in the arch specific file
149 * probe the system to see if we can use the offset initialized here. If these
150 * run-time checks don't succeed we just use the fallbacks.
152 * In case we would wish to provide fast inlined tls for aot code, we would need
153 * to be sure that, at run-time, these two platform checks would never fail
154 * otherwise the tls getter/setters that we emitted would not work. Normally,
155 * there is little incentive to support this since tls access is most common in
156 * wrappers and managed allocators, both of which are not aot-ed by default.
157 * So far, we never supported inlined fast tls on full-aot systems.
160 #ifdef MONO_KEYWORD_THREAD
163 #if HAVE_TLS_MODEL_ATTR
165 #if defined(__PIC__) && !defined(PIC)
167 * Must be compiling -fPIE, for executables. Build PIC
168 * but with initial-exec.
169 * http://bugs.gentoo.org/show_bug.cgi?id=165547
172 #define PIC_INITIAL_EXEC
176 * Define this if you want a faster libmono, which cannot be loaded dynamically as a
179 //#define PIC_INITIAL_EXEC
183 #ifdef PIC_INITIAL_EXEC
184 #define MONO_TLS_FAST __attribute__ ((__tls_model__("initial-exec")))
186 #if defined (__powerpc__)
187 /* local dynamic requires a call to __tls_get_addr to look up the
188 TLS block address via the Dynamic Thread Vector. In this case Thread
189 Pointer relative offsets can't be used as this modules TLS was
190 allocated separately (none contiguoiusly) from the initial TLS
193 For now we will disable this. */
194 #define MONO_TLS_FAST
196 #define MONO_TLS_FAST __attribute__ ((__tls_model__("local-dynamic")))
202 #define MONO_TLS_FAST __attribute__ ((__tls_model__("local-exec")))
207 #define MONO_TLS_FAST
210 // Tls variables for each MonoTlsKey.
212 extern MONO_KEYWORD_THREAD MonoInternalThread
*mono_tls_thread MONO_TLS_FAST
;
213 extern MONO_KEYWORD_THREAD MonoJitTlsData
*mono_tls_jit_tls MONO_TLS_FAST
;
214 extern MONO_KEYWORD_THREAD MonoDomain
*mono_tls_domain MONO_TLS_FAST
;
215 extern MONO_KEYWORD_THREAD SgenThreadInfo
*mono_tls_sgen_thread_info MONO_TLS_FAST
;
216 extern MONO_KEYWORD_THREAD MonoLMF
**mono_tls_lmf_addr MONO_TLS_FAST
;
218 #elif defined(DISABLE_THREADS)
220 extern MonoInternalThread
*mono_tls_thread
;
221 extern MonoJitTlsData
*mono_tls_jit_tls
;
222 extern MonoDomain
*mono_tls_domain
;
223 extern SgenThreadInfo
*mono_tls_sgen_thread_info
;
224 extern MonoLMF
**mono_tls_lmf_addr
;
228 extern MonoNativeTlsKey mono_tls_key_thread
;
229 extern MonoNativeTlsKey mono_tls_key_jit_tls
;
230 extern MonoNativeTlsKey mono_tls_key_domain
;
231 extern MonoNativeTlsKey mono_tls_key_sgen_thread_info
;
232 extern MonoNativeTlsKey mono_tls_key_lmf_addr
;
236 extern gint32 mono_tls_offsets
[TLS_KEY_NUM
];
238 #if defined(MONO_KEYWORD_THREAD) || defined(DISABLE_THREADS)
239 #define MONO_TLS_GET_VALUE(tls_var,tls_key) (tls_var)
240 #define MONO_TLS_SET_VALUE(tls_var,tls_key,value) (tls_var = value)
242 #define MONO_TLS_GET_VALUE(tls_var,tls_key) (mono_native_tls_get_value (tls_key))
243 #define MONO_TLS_SET_VALUE(tls_var,tls_key,value) (mono_native_tls_set_value (tls_key, value))
246 #endif /* __MONO_TLS_H__ */