try to fix thread-local variables for Max OS X Lion

This commit is contained in:
Matthew Flatt 2011-05-08 08:00:46 -06:00
parent 695039626c
commit 9188e36ef1
2 changed files with 51 additions and 44 deletions

View File

@ -327,6 +327,9 @@ typedef struct Thread_Local_Variables {
/* Using Pthread getspecific() */
# include <pthread.h>
MZ_EXTERN pthread_key_t scheme_thread_local_key;
# if defined(__APPLE__) && defined(__MACH__)
MZ_EXTERN int scheme_thread_local_offset;
# endif
# ifndef INLINE_GETSPECIFIC_ASSEMBLY_CODE
# define scheme_get_thread_local_variables() ((Thread_Local_Variables *)pthread_getspecific(scheme_thread_local_key))
# ifdef MZ_XFORM
@ -341,13 +344,13 @@ static inline Thread_Local_Variables *scheme_get_thread_local_variables() {
Thread_Local_Variables *x = NULL;
# if defined(__APPLE__) && defined(__MACH__)
# if defined(__x86_64__)
asm volatile("movq %%gs:0x60(,%1,8), %0" : "=r"(x) : "r"(scheme_thread_local_key));
asm("movq %%gs:0(%1,%2,8), %0" : "=r"(x) : "r"(scheme_thread_local_offset), "r"((int)scheme_thread_local_key));
# else
asm volatile("movl %%gs:0x48(,%1,4), %0" : "=r"(x) : "r"(scheme_thread_local_key));
asm("movl %%gs:0(%1,%2,4), %0" : "=r"(x) : "r"(scheme_thread_local_offset), "r"(scheme_thread_local_key));
# endif
# elif defined(linux)
# if defined(__x86_64__)
asm volatile( "mov %1, %%eax;"
asm( "mov %1, %%eax;"
"shl $0x4, %%rax;"
"mov %%fs:0x10, %%rdx;"
"mov 0x118(%%rax,%%rdx), %0;"

View File

@ -67,6 +67,12 @@ SHARED_OK THREAD_LOCAL Thread_Local_Variables scheme_thread_locals;
# endif
#endif
#if defined(__APPLE__) && defined(__MACH__)
# include <sys/param.h>
# include <sys/sysctl.h>
int scheme_thread_local_offset = 0;
#endif
extern int scheme_num_copied_stacks;
SHARED_OK static uintptr_t scheme_primordial_os_thread_stack_base;
THREAD_LOCAL_DECL(static uintptr_t scheme_os_thread_stack_base);
@ -198,47 +204,6 @@ void scheme_set_thread_local_variables(Thread_Local_Variables *tlvs) XFORM_SKIP_
}
#endif
#if 0 && defined(IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS) && defined(INLINE_GETSPECIFIC_ASSEMBLY_CODE)
/* This code is dsiabled */
static void macosx_get_thread_local_key_for_assembly_code() XFORM_SKIP_PROC
{
/* Our [highly questionable] strategy for inlining pthread_getspecific() is taken from
the Go implementation (see "http://golang.org/src/libcgo/darwin_386.c").
In brief, we assume that thread-local variables are going to be
accessed via the gs segment register at offset 0x48 (i386) or 0x60 (x86_64),
and we also hardwire the thread-local key 0x110. Here we have to try to get
that particular key and double-check that it worked. */
pthread_key_t unwanted[16];
int num_unwanted = 0;
while (1) {
if (pthread_key_create(&scheme_thread_local_key, NULL)) {
fprintf(stderr, "pthread key create failed\n");
abort();
}
if (scheme_thread_local_key == 0x110)
break;
else {
if (num_unwanted == 24) {
fprintf(stderr, "pthread key create never produced 0x110 for inline hack\n");
abort();
}
unwanted[num_unwanted++] = scheme_thread_local_key;
}
}
pthread_setspecific(scheme_thread_local_key, (void *)0xaced);
if (scheme_get_thread_local_variables() != (Thread_Local_Variables *)0xaced) {
fprintf(stderr, "pthread getspecific inline hack failed\n");
abort();
}
while (num_unwanted--) {
pthread_key_delete(unwanted[num_unwanted]);
}
}
#endif
#ifdef IMPLEMENT_THREAD_LOCAL_VIA_WIN_TLS
void scheme_register_tls_space(void *tls_space, int tls_index) XFORM_SKIP_PROC
{
@ -267,6 +232,45 @@ void scheme_setup_thread_local_key_if_needed() XFORM_SKIP_PROC
fprintf(stderr, "pthread key create failed\n");
abort();
}
# if defined(__APPLE__) && defined(__MACH__)
/* Darwin version 11 (Max OS X Lion) changes the offset from %gs
for thread-local storage. */
{
int name[2];
char vers[128];
size_t len;
int i, vn = 0, bad = 0;
name[0] = CTL_KERN;
name[1] = KERN_OSRELEASE;
len = sizeof(vers);
if (sysctl(name, 2, vers, &len, NULL, 0))
bad = 1;
else {
for (i = 0; vers[i] && (vers[i] != '.'); i++) {
if ((vers[i] < '0') || (vers[i] > '9'))
break;
vn = (vn * 10) + (vers[i] - '0');
}
if ((vers[i] == '.') && (vn > 0) && (vn < 1000)) {
if (vn > 10)
scheme_thread_local_offset = 0;
else {
# if defined(__x86_64__)
scheme_thread_local_offset = 0x60;
# else
scheme_thread_local_offset = 0x48;
# endif
}
} else
bad = 1;
}
if (bad) {
fprintf(stderr, "kernel version lookup failed\n");
abort();
}
}
# endif
#endif
#ifdef IMPLEMENT_THREAD_LOCAL_VIA_WIN_TLS
{