mono-tls.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /**
  2. * \file
  3. * Low-level TLS support
  4. *
  5. * Author:
  6. * Rodrigo Kumpera (kumpera@gmail.com)
  7. *
  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.
  11. */
  12. #ifndef __MONO_TLS_H__
  13. #define __MONO_TLS_H__
  14. #include <config.h>
  15. #include <glib.h>
  16. #include <mono/utils/mono-forward-internal.h>
  17. #include <mono/utils/mach-support.h>
  18. // FIXME: Make this more visible.
  19. #if __cplusplus
  20. #define MONO_INLINE inline
  21. #elif _MSC_VER
  22. #define MONO_INLINE __inline
  23. #else
  24. #define MONO_INLINE static inline
  25. #endif
  26. /* TLS entries used by the runtime */
  27. // This ordering is mimiced in MONO_JIT_ICALLS (alphabetical).
  28. typedef enum {
  29. TLS_KEY_DOMAIN = 0, // mono_domain_get ()
  30. TLS_KEY_JIT_TLS = 1,
  31. TLS_KEY_LMF_ADDR = 2,
  32. TLS_KEY_SGEN_THREAD_INFO = 3,
  33. TLS_KEY_THREAD = 4, // mono_thread_internal_current ()
  34. TLS_KEY_NUM = 5
  35. } MonoTlsKey;
  36. #if __cplusplus
  37. g_static_assert (TLS_KEY_DOMAIN == 0);
  38. #endif
  39. // There are only JIT icalls to get TLS, not set TLS.
  40. #define mono_get_tls_key_to_jit_icall_id(a) ((MonoJitICallId)((a) + MONO_JIT_ICALL_mono_tls_get_domain_extern))
  41. #ifdef HOST_WIN32
  42. #include <windows.h>
  43. // Some Windows SDKs define TLS to be FLS.
  44. // That is presumably catastrophic when combined with mono_amd64_emit_tls_get / mono_x86_emit_tls_get.
  45. // It also is not consistent.
  46. // FLS is a reasonable idea perhaps, but we would need to be consistent and to adjust JIT.
  47. // And there is __declspec(fiber).
  48. #undef TlsAlloc
  49. #undef TlsFree
  50. #undef TlsGetValue
  51. #undef TlsSetValue
  52. #define MonoNativeTlsKey DWORD
  53. #define mono_native_tls_alloc(key,destructor) ((*(key) = TlsAlloc ()) != TLS_OUT_OF_INDEXES && destructor == NULL)
  54. #define mono_native_tls_free TlsFree
  55. #define mono_native_tls_set_value TlsSetValue
  56. #ifdef HAVE_WINTERNL_H
  57. #include <winternl.h>
  58. #else
  59. typedef struct _TEB {
  60. PVOID Reserved1[12];
  61. PVOID ProcessEnvironmentBlock;
  62. PVOID Reserved2[399];
  63. BYTE Reserved3[1952];
  64. PVOID TlsSlots[64];
  65. BYTE Reserved4[8];
  66. PVOID Reserved5[26];
  67. PVOID ReservedForOle;
  68. PVOID Reserved6[4];
  69. PVOID TlsExpansionSlots;
  70. } TEB, *PTEB;
  71. #endif
  72. // TlsGetValue always writes 0 to LastError. Which can cause problems. This never changes LastError.
  73. //
  74. MONO_INLINE
  75. void*
  76. mono_native_tls_get_value (unsigned index)
  77. {
  78. PTEB const teb = NtCurrentTeb ();
  79. if (index < TLS_MINIMUM_AVAILABLE)
  80. return teb->TlsSlots [index];
  81. void** const p = (void**)teb->TlsExpansionSlots;
  82. return p ? p [index - TLS_MINIMUM_AVAILABLE] : NULL;
  83. }
  84. #else
  85. #include <pthread.h>
  86. #define MonoNativeTlsKey pthread_key_t
  87. #define mono_native_tls_get_value pthread_getspecific
  88. MONO_INLINE int
  89. mono_native_tls_alloc (MonoNativeTlsKey *key, void *destructor)
  90. {
  91. return pthread_key_create (key, (void (*)(void*)) destructor) == 0;
  92. }
  93. MONO_INLINE void
  94. mono_native_tls_free (MonoNativeTlsKey key)
  95. {
  96. pthread_key_delete (key);
  97. }
  98. MONO_INLINE int
  99. mono_native_tls_set_value (MonoNativeTlsKey key, gpointer value)
  100. {
  101. return !pthread_setspecific (key, value);
  102. }
  103. #endif /* HOST_WIN32 */
  104. void mono_tls_init_gc_keys (void);
  105. void mono_tls_init_runtime_keys (void);
  106. void mono_tls_free_keys (void);
  107. G_EXTERN_C MonoInternalThread *mono_tls_get_thread_extern (void);
  108. G_EXTERN_C MonoJitTlsData *mono_tls_get_jit_tls_extern (void);
  109. G_EXTERN_C MonoDomain *mono_tls_get_domain_extern (void);
  110. G_EXTERN_C SgenThreadInfo *mono_tls_get_sgen_thread_info_extern (void);
  111. G_EXTERN_C MonoLMF **mono_tls_get_lmf_addr_extern (void);
  112. /*
  113. * On all platforms we should be able to use either __thread or __declspec (thread)
  114. * or pthread/TlsGetValue.
  115. * Certain platforms will support fast tls only when using one of the thread local
  116. * storage backends. By default this is __thread if we have MONO_KEYWORD_THREAD defined.
  117. *
  118. * By default all platforms will call into these native getters whenever they need
  119. * to get a tls value. On certain platforms we can try to be faster than this and
  120. * avoid the call. We call this fast tls and each platform defines its own way to
  121. * achieve this. For this, a platform has to define MONO_ARCH_HAVE_INLINED_TLS,
  122. * and provide alternative getters/setters for a MonoTlsKey. In order to have fast
  123. * getter/setters, the platform has to declare a way to fetch an internal offset
  124. * (MONO_THREAD_VAR_OFFSET) which is stored here, and in the arch specific file
  125. * probe the system to see if we can use the offset initialized here. If these
  126. * run-time checks don't succeed we just use the fallbacks.
  127. *
  128. * In case we would wish to provide fast inlined tls for aot code, we would need
  129. * to be sure that, at run-time, these two platform checks would never fail
  130. * otherwise the tls getter/setters that we emitted would not work. Normally,
  131. * there is little incentive to support this since tls access is most common in
  132. * wrappers and managed allocators, both of which are not aot-ed by default.
  133. * So far, we never supported inlined fast tls on full-aot systems.
  134. */
  135. #ifdef MONO_KEYWORD_THREAD
  136. /* tls attribute */
  137. #if HAVE_TLS_MODEL_ATTR
  138. #if defined(__PIC__) && !defined(PIC)
  139. /*
  140. * Must be compiling -fPIE, for executables. Build PIC
  141. * but with initial-exec.
  142. * http://bugs.gentoo.org/show_bug.cgi?id=165547
  143. */
  144. #define PIC
  145. #define PIC_INITIAL_EXEC
  146. #endif
  147. /*
  148. * Define this if you want a faster libmono, which cannot be loaded dynamically as a
  149. * module.
  150. */
  151. //#define PIC_INITIAL_EXEC
  152. #if defined(PIC)
  153. #ifdef PIC_INITIAL_EXEC
  154. #define MONO_TLS_FAST __attribute__ ((__tls_model__("initial-exec")))
  155. #else
  156. #if defined (__powerpc__)
  157. /* local dynamic requires a call to __tls_get_addr to look up the
  158. TLS block address via the Dynamic Thread Vector. In this case Thread
  159. Pointer relative offsets can't be used as this modules TLS was
  160. allocated separately (none contiguoiusly) from the initial TLS
  161. block.
  162. For now we will disable this. */
  163. #define MONO_TLS_FAST
  164. #else
  165. #define MONO_TLS_FAST __attribute__ ((__tls_model__("local-dynamic")))
  166. #endif
  167. #endif
  168. #else
  169. #define MONO_TLS_FAST __attribute__ ((__tls_model__("local-exec")))
  170. #endif
  171. #else
  172. #define MONO_TLS_FAST
  173. #endif
  174. // Tls variables for each MonoTlsKey.
  175. //
  176. extern MONO_KEYWORD_THREAD MonoInternalThread *mono_tls_thread MONO_TLS_FAST;
  177. extern MONO_KEYWORD_THREAD MonoJitTlsData *mono_tls_jit_tls MONO_TLS_FAST;
  178. extern MONO_KEYWORD_THREAD MonoDomain *mono_tls_domain MONO_TLS_FAST;
  179. extern MONO_KEYWORD_THREAD SgenThreadInfo *mono_tls_sgen_thread_info MONO_TLS_FAST;
  180. extern MONO_KEYWORD_THREAD MonoLMF **mono_tls_lmf_addr MONO_TLS_FAST;
  181. #elif defined(DISABLE_THREADS)
  182. extern MonoInternalThread *mono_tls_thread;
  183. extern MonoJitTlsData *mono_tls_jit_tls;
  184. extern MonoDomain *mono_tls_domain;
  185. extern SgenThreadInfo *mono_tls_sgen_thread_info;
  186. extern MonoLMF **mono_tls_lmf_addr;
  187. #else
  188. extern MonoNativeTlsKey mono_tls_key_thread;
  189. extern MonoNativeTlsKey mono_tls_key_jit_tls;
  190. extern MonoNativeTlsKey mono_tls_key_domain;
  191. extern MonoNativeTlsKey mono_tls_key_sgen_thread_info;
  192. extern MonoNativeTlsKey mono_tls_key_lmf_addr;
  193. #endif
  194. extern gint32 mono_tls_offsets [TLS_KEY_NUM];
  195. #if defined(MONO_KEYWORD_THREAD) || defined(DISABLE_THREADS)
  196. #define MONO_TLS_GET_VALUE(tls_var,tls_key) (tls_var)
  197. #define MONO_TLS_SET_VALUE(tls_var,tls_key,value) (tls_var = value)
  198. #else
  199. #define MONO_TLS_GET_VALUE(tls_var,tls_key) (mono_native_tls_get_value (tls_key))
  200. #define MONO_TLS_SET_VALUE(tls_var,tls_key,value) (mono_native_tls_set_value (tls_key, value))
  201. #endif
  202. #endif /* __MONO_TLS_H__ */