Allow shared_so linux GC testing via homespun access to ThreadLocalVariables table
svn: r17477
This commit is contained in:
parent
63c917fd8f
commit
ee641b80ac
|
@ -23,7 +23,7 @@
|
|||
# define USE_THREAD_LOCAL
|
||||
# if _MSC_VER
|
||||
# define THREAD_LOCAL __declspec(thread)
|
||||
# elif defined(OS_X)
|
||||
# elif defined(OS_X) || (defined(linux) && defined(MZ_USES_SHARED_LIB))
|
||||
# define IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
|
||||
# if defined(__x86_64__) || defined(__i386__)
|
||||
# define INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
||||
|
@ -236,11 +236,28 @@ START_XFORM_SKIP;
|
|||
# endif
|
||||
static inline Thread_Local_Variables *scheme_get_thread_local_variables() __attribute__((used));
|
||||
static inline Thread_Local_Variables *scheme_get_thread_local_variables() {
|
||||
Thread_Local_Variables *x;
|
||||
# if defined(__x86_64__)
|
||||
Thread_Local_Variables *x = NULL;
|
||||
# if defined(OS_X)
|
||||
# if defined(__x86_64__)
|
||||
asm volatile("movq %%gs:0x8A0, %0" : "=r"(x));
|
||||
# else
|
||||
# else
|
||||
asm volatile("movl %%gs:0x468, %0" : "=r"(x));
|
||||
# endif
|
||||
# elif defined(linux) && defined(MZ_USES_SHARED_LIB)
|
||||
# if defined(__x86_64__)
|
||||
asm volatile( "mov %1, %%eax;"
|
||||
"shl $0x4, %%rax;"
|
||||
"mov %%fs:0x10, %%rdx;"
|
||||
"mov 0x118(%%rax,%%rdx), %0;"
|
||||
:"=r"(x) /* output */
|
||||
:"r"(scheme_thread_local_key)
|
||||
:"%rax", "%rdx" /* clobbered register */
|
||||
);
|
||||
# else
|
||||
# error scheme_get_thread_local_variables no defined on this platform
|
||||
# endif
|
||||
# else
|
||||
# error scheme_get_thread_local_variables no defined on this platform
|
||||
# endif
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -178,10 +178,8 @@ static int do_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, vo
|
|||
return return_code;
|
||||
}
|
||||
|
||||
int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void *data) XFORM_SKIP_PROC
|
||||
{
|
||||
#ifdef IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
|
||||
# ifdef INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
||||
#if defined(IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS) && defined(INLINE_GETSPECIFIC_ASSEMBLY_CODE)
|
||||
static void macosx_get_thread_local_key_for_assembly_code() {
|
||||
/* 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
|
||||
|
@ -190,14 +188,12 @@ int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void
|
|||
that particular key and double-check that it worked. */
|
||||
pthread_key_t unwanted[16];
|
||||
int num_unwanted = 0;
|
||||
# endif
|
||||
|
||||
while (1) {
|
||||
if (pthread_key_create(&scheme_thread_local_key, NULL)) {
|
||||
fprintf(stderr, "pthread key create failed\n");
|
||||
abort();
|
||||
}
|
||||
# ifdef INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
||||
if (scheme_thread_local_key == 0x108)
|
||||
break;
|
||||
else {
|
||||
|
@ -207,25 +203,56 @@ int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void
|
|||
}
|
||||
unwanted[num_unwanted++] = scheme_thread_local_key;
|
||||
}
|
||||
# else
|
||||
break;
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
||||
scheme_init_os_thread();
|
||||
void scheme_setup_thread_local_key_if_needed() {
|
||||
#ifdef IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
|
||||
# ifdef INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
||||
# if defined(linux)
|
||||
scheme_thread_local_key = 0;
|
||||
if (pthread_key_create(&scheme_thread_local_key, NULL)) {
|
||||
fprintf(stderr, "pthread key create failed\n");
|
||||
abort();
|
||||
}
|
||||
/*
|
||||
if (scheme_thread_local_key != 0) {
|
||||
fprintf(stderr, "pthread getspecific inline hack failed scheme_thread_local_key %i\n", scheme_thread_local_key);
|
||||
abort();
|
||||
}
|
||||
*/
|
||||
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 to return set data\n");
|
||||
abort();
|
||||
}
|
||||
# else
|
||||
macosx_get_thread_local_key_for_assembly_code();
|
||||
# endif
|
||||
# else
|
||||
if (pthread_key_create(&scheme_thread_local_key, NULL)) {
|
||||
fprintf(stderr, "pthread key create failed\n");
|
||||
abort();
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void *data) XFORM_SKIP_PROC
|
||||
{
|
||||
scheme_setup_thread_local_key_if_needed();
|
||||
scheme_init_os_thread();
|
||||
return do_main_stack_setup(no_auto_statics, _main, data);
|
||||
}
|
||||
|
||||
|
@ -275,6 +302,15 @@ extern void GC_attach_current_thread_exceptions_to_handler();
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
|
||||
void scheme_set_thread_local_variables(void *tlvas) XFORM_SKIP_PROC {
|
||||
pthread_setspecific(scheme_thread_local_key, tlvas);
|
||||
}
|
||||
void* scheme_dbg_get_thread_local_variables() XFORM_SKIP_PROC {
|
||||
return pthread_getspecific(scheme_thread_local_key);
|
||||
}
|
||||
#endif
|
||||
|
||||
void scheme_init_os_thread() XFORM_SKIP_PROC
|
||||
{
|
||||
#ifdef IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
|
||||
|
|
Loading…
Reference in New Issue
Block a user