The purpose of this commit is to unify tls access across all platforms. We had tls information spread out throughout the entire code which was guarded with many defines/capabilities which made very hard to follow what was going on. Also this made switching between pthread and __thread very unstable since there were a lot of dependencies between different pieces of the tls infrastructure. Also it was not very clear what happens if one of the tls pieces failed.
Now we are moving all the tls variables to a single module that provides getters/setters and initialization API. Runtime code now knows that we can always access a tls variable (from managed code, we just do a nowrapper icall into the same global geters/setters). Even though we used to these type of calls all around before, it is worth mentioning that runtime should account for a thread to be in this type of unregistered code without m2n wrapper and no register jinfo.
On average this makes common tls intensive methods (m2n wrappers and managed allocator) 20% slower, with potential for more regression if we use tls getters/setters recklessly. As a consequence we will re-enable the most important pieces of fast tls code in the future.
GC_key_t GC_thread_key;
#ifdef USE_COMPILER_TLS
-__thread MONO_TLS_FAST void* GC_thread_tls;
+__thread void* GC_thread_tls;
/*
* gcc errors out with /tmp/ccdPMFuq.s:2994: Error: symbol `.LTLS4' is already defined
}
#if defined(USE_COMPILER_TLS) && defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
-extern __thread MONO_TLS_FAST void* GC_thread_tls;
+extern __thread void* GC_thread_tls;
#include "metadata-internals.h"
static int
const char *name = NULL;
WrapperInfo *info;
+ g_assert_not_reached ();
+
if (atype == ATYPE_FREEPTR) {
name = slowpath ? "SlowAllocPtrfree" : "AllocPtrfree";
} else if (atype == ATYPE_FREEPTR_FOR_BOX) {
MonoMethod*
mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean known_instance_size)
{
- int offset = -1;
int atype;
- MONO_THREAD_VAR_OFFSET (GC_thread_tls, offset);
- /*g_print ("thread tls: %d\n", offset);*/
- if (offset == -1)
- return NULL;
+ /*
+ * Tls implementation changed, we jump to tls native getters/setters.
+ * Is boehm managed allocator ok with this ? Do we even care ?
+ */
+ return NULL;
+
if (!SMALL_ENOUGH (klass->instance_size))
return NULL;
if (mono_class_has_finalizer (klass) || mono_class_is_marshalbyref (klass))
MonoMethod*
mono_gc_get_managed_allocator_by_type (int atype, ManagedAllocatorVariant variant)
{
- int offset = -1;
MonoMethod *res;
gboolean slowpath = variant != MANAGED_ALLOCATOR_REGULAR;
MonoMethod **cache = slowpath ? slowpath_alloc_method_cache : alloc_method_cache;
- MONO_THREAD_VAR_OFFSET (GC_thread_tls, offset);
- mono_tls_key_set_offset (TLS_KEY_BOEHM_GC_THREAD, offset);
+ return NULL;
res = cache [atype];
if (res)
return res;
- res = create_allocator (atype, TLS_KEY_BOEHM_GC_THREAD, slowpath);
+ res = create_allocator (atype, -1, slowpath);
mono_os_mutex_lock (&mono_gc_lock);
if (cache [atype]) {
mono_free_method (res);
//#define DEBUG_DOMAIN_UNLOAD 1
-/* we need to use both the Tls* functions and __thread because
- * some archs may generate faster jit code with one meachanism
- * or the other (we used to do it because tls slots were GC-tracked,
- * but we can't depend on this).
- */
-static MonoNativeTlsKey appdomain_thread_id;
-
-#ifdef MONO_HAVE_FAST_TLS
-
-MONO_FAST_TLS_DECLARE(tls_appdomain);
-
-#define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
-
+#define GET_APPDOMAIN() ((MonoDomain*)mono_tls_get_domain ())
#define SET_APPDOMAIN(x) do { \
MonoThreadInfo *info; \
- MONO_FAST_TLS_SET (tls_appdomain,x); \
- mono_native_tls_set_value (appdomain_thread_id, x); \
+ mono_tls_set_domain (x); \
info = mono_thread_info_current (); \
if (info) \
mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \
} while (FALSE)
-#else /* !MONO_HAVE_FAST_TLS */
-
-#define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id))
-#define SET_APPDOMAIN(x) do { \
- MonoThreadInfo *info; \
- mono_native_tls_set_value (appdomain_thread_id, x); \
- info = mono_thread_info_current (); \
- if (info) \
- mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \
- } while (FALSE)
-
-#endif
-
#define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
#define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
static const MonoRuntimeInfo*
get_runtime_by_version (const char *version);
-MonoNativeTlsKey
-mono_domain_get_tls_key (void)
-{
- return appdomain_thread_id;
-}
-
-gint32
-mono_domain_get_tls_offset (void)
-{
- int offset = -1;
-
-#ifdef HOST_WIN32
- if (appdomain_thread_id)
- offset = appdomain_thread_id;
-#else
- MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
-#endif
- return offset;
-}
-
#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
#define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
mono_gc_base_init ();
mono_thread_info_attach (&dummy);
- MONO_FAST_TLS_INIT (tls_appdomain);
- mono_native_tls_alloc (&appdomain_thread_id, NULL);
-
mono_coop_mutex_init_recursive (&appdomains_mutex);
mono_metadata_init ();
mono_images_cleanup ();
mono_metadata_cleanup ();
- mono_native_tls_free (appdomain_thread_id);
mono_coop_mutex_destroy (&appdomains_mutex);
mono_w32process_cleanup ();
void (*set_cast_details) (MonoClass *from, MonoClass *to);
void (*debug_log) (int level, MonoString *category, MonoString *message);
gboolean (*debug_log_is_enabled) (void);
- gboolean (*tls_key_supported) (MonoTlsKey key);
void (*init_delegate) (MonoDelegate *del);
MonoObject* (*runtime_invoke) (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error);
void* (*compile_method) (MonoMethod *method, MonoError *error);
mono_runtime_init_tls (void)
{
mono_marshal_init_tls ();
- mono_thread_init_tls ();
}
{
}
-#ifdef HAVE_KW_THREAD
-extern __thread SgenThreadInfo *sgen_thread_info;
-#define TLAB_ACCESS_INIT
-#define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
-#else
-extern MonoNativeTlsKey thread_info_key;
-#define TLAB_ACCESS_INIT SgenThreadInfo *__thread_info__ = mono_native_tls_get_value (thread_info_key)
-#define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
-#endif
-
-#ifdef HAVE_KW_THREAD
-#define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
-#else
+#define TLAB_ACCESS_INIT SgenThreadInfo *__thread_info__ = (SgenThreadInfo*)mono_tls_get_sgen_thread_info ()
#define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
-#endif
/* Enter must be visible before anything is done in the critical region. */
#define ENTER_CRITICAL_REGION do { mono_atomic_store_acquire (&IN_CRITICAL_REGION, 1); } while (0)
/* Functions supplied by the runtime to be called by the GC */
static MonoGCCallbacks gc_callbacks;
-#ifdef HAVE_KW_THREAD
-__thread SgenThreadInfo *sgen_thread_info;
-#else
-MonoNativeTlsKey thread_info_key;
-#endif
-
#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
static gboolean use_managed_allocator = TRUE;
#ifdef MANAGED_ALLOCATION
-
-#if defined(HAVE_KW_THREAD) || defined(TARGET_OSX) || defined(TARGET_WIN32) || defined(TARGET_ANDROID) || defined(TARGET_IOS)
-
// Cache the SgenThreadInfo pointer in a local 'var'.
#define EMIT_TLS_ACCESS_VAR(mb, var) \
do { \
mono_mb_emit_byte ((mb), CEE_LDIND_I); \
} while (0)
-#else
-#define EMIT_TLS_ACCESS_VAR(mb, _var) do { g_error ("sgen is not supported when using --with-tls=pthread.\n"); } while (0)
-#define EMIT_TLS_ACCESS_NEXT_ADDR(mb, _var) do { g_error ("sgen is not supported when using --with-tls=pthread.\n"); } while (0)
-#define EMIT_TLS_ACCESS_TEMP_END(mb, _var) do { g_error ("sgen is not supported when using --with-tls=pthread.\n"); } while (0)
-#define EMIT_TLS_ACCESS_IN_CRITICAL_REGION_ADDR(mb, _var) do { g_error ("sgen is not supported when using --with-tls=pthread.\n"); } while (0)
-
-#endif
-
/* FIXME: Do this in the JIT, where specialized allocation sequences can be created
* for each class. This is currently not easy to do, as it is hard to generate basic
* blocks + branches, but it is easy with the linear IL codebase.
#ifdef MANAGED_ALLOCATION
if (collect_before_allocs)
return NULL;
- if (!mono_runtime_has_tls_get ())
- return NULL;
if (klass->instance_size > tlab_size)
return NULL;
if (known_instance_size && ALIGN_TO (klass->instance_size, SGEN_ALLOC_ALIGN) >= SGEN_MAX_SMALL_OBJ_SIZE)
#ifdef MANAGED_ALLOCATION
if (klass->rank != 1)
return NULL;
- if (!mono_runtime_has_tls_get ())
- return NULL;
if (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS)
return NULL;
if (has_per_allocation_action)
if (variant == MANAGED_ALLOCATOR_REGULAR && !use_managed_allocator)
return NULL;
- if (variant == MANAGED_ALLOCATOR_REGULAR && !mono_runtime_has_tls_get ())
- return NULL;
-
switch (variant) {
case MANAGED_ALLOCATOR_REGULAR: cache = alloc_method_cache; break;
case MANAGED_ALLOCATOR_SLOW_PATH: cache = slowpath_alloc_method_cache; break;
size_t stsize = 0;
guint8 *staddr = NULL;
-#ifndef HAVE_KW_THREAD
- g_assert (!mono_native_tls_get_value (thread_info_key));
- mono_native_tls_set_value (thread_info_key, info);
-#else
- sgen_thread_info = info;
-#endif
+ mono_tls_set_sgen_thread_info (info);
info->client_info.skip = 0;
{
MonoNativeThreadId tid;
-#ifndef HAVE_KW_THREAD
- mono_native_tls_set_value (thread_info_key, NULL);
-#else
- sgen_thread_info = NULL;
-#endif
+ mono_tls_set_sgen_thread_info (NULL);
tid = mono_thread_info_get_tid (p);
mono_sgen_init_stw ();
-#ifndef HAVE_KW_THREAD
- mono_native_tls_alloc (&thread_info_key, NULL);
-#if defined(TARGET_OSX) || defined(TARGET_WIN32) || defined(TARGET_ANDROID) || defined(TARGET_IOS)
- /*
- * CEE_MONO_TLS requires the tls offset, not the key, so the code below only works on darwin,
- * where the two are the same.
- */
- mono_tls_key_set_offset (TLS_KEY_SGEN_THREAD_INFO, thread_info_key);
-#endif
-#else
- {
- int tls_offset = -1;
- MONO_THREAD_VAR_OFFSET (sgen_thread_info, tls_offset);
- mono_tls_key_set_offset (TLS_KEY_SGEN_THREAD_INFO, tls_offset);
- }
-#endif
+ mono_tls_init_gc_keys ();
mono_gc_register_thread (&dummy);
}
sgen_gc_init ();
-#if defined(HAVE_KW_THREAD)
- /* This can happen with using libmonosgen.so */
- if (mono_tls_key_get_offset (TLS_KEY_SGEN_THREAD_INFO) == -1)
- sgen_set_use_managed_allocator (FALSE);
-#endif
-
gc_inited = TRUE;
}
void mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean permanent, MonoError *error);
-void mono_runtime_set_has_tls_get (gboolean val);
-gboolean mono_runtime_has_tls_get (void);
-
void mono_thread_suspend_all_other_threads (void);
gboolean mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout);
MonoThread *
mono_thread_attach_full (MonoDomain *domain, gboolean force_attach);
-void mono_thread_init_tls (void);
-
/* Can't include utils/mono-threads.h because of the THREAD_INFO_TYPE wizardry */
void mono_threads_add_joinable_thread (gpointer tid);
void mono_threads_join_threads (void);
*/
static MonoGHashTable *threads_starting_up = NULL;
-/* The TLS key that holds the MonoObject assigned to each thread */
-static MonoNativeTlsKey current_object_key;
-
/* Contains tids */
/* Protected by the threads lock */
static GHashTable *joinable_threads;
static int joinable_thread_count;
-#ifdef MONO_HAVE_FAST_TLS
-/* we need to use both the Tls* functions and __thread because
- * the gc needs to see all the threads
- */
-MONO_FAST_TLS_DECLARE(tls_current_object);
-#define SET_CURRENT_OBJECT(x) do { \
- MONO_FAST_TLS_SET (tls_current_object, x); \
- mono_native_tls_set_value (current_object_key, x); \
-} while (FALSE)
-#define GET_CURRENT_OBJECT() ((MonoInternalThread*) MONO_FAST_TLS_GET (tls_current_object))
-#else
-#define SET_CURRENT_OBJECT(x) mono_native_tls_set_value (current_object_key, x)
-#define GET_CURRENT_OBJECT() (MonoInternalThread*) mono_native_tls_get_value (current_object_key)
-#endif
+#define SET_CURRENT_OBJECT(x) mono_tls_set_thread (x)
+#define GET_CURRENT_OBJECT() (MonoInternalThread*) mono_tls_get_thread ()
/* function called at thread start */
static MonoThreadStartCB mono_thread_start_cb = NULL;
return InterlockedIncrement (&managed_thread_id_counter);
}
-MonoNativeTlsKey
-mono_thread_get_tls_key (void)
-{
- return current_object_key;
-}
-
-gint32
-mono_thread_get_tls_offset (void)
-{
- int offset = -1;
-
-#ifdef HOST_WIN32
- if (current_object_key)
- offset = current_object_key;
-#else
- MONO_THREAD_VAR_OFFSET (tls_current_object,offset);
-#endif
- return offset;
-}
-
static inline MonoNativeThreadId
thread_get_tid (MonoInternalThread *thread)
{
mono_profiler_context_unloaded (ctx);
}
-void
-mono_thread_init_tls (void)
-{
- MONO_FAST_TLS_INIT (tls_current_object);
- mono_native_tls_alloc (¤t_object_key, NULL);
-}
-
void mono_thread_init (MonoThreadStartCB start_cb,
MonoThreadAttachCB attach_cb)
{
mono_init_static_data_info (&thread_static_info);
mono_init_static_data_info (&context_static_info);
- THREAD_DEBUG (g_message ("%s: Allocated current_object_key %d", __func__, current_object_key));
-
mono_thread_start_cb = start_cb;
mono_thread_attach_cb = attach_cb;
}
mono_os_mutex_destroy (&small_id_mutex);
mono_os_event_destroy (&background_change_event);
#endif
-
- mono_native_tls_free (current_object_key);
}
void
return ret;
}
-static gboolean has_tls_get = FALSE;
-
-void
-mono_runtime_set_has_tls_get (gboolean val)
-{
- has_tls_get = val;
-}
-
-gboolean
-mono_runtime_has_tls_get (void)
-{
- return has_tls_get;
-}
-
static void
self_interrupt_thread (void *_unused)
{
arm_sources = \
mini-arm.c \
- mini-arm-tls.S \
mini-arm.h \
- mini-arm-tls.h \
exceptions-arm.c \
tramp-arm.c \
mini-arm-gsharedvt.c \
/* stelemref */
add_method (acfg, mono_marshal_get_stelemref ());
- if (MONO_ARCH_HAVE_TLS_GET) {
- /* Managed Allocators */
- nallocators = mono_gc_get_managed_allocator_types ();
- for (i = 0; i < nallocators; ++i) {
- if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_REGULAR)))
- add_method (acfg, m);
- if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_SLOW_PATH)))
- add_method (acfg, m);
- }
+ /* Managed Allocators */
+ nallocators = mono_gc_get_managed_allocator_types ();
+ for (i = 0; i < nallocators; ++i) {
+ if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_REGULAR)))
+ add_method (acfg, m);
+ if ((m = mono_gc_get_managed_allocator_by_type (i, MANAGED_ALLOCATOR_SLOW_PATH)))
+ add_method (acfg, m);
}
/* write barriers */
encode_value (get_image_index (acfg, patch_info->data.image), p, &p);
break;
case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
- case MONO_PATCH_INFO_JIT_TLS_ID:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_GC_NURSERY_START:
case MONO_PATCH_INFO_GC_NURSERY_BITS:
encode_method_ref (acfg, patch_info->data.method, p, &p);
break;
case MONO_PATCH_INFO_AOT_JIT_INFO:
+ case MONO_PATCH_INFO_GET_TLS_TRAMP:
+ case MONO_PATCH_INFO_SET_TLS_TRAMP:
encode_value (patch_info->data.index, p, &p);
break;
case MONO_PATCH_INFO_INTERNAL_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
encode_signature (acfg, (MonoMethodSignature*)patch_info->data.target, p, &p);
break;
- case MONO_PATCH_INFO_TLS_OFFSET:
- encode_value (GPOINTER_TO_INT (patch_info->data.target), p, &p);
- break;
case MONO_PATCH_INFO_GSHAREDVT_CALL:
encode_signature (acfg, (MonoMethodSignature*)patch_info->data.gsharedvt->sig, p, &p);
encode_method_ref (acfg, patch_info->data.gsharedvt->method, p, &p);
encode_method_ref (acfg, patch_info->data.virt_method->method, p, &p);
break;
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
- case MONO_PATCH_INFO_GET_TLS_TRAMP:
case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
break;
default:
get_got_offset (acfg, FALSE, ji);
get_got_offset (acfg, TRUE, ji);
- ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
- ji->type = MONO_PATCH_INFO_JIT_TLS_ID;
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
-
ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
ji->type = MONO_PATCH_INFO_AOT_MODULE;
get_got_offset (acfg, FALSE, ji);
get_got_offset (acfg, FALSE, ji);
get_got_offset (acfg, TRUE, ji);
- ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
- ji->type = MONO_PATCH_INFO_GET_TLS_TRAMP;
- get_got_offset (acfg, FALSE, ji);
- get_got_offset (acfg, TRUE, ji);
+ for (i = 0; i < TLS_KEY_NUM; i++) {
+ ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_GET_TLS_TRAMP;
+ ji->data.index = i;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+
+ ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_SET_TLS_TRAMP;
+ ji->data.index = i;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+ }
ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
ji->type = MONO_PATCH_INFO_JIT_THREAD_ATTACH;
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_GC_NURSERY_START:
case MONO_PATCH_INFO_GC_NURSERY_BITS:
- case MONO_PATCH_INFO_JIT_TLS_ID:
break;
case MONO_PATCH_INFO_CASTCLASS_CACHE:
ji->data.index = decode_value (p, &p);
case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
ji->data.target = decode_signature (aot_module, p, &p);
break;
- case MONO_PATCH_INFO_TLS_OFFSET:
- ji->data.target = GINT_TO_POINTER (decode_value (p, &p));
- break;
case MONO_PATCH_INFO_GSHAREDVT_CALL: {
MonoJumpInfoGSharedVtCall *info = (MonoJumpInfoGSharedVtCall *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoGSharedVtCall));
info->sig = decode_signature (aot_module, p, &p);
break;
}
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
- case MONO_PATCH_INFO_GET_TLS_TRAMP:
case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
break;
+ case MONO_PATCH_INFO_GET_TLS_TRAMP:
+ case MONO_PATCH_INFO_SET_TLS_TRAMP:
case MONO_PATCH_INFO_AOT_JIT_INFO:
ji->data.index = decode_value (p, &p);
break;
br_reg: src1:i len:8
bigmul: len:8 dest:l src1:i src2:i
bigmul_un: len:8 dest:l src1:i src2:i
-tls_get: len:24 dest:i clob:c
-tls_get_reg: len:28 dest:i src1:i clob:c
-tls_set: len:24 src1:i clob:c
-tls_set_reg: len:28 src1:i src2:i clob:c
# 32 bit opcodes
int_add: dest:i src1:i src2:i len:4
endfilter: len:96
endfinally: len:96
aot_const: dest:i len:48
-tls_get: dest:i len:48
atomic_add_i4: src1:b src2:i dest:i len:48
atomic_add_i8: src1:b src2:i dest:i len:48
atomic_exchange_i4: src1:b src2:i dest:i len:48
#ppc_subfze: dest:i src1:i len:4
bigmul: len:52 dest:l src1:i src2:i
bigmul_un: len:52 dest:l src1:i src2:i
-tls_get: len:8 dest:i
mips_beq: src1:i src2:i len:24
mips_bgez: src1:i len:24
mips_bgtz: src1:i len:24
ppc_subfze: dest:i src1:i len:4
bigmul: len:12 dest:l src1:i src2:i
bigmul_un: len:12 dest:l src1:i src2:i
-tls_get: len:20 dest:i
# Linear IR opcodes
dummy_use: src1:i len:0
ppc_subfze: dest:i src1:i len:4
bigmul: len:12 dest:i src1:i src2:i
bigmul_un: len:12 dest:i src1:i src2:i
-tls_get: len:8 dest:i
# Linear IR opcodes
dummy_use: src1:i len:0
sub_ovf_un_carry: dest:i src1:1 src2:i len:12
subcc: dest:i src1:i src2:i len:12
throw: src1:i len:26
-tls_get: len:40 dest:i
vcall: len:22 clob:c
vcall_membase: src1:b len:12 clob:c
vcall_reg: src1:i len:8 clob:c
EXCEPTION_RECORD* er;
CONTEXT* ctx;
LONG res;
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
/* If the thread is not managed by the runtime return early */
if (!jit_tls)
static void
handle_signal_exception (gpointer obj)
{
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoContext ctx;
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
* signal is disabled, and we could run arbitrary code though the debugger. So
* resume into the normal stack and do most work there if possible.
*/
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
/* Pass the ctx parameter in TLS */
mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
static void
restore_soft_guard_pages (void)
{
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
if (jit_tls->stack_ovf_guard_base)
mono_mprotect (jit_tls->stack_ovf_guard_base, jit_tls->stack_ovf_guard_size, MONO_MMAP_NONE);
}
static void
handle_signal_exception (gpointer obj)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
MonoContext ctx;
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
* signal is disabled, and we could run arbitrary code though the debugger. So
* resume into the normal stack and do most work there if possible.
*/
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
guint64 sp = UCONTEXT_REG_SP (sigctx);
/* Pass the ctx parameter in TLS */
static void
handle_signal_exception (gpointer obj)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
MonoContext ctx;
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
/*
* Resume into the normal stack and handle the exception there.
*/
- jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ jit_tls = mono_tls_get_jit_tls ();
/* Pass the ctx parameter in TLS */
mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
static void
handle_signal_exception (gpointer obj)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
MonoContext ctx;
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
* signal is disabled, and we could run arbitrary code though the debugger. So
* resume into the normal stack and do most work there if possible.
*/
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
guint64 sp = UCONTEXT_GREGS (sigctx) [mips_sp];
/* Pass the ctx parameter in TLS */
static void
handle_signal_exception (gpointer obj)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
MonoContext ctx;
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
* signal is disabled, and we could run arbitrary code though the debugger. So
* resume into the normal stack and do most work there if possible.
*/
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
mgreg_t sp;
void *sigctx = ctx;
int frame_size;
static void
handle_signal_exception (gpointer obj)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
MonoContext ctx;
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
* signal is disabled, and we could run arbitrary code though the debugger. So
* resume into the normal stack and do most work there if possible.
*/
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
/* Pass the ctx parameter in TLS */
mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
DWORD page_size;
MonoDomain *domain = mono_domain_get ();
MonoJitInfo rji;
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
MonoLMF *lmf = jit_tls->lmf;
MonoContext initial_ctx;
MonoContext ctx;
EXCEPTION_RECORD* er;
CONTEXT* ctx;
LONG res;
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
/* If the thread is not managed by the runtime return early */
if (!jit_tls)
static void
handle_signal_exception (gpointer obj)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
MonoContext ctx;
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
* signal is disabled, and we could run arbitrary code though the debugger. So
* resume into the normal stack and do most work there if possible.
*/
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
/* Pass the ctx parameter in TLS */
mono_sigctx_to_monoctx (ctx, &jit_tls->ex_ctx);
return TRUE;
#elif defined (TARGET_WIN32)
MonoContext mctx;
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
struct sigcontext *ctx = (struct sigcontext *)sigctx;
mono_sigctx_to_monoctx (sigctx, &jit_tls->ex_ctx);
static void
restore_soft_guard_pages (void)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
if (jit_tls->stack_ovf_guard_base)
mono_mprotect (jit_tls->stack_ovf_guard_base, jit_tls->stack_ovf_guard_size, MONO_MMAP_NONE);
}
#define NEW_LDTOKENCONST(cfg,dest,image,token,generic_context) NEW_AOTCONST_TOKEN ((cfg), (dest), MONO_PATCH_INFO_LDTOKEN, (image), (token), (generic_context), STACK_PTR, NULL)
-#define NEW_TLS_OFFSETCONST(cfg,dest,key) do { \
- if (cfg->compile_aot) { \
- NEW_AOTCONST ((cfg), (dest), MONO_PATCH_INFO_TLS_OFFSET, GINT_TO_POINTER (key)); \
- } else { \
- int _offset = mini_get_tls_offset ((key)); \
- NEW_PCONST ((cfg), (dest), GINT_TO_POINTER (_offset)); \
- } \
- } while (0)
-
#define NEW_DECLSECCONST(cfg,dest,image,entry) do { \
if (cfg->compile_aot) { \
NEW_AOTCONST_TOKEN (cfg, dest, MONO_PATCH_INFO_DECLSEC, image, (entry).index, NULL, STACK_OBJ, NULL); \
MonoClass *oklass;
if (mini_get_debug_options ()->better_cast_details) {
- jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
jit_tls->class_cast_from = NULL;
}
gpointer cached_vtable, obj_vtable;
if (mini_get_debug_options ()->better_cast_details) {
- jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
jit_tls->class_cast_from = NULL;
}
static MonoInst*
emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, int context_used, MonoInst **sp);
+inline static MonoInst*
+mono_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, MonoInst *addr, MonoInst *imt_arg, MonoInst *rgctx_arg);
+
/* helper methods signatures */
static MonoMethodSignature *helper_sig_domain_get;
static MonoMethodSignature *helper_sig_rgctx_lazy_fetch_trampoline;
static MonoMethodSignature *helper_sig_llvmonly_imt_trampoline;
static MonoMethodSignature *helper_sig_jit_thread_attach;
+static MonoMethodSignature *helper_sig_get_tls_tramp;
+static MonoMethodSignature *helper_sig_set_tls_tramp;
/* type loading helpers */
static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, System.Runtime.CompilerServices, RuntimeHelpers)
helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
helper_sig_llvmonly_imt_trampoline = mono_create_icall_signature ("ptr ptr ptr");
helper_sig_jit_thread_attach = mono_create_icall_signature ("ptr ptr");
+ helper_sig_get_tls_tramp = mono_create_icall_signature ("ptr");
+ helper_sig_set_tls_tramp = mono_create_icall_signature ("void ptr");
}
static MONO_NEVER_INLINE void
}
}
-static void
-emit_tls_set (MonoCompile *cfg, int sreg1, MonoTlsKey tls_key)
+MonoInst*
+mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key)
{
- MonoInst *ins, *c;
+ if (cfg->compile_aot) {
+ MonoInst *addr;
+ /*
+ * tls getters are critical pieces of code and we don't want to resolve them
+ * through the standard plt/tramp mechanism since we might expose ourselves
+ * to crashes and infinite recursions.
+ */
+ EMIT_NEW_AOTCONST (cfg, addr, MONO_PATCH_INFO_GET_TLS_TRAMP, (void*)key);
+ return mono_emit_calli (cfg, helper_sig_get_tls_tramp, NULL, addr, NULL, NULL);
+ } else {
+ gpointer getter = mono_tls_get_tls_getter (key, FALSE);
+ return mono_emit_jit_icall (cfg, getter, NULL);
+ }
+}
+static MonoInst*
+mono_create_tls_set (MonoCompile *cfg, MonoInst *value, MonoTlsKey key)
+{
if (cfg->compile_aot) {
- EMIT_NEW_TLS_OFFSETCONST (cfg, c, tls_key);
- MONO_INST_NEW (cfg, ins, OP_TLS_SET_REG);
- ins->sreg1 = sreg1;
- ins->sreg2 = c->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
+ MonoInst *addr;
+ EMIT_NEW_AOTCONST (cfg, addr, MONO_PATCH_INFO_SET_TLS_TRAMP, (void*)key);
+ return mono_emit_calli (cfg, helper_sig_set_tls_tramp, &value, addr, NULL, NULL);
} else {
- MONO_INST_NEW (cfg, ins, OP_TLS_SET);
- ins->sreg1 = sreg1;
- ins->inst_offset = mini_get_tls_offset (tls_key);
- MONO_ADD_INS (cfg->cbb, ins);
+ gpointer setter = mono_tls_get_tls_setter (key, FALSE);
+ return mono_emit_jit_icall (cfg, setter, &value);
}
}
* lmf->prev_lmf = *lmf_addr
* *lmf_addr = lmf
*/
- int lmf_reg, prev_lmf_reg;
MonoInst *ins, *lmf_ins;
if (!cfg->lmf_ir)
return;
- if (cfg->lmf_ir_mono_lmf && mini_tls_get_supported (cfg, TLS_KEY_LMF)) {
+ if (cfg->lmf_ir_mono_lmf) {
+ MonoInst *lmf_vara_ins, *lmf_ins;
/* Load current lmf */
- lmf_ins = mono_get_lmf_intrinsic (cfg);
+ lmf_ins = mono_create_tls_get (cfg, TLS_KEY_LMF);
g_assert (lmf_ins);
- MONO_ADD_INS (cfg->cbb, lmf_ins);
- EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
- lmf_reg = ins->dreg;
+ EMIT_NEW_VARLOADA (cfg, lmf_vara_ins, cfg->lmf_var, NULL);
/* Save previous_lmf */
- EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), lmf_ins->dreg);
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_vara_ins->dreg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), lmf_ins->dreg);
/* Set new LMF */
- emit_tls_set (cfg, lmf_reg, TLS_KEY_LMF);
+ mono_create_tls_set (cfg, lmf_vara_ins, TLS_KEY_LMF);
} else {
+ int lmf_reg, prev_lmf_reg;
/*
* Store lmf_addr in a variable, so it can be allocated to a global register.
*/
cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
#ifdef HOST_WIN32
- ins = mono_get_jit_tls_intrinsic (cfg);
- if (ins) {
- int jit_tls_dreg = ins->dreg;
+ ins = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
+ g_assert (ins);
+ int jit_tls_dreg = ins->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- lmf_reg = alloc_preg (cfg);
- EMIT_NEW_BIALU_IMM (cfg, lmf_ins, OP_PADD_IMM, lmf_reg, jit_tls_dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf));
- } else {
- lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL);
- }
+ lmf_reg = alloc_preg (cfg);
+ EMIT_NEW_BIALU_IMM (cfg, lmf_ins, OP_PADD_IMM, lmf_reg, jit_tls_dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf));
#else
- lmf_ins = mono_get_lmf_addr_intrinsic (cfg);
- if (lmf_ins) {
- MONO_ADD_INS (cfg->cbb, lmf_ins);
- } else {
-#ifdef TARGET_IOS
- MonoInst *args [16], *jit_tls_ins, *ins;
-
- /* Inline mono_get_lmf_addr () */
- /* jit_tls = pthread_getspecific (mono_jit_tls_id); lmf_addr = &jit_tls->lmf; */
-
- /* Load mono_jit_tls_id */
- if (cfg->compile_aot)
- EMIT_NEW_AOTCONST (cfg, args [0], MONO_PATCH_INFO_JIT_TLS_ID, NULL);
- else
- EMIT_NEW_ICONST (cfg, args [0], mono_jit_tls_id);
- /* call pthread_getspecific () */
- jit_tls_ins = mono_emit_jit_icall (cfg, pthread_getspecific, args);
- /* lmf_addr = &jit_tls->lmf */
- EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, cfg->lmf_addr_var->dreg, jit_tls_ins->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf));
- lmf_ins = ins;
-#else
- lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL);
-#endif
- }
+ lmf_ins = mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR);
+ g_assert (lmf_ins);
#endif
lmf_ins->dreg = cfg->lmf_addr_var->dreg;
static void
emit_pop_lmf (MonoCompile *cfg)
{
- int lmf_reg, lmf_addr_reg, prev_lmf_reg;
+ int lmf_reg, lmf_addr_reg;
MonoInst *ins;
if (!cfg->lmf_ir)
EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
lmf_reg = ins->dreg;
- if (cfg->lmf_ir_mono_lmf && mini_tls_get_supported (cfg, TLS_KEY_LMF)) {
+ if (cfg->lmf_ir_mono_lmf) {
/* Load previous_lmf */
- prev_lmf_reg = alloc_preg (cfg);
- EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
+ EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, alloc_preg (cfg), lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
/* Set new LMF */
- emit_tls_set (cfg, prev_lmf_reg, TLS_KEY_LMF);
+ mono_create_tls_set (cfg, ins, TLS_KEY_LMF);
} else {
+ int prev_lmf_reg;
/*
* Emit IR to pop the LMF:
* *(lmf->lmf_addr) = lmf->prev_lmf
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
}
- tls_get = mono_get_jit_tls_intrinsic (cfg);
+ tls_get = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
if (!tls_get) {
fprintf (stderr, "error: --debug=casts not supported on this platform.\n.");
exit (1);
}
- MONO_ADD_INS (cfg->cbb, tls_get);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
{
/* Reset the variables holding the cast details */
if (mini_get_debug_options ()->better_cast_details) {
- MonoInst *tls_get = mono_get_jit_tls_intrinsic (cfg);
-
- MONO_ADD_INS (cfg->cbb, tls_get);
+ MonoInst *tls_get = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
/* It is enough to reset the from field */
MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, tls_get->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, class_cast_from), 0);
}
is_special_static = mono_class_field_is_special_static (field);
if (is_special_static && ((gsize)addr & 0x80000000) == 0)
- thread_ins = mono_get_thread_intrinsic (cfg);
+ thread_ins = mono_create_tls_get (cfg, TLS_KEY_THREAD);
else
thread_ins = NULL;
GSHAREDVT_FAILURE (op);
- MONO_ADD_INS (cfg->cbb, thread_ins);
static_data_reg = alloc_ireg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, MONO_STRUCT_OFFSET (MonoInternalThread, static_data));
g_assert (key < TLS_KEY_NUM);
ins = mono_create_tls_get (cfg, key);
- if (!ins) {
- if (cfg->compile_aot) {
- DISABLE_AOT (cfg);
- MONO_INST_NEW (cfg, ins, OP_TLS_GET);
- ins->dreg = alloc_preg (cfg);
- ins->type = STACK_PTR;
- } else {
- g_assert_not_reached ();
- }
- }
+ g_assert (ins);
ins->type = STACK_PTR;
- MONO_ADD_INS (cfg->cbb, ins);
*sp++ = ins;
ip += 6;
break;
EMIT_NEW_PCONST (cfg, ins, NULL);
MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
- ad_ins = mono_get_domain_intrinsic (cfg);
- jit_tls_ins = mono_get_jit_tls_intrinsic (cfg);
+ ad_ins = mono_create_tls_get (cfg, TLS_KEY_DOMAIN);
+ jit_tls_ins = mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
- if (cfg->backend->have_tls_get && ad_ins && jit_tls_ins) {
+ if (ad_ins && jit_tls_ins) {
NEW_BBLOCK (cfg, next_bb);
NEW_BBLOCK (cfg, call_bb);
} else {
EMIT_NEW_PCONST (cfg, domain_ins, cfg->domain);
}
- MONO_ADD_INS (cfg->cbb, ad_ins);
MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, ad_ins->dreg, domain_ins->dreg);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, call_bb);
- MONO_ADD_INS (cfg->cbb, jit_tls_ins);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, jit_tls_ins->dreg, 0);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, call_bb);
cfg->cbb = init_localsbb;
- if ((get_domain = mono_get_domain_intrinsic (cfg))) {
- MONO_ADD_INS (cfg->cbb, get_domain);
- } else {
- get_domain = mono_emit_jit_icall (cfg, mono_domain_get, NULL);
- }
+ get_domain = mono_create_tls_get (cfg, TLS_KEY_DOMAIN);
NEW_TEMPSTORE (cfg, store, cfg->domainvar->inst_c0, get_domain);
MONO_ADD_INS (cfg->cbb, store);
}
if (cfg->method->save_lmf) {
cfg->lmf_ir = TRUE;
#if !defined(TARGET_WIN32)
- if (mono_get_lmf_tls_offset () != -1 && !optimize_for_xen)
+ if (!optimize_for_xen)
cfg->lmf_ir_mono_lmf = TRUE;
#endif
}
return code;
}
- /*
- * mono_arch_translate_tls_offset:
- *
- * Translate the TLS offset OFFSET computed by MONO_THREAD_VAR_OFFSET () into a format usable by OP_TLS_GET_REG/OP_TLS_SET_REG.
- */
-int
-mono_arch_translate_tls_offset (int offset)
-{
-#ifdef __APPLE__
- return tls_gs_offset + (offset * 8);
-#else
- return offset;
-#endif
-}
-
/*
* emit_setup_lmf:
*
if (method->save_lmf) {
/* check if we need to restore protection of the stack after a stack overflow */
+ /* FIXME */
+#if 0
if (!cfg->compile_aot && mono_get_jit_tls_offset () != -1) {
guint8 *patch;
code = mono_amd64_emit_tls_get (code, AMD64_RCX, mono_get_jit_tls_offset ());
} else {
/* FIXME: maybe save the jit tls in the prolog */
}
+#endif
if (cfg->used_int_regs & (1 << AMD64_RBP)) {
amd64_mov_reg_membase (code, AMD64_RBP, cfg->frame_reg, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rbp), 8);
}
#define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
#define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
#define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
-#define MONO_ARCH_HAVE_TLS_GET (mono_amd64_have_tls_get ())
#define MONO_ARCH_IMT_REG AMD64_R10
#define MONO_ARCH_IMT_SCRATCH_REG AMD64_R11
#define MONO_ARCH_VTABLE_REG MONO_AMD64_ARG_REG1
#define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1
#endif
-#if defined(TARGET_OSX) || defined(__linux__) || defined(TARGET_WIN32)
-#define MONO_ARCH_HAVE_TLS_GET_REG 1
-#endif
-
#define MONO_ARCH_GSHAREDVT_SUPPORTED 1
guint64
mono_amd64_get_original_ip (void);
-guint8*
-mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset);
-
-gboolean
-mono_amd64_have_tls_get (void);
-
GSList*
mono_amd64_get_exception_trampolines (gboolean aot);
-int
-mono_amd64_get_tls_gs_offset (void) MONO_LLVM_INTERNAL;
-
gpointer
mono_amd64_handler_block_trampoline_helper (void);
+++ /dev/null
-/*
- * mini-arm-tls.S: tls getters and setters for arm platforms
- *
- * Copyright 2015 Xamarin, Inc.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-
-#ifndef MONO_CROSS_COMPILE
-
- /*
- * The following thunks fetch the value corresponding to the key/offset
- * passed in R0. These thunks don't do jumps to external code so execution
- * within can be tracked. The tls value is returned in R0.
- */
-
-.macro DECLARE_GLOBAL_SYMBOL name
-#ifdef TARGET_MACH
- .global _\name
-_\name:
-#else
- .global \name
-\name:
-#endif
-.endm
-
- .text
-/* no .arch on clang. it only supports armv6+ anyway */
-#ifndef TARGET_MACH
- .arch armv5
-#endif
- .arm
- .align 4
-
-DECLARE_GLOBAL_SYMBOL mono_fast_get_tls_key
-#if defined(__linux__)
- mrc p15, 0, r1, c13, c0, 3
-#if defined(HAVE_KW_THREAD)
- ldr r0, [r1, r0]
-#elif defined(TARGET_ANDROID)
- ldr r0, [r1, r0, lsl #2]
-#endif
- bx lr
-#elif defined(TARGET_IOS)
- mrc p15, 0, r1, c13, c0, 3
- bic r1, r1, #3
- ldr r0, [r1, r0, lsl #2]
- bx lr
-#endif
-DECLARE_GLOBAL_SYMBOL mono_fast_get_tls_key_end
-
- /*
- * The following thunks fetch the value corresponding to the key/offset
- * passed in R0. These thunks are used in the unlikely cases where we determine
- * at runtime that the current implementation is not accounted for.
- */
-
- .align 4
-DECLARE_GLOBAL_SYMBOL mono_fallback_get_tls_key
-#if defined(__linux__) && defined(HAVE_KW_THREAD) && defined(__ARM_EABI__)
- push {lr}
- mov r1, r0
- bl __aeabi_read_tp
- ldr r0, [r0, r1]
- pop {pc}
-#elif defined(TARGET_IOS)
- push {r7, lr}
- mov r7, sp
- bl _pthread_getspecific
- pop {r7, pc}
-#elif defined(TARGET_ANDROID)
- push {lr}
- bl pthread_getspecific
- pop {pc}
-#endif
- /*
- * The following thunks set the value corresponding to the key/offset
- * passed in R0. These thunks don't do jumps to external code so execution
- * within can be tracked. The tls value is passed in R1.
- */
-
- .align 4
-DECLARE_GLOBAL_SYMBOL mono_fast_set_tls_key
-#if defined(__linux__)
- mrc p15, 0, r2, c13, c0, 3
-#if defined(HAVE_KW_THREAD)
- str r1, [r2, r0]
-#elif defined(TARGET_ANDROID)
- str r1, [r2, r0, lsl #2]
-#endif
- bx lr
-#elif defined(TARGET_IOS)
- mrc p15, 0, r2, c13, c0, 3
- bic r2, r2, #3
- str r1, [r2, r0, lsl #2]
- bx lr
-#endif
-DECLARE_GLOBAL_SYMBOL mono_fast_set_tls_key_end
-
- /*
- * The following thunks set the value corresponding to the key/offset
- * passed in R0. These thunks are used in the unlikely cases where we determine
- * at runtime that the current implementation is not accounted for.
- */
-
- .align 4
-DECLARE_GLOBAL_SYMBOL mono_fallback_set_tls_key
-#if defined(__linux__) && defined(HAVE_KW_THREAD) && defined(__ARM_EABI__)
- push {lr}
- mov r2, r0
- bl __aeabi_read_tp
- str r1, [r0, r2]
- pop {pc}
-#elif defined(TARGET_IOS)
- push {r7, lr}
- mov r7, sp
- bl _pthread_setspecific
- pop {r7, pc}
-#elif defined(TARGET_ANDROID)
- push {lr}
- bl pthread_setspecific
- pop {pc}
-#endif
-
-
- /* Additional tls getters/setters */
-
-#if defined(TARGET_ANDROID)
- .align 4
-DECLARE_GLOBAL_SYMBOL mono_fast_get_tls_key2
- bic r0, r0, #0x80000000
- mrc p15, 0, r1, cr13, cr0, #3
- lsls r0, r0, #3
- ldr r1, [r1, #4]
- add r0, r1
- ldr r0, [r0, #0x68]
- bx lr
-DECLARE_GLOBAL_SYMBOL mono_fast_get_tls_key2_end
-
- /*
- * In order to use this fast setter we need to make sure that the key was
- * already set at least once using the pthread api, otherwise it will not
- * interwork with the api.
- */
- .align 4
-DECLARE_GLOBAL_SYMBOL mono_fast_set_tls_key2
- bic r0, r0, #0x80000000
- mrc p15, 0, r2, cr13, cr0, #3
- lsls r0, r0, #3
- ldr r2, [r2, #4]
- add r0, r2
- str r1, [r0, #0x68]
- bx lr
-DECLARE_GLOBAL_SYMBOL mono_fast_set_tls_key2_end
-#endif
-
-#endif
-
+++ /dev/null
-#ifndef __MONO_MINI_ARM_TLS_H__
-#define __MONO_MINI_ARM_TLS_H__
-
-/* Fast inlined tls getters/setters */
-
-int mono_fast_get_tls_key (int);
-void mono_fast_set_tls_key (int, int);
-int mono_fast_get_tls_key2 (int);
-void mono_fast_set_tls_key2 (int, int);
-
-/* Fallback tls getters/setters */
-
-int mono_fallback_get_tls_key (int);
-void mono_fallback_set_tls_key (int, int);
-
-/* End of thunks */
-
-void mono_fast_get_tls_key_end (void);
-void mono_fast_set_tls_key_end (void);
-void mono_fast_get_tls_key2_end (void);
-void mono_fast_set_tls_key2_end (void);
-
-#if defined(__linux__) && defined(HAVE_KW_THREAD) && defined(__ARM_EABI__)
-void* __aeabi_read_tp (void);
-#endif
-
-/* Structure that maps a possible tls implementation to the corresponding thunks */
-typedef struct {
- guint32 *expected_code;
- int expected_code_length;
- gboolean check_kernel_helper;
- gpointer get_tls_thunk;
- gpointer get_tls_thunk_end;
- gpointer set_tls_thunk;
- gpointer set_tls_thunk_end;
-} MonoTlsImplementation;
-
-
-static MonoTlsImplementation known_tls_implementations [] = {
-#if defined(HAVE_KW_THREAD) && defined(__linux__) && defined(__ARM_EABI__)
- { (guint32[]) {0x0f70ee1d, 0xbf004770}, 8, FALSE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end },
- { (guint32[]) {0xe3e00a0f, 0xe240f01f}, 8, TRUE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end }
-#elif defined(TARGET_IOS)
- { (guint32[]) {0x1f70ee1d, 0x0103f021, 0x0020f851, 0xbf004770}, 16, FALSE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end }
-#elif defined(TARGET_ANDROID)
- { (guint32[]) {0xe2403003, 0xe353003c, 0xe92d4010, 0xe1a04000, 0x9a000001, 0xe3a00000, 0xe8bd8010, 0xe3e00a0f, 0xe240101f, 0xe12fff31, 0xe7900104, 0xe8bd8010}, 48, TRUE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end}, /* 1.5 */
- { (guint32[]) {0xe2402003, 0xe1a03000, 0xe352003c, 0x8a000002, 0xee1d0f70, 0xe7900103, 0xe12fff1e}, 28, FALSE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end}, /* 4.2 */
- { (guint32[]) {0xe2403007, 0xe3530084, 0x8a000002, 0xee1d1f70, 0xe7910100, 0xe12fff1e, 0xe3a00000, 0xe12fff1e}, 32, FALSE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end}, /* 4.4 */
- { (guint32[]) {0x2b8c1fc3, 0xee1dd804, 0xf8511f70, 0x47700020, 0x47702000}, 20, FALSE, mono_fast_get_tls_key, mono_fast_get_tls_key_end, mono_fast_set_tls_key, mono_fast_set_tls_key_end}, /* 5.0 */
- { (guint32[]) {0xb5104b0f, 0xda114298, 0xf020490e, 0xee1d4000, 0x00c24f70, 0xf8514479, 0x68631030, 0xd50707cc, 0x6e54441a, 0xd103428c, 0xbd106e90}, 44, FALSE, mono_fast_get_tls_key2, mono_fast_get_tls_key2_end, mono_fast_set_tls_key2, mono_fast_set_tls_key2_end} /* 6.0 */
-#endif
-};
-
-static gboolean
-known_kernel_helper (void)
-{
-#ifdef __linux__
- const guint32* kuser_get_tls = (void*)0xffff0fe0; /* linux kernel user helper on arm */
- guint32 expected [] = {0xee1d0f70, 0xe12fff1e};
-
- /* Expecting mrc + bx lr in the kuser_get_tls kernel helper */
- return memcmp (kuser_get_tls, expected, 8) == 0;
-#else
- g_error ("Trying to check linux kernel helper on non linux platform");
- return FALSE;
-#endif
-}
-
-static void
-dump_code (guint32 *ptr)
-{
- char current_impl [256];
- char hex [16];
- int i;
- guint32 page_mask = ~((guint32)mono_pagesize () - 1);
-
- current_impl [0] = 0;
- for (i = 0; i < 16; i++) {
- /* Don't risk page fault since we don't know where the code ends */
- if (((guint32)&ptr [i] & page_mask) != ((guint32)ptr & page_mask))
- break;
- sprintf (hex, "0x%x ", ptr [i]);
- strcat (current_impl, hex);
- }
-
- g_warning (current_impl);
-}
-
-static MonoTlsImplementation
-mono_arm_get_tls_implementation (void)
-{
-#ifdef MONO_CROSS_COMPILE
- g_assert_not_reached ();
-#else
- /* Discard thumb bit */
-#if defined(__linux__) && defined(HAVE_KW_THREAD) && defined(__ARM_EABI__)
- guint32* check_addr = (guint32*) ((guint32)__aeabi_read_tp & 0xfffffffe);
-#else
- guint32* check_addr = (guint32*) ((guint32)pthread_getspecific & 0xfffffffe);
-#endif
- int i;
-
- if (!mini_get_debug_options ()->arm_use_fallback_tls) {
- for (i = 0; i < sizeof (known_tls_implementations) / sizeof (MonoTlsImplementation); i++) {
- if (memcmp (check_addr, known_tls_implementations [i].expected_code, known_tls_implementations [i].expected_code_length) == 0) {
- if ((known_tls_implementations [i].check_kernel_helper && known_kernel_helper ()) ||
- !known_tls_implementations [i].check_kernel_helper)
- return known_tls_implementations [i];
- }
- }
- }
-
- g_warning ("No fast tls on device. Using fallbacks. Current implementation : ");
- dump_code (check_addr);
-
- return (MonoTlsImplementation) { NULL, 0, FALSE, mono_fallback_get_tls_key, NULL, mono_fallback_set_tls_key, NULL };
-#endif
-}
-#endif
#include <mono/utils/mono-threads-coop.h>
#include "mini-arm.h"
-#include "mini-arm-tls.h"
#include "cpu-arm.h"
#include "trace.h"
#include "ir-emit.h"
#include "mini-gc.h"
#include "mono/arch/arm/arm-vfp-codegen.h"
-#if (defined(HAVE_KW_THREAD) && defined(__linux__) && defined(__ARM_EABI__)) \
- || defined(TARGET_ANDROID) \
- || (defined(TARGET_IOS) && !defined(TARGET_WATCHOS))
-#define HAVE_FAST_TLS
-#endif
-
/* Sanity check: This makes no sense */
#if defined(ARM_FPU_NONE) && (defined(ARM_FPU_VFP) || defined(ARM_FPU_VFP_HARD))
#error "ARM_FPU_NONE is defined while one of ARM_FPU_VFP/ARM_FPU_VFP_HARD is defined"
return code;
}
-static guint8*
-mono_arm_emit_tls_get (MonoCompile *cfg, guint8* code, int dreg, int tls_offset)
-{
-#ifdef HAVE_FAST_TLS
- code = mono_arm_emit_load_imm (code, ARMREG_R0, tls_offset);
- if (cfg->compile_aot) {
- /*
- * This opcode is generated by CEE_MONO_JIT_ATTACH, so it can execute on
- * threads which are not yet attached to the runtime. This means we can't
- * call it directly, since the call would go through the trampoline code
- * which assumes the thread is attached. So use a separate patch info type
- * for it, and load it from a preinitialized GOT slot.
- */
- code = emit_aotconst (cfg, code, ARMREG_R1, MONO_PATCH_INFO_GET_TLS_TRAMP, NULL);
- code = emit_call_reg (code, ARMREG_R1);
- } else {
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- "mono_get_tls_key");
- code = emit_call_seq (cfg, code);
- }
- if (dreg != ARMREG_R0)
- ARM_MOV_REG_REG (code, dreg, ARMREG_R0);
-#else
- g_assert_not_reached ();
-#endif
- return code;
-}
-
-static guint8*
-mono_arm_emit_tls_get_reg (MonoCompile *cfg, guint8* code, int dreg, int tls_offset_reg)
-{
-#ifdef HAVE_FAST_TLS
- if (tls_offset_reg != ARMREG_R0)
- ARM_MOV_REG_REG (code, ARMREG_R0, tls_offset_reg);
- if (cfg->compile_aot) {
- code = emit_aotconst (cfg, code, ARMREG_R1, MONO_PATCH_INFO_GET_TLS_TRAMP, NULL);
- code = emit_call_reg (code, ARMREG_R1);
- } else {
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- "mono_get_tls_key");
- code = emit_call_seq (cfg, code);
- }
- if (dreg != ARMREG_R0)
- ARM_MOV_REG_REG (code, dreg, ARMREG_R0);
-#else
- g_assert_not_reached ();
-#endif
- return code;
-}
-
-static guint8*
-mono_arm_emit_tls_set (MonoCompile *cfg, guint8* code, int sreg, int tls_offset)
-{
-#ifdef HAVE_FAST_TLS
- if (sreg != ARMREG_R1)
- ARM_MOV_REG_REG (code, ARMREG_R1, sreg);
- code = mono_arm_emit_load_imm (code, ARMREG_R0, tls_offset);
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- "mono_set_tls_key");
- code = emit_call_seq (cfg, code);
-#else
- g_assert_not_reached ();
-#endif
- return code;
-}
-
-static guint8*
-mono_arm_emit_tls_set_reg (MonoCompile *cfg, guint8* code, int sreg, int tls_offset_reg)
-{
-#ifdef HAVE_FAST_TLS
- /* Get sreg in R1 and tls_offset_reg in R0 */
- if (tls_offset_reg == ARMREG_R1) {
- if (sreg == ARMREG_R0) {
- /* swap sreg and tls_offset_reg */
- ARM_EOR_REG_REG (code, sreg, sreg, tls_offset_reg);
- ARM_EOR_REG_REG (code, tls_offset_reg, sreg, tls_offset_reg);
- ARM_EOR_REG_REG (code, sreg, sreg, tls_offset_reg);
- } else {
- ARM_MOV_REG_REG (code, ARMREG_R0, tls_offset_reg);
- if (sreg != ARMREG_R1)
- ARM_MOV_REG_REG (code, ARMREG_R1, sreg);
- }
- } else {
- if (sreg != ARMREG_R1)
- ARM_MOV_REG_REG (code, ARMREG_R1, sreg);
- if (tls_offset_reg != ARMREG_R0)
- ARM_MOV_REG_REG (code, ARMREG_R0, tls_offset_reg);
- }
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- "mono_set_tls_key");
- code = emit_call_seq (cfg, code);
-#else
- g_assert_not_reached ();
-#endif
- return code;
-}
-
/*
* emit_save_lmf:
*
static guint8*
emit_save_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
{
- gboolean get_lmf_fast = FALSE;
int i;
- if (mono_arm_have_tls_get ()) {
- get_lmf_fast = TRUE;
- if (cfg->compile_aot) {
- /* OP_AOTCONST */
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_TLS_OFFSET, (gpointer)TLS_KEY_LMF_ADDR);
- ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0);
- ARM_B (code, 0);
- *(gpointer*)code = NULL;
- code += 4;
- /* Load the value from the GOT */
- ARM_LDR_REG_REG (code, ARMREG_R1, ARMREG_PC, ARMREG_R1);
- code = mono_arm_emit_tls_get_reg (cfg, code, ARMREG_R0, ARMREG_R1);
- } else {
- gint32 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset ();
- g_assert (lmf_addr_tls_offset != -1);
- code = mono_arm_emit_tls_get (cfg, code, ARMREG_R0, lmf_addr_tls_offset);
- }
- }
-
- if (!get_lmf_fast) {
- mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_get_lmf_addr");
- code = emit_call_seq (cfg, code);
- }
+ mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+ (gpointer)"mono_get_lmf_addr");
+ code = emit_call_seq (cfg, code);
/* we build the MonoLMF structure on the stack - see mini-arm.h */
/* lmf_offset is the offset from the previous stack pointer,
* alloc_size is the total stack space allocated, so the offset
#endif /* #ifndef DISABLE_JIT */
-/*
- * mono_arm_have_tls_get:
- *
- * Returns whether we have tls access implemented on the current
- * platform
- */
-gboolean
-mono_arm_have_tls_get (void)
-{
-#ifdef HAVE_FAST_TLS
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
/*
* mono_arch_get_argument_info:
* @csig: a method signature
ARM_MCR (code, 15, 0, ARMREG_R0, 7, 10, 5);
}
break;
- case OP_TLS_GET:
- code = mono_arm_emit_tls_get (cfg, code, ins->dreg, ins->inst_offset);
- break;
- case OP_TLS_GET_REG:
- code = mono_arm_emit_tls_get_reg (cfg, code, ins->dreg, ins->sreg1);
- break;
- case OP_TLS_SET:
- code = mono_arm_emit_tls_set (cfg, code, ins->sreg1, ins->inst_offset);
- break;
- case OP_TLS_SET_REG:
- code = mono_arm_emit_tls_set_reg (cfg, code, ins->sreg1, ins->sreg2);
- break;
case OP_ATOMIC_EXCHANGE_I4:
case OP_ATOMIC_CAS_I4:
case OP_ATOMIC_ADD_I4: {
mono_register_jit_icall (mono_arm_throw_exception, "mono_arm_throw_exception", mono_create_icall_signature ("void"), TRUE);
mono_register_jit_icall (mono_arm_throw_exception_by_token, "mono_arm_throw_exception_by_token", mono_create_icall_signature ("void"), TRUE);
mono_register_jit_icall (mono_arm_unaligned_stack, "mono_arm_unaligned_stack", mono_create_icall_signature ("void"), TRUE);
-
-#ifndef MONO_CROSS_COMPILE
- if (mono_arm_have_tls_get ()) {
- MonoTlsImplementation tls_imp = mono_arm_get_tls_implementation ();
-
- mono_register_jit_icall (tls_imp.get_tls_thunk, "mono_get_tls_key", mono_create_icall_signature ("ptr ptr"), TRUE);
- mono_register_jit_icall (tls_imp.set_tls_thunk, "mono_set_tls_key", mono_create_icall_signature ("void ptr ptr"), TRUE);
-
- get_tls_tramp = tls_imp.get_tls_thunk;
-
- if (tls_imp.get_tls_thunk_end) {
- mono_tramp_info_register (
- mono_tramp_info_create (
- "mono_get_tls_key",
- (guint8*)tls_imp.get_tls_thunk,
- (guint8*)tls_imp.get_tls_thunk_end - (guint8*)tls_imp.get_tls_thunk,
- NULL,
- mono_arch_get_cie_program ()
- ),
- NULL
- );
- mono_tramp_info_register (
- mono_tramp_info_create (
- "mono_set_tls_key",
- (guint8*)tls_imp.set_tls_thunk,
- (guint8*)tls_imp.set_tls_thunk_end - (guint8*)tls_imp.set_tls_thunk,
- NULL,
- mono_arch_get_cie_program ()
- ),
- NULL
- );
- }
- }
-#endif
}
#define patch_lis_ori(ip,val) do {\
gpointer
mono_arch_get_get_tls_tramp (void)
{
- return get_tls_tramp;
+ return NULL;
}
static guint8*
#define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
#define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
#define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT 1
-#define MONO_ARCH_HAVE_GET_TLS_TRAMP 1
-
-#define MONO_ARCH_HAVE_TLS_GET (mono_arm_have_tls_get ())
-#define MONO_ARCH_HAVE_TLS_GET_REG 1
#ifdef TARGET_WATCHOS
#define MONO_ARCH_DISABLE_HW_TRAPS 1
#else
#define MONO_ARCH_REDZONE_SIZE 0
-#if !defined(__PIC__)
-#define MONO_ARCH_HAVE_TLS_GET 1
-#endif
-#define MONO_ARCH_HAVE_TLS_GET_REG 1
#endif
mini_above_abort_threshold (void)
{
gpointer sp = mono_thread_get_managed_sp ();
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData*) mono_tls_get_jit_tls ();
if (!sp)
return TRUE;
mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
{
if (!start_ctx) {
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
if (jit_tls && jit_tls->orig_ex_ctx_set)
start_ctx = &jit_tls->orig_ex_ctx;
}
{
MonoError error;
MonoDomain *domain = mono_domain_get ();
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoLMF *lmf = mono_get_lmf ();
MonoJitInfo *ji = NULL;
MonoContext ctx, new_ctx;
MonoDomain *domain = mono_domain_get ();
MonoJitInfo *ji = NULL;
static int (*call_filter) (MonoContext *, gpointer) = NULL;
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoLMF *lmf = mono_get_lmf ();
MonoArray *initial_trace_ips = NULL;
GList *trace_ips = NULL;
MonoDomain *domain = mono_domain_get ();
MonoJitInfo *ji, *prev_ji;
static int (*call_filter) (MonoContext *, gpointer) = NULL;
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoLMF *lmf = mono_get_lmf ();
MonoException *mono_ex;
gboolean stack_overflow = FALSE;
{
static int (*call_filter) (MonoContext *, gpointer) = NULL;
MonoDomain *domain = mono_domain_get ();
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoLMF *lmf = mono_get_lmf ();
MonoContext ctx, new_ctx;
MonoJitInfo *ji, rji;
static G_GNUC_UNUSED void
try_more_restore (void)
{
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
if (try_restore_stack_protection (jit_tls, 500))
jit_tls->restore_stack_prot = NULL;
}
static G_GNUC_UNUSED void
restore_stack_protection (void)
{
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoException *ex = mono_domain_get ()->stack_overflow_ex;
/* if we can't restore the stack protection, keep a callback installed so
* we'll try to restore as much stack as we can at each return from unmanaged
#ifdef MONO_ARCH_USE_SIGACTION
struct sigaction sa;
#endif
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
if (handling_sigsegv)
return;
{
MONO_REQ_GC_UNSAFE_MODE;
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
MonoContext new_ctx;
MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
static gboolean
mono_current_thread_has_handle_block_guard (void)
{
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
return jit_tls && jit_tls->handler_block_return_address != NULL;
}
MonoJitTlsData *jit_tls = NULL;
if (mini_get_debug_options ()->better_cast_details) {
- jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
jit_tls->class_cast_from = from;
jit_tls->class_cast_to = to;
}
mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
{
#ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
jit_tls->ex_ctx = *ctx;
mono_arch_setup_async_callback (ctx, async_cb, user_data);
} else {
tls->unwind_state.valid = FALSE;
}
- tls->unwind_state.unwind_data [MONO_UNWIND_DATA_JIT_TLS] = mono_native_tls_get_value (mono_jit_tls_id);
+ tls->unwind_state.unwind_data [MONO_UNWIND_DATA_JIT_TLS] = mono_tls_get_jit_tls ();
tls->unwind_state.unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
}
break;
}
- case OP_TLS_GET:
- ia64_adds_imm (code, ins->dreg, ins->inst_offset, IA64_TP);
- ia64_ld8 (code, ins->dreg, ins->dreg);
- break;
-
/* Synchronization */
case OP_MEMORY_BARRIER:
ia64_mf (code);
break;
#endif
}
- case OP_TLS_GET: {
-#if (defined(TARGET_AMD64) || defined(TARGET_X86)) && defined(__linux__)
-#ifdef TARGET_AMD64
- // 257 == FS segment register
- LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
-#else
- // 256 == GS segment register
- LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
-#endif
- // FIXME: XEN
- values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), ins->inst_offset, TRUE), ptrtype, ""), "");
-#elif defined(TARGET_AMD64) && defined(TARGET_OSX)
- /* See mono_amd64_emit_tls_get () */
- int offset = mono_amd64_get_tls_gs_offset () + (ins->inst_offset * 8);
-
- // 256 == GS segment register
- LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
- values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), offset, TRUE), ptrtype, ""), "");
-#else
- set_failure (ctx, "opcode tls-get");
- break;
-#endif
-
- break;
- }
- case OP_TLS_GET_REG: {
-#if defined(TARGET_AMD64) && defined(__linux__)
- // 257 == FS segment register
- LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
- values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt64Type ()), ptrtype, ""), "");
-#elif defined(TARGET_AMD64) && defined(TARGET_OSX)
- /* See emit_tls_get_reg () */
- // 256 == GS segment register
- LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
- values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt32Type ()), ptrtype, ""), "");
-#else
- set_failure (ctx, "opcode tls-get");
- break;
-#endif
- break;
- }
-
- case OP_TLS_SET_REG: {
-#if defined(TARGET_AMD64) && defined(TARGET_OSX)
- /* See emit_tls_get_reg () */
- // 256 == GS segment register
- LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
- LLVMBuildStore (builder, convert (ctx, lhs, IntPtrType ()), LLVMBuildIntToPtr (builder, convert (ctx, rhs, LLVMInt32Type ()), ptrtype, ""));
-#else
- set_failure (ctx, "opcode tls-set-reg");
- break;
-#endif
- break;
- }
case OP_GC_SAFE_POINT: {
LLVMValueRef val, cmp, callee;
LLVMBasicBlockRef poll_bb, cont_bb;
static mono_mutex_t mini_arch_mutex;
int mono_exc_esp_offset = 0;
-static int tls_mode = TLS_MODE_DETECT;
-static int lmf_pthread_key = -1;
-static int monothread_key = -1;
/* Whenever the host is little-endian */
static int little_endian;
cfg->bb_exit->max_offset += 16; \
} while (0)
-
-#define emit_linuxthreads_tls(code,dreg,key) do {\
- int off1, off2; \
- off1 = offsets_from_pthread_key ((key), &off2); \
- g_assert_not_reached (); \
- ppc_lwz ((code), (dreg), off1, ppc_r2); \
- ppc_lwz ((code), (dreg), off2, (dreg)); \
- } while (0);
-
-
-#define emit_tls_access(code,dreg,key) do { \
- switch (tls_mode) { \
- case TLS_MODE_LTHREADS: emit_linuxthreads_tls(code,dreg,key); break; \
- default: g_assert_not_reached (); \
- } \
- } while (0)
-
#define MONO_EMIT_NEW_LOAD_R8(cfg,dr,addr) do { \
MonoInst *inst; \
MONO_INST_NEW ((cfg), (inst), OP_R8CONST); \
}
}
-#if 0
-static int
-offsets_from_pthread_key (guint32 key, int *offset2)
-{
- int idx1 = key / 32;
- int idx2 = key % 32;
- *offset2 = idx2 * sizeof (gpointer);
- return 284 + idx1 * sizeof (gpointer);
-}
-#endif
-
static void mono_arch_compute_omit_fp (MonoCompile *cfg);
const char*
mips_nop (code);
break;
}
- case OP_TLS_GET:
- g_assert_not_reached();
-#if 0
- emit_tls_access (code, ins->dreg, ins->inst_offset);
-#endif
- break;
case OP_BIGMUL:
mips_mult (code, ins->sreg1, ins->sreg2);
mips_mflo (code, ins->dreg);
mips_load_const (code, mips_at, MIPS_LMF_MAGIC1);
mips_sw (code, mips_at, mips_sp, lmf_offset + G_STRUCT_OFFSET(MonoLMF, magic));
- if (lmf_pthread_key != -1) {
- g_assert_not_reached();
-#if 0
- emit_tls_access (code, mips_temp, lmf_pthread_key);
-#endif
- if (G_STRUCT_OFFSET (MonoJitTlsData, lmf)) {
- int offset = G_STRUCT_OFFSET (MonoJitTlsData, lmf);
- g_assert (mips_is_imm16(offset));
- mips_addiu (code, mips_a0, mips_temp, offset);
- }
- } else {
- /* This can/will clobber the a0-a3 registers */
- mips_call (code, mips_t9, (gpointer)mono_get_lmf_addr);
- }
+ /* This can/will clobber the a0-a3 registers */
+ mips_call (code, mips_t9, (gpointer)mono_get_lmf_addr);
/* mips_v0 is the result from mono_get_lmf_addr () (MonoLMF **) */
g_assert (mips_is_imm16(lmf_offset + G_STRUCT_OFFSET(MonoLMF, lmf_addr)));
#endif
}
-/*
- * Thread local storage support
- */
-static void
-setup_tls_access (void)
-{
- guint32 ptk;
- //guint32 *ins, *code;
-
- if (tls_mode == TLS_MODE_FAILED)
- return;
-
- if (g_getenv ("MONO_NO_TLS")) {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
-
- if (tls_mode == TLS_MODE_DETECT) {
- /* XXX */
- tls_mode = TLS_MODE_FAILED;
- return;
-#if 0
-
- ins = (guint32*)pthread_getspecific;
- /* uncond branch to the real method */
- if ((*ins >> 26) == 18) {
- gint32 val;
- val = (*ins & ~3) << 6;
- val >>= 6;
- if (*ins & 2) {
- /* absolute */
- ins = (guint32*)val;
- } else {
- ins = (guint32*) ((char*)ins + val);
- }
- }
- code = &cmplwi_1023;
- ppc_cmpli (code, 0, 0, ppc_r3, 1023);
- code = &li_0x48;
- ppc_li (code, ppc_r4, 0x48);
- code = &blr_ins;
- ppc_blr (code);
- if (*ins == cmplwi_1023) {
- int found_lwz_284 = 0;
- for (ptk = 0; ptk < 20; ++ptk) {
- ++ins;
- if (!*ins || *ins == blr_ins)
- break;
- if ((guint16)*ins == 284 && (*ins >> 26) == 32) {
- found_lwz_284 = 1;
- break;
- }
- }
- if (!found_lwz_284) {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
- tls_mode = TLS_MODE_LTHREADS;
- } else if (*ins == li_0x48) {
- ++ins;
- /* uncond branch to the real method */
- if ((*ins >> 26) == 18) {
- gint32 val;
- val = (*ins & ~3) << 6;
- val >>= 6;
- if (*ins & 2) {
- /* absolute */
- ins = (guint32*)val;
- } else {
- ins = (guint32*) ((char*)ins + val);
- }
- code = &val;
- ppc_li (code, ppc_r0, 0x7FF2);
- if (ins [1] == val) {
- /* Darwin on G4, implement */
- tls_mode = TLS_MODE_FAILED;
- return;
- } else {
- code = &val;
- ppc_mfspr (code, ppc_r3, 104);
- if (ins [1] != val) {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
- tls_mode = TLS_MODE_DARWIN_G5;
- }
- } else {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
- } else {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
-#endif
- }
- if (lmf_pthread_key == -1) {
- ptk = mono_jit_tls_id;
- if (ptk < 1024) {
- /*g_print ("MonoLMF at: %d\n", ptk);*/
- /*if (!try_offset_access (mono_get_lmf_addr (), ptk)) {
- init_tls_failed = 1;
- return;
- }*/
- lmf_pthread_key = ptk;
- }
- }
- if (monothread_key == -1) {
- ptk = mono_thread_get_tls_key ();
- if (ptk < 1024) {
- monothread_key = ptk;
- /*g_print ("thread inited: %d\n", ptk);*/
- } else {
- /*g_print ("thread not inited yet %d\n", ptk);*/
- }
- }
-}
-
void
mono_arch_finish_init (void)
{
- setup_tls_access ();
}
void
if (call_chain_depth == 0) {
mono_profiler_stat_hit ((guchar *)mono_arch_ip_from_context (ctx), ctx);
} else {
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
int current_frame_index = 1;
MonoContext mono_context;
guchar *ips [call_chain_depth + 1];
if (mono_thread_info_get_small_id () == -1)
return; //an non-attached thread got the signal
- if (!mono_domain_get () || !mono_native_tls_get_value (mono_jit_tls_id))
+ if (!mono_domain_get () || !mono_tls_get_jit_tls ())
return; //thread in the process of dettaching
InterlockedIncrement (&profiler_signals_accepted);
static mono_mutex_t mini_arch_mutex;
int mono_exc_esp_offset = 0;
-static int tls_mode = TLS_MODE_DETECT;
-static int lmf_pthread_key = -1;
/*
* The code generated for sequence points reads from this location, which is
/* Enabled breakpoints read from this trigger page */
static gpointer bp_trigger_page;
-static int
-offsets_from_pthread_key (guint32 key, int *offset2)
-{
- int idx1 = key / 32;
- int idx2 = key % 32;
- *offset2 = idx2 * sizeof (gpointer);
- return 284 + idx1 * sizeof (gpointer);
-}
-
-#define emit_linuxthreads_tls(code,dreg,key) do {\
- int off1, off2; \
- off1 = offsets_from_pthread_key ((key), &off2); \
- ppc_ldptr ((code), (dreg), off1, ppc_r2); \
- ppc_ldptr ((code), (dreg), off2, (dreg)); \
- } while (0);
-
-#define emit_darwing5_tls(code,dreg,key) do {\
- int off1 = 0x48 + key * sizeof (gpointer); \
- ppc_mfspr ((code), (dreg), 104); \
- ppc_ldptr ((code), (dreg), off1, (dreg)); \
- } while (0);
-
-/* FIXME: ensure the sc call preserves all but r3 */
-#define emit_darwing4_tls(code,dreg,key) do {\
- int off1 = 0x48 + key * sizeof (gpointer); \
- if ((dreg) != ppc_r3) ppc_mr ((code), ppc_r12, ppc_r3); \
- ppc_li ((code), ppc_r0, 0x7FF2); \
- ppc_sc ((code)); \
- ppc_lwz ((code), (dreg), off1, ppc_r3); \
- if ((dreg) != ppc_r3) ppc_mr ((code), ppc_r3, ppc_r12); \
- } while (0);
-
-#ifdef PPC_THREAD_PTR_REG
-#define emit_nptl_tls(code,dreg,key) do { \
- int off1 = key; \
- int off2 = key >> 15; \
- if ((off2 == 0) || (off2 == -1)) { \
- ppc_ldptr ((code), (dreg), off1, PPC_THREAD_PTR_REG); \
- } else { \
- int off3 = (off2 + 1) > 1; \
- ppc_addis ((code), ppc_r12, PPC_THREAD_PTR_REG, off3); \
- ppc_ldptr ((code), (dreg), off1, ppc_r12); \
- } \
- } while (0);
-#else
-#define emit_nptl_tls(code,dreg,key) do { \
- g_assert_not_reached (); \
- } while (0)
-#endif
-
-#define emit_tls_access(code,dreg,key) do { \
- switch (tls_mode) { \
- case TLS_MODE_LTHREADS: emit_linuxthreads_tls(code,dreg,key); break; \
- case TLS_MODE_NPTL: emit_nptl_tls(code,dreg,key); break; \
- case TLS_MODE_DARWIN_G5: emit_darwing5_tls(code,dreg,key); break; \
- case TLS_MODE_DARWIN_G4: emit_darwing4_tls(code,dreg,key); break; \
- default: g_assert_not_reached (); \
- } \
- } while (0)
-
#define MONO_EMIT_NEW_LOAD_R8(cfg,dr,addr) do { \
MonoInst *inst; \
MONO_INST_NEW ((cfg), (inst), OP_R8CONST); \
ppc_nop (code);
break;
}
- case OP_TLS_GET:
- emit_tls_access (code, ins->dreg, ins->inst_offset);
- break;
case OP_BIGMUL:
ppc_mullw (code, ppc_r0, ins->sreg1, ins->sreg2);
ppc_mulhw (code, ppc_r3, ins->sreg1, ins->sreg2);
}
if (method->save_lmf) {
- if (lmf_pthread_key != -1) {
- emit_tls_access (code, ppc_r3, lmf_pthread_key);
- if (tls_mode != TLS_MODE_NPTL && G_STRUCT_OFFSET (MonoJitTlsData, lmf))
- ppc_addi (code, ppc_r3, ppc_r3, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
+ if (cfg->compile_aot) {
+ /* Compute the got address which is needed by the PLT entry */
+ 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_INTERNAL_METHOD,
+ (gpointer)"mono_tls_get_lmf_addr");
+ if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
+ ppc_load_func (code, PPC_CALL_REG, 0);
+ ppc_mtlr (code, PPC_CALL_REG);
+ ppc_blrl (code);
} else {
- if (cfg->compile_aot) {
- /* Compute the got address which is needed by the PLT entry */
- 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_INTERNAL_METHOD,
- (gpointer)"mono_get_lmf_addr");
- if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
- ppc_load_func (code, PPC_CALL_REG, 0);
- ppc_mtlr (code, PPC_CALL_REG);
- ppc_blrl (code);
- } else {
- ppc_bl (code, 0);
- }
+ ppc_bl (code, 0);
}
/* we build the MonoLMF structure on the stack - see mini-ppc.h */
/* lmf_offset is the offset from the previous stack pointer,
}
#endif
-static void
-setup_tls_access (void)
-{
-#if defined(__linux__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
- size_t conf_size = 0;
- char confbuf[128];
-#else
- /* FIXME for darwin */
- guint32 *ins, *code;
- guint32 cmplwi_1023, li_0x48, blr_ins;
-#endif
-
-#ifdef TARGET_PS3
- tls_mode = TLS_MODE_FAILED;
-#endif
-
- if (tls_mode == TLS_MODE_FAILED)
- return;
- if (g_getenv ("MONO_NO_TLS")) {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
-
- if (tls_mode == TLS_MODE_DETECT) {
-#if defined(__APPLE__) && defined(__mono_ppc__) && !defined(__mono_ppc64__)
- tls_mode = TLS_MODE_DARWIN_G4;
-#elif defined(__linux__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
- conf_size = confstr ( _CS_GNU_LIBPTHREAD_VERSION, confbuf, sizeof(confbuf));
- if ((conf_size > 4) && (strncmp (confbuf, "NPTL", 4) == 0))
- tls_mode = TLS_MODE_NPTL;
-#elif !defined(TARGET_PS3)
- ins = (guint32*)pthread_getspecific;
- /* uncond branch to the real method */
- if ((*ins >> 26) == 18) {
- gint32 val;
- val = (*ins & ~3) << 6;
- val >>= 6;
- if (*ins & 2) {
- /* absolute */
- ins = (guint32*)(long)val;
- } else {
- ins = (guint32*) ((char*)ins + val);
- }
- }
- code = &cmplwi_1023;
- ppc_cmpli (code, 0, 0, ppc_r3, 1023);
- code = &li_0x48;
- ppc_li (code, ppc_r4, 0x48);
- code = &blr_ins;
- ppc_blr (code);
- if (*ins == cmplwi_1023) {
- int found_lwz_284 = 0;
- guint32 ptk;
- for (ptk = 0; ptk < 20; ++ptk) {
- ++ins;
- if (!*ins || *ins == blr_ins)
- break;
- if ((guint16)*ins == 284 && (*ins >> 26) == 32) {
- found_lwz_284 = 1;
- break;
- }
- }
- if (!found_lwz_284) {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
- tls_mode = TLS_MODE_LTHREADS;
- } else if (*ins == li_0x48) {
- ++ins;
- /* uncond branch to the real method */
- if ((*ins >> 26) == 18) {
- gint32 val;
- val = (*ins & ~3) << 6;
- val >>= 6;
- if (*ins & 2) {
- /* absolute */
- ins = (guint32*)(long)val;
- } else {
- ins = (guint32*) ((char*)ins + val);
- }
- code = (guint32*)&val;
- ppc_li (code, ppc_r0, 0x7FF2);
- if (ins [1] == val) {
- /* Darwin on G4, implement */
- tls_mode = TLS_MODE_FAILED;
- return;
- } else {
- code = (guint32*)&val;
- ppc_mfspr (code, ppc_r3, 104);
- if (ins [1] != val) {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
- tls_mode = TLS_MODE_DARWIN_G5;
- }
- } else {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
- } else {
- tls_mode = TLS_MODE_FAILED;
- return;
- }
-#endif
- }
-#ifndef TARGET_PS3
- if (tls_mode == TLS_MODE_DETECT)
- tls_mode = TLS_MODE_FAILED;
- if (tls_mode == TLS_MODE_FAILED)
- return;
- if ((lmf_pthread_key == -1) && (tls_mode == TLS_MODE_NPTL)) {
- lmf_pthread_key = mono_get_lmf_addr_tls_offset();
- }
-
-#if 0
- /* if not TLS_MODE_NPTL or local dynamic (as indicated by
- mono_get_lmf_addr_tls_offset returning -1) then use keyed access. */
- if (lmf_pthread_key == -1) {
- guint32 ptk = mono_jit_tls_id;
- if (ptk < 1024) {
- /*g_print ("MonoLMF at: %d\n", ptk);*/
- /*if (!try_offset_access (mono_get_lmf_addr (), ptk)) {
- init_tls_failed = 1;
- return;
- }*/
- lmf_pthread_key = ptk;
- }
- }
-#endif
-
-#endif
-}
-
void
mono_arch_finish_init (void)
{
- setup_tls_access ();
}
void
static guint32 default_opt = 0;
static gboolean default_opt_set = FALSE;
-MonoNativeTlsKey mono_jit_tls_id;
-
-#ifdef MONO_HAVE_FAST_TLS
-MONO_FAST_TLS_DECLARE(mono_jit_tls);
-#endif
-
gboolean mono_compile_aot = FALSE;
/* If this is set, no code is generated dynamically, everything is taken from AOT files */
gboolean mono_aot_only = FALSE;
mono_register_jit_icall (func, name, sig, save);
}
-#ifdef MONO_HAVE_FAST_TLS
-MONO_FAST_TLS_DECLARE(mono_lmf_addr);
-#ifdef MONO_ARCH_ENABLE_MONO_LMF_VAR
-/*
- * When this is defined, the current lmf is stored in this tls variable instead of in
- * jit_tls->lmf.
- */
-MONO_FAST_TLS_DECLARE(mono_lmf);
-#endif
-#endif
-
-gint32
-mono_get_jit_tls_offset (void)
-{
- int offset;
-
-#ifdef HOST_WIN32
- if (mono_jit_tls_id)
- offset = mono_jit_tls_id;
- else
- /* FIXME: Happens during startup */
- offset = -1;
-#else
- MONO_THREAD_VAR_OFFSET (mono_jit_tls, offset);
-#endif
- return offset;
-}
-
-gint32
-mono_get_lmf_tls_offset (void)
-{
-#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
- int offset;
- MONO_THREAD_VAR_OFFSET(mono_lmf,offset);
- return offset;
-#else
- return -1;
-#endif
-}
-
-gint32
-mono_get_lmf_addr_tls_offset (void)
-{
- int offset;
- MONO_THREAD_VAR_OFFSET(mono_lmf_addr,offset);
- return offset;
-}
-
MonoLMF *
mono_get_lmf (void)
{
-#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
- return (MonoLMF *)MONO_FAST_TLS_GET (mono_lmf);
+#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
+ return (MonoLMF *)mono_tls_get_lmf ();
#else
MonoJitTlsData *jit_tls;
- if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
+ if ((jit_tls = mono_tls_get_jit_tls ()))
return jit_tls->lmf;
/*
* We do not assert here because this function can be called from
MonoLMF **
mono_get_lmf_addr (void)
{
-#ifdef MONO_HAVE_FAST_TLS
- return (MonoLMF **)MONO_FAST_TLS_GET (mono_lmf_addr);
-#else
- MonoJitTlsData *jit_tls;
-
- jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
- if (G_LIKELY (jit_tls))
- return &jit_tls->lmf;
-
- /*
- * When resolving the call to mono_jit_thread_attach full-aot will look
- * in the plt, which causes a call into the generic trampoline, which in turn
- * tries to resolve the lmf_addr creating a cyclic dependency. We cannot
- * call mono_jit_thread_attach from the native-to-managed wrapper, without
- * mono_get_lmf_addr, and mono_get_lmf_addr requires the thread to be attached.
- */
-
- mono_thread_attach (mono_get_root_domain ());
- mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
-
- if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
- return &jit_tls->lmf;
-
- g_assert_not_reached ();
- return NULL;
-#endif
+ return (MonoLMF **)mono_tls_get_lmf_addr ();
}
void
mono_set_lmf (MonoLMF *lmf)
{
-#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
- MONO_FAST_TLS_SET (mono_lmf, lmf);
+#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
+ mono_tls_set_lmf (lmf);
#endif
(*mono_get_lmf_addr ()) = lmf;
MonoJitTlsData*
mono_get_jit_tls (void)
{
- return (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ return (MonoJitTlsData *)mono_tls_get_jit_tls ();
}
static void
{
MonoThreadInfo *info;
- mono_native_tls_set_value (mono_jit_tls_id, jit_tls);
-
-#ifdef MONO_HAVE_FAST_TLS
- MONO_FAST_TLS_SET (mono_jit_tls, jit_tls);
-#endif
+ mono_tls_set_jit_tls (jit_tls);
/* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
info = mono_thread_info_current ();
{
MonoThreadInfo *info;
-#ifdef MONO_HAVE_FAST_TLS
- MONO_FAST_TLS_SET (mono_lmf_addr, lmf_addr);
-#endif
+ mono_tls_set_lmf_addr (lmf_addr);
/* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
info = mono_thread_info_current ();
g_assert (domain);
-#ifdef MONO_HAVE_FAST_TLS
- attached = MONO_FAST_TLS_GET (mono_lmf_addr) != NULL;
-#else
- attached = mono_native_tls_get_value (mono_jit_tls_id) != NULL;
-#endif
+ attached = mono_tls_get_jit_tls () != NULL;
if (!attached) {
mono_thread_attach (domain);
MonoJitTlsData *jit_tls;
MonoLMF *lmf;
- jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
if (jit_tls)
return jit_tls;
jit_tls->first_lmf = lmf;
-#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
+#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
/* jit_tls->lmf is unused */
- MONO_FAST_TLS_SET (mono_lmf, lmf);
- mono_set_lmf_addr (MONO_FAST_TLS_ADDR (mono_lmf));
+ mono_tls_set_lmf (lmf);
+ mono_set_lmf_addr (mono_tls_get_tls_addr (TLS_KEY_LMF));
#else
mono_set_lmf_addr (&jit_tls->lmf);
free_jit_tls_data (jit_tls);
}
-int
-mini_get_tls_offset (MonoTlsKey key)
-{
- int offset;
- g_assert (MONO_ARCH_HAVE_TLS_GET);
-
- switch (key) {
- case TLS_KEY_THREAD:
- offset = mono_thread_get_tls_offset ();
- break;
- case TLS_KEY_JIT_TLS:
- offset = mono_get_jit_tls_offset ();
- break;
- case TLS_KEY_DOMAIN:
- offset = mono_domain_get_tls_offset ();
- break;
- case TLS_KEY_LMF:
- offset = mono_get_lmf_tls_offset ();
- break;
- case TLS_KEY_LMF_ADDR:
- offset = mono_get_lmf_addr_tls_offset ();
- break;
- default:
- offset = mono_tls_key_get_offset (key);
- g_assert (offset != -1);
- break;
- }
-
- return offset;
-}
-
-static gboolean
-mini_tls_key_supported (MonoTlsKey key)
-{
- if (!MONO_ARCH_HAVE_TLS_GET)
- return FALSE;
-
- return mini_get_tls_offset (key) != -1;
-}
-
MonoJumpInfo *
mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, gconstpointer target)
{
case MONO_PATCH_INFO_SEQ_POINT_INFO:
case MONO_PATCH_INFO_METHOD_RGCTX:
case MONO_PATCH_INFO_SIGNATURE:
- case MONO_PATCH_INFO_TLS_OFFSET:
case MONO_PATCH_INFO_METHOD_CODE_SLOT:
case MONO_PATCH_INFO_AOT_JIT_INFO:
+ case MONO_PATCH_INFO_GET_TLS_TRAMP:
+ case MONO_PATCH_INFO_SET_TLS_TRAMP:
return (ji->type << 8) | (gssize)ji->data.target;
case MONO_PATCH_INFO_GSHAREDVT_CALL:
return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_GC_NURSERY_START:
case MONO_PATCH_INFO_GC_NURSERY_BITS:
- case MONO_PATCH_INFO_JIT_TLS_ID:
case MONO_PATCH_INFO_GOT_OFFSET:
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
case MONO_PATCH_INFO_AOT_MODULE:
- case MONO_PATCH_INFO_GET_TLS_TRAMP:
case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
return (ji->type << 8);
case MONO_PATCH_INFO_CASTCLASS_CACHE:
target = mono_domain_alloc0 (domain, sizeof (gpointer));
break;
}
- case MONO_PATCH_INFO_JIT_TLS_ID: {
- target = (gpointer) (size_t) mono_jit_tls_id;
- break;
- }
- case MONO_PATCH_INFO_TLS_OFFSET: {
- int offset;
-
- offset = mini_get_tls_offset ((MonoTlsKey)GPOINTER_TO_INT (patch_info->data.target));
-#ifdef MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET
- offset = mono_arch_translate_tls_offset (offset);
-#endif
- target = GINT_TO_POINTER (offset);
- break;
- }
case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
target = NULL;
break;
target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE);
break;
case MONO_PATCH_INFO_GET_TLS_TRAMP:
-#ifdef MONO_ARCH_HAVE_GET_TLS_TRAMP
- target = mono_arch_get_get_tls_tramp ();
-#else
- target = NULL;
-#endif
+ target = mono_tls_get_tls_getter (patch_info->data.index, FALSE);
+ break;
+ case MONO_PATCH_INFO_SET_TLS_TRAMP:
+ target = mono_tls_get_tls_setter (patch_info->data.index, FALSE);
break;
case MONO_PATCH_INFO_JIT_THREAD_ATTACH: {
MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_jit_thread_attach");
MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
{
MonoJitInfo *ji;
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
gpointer fault_addr = NULL;
#ifdef HAVE_SIG_INFO
MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
mono_set_generic_sharing_vt_supported (TRUE);
#endif
-#ifdef MONO_HAVE_FAST_TLS
- MONO_FAST_TLS_INIT (mono_jit_tls);
- MONO_FAST_TLS_INIT (mono_lmf_addr);
-#ifdef MONO_ARCH_ENABLE_MONO_LMF_VAR
- MONO_FAST_TLS_INIT (mono_lmf);
-#endif
-#endif
-
- mono_runtime_set_has_tls_get (MONO_ARCH_HAVE_TLS_GET);
+ mono_tls_init_runtime_keys ();
if (!global_codeman)
global_codeman = mono_code_manager_new ();
callbacks.set_cast_details = mono_set_cast_details;
callbacks.debug_log = mono_debugger_agent_debug_log;
callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
- callbacks.tls_key_supported = mini_tls_key_supported;
callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
callbacks.get_imt_trampoline = mini_get_imt_trampoline;
callbacks.imt_entry_inited = mini_imt_entry_inited;
mono_trampolines_init ();
- mono_native_tls_alloc (&mono_jit_tls_id, NULL);
-
if (default_opt & MONO_OPT_AOT)
mono_aot_init ();
#ifdef TARGET_IOS
register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
#endif
+ /* Register tls icalls */
+ register_icall_no_wrapper (mono_tls_get_thread, "mono_tls_get_thread", "ptr");
+ register_icall_no_wrapper (mono_tls_get_jit_tls, "mono_tls_get_jit_tls", "ptr");
+ register_icall_no_wrapper (mono_tls_get_domain, "mono_tls_get_domain", "ptr");
+ register_icall_no_wrapper (mono_tls_get_lmf, "mono_tls_get_lmf", "ptr");
+ register_icall_no_wrapper (mono_tls_get_sgen_thread_info, "mono_tls_get_sgen_thread_info", "ptr");
+ register_icall_no_wrapper (mono_tls_get_lmf_addr, "mono_tls_get_lmf_addr", "ptr");
+ register_icall_no_wrapper (mono_tls_set_thread, "mono_tls_set_thread", "void ptr");
+ register_icall_no_wrapper (mono_tls_set_jit_tls, "mono_tls_set_jit_tls", "void ptr");
+ register_icall_no_wrapper (mono_tls_set_domain, "mono_tls_set_domain", "void ptr");
+ register_icall_no_wrapper (mono_tls_set_lmf, "mono_tls_set_lmf", "void ptr");
+ register_icall_no_wrapper (mono_tls_set_sgen_thread_info, "mono_tls_set_sgen_thread_info", "void ptr");
+ register_icall_no_wrapper (mono_tls_set_lmf_addr, "mono_tls_set_lmf_addr", "void ptr");
}
MonoJitStats mono_jit_stats = {0};
mono_profiler_shutdown ();
- free_jit_tls_data ((MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id));
+ free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ());
mono_icall_cleanup ();
if (mono_inject_async_exc_method)
mono_method_desc_free (mono_inject_async_exc_method);
- mono_native_tls_free (mono_jit_tls_id);
+ mono_tls_free_keys ();
mono_os_mutex_destroy (&jit_mutex);
__thread int indent_level = 0;
-static gint appdomain_tls_offset = -1,
- lmf_tls_offset = -1,
- lmf_addr_tls_offset = -1;
-
-pthread_key_t lmf_addr_key;
-
-gboolean lmf_addr_key_inited = FALSE;
-
/*
* The code generated for sequence points reads from this location,
* which is made read-only when single stepping is enabled.
case OP_S390_SETF4RET:
s390_ledbr (code, ins->dreg, ins->sreg1);
break;
- case OP_TLS_GET: {
- if (s390_is_imm16 (ins->inst_offset)) {
- s390_lghi (code, s390_r13, ins->inst_offset);
- } else if (s390_is_imm32 (ins->inst_offset)) {
- s390_lgfi (code, s390_r13, ins->inst_offset);
- } else {
- S390_SET (code, s390_r13, ins->inst_offset);
- }
- s390_ear (code, s390_r1, 0);
- s390_sllg(code, s390_r1, s390_r1, 0, 32);
- s390_ear (code, s390_r1, 1);
- s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
- }
- break;
case OP_JMP: {
if (cfg->method->save_lmf)
restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
/*---------------------------------------------------------------*/
/* On return from this call r2 have the address of the &lmf */
/*---------------------------------------------------------------*/
- if (lmf_addr_tls_offset == -1) {
- mono_add_patch_info (cfg, code - cfg->native_code,
- MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_get_lmf_addr");
- S390_CALL_TEMPLATE(code, s390_r1);
- } else {
- /*-------------------------------------------------------*/
- /* Get LMF by getting value from thread level storage */
- /*-------------------------------------------------------*/
- s390_ear (code, s390_r1, 0);
- s390_sllg(code, s390_r1, s390_r1, 0, 32);
- s390_ear (code, s390_r1, 1);
- s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
- }
+ mono_add_patch_info (cfg, code - cfg->native_code,
+ MONO_PATCH_INFO_INTERNAL_METHOD,
+ (gpointer)"mono_tls_get_lmf_addr");
+ S390_CALL_TEMPLATE(code, s390_r1);
/*---------------------------------------------------------------*/
/* Set lmf.lmf_addr = jit_tls->lmf */
void
mono_arch_finish_init (void)
{
- appdomain_tls_offset = mono_domain_get_tls_offset();
- lmf_tls_offset = mono_get_lmf_tls_offset();
- lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
}
/*========================= End of Function ========================*/
mono_arch_regname (tree->sreg1));
done = 1;
break;
- case OP_TLS_GET:
- printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
- tree->inst_imm,
- mono_arch_regname (tree->sreg1));
- done = 1;
- break;
case OP_S390_BKCHAIN:
printf ("[previous_frame(%s)]",
mono_arch_regname (tree->sreg1));
#define MONO_ARCH_NEED_DIV_CHECK 1
#define MONO_ARCH_SIGNAL_STACK_SIZE 256*1024
#define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
-#define MONO_ARCH_HAVE_TLS_GET 1
#define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
#define MONO_ARCH_IMT_REG s390_r9
#define MONO_ARCH_VTABLE_REG S390_FIRST_ARG_REG
MonoContext ctx;
MonoException *exc;
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
gpointer resume_ip = jit_tls->handler_block_return_address;
memcpy (&ctx, &jit_tls->handler_block_context, sizeof (MonoContext));
gboolean
MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
jit_tls->mono_win_chained_exception_needs_run = TRUE;
return TRUE;
}
return code;
}
- /*
- * mono_arch_translate_tls_offset:
- *
- * Translate the TLS offset OFFSET computed by MONO_THREAD_VAR_OFFSET () into a format usable by OP_TLS_GET_REG/OP_TLS_SET_REG.
- */
-int
-mono_arch_translate_tls_offset (int offset)
-{
-#ifdef __APPLE__
- return tls_gs_offset + (offset * 4);
-#else
- return offset;
-#endif
-}
-
/*
* emit_setup_lmf:
*
if (method->save_lmf) {
gint32 lmf_offset = cfg->lmf_var->inst_offset;
guint8 *patch;
- gboolean supported = FALSE;
-
- if (cfg->compile_aot) {
-#if defined(MONO_HAVE_FAST_TLS)
- supported = TRUE;
-#endif
- } else if (mono_get_jit_tls_offset () != -1) {
- supported = TRUE;
- }
/* check if we need to restore protection of the stack after a stack overflow */
+ /* FIXME */
+#if 0
if (supported) {
if (cfg->compile_aot) {
code = emit_load_aotconst (NULL, code, cfg, NULL, X86_ECX, MONO_PATCH_INFO_TLS_OFFSET, GINT_TO_POINTER (TLS_KEY_JIT_TLS));
} else {
/* FIXME: maybe save the jit tls in the prolog */
}
+#endif
/* restore caller saved regs */
if (cfg->used_int_regs & (1 << X86_EBX)) {
/* X86 uses jit_tls->lmf (See emit_push_lmf ()) */
#define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
#endif
-#define MONO_ARCH_HAVE_TLS_GET (mono_x86_have_tls_get ())
#define MONO_ARCH_IMT_REG X86_EDX
#define MONO_ARCH_VTABLE_REG X86_EDX
#define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG
#define MONO_ARCH_GSHAREDVT_SUPPORTED 1
#define MONO_ARCH_HAVE_OP_TAIL_CALL 1
#define MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET 1
-#define MONO_ARCH_HAVE_TLS_GET_REG 1
#define MONO_ARCH_HAVE_DUMMY_INIT 1
#define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
#define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
g_free (cfg);
}
-static MonoInst*
-mono_create_tls_get_offset (MonoCompile *cfg, int offset)
-{
- MonoInst* ins;
-
- if (!cfg->backend->have_tls_get)
- return NULL;
-
- if (offset == -1)
- return NULL;
-
- MONO_INST_NEW (cfg, ins, OP_TLS_GET);
- ins->dreg = mono_alloc_preg (cfg);
- ins->inst_offset = offset;
- return ins;
-}
-
-gboolean
-mini_tls_get_supported (MonoCompile *cfg, MonoTlsKey key)
-{
- if (!cfg->backend->have_tls_get)
- return FALSE;
-
- if (cfg->compile_aot)
- return cfg->backend->have_tls_get_reg;
- else
- return mini_get_tls_offset (key) != -1;
-}
-
-MonoInst*
-mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key)
-{
- if (!cfg->backend->have_tls_get)
- return NULL;
-
-#ifdef HAVE_KW_THREAD
- /*
- * MONO_THREAD_VAR_OFFSET definitions don't work when loading mono as a
- * dynamic library. This means that we need to be conservative and don't
- * aot code that contains these tls chunks.
- *
- * FIXME Remove HAVE_KW_THREAD altogether and use only pthread since it
- * simplifies the code alot.
- */
- if (!cfg->full_aot)
- cfg->disable_aot = TRUE;
-#endif
- /*
- * TLS offsets might be different at AOT time, so load them from a GOT slot and
- * use a different opcode.
- */
- if (cfg->compile_aot) {
- if (cfg->backend->have_tls_get_reg) {
- MonoInst *ins, *c;
-
- EMIT_NEW_TLS_OFFSETCONST (cfg, c, key);
- MONO_INST_NEW (cfg, ins, OP_TLS_GET_REG);
- ins->dreg = mono_alloc_preg (cfg);
- ins->sreg1 = c->dreg;
- return ins;
- } else {
- return NULL;
- }
- }
-
- return mono_create_tls_get_offset (cfg, mini_get_tls_offset (key));
-}
-
-MonoInst*
-mono_get_jit_tls_intrinsic (MonoCompile *cfg)
-{
- return mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
-}
-
-MonoInst*
-mono_get_domain_intrinsic (MonoCompile* cfg)
-{
- return mono_create_tls_get (cfg, TLS_KEY_DOMAIN);
-}
-
-MonoInst*
-mono_get_thread_intrinsic (MonoCompile* cfg)
-{
- return mono_create_tls_get (cfg, TLS_KEY_THREAD);
-}
-
-MonoInst*
-mono_get_lmf_intrinsic (MonoCompile* cfg)
-{
- return mono_create_tls_get (cfg, TLS_KEY_LMF);
-}
-
-MonoInst*
-mono_get_lmf_addr_intrinsic (MonoCompile* cfg)
-{
- return mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR);
-}
-
void
mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
{
#endif
#ifdef MONO_ARCH_GSHARED_SUPPORTED
backend->gshared_supported = 1;
-#endif
- if (MONO_ARCH_HAVE_TLS_GET)
- backend->have_tls_get = 1;
-#ifdef MONO_ARCH_HAVE_TLS_GET_REG
- backend->have_tls_get_reg = 1;
#endif
if (MONO_ARCH_USE_FPSTACK)
backend->use_fpstack = 1;
typedef struct MonoSpillInfo MonoSpillInfo;
typedef struct MonoTraceSpec MonoTraceSpec;
-extern MonoNativeTlsKey mono_jit_tls_id;
extern MonoTraceSpec *mono_jit_trace_calls;
extern gboolean mono_break_on_exc;
extern int mono_exc_esp_offset;
guint emulate_long_shift_opts : 1;
guint have_objc_get_selector : 1;
guint have_generalized_imt_trampoline : 1;
- guint have_tls_get : 1;
- guint have_tls_get_reg : 1;
guint have_liverange_ops: 1;
guint have_op_tail_call : 1;
guint have_dummy_init : 1;
MonoJitTlsData* mono_get_jit_tls (void);
MONO_API MonoDomain* mono_jit_thread_attach (MonoDomain *domain);
MONO_API void mono_jit_set_domain (MonoDomain *domain);
-gint32 mono_get_jit_tls_offset (void);
-gint32 mono_get_lmf_tls_offset (void);
-gint32 mono_get_lmf_addr_tls_offset (void);
-int mini_get_tls_offset (MonoTlsKey key);
-gboolean mini_tls_get_supported (MonoCompile *cfg, MonoTlsKey key);
MonoInst* mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key);
-MonoInst* mono_get_jit_tls_intrinsic (MonoCompile *cfg);
-MonoInst* mono_get_domain_intrinsic (MonoCompile* cfg);
-MonoInst* mono_get_thread_intrinsic (MonoCompile* cfg);
-MonoInst* mono_get_lmf_intrinsic (MonoCompile* cfg);
-MonoInst* mono_get_lmf_addr_intrinsic (MonoCompile* cfg);
GList *mono_varlist_insert_sorted (MonoCompile *cfg, GList *list, MonoMethodVar *mv, int sort_type);
GList *mono_varlist_sort (MonoCompile *cfg, GList *list, int sort_type);
void mono_analyze_liveness (MonoCompile *cfg);
void MONO_SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) ;
gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal);
-#ifndef MONO_ARCH_HAVE_TLS_GET
-#define MONO_ARCH_HAVE_TLS_GET 0
-#endif
-
#ifdef MONO_ARCH_VARARG_ICALLS
#define ARCH_VARARG_ICALLS 1
#else
PATCH_INFO(SIGNATURE, "signature")
PATCH_INFO(GSHAREDVT_CALL, "gsharedvt_call")
PATCH_INFO(GSHAREDVT_METHOD, "gsharedvt_method")
-PATCH_INFO(JIT_TLS_ID, "jit_tls_id")
-PATCH_INFO(TLS_OFFSET, "tls_offset")
PATCH_INFO(OBJC_SELECTOR_REF, "objc_selector_ref")
PATCH_INFO(METHOD_CODE_SLOT, "method_code_slot")
PATCH_INFO(LDSTR_LIT, "ldstr_lit")
PATCH_INFO(ICALL_ADDR_CALL, "icall_addr_call")
PATCH_INFO(GET_TLS_TRAMP, "get_tls_tramp")
PATCH_INFO(JIT_THREAD_ATTACH, "jit_thread_attach")
+PATCH_INFO(SET_TLS_TRAMP, "set_tls_tramp")
if (cont->domain)
return mono_get_exception_argument ("cont", "Already marked");
- jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
lmf = mono_get_lmf();
cont->domain = mono_domain_get ();
cont->thread_id = mono_native_thread_id_get ();
gpointer
mono_amd64_handler_block_trampoline_helper (void)
{
- MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
return jit_tls->handler_block_return_address;
}
static gpointer
handler_block_trampoline_helper (gpointer *ptr)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
return jit_tls->handler_block_return_address;
}
static gpointer
handler_block_trampoline_helper (gpointer *ptr)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
return jit_tls->handler_block_return_address;
}
static void
handler_block_trampoline_helper (gpointer *ptr)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
*ptr = jit_tls->handler_block_return_address;
}
static gpointer
handler_block_trampoline_helper (void)
{
- MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
+ MonoJitTlsData *jit_tls = mono_tls_get_jit_tls ();
return jit_tls->handler_block_return_address;
}
* We are in a method frame after the call emitted by OP_CALL_HANDLER.
*/
- if (mono_get_jit_tls_offset () != -1) {
- code = mono_x86_emit_tls_get (code, X86_EAX, mono_get_jit_tls_offset ());
- x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (MonoJitTlsData, handler_block_return_address), 4);
- } else {
- /*Slow path uses a c helper*/
- x86_call_code (code, handler_block_trampoline_helper);
- }
+ /*Slow path uses a c helper*/
+ x86_call_code (code, handler_block_trampoline_helper);
/* Simulate a call */
/*Fix stack alignment*/
x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x4);
* tlab_real_end points to the end of the TLAB.
*/
-#ifdef HAVE_KW_THREAD
-#define TLAB_START (sgen_thread_info->tlab_start)
-#define TLAB_NEXT (sgen_thread_info->tlab_next)
-#define TLAB_TEMP_END (sgen_thread_info->tlab_temp_end)
-#define TLAB_REAL_END (sgen_thread_info->tlab_real_end)
-#else
#define TLAB_START (__thread_info__->tlab_start)
#define TLAB_NEXT (__thread_info__->tlab_next)
#define TLAB_TEMP_END (__thread_info__->tlab_temp_end)
#define TLAB_REAL_END (__thread_info__->tlab_real_end)
-#endif
static GCObject*
alloc_degraded (GCVTable vtable, size_t size, gboolean for_mature)
#define MONO_ATTR_FORMAT_PRINTF(fmt_pos,arg_pos)
#endif
-#ifdef HAVE_KW_THREAD
-
-#define MONO_HAVE_FAST_TLS
-#define MONO_FAST_TLS_SET(x,y) x = y
-#define MONO_FAST_TLS_GET(x) x
-#define MONO_FAST_TLS_INIT(x)
-#define MONO_FAST_TLS_DECLARE(x) static __thread gpointer x MONO_TLS_FAST MONO_ATTR_USED;
-
-#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
-
-#if defined(__GNUC__) && defined(__i386__)
-#if defined(PIC)
-#define MONO_THREAD_VAR_OFFSET(var,offset) do { int tmp; __asm ("call 1f; 1: popl %0; addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %0; movl " #var "@gotntpoff(%0), %1" : "=r" (tmp), "=r" (offset)); } while (0)
-#else
-#define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("movl $" #var "@ntpoff, %0" : "=r" (offset))
-#endif
-#elif defined(__x86_64__)
-#if defined(PIC)
-// This only works if libmono is linked into the application
-#define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; __asm ("movq " #var "@GOTTPOFF(%%rip), %0" : "=r" (foo)); offset = foo; } while (0)
-#else
-#define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; __asm ("movq $" #var "@TPOFF, %0" : "=r" (foo)); offset = foo; } while (0)
-#endif
-#elif defined(__ia64__) && !defined(__INTEL_COMPILER)
-#if defined(PIC)
-#define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @ltoff(@tprel(" #var "#)), gp ;; ld8 %0 = [%0]\n" : "=r" (offset))
-#else
-#define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("addl %0 = @tprel(" #var "#), r0 ;;\n" : "=r" (offset))
-#endif
-#elif defined(__arm__) && defined(__ARM_EABI__) && !defined(PIC)
-#define MONO_THREAD_VAR_OFFSET(var,offset) __asm (" ldr %0, 1f; b 2f; 1: .word " #var "(tpoff); 2:" : "=r" (offset))
-#elif defined(__aarch64__) && !defined(PIC)
-#define MONO_THREAD_VAR_OFFSET(var,offset) \
- __asm ( "mov %0, #0\n add %0, %0, #:tprel_hi12:" #var "\n add %0, %0, #:tprel_lo12_nc:" #var "\n" \
- : "=r" (offset))
-#elif defined(__mono_ppc__) && defined(__GNUC__)
-#if defined(PIC)
-#ifdef PIC_INITIAL_EXEC
-
-#if defined(__mono_ppc64__)
-#define MONO_THREAD_VAR_OFFSET(var,offset) \
- do { long off; \
- __asm ( "ld %0," #var "@got@tprel(2)\n" \
- : "=r" (off)); \
- (offset) = off; } while (0)
-#else
-/* must be powerpc32 */
-#define MONO_THREAD_VAR_OFFSET(var,offset) \
- __asm ( "lwz %0," #var "@got@tprel(30)\n" \
- : "=r" (offset))
-#endif
-
-#else
-
-/* 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_THREAD_VAR_OFFSET(var,offset) (offset) = -1
-
-#endif
-#else
-/* Must be local-exec TLS */
-#define MONO_THREAD_VAR_OFFSET(var,offset) \
- __asm ( "lis %0," #var "@tprel@ha\n" \
- "addi %0,%0, " #var "@tprel@l\n" \
- : "=r" (offset))
-#endif
-#elif defined(__s390x__)
-# if defined(__PIC__)
-# if !defined(__PIE__)
-// This only works if libmono is linked into the application
-# define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
- __asm__ ("basr %%r1,0\n\t" \
- "j 0f\n\t" \
- ".quad " #var "@TLSGD\n" \
- "0:\n\t" \
- "lg %%r2,4(%%r1)\n\t" \
- "brasl %%r14,__tls_get_offset@PLT:tls_gdcall:"#var"\n\t" \
- "lgr %0,%%r2\n\t" \
- : "=r" (foo) : \
- : "1", "2", "14", "cc"); \
- offset = foo; } while (0)
-# elif __PIE__ == 1
-# define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
- __asm__ ("lg %0," #var "@GOTNTPOFF(%%r12)\n\t" \
- : "=r" (foo)); \
- offset = foo; } while (0)
-# elif __PIE__ == 2
-# define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
- __asm__ ("larl %%r1," #var "@INDNTPOFF\n\t" \
- "lg %0,0(%%r1)\n\t" \
- : "=r" (foo) : \
- : "1", "cc"); \
- offset = foo; } while (0)
-# endif
-# else
-# define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo; \
- __asm__ ("basr %%r1,0\n\t" \
- "j 0f\n\t" \
- ".quad " #var "@NTPOFF\n" \
- "0:\n\t" \
- "lg %0,4(%%r1)\n\t" \
- : "=r" (foo) : : "1"); \
- offset = foo; } while (0)
-# endif
-#else
-#define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
-#endif
-
-#if defined(PIC) && !defined(PIC_INITIAL_EXEC)
-/*
- * The above definitions do not seem to work if libmono is loaded dynamically as a module.
- * See bug #78767.
- */
-#undef MONO_THREAD_VAR_OFFSET
-#define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
-#endif
-
-#elif !defined(MONO_CROSS_COMPILE) && defined(PLATFORM_MACOSX) && (defined(__i386__) || defined(__x86_64__))
-
-#define MONO_HAVE_FAST_TLS 1
-#define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
-#define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
-#define MONO_FAST_TLS_ADDR(x) (mono_mach_get_tls_address_from_thread (pthread_self (), x))
-#define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
-#define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;
-
-#define MONO_THREAD_VAR_OFFSET(x,y) ({ \
- __typeof__(x) _x = (x); \
- pthread_key_t _y; \
- (void) (&_x == &_y); \
- y = (gint32) x; })
-
-#elif !defined(MONO_CROSS_COMPILE) && (defined(PLATFORM_ANDROID) || defined(TARGET_IOS)) && defined(TARGET_ARM)
-
-#define MONO_HAVE_FAST_TLS
-#define MONO_FAST_TLS_SET(x,y) pthread_setspecific(x, y)
-#define MONO_FAST_TLS_GET(x) pthread_getspecific(x)
-#define MONO_FAST_TLS_INIT(x) pthread_key_create(&x, NULL)
-#define MONO_FAST_TLS_DECLARE(x) static pthread_key_t x;
-
-#define MONO_THREAD_VAR_OFFSET(var, offset) do { offset = (int)var; } while (0)
-
-#else /* no HAVE_KW_THREAD */
-
-#define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
-
-/*Macros to facilitate user code*/
-#define MONO_FAST_TLS_INIT(x)
-#endif
-
-#if defined(MONO_HAVE_FAST_TLS) && !defined(MONO_FAST_TLS_ADDR)
-#define MONO_FAST_TLS_ADDR(x) (&(x))
-#endif
-
-
/* Deal with Microsoft C compiler differences */
#ifdef _MSC_VER
static MonoThreadInfoRuntimeCallbacks runtime_callbacks;
static MonoNativeTlsKey thread_info_key, thread_exited_key;
#ifdef HAVE_KW_THREAD
-static __thread guint32 tls_small_id MONO_TLS_FAST;
+static __thread guint32 tls_small_id;
#else
static MonoNativeTlsKey small_id_key;
#endif
/*
* mono-tls.c: Low-level TLS support
*
+ * Thread local variables that are accessed both from native and managed code
+ * are defined here and should be accessed only through this APIs
+ *
* Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
*/
#include <config.h>
+#include <mono/utils/mach-support.h>
#include "mono-tls.h"
-static int tls_offsets [TLS_KEY_NUM];
-static gboolean tls_offset_set [TLS_KEY_NUM];
+#ifdef HAVE_KW_THREAD
+#define USE_KW_THREAD
+#endif
-/*
- * mono_tls_key_get_offset:
- *
- * Return the TLS offset used by the TLS var identified by KEY, previously initialized by a call to
- * mono_tls_key_set_offset (). Return -1 if the offset is not known.
- */
-int
-mono_tls_key_get_offset (MonoTlsKey key)
+/* Tls variables for each MonoTlsKey */
+#ifdef USE_KW_THREAD
+static __thread gpointer mono_tls_thread;
+static __thread gpointer mono_tls_jit_tls;
+static __thread gpointer mono_tls_domain;
+static __thread gpointer mono_tls_lmf;
+static __thread gpointer mono_tls_sgen_thread_info;
+static __thread gpointer mono_tls_lmf_addr;
+#else
+static MonoNativeTlsKey mono_tls_key_thread;
+static MonoNativeTlsKey mono_tls_key_jit_tls;
+static MonoNativeTlsKey mono_tls_key_domain;
+static MonoNativeTlsKey mono_tls_key_lmf;
+static MonoNativeTlsKey mono_tls_key_sgen_thread_info;
+static MonoNativeTlsKey mono_tls_key_lmf_addr;
+#endif
+
+#ifdef USE_KW_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
+
+void
+mono_tls_init_gc_keys (void)
+{
+#ifndef USE_KW_THREAD
+ mono_native_tls_alloc (&mono_tls_key_sgen_thread_info, NULL);
+#endif
+}
+
+void
+mono_tls_init_runtime_keys (void)
+{
+#ifndef USE_KW_THREAD
+ mono_native_tls_alloc (&mono_tls_key_thread, NULL);
+ mono_native_tls_alloc (&mono_tls_key_jit_tls, NULL);
+ mono_native_tls_alloc (&mono_tls_key_domain, NULL);
+ mono_native_tls_alloc (&mono_tls_key_lmf, NULL);
+ mono_native_tls_alloc (&mono_tls_key_lmf_addr, NULL);
+#endif
+}
+
+void
+mono_tls_free_keys (void)
{
- g_assert (tls_offset_set [key]);
- return tls_offsets [key];
+#ifndef USE_KW_THREAD
+ mono_native_tls_free (mono_tls_key_thread);
+ mono_native_tls_free (mono_tls_key_jit_tls);
+ mono_native_tls_free (mono_tls_key_domain);
+ mono_native_tls_free (mono_tls_key_lmf);
+ mono_native_tls_free (mono_tls_key_sgen_thread_info);
+ mono_native_tls_free (mono_tls_key_lmf_addr);
+#endif
}
/*
- * mono_tls_key_set_offset:
- *
- * Set the TLS offset used by the TLS var identified by KEY.
+ * Returns the getter (gpointer (*)(void)) for the mono tls key.
+ * Managed code will always get the value by calling this getter.
*/
-void
-mono_tls_key_set_offset (MonoTlsKey key, int offset)
+gpointer
+mono_tls_get_tls_getter (MonoTlsKey key, gboolean name)
+{
+ switch (key) {
+ case TLS_KEY_THREAD:
+ return name ? (gpointer)"mono_tls_get_thread" : (gpointer)mono_tls_get_thread;
+ case TLS_KEY_JIT_TLS:
+ return name ? (gpointer)"mono_tls_get_jit_tls" : (gpointer)mono_tls_get_jit_tls;
+ case TLS_KEY_DOMAIN:
+ return name ? (gpointer)"mono_tls_get_domain" : (gpointer)mono_tls_get_domain;
+ case TLS_KEY_LMF:
+ return name ? (gpointer)"mono_tls_get_lmf" : (gpointer)mono_tls_get_lmf;
+ case TLS_KEY_SGEN_THREAD_INFO:
+ return name ? (gpointer)"mono_tls_get_sgen_thread_info" : (gpointer)mono_tls_get_sgen_thread_info;
+ case TLS_KEY_LMF_ADDR:
+ return name ? (gpointer)"mono_tls_get_lmf_addr" : (gpointer)mono_tls_get_lmf_addr;
+ }
+ g_assert_not_reached ();
+ return NULL;
+}
+
+/* Returns the setter (void (*)(gpointer)) for the mono tls key */
+gpointer
+mono_tls_get_tls_setter (MonoTlsKey key, gboolean name)
+{
+ switch (key) {
+ case TLS_KEY_THREAD:
+ return name ? (gpointer)"mono_tls_set_thread" : (gpointer)mono_tls_set_thread;
+ case TLS_KEY_JIT_TLS:
+ return name ? (gpointer)"mono_tls_set_jit_tls" : (gpointer)mono_tls_set_jit_tls;
+ case TLS_KEY_DOMAIN:
+ return name ? (gpointer)"mono_tls_set_domain" : (gpointer)mono_tls_set_domain;
+ case TLS_KEY_LMF:
+ return name ? (gpointer)"mono_tls_set_lmf" : (gpointer)mono_tls_set_lmf;
+ case TLS_KEY_SGEN_THREAD_INFO:
+ return name ? (gpointer)"mono_tls_set_sgen_thread_info" : (gpointer)mono_tls_set_sgen_thread_info;
+ case TLS_KEY_LMF_ADDR:
+ return name ? (gpointer)"mono_tls_set_lmf_addr" : (gpointer)mono_tls_set_lmf_addr;
+ }
+ g_assert_not_reached ();
+ return NULL;
+}
+
+gpointer
+mono_tls_get_tls_addr (MonoTlsKey key)
+{
+ if (key == TLS_KEY_LMF) {
+#if defined(USE_KW_THREAD)
+ return &mono_tls_lmf;
+#elif defined(TARGET_MACH)
+ return mono_mach_get_tls_address_from_thread (pthread_self (), mono_tls_key_lmf);
+#endif
+ }
+ /* Implement if we ever need for other targets/keys */
+ g_assert_not_reached ();
+ return NULL;
+}
+
+/* Getters for each tls key */
+gpointer mono_tls_get_thread (void)
+{
+ return MONO_TLS_GET_VALUE (mono_tls_thread, mono_tls_key_thread);
+}
+
+gpointer mono_tls_get_jit_tls (void)
+{
+ return MONO_TLS_GET_VALUE (mono_tls_jit_tls, mono_tls_key_jit_tls);
+}
+
+gpointer mono_tls_get_domain (void)
+{
+ return MONO_TLS_GET_VALUE (mono_tls_domain, mono_tls_key_domain);
+}
+
+gpointer mono_tls_get_lmf (void)
+{
+ return MONO_TLS_GET_VALUE (mono_tls_lmf, mono_tls_key_lmf);
+}
+
+gpointer mono_tls_get_sgen_thread_info (void)
+{
+ return MONO_TLS_GET_VALUE (mono_tls_sgen_thread_info, mono_tls_key_sgen_thread_info);
+}
+
+gpointer mono_tls_get_lmf_addr (void)
+{
+ return MONO_TLS_GET_VALUE (mono_tls_lmf_addr, mono_tls_key_lmf_addr);
+}
+
+/* Setters for each tls key */
+void mono_tls_set_thread (gpointer value)
+{
+ MONO_TLS_SET_VALUE (mono_tls_thread, mono_tls_key_thread, value);
+}
+
+void mono_tls_set_jit_tls (gpointer value)
+{
+ MONO_TLS_SET_VALUE (mono_tls_jit_tls, mono_tls_key_jit_tls, value);
+}
+
+void mono_tls_set_domain (gpointer value)
+{
+ MONO_TLS_SET_VALUE (mono_tls_domain, mono_tls_key_domain, value);
+}
+
+void mono_tls_set_lmf (gpointer value)
+{
+ MONO_TLS_SET_VALUE (mono_tls_lmf, mono_tls_key_lmf, value);
+}
+
+void mono_tls_set_sgen_thread_info (gpointer value)
+{
+ MONO_TLS_SET_VALUE (mono_tls_sgen_thread_info, mono_tls_key_sgen_thread_info, value);
+}
+
+void mono_tls_set_lmf_addr (gpointer value)
{
- tls_offsets [key] = offset;
- tls_offset_set [key] = TRUE;
+ MONO_TLS_SET_VALUE (mono_tls_lmf_addr, mono_tls_key_lmf_addr, value);
}
TLS_KEY_DOMAIN = 2,
TLS_KEY_LMF = 3,
TLS_KEY_SGEN_THREAD_INFO = 4,
- TLS_KEY_BOEHM_GC_THREAD = 5,
- TLS_KEY_LMF_ADDR = 6,
- TLS_KEY_NUM = 7
+ TLS_KEY_LMF_ADDR = 5,
+ TLS_KEY_NUM = 6
} MonoTlsKey;
#ifdef HOST_WIN32
#endif /* HOST_WIN32 */
-int mono_tls_key_get_offset (MonoTlsKey key);
-void mono_tls_key_set_offset (MonoTlsKey key, int offset);
+void mono_tls_init_gc_keys (void);
+void mono_tls_init_runtime_keys (void);
+void mono_tls_free_keys (void);
+gpointer mono_tls_get_tls_getter (MonoTlsKey key, gboolean name);
+gpointer mono_tls_get_tls_setter (MonoTlsKey key, gboolean name);
+gpointer mono_tls_get_tls_addr (MonoTlsKey key);
+
+gpointer mono_tls_get_thread (void);
+gpointer mono_tls_get_jit_tls (void);
+gpointer mono_tls_get_domain (void);
+gpointer mono_tls_get_lmf (void);
+gpointer mono_tls_get_sgen_thread_info (void);
+gpointer mono_tls_get_lmf_addr (void);
+
+void mono_tls_set_thread (gpointer value);
+void mono_tls_set_jit_tls (gpointer value);
+void mono_tls_set_domain (gpointer value);
+void mono_tls_set_lmf (gpointer value);
+void mono_tls_set_sgen_thread_info (gpointer value);
+void mono_tls_set_lmf_addr (gpointer value);
#endif /* __MONO_TLS_H__ */