update readme (#21797)
[mono-project.git] / mono / utils / mono-tls.h
blob671cd3a2278c184a0ed8174158e619ca1093de7d
1 /**
2 * \file
3 * Low-level TLS support
5 * Author:
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__
16 #include <config.h>
17 #include <glib.h>
18 #include <mono/utils/mono-forward-internal.h>
19 #include <mono/utils/mach-support.h>
21 // FIXME: Make this more visible.
22 #if __cplusplus
23 #define MONO_INLINE inline
24 #elif _MSC_VER
25 #define MONO_INLINE __inline
26 #else
27 #define MONO_INLINE static inline
28 #endif
30 /* TLS entries used by the runtime */
31 // This ordering is mimiced in MONO_JIT_ICALLS (alphabetical).
32 typedef enum {
33 TLS_KEY_DOMAIN = 0, // mono_domain_get ()
34 TLS_KEY_JIT_TLS = 1,
35 TLS_KEY_LMF_ADDR = 2,
36 TLS_KEY_SGEN_THREAD_INFO = 3,
37 TLS_KEY_THREAD = 4, // mono_thread_internal_current ()
38 TLS_KEY_NUM = 5
39 } MonoTlsKey;
41 #if __cplusplus
42 g_static_assert (TLS_KEY_DOMAIN == 0);
43 #endif
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))
47 #ifdef HOST_WIN32
49 #include <windows.h>
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).
56 #undef TlsAlloc
57 #undef TlsFree
58 #undef TlsGetValue
59 #undef TlsSetValue
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
67 #include <winternl.h>
68 #else
69 typedef struct _TEB {
70 PVOID Reserved1[12];
71 PVOID ProcessEnvironmentBlock;
72 PVOID Reserved2[399];
73 BYTE Reserved3[1952];
74 PVOID TlsSlots[64];
75 BYTE Reserved4[8];
76 PVOID Reserved5[26];
77 PVOID ReservedForOle;
78 PVOID Reserved6[4];
79 PVOID TlsExpansionSlots;
80 } TEB, *PTEB;
81 #endif
83 // TlsGetValue always writes 0 to LastError. Which can cause problems. This never changes LastError.
85 MONO_INLINE
86 void*
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;
99 #else
101 #include <pthread.h>
103 #define MonoNativeTlsKey pthread_key_t
104 #define mono_native_tls_get_value pthread_getspecific
106 MONO_INLINE int
107 mono_native_tls_alloc (MonoNativeTlsKey *key, void *destructor)
109 return pthread_key_create (key, (void (*)(void*)) destructor) == 0;
112 MONO_INLINE void
113 mono_native_tls_free (MonoNativeTlsKey key)
115 pthread_key_delete (key);
118 MONO_INLINE int
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
162 /* tls attribute */
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
171 #define PIC
172 #define PIC_INITIAL_EXEC
173 #endif
176 * Define this if you want a faster libmono, which cannot be loaded dynamically as a
177 * module.
179 //#define PIC_INITIAL_EXEC
181 #if defined(PIC)
183 #ifdef PIC_INITIAL_EXEC
184 #define MONO_TLS_FAST __attribute__ ((__tls_model__("initial-exec")))
185 #else
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
191 block.
193 For now we will disable this. */
194 #define MONO_TLS_FAST
195 #else
196 #define MONO_TLS_FAST __attribute__ ((__tls_model__("local-dynamic")))
197 #endif
198 #endif
200 #else
202 #define MONO_TLS_FAST __attribute__ ((__tls_model__("local-exec")))
204 #endif
206 #else
207 #define MONO_TLS_FAST
208 #endif
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;
226 #else
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;
234 #endif
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)
241 #else
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))
244 #endif
246 #endif /* __MONO_TLS_H__ */