Perform TLS offset detection during startup.
authorRodrigo Kumpera <kumpera@gmail.com>
Wed, 12 Jun 2013 19:35:20 +0000 (15:35 -0400)
committerRodrigo Kumpera <kumpera@gmail.com>
Wed, 12 Jun 2013 19:42:50 +0000 (15:42 -0400)
* mono-suppport-x86.c (mono_mach_init): Probe TLS slots using an
unlikely canary. Right now only two offsets are known.

* mono-threads.c (mono_threads_init): Initialize mach from here
as remote TLS reads are required for mono-threads to work.

mono/utils/mach-support-amd64.c
mono/utils/mach-support-arm.c
mono/utils/mach-support-unknown.c
mono/utils/mach-support-x86.c
mono/utils/mach-support.h
mono/utils/mono-threads.c

index e889a522c496690f3d89fc9dd8932775085deb4d..06b2cf14174d0494707f2e6b8c484245ca2d351b 100644 (file)
@@ -100,4 +100,9 @@ mono_mach_arch_get_tls_value_from_thread (pthread_t thread, guint32 key)
        return *(void**)mono_mach_get_tls_address_from_thread (thread, key);
 }
 
+void
+mono_mach_init (pthread_key_t key)
+{
+}
+
 #endif
index bd1c79de85581c155ef8eb32f4c87861cf0293e2..58ca5cbde63a244c3564c9afb0281dcb0d06a7a0 100644 (file)
@@ -102,4 +102,9 @@ mono_mach_arch_get_tls_value_from_thread (pthread_t thread, guint32 key)
        return *(void**)mono_mach_get_tls_address_from_thread (thread, key);
 }
 
+void
+mono_mach_init (pthread_key_t key)
+{
+}
+
 #endif
index fbba8dc882e8c6b4cfa5f61fd013ce65a05f4d16..9fece2272160425161aa10e057a593e3183ab9e8 100644 (file)
@@ -70,4 +70,10 @@ mono_mach_arch_get_tls_value_from_thread (pthread_t thread, guint32 key)
 {
        g_assert_not_reached ();
 }
+
+void
+mono_mach_init (pthread_key_t key)
+{
+}
+
 #endif
index e65fe6bdeefe05a40f603c9d482fedbb2baa8b04..76d2b06beef149fdee73ddc7c1977bc6c2f40d42 100644 (file)
 #include "utils/mono-sigcontext.h"
 #include "mach-support.h"
 
+/* Known offsets used for TLS storage*/
+
+/* All OSX versions up to 10.8 */
+#define TLS_VECTOR_OFFSET_CATS 0x48
+#define TLS_VECTOR_OFFSET_10_9 0xb0
+
+static int tls_vector_offset;
+
 void *
 mono_mach_arch_get_ip (thread_state_t state)
 {
@@ -85,11 +93,11 @@ void *
 mono_mach_get_tls_address_from_thread (pthread_t thread, pthread_key_t key)
 {
        /* OSX stores TLS values in a hidden array inside the pthread_t structure
-        * They are keyed off a giant array offset 0x48 into the pointer.  This value
+        * They are keyed off a giant array from a known offset into the pointer.  This value
         * is baked into their pthread_getspecific implementation
         */
        intptr_t *p = (intptr_t *) thread;
-       intptr_t **tsd = (intptr_t **) ((char*)p + 0x48);
+       intptr_t **tsd = (intptr_t **) ((char*)p + tls_vector_offset);
 
        return (void *) &tsd [key];     
 }
@@ -100,5 +108,29 @@ mono_mach_arch_get_tls_value_from_thread (pthread_t thread, guint32 key)
        return *(void**)mono_mach_get_tls_address_from_thread (thread, key);
 }
 
+void
+mono_mach_init (pthread_key_t key)
+{
+       void *old_value = pthread_getspecific (key);
+       void *canary = (void*)0xDEADBEEFu;
+
+       pthread_key_create (&key, NULL);
+       g_assert (old_value != canary);
+
+       pthread_setspecific (key, canary);
+
+       /*First we probe for cats*/
+       tls_vector_offset = TLS_VECTOR_OFFSET_CATS;
+       if (mono_mach_arch_get_tls_value_from_thread (pthread_self (), key) == canary)
+               goto ok;
+
+       tls_vector_offset = TLS_VECTOR_OFFSET_10_9;
+       if (mono_mach_arch_get_tls_value_from_thread (pthread_self (), key) == canary)
+               goto ok;
+
+       g_error ("could not discover the mach TLS offset");
+ok:
+       pthread_setspecific (key, old_value);
+}
 
 #endif
index ffed22f53c994741b4cad802c8340ce62c39e6f8..55fd9850fc27e64d3ccbc43a4f96cb697cccbf40 100644 (file)
@@ -23,6 +23,7 @@ extern pthread_t pthread_from_mach_thread_np(mach_port_t);
 
 void *mono_mach_arch_get_ip (thread_state_t state) MONO_INTERNAL;
 void *mono_mach_arch_get_sp (thread_state_t state) MONO_INTERNAL;
+void mono_mach_init (pthread_key_t key) MONO_INTERNAL;
 
 int mono_mach_arch_get_mcontext_size (void) MONO_INTERNAL;
 void mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context) MONO_INTERNAL;
index feff58fdbe4660b80209ddc688d677fde57f3b9f..bf7cdbc91140c2c12b567968b952755882c01b2a 100644 (file)
 
 #include <errno.h>
 
+#if defined(__MACH__)
+#include <mono/utils/mach-support.h>
+#endif
+
 #define THREADS_DEBUG(...)
 //#define THREADS_DEBUG(...) g_message(__VA_ARGS__)
 
@@ -281,6 +285,10 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
        mono_thread_smr_init ();
        mono_threads_init_platform ();
 
+#if defined(__MACH__)
+       mono_mach_init (thread_info_key);
+#endif
+
        mono_threads_inited = TRUE;
 
        g_assert (sizeof (MonoNativeThreadId) <= sizeof (uintptr_t));