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
|
# define USE_THREAD_LOCAL
|
||||||
# if _MSC_VER
|
# if _MSC_VER
|
||||||
# define THREAD_LOCAL __declspec(thread)
|
# 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
|
# define IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
|
||||||
# if defined(__x86_64__) || defined(__i386__)
|
# if defined(__x86_64__) || defined(__i386__)
|
||||||
# define INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
# define INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
||||||
|
@ -236,11 +236,28 @@ START_XFORM_SKIP;
|
||||||
# endif
|
# endif
|
||||||
static inline Thread_Local_Variables *scheme_get_thread_local_variables() __attribute__((used));
|
static inline Thread_Local_Variables *scheme_get_thread_local_variables() __attribute__((used));
|
||||||
static inline Thread_Local_Variables *scheme_get_thread_local_variables() {
|
static inline Thread_Local_Variables *scheme_get_thread_local_variables() {
|
||||||
Thread_Local_Variables *x;
|
Thread_Local_Variables *x = NULL;
|
||||||
|
# if defined(OS_X)
|
||||||
# if defined(__x86_64__)
|
# if defined(__x86_64__)
|
||||||
asm volatile("movq %%gs:0x8A0, %0" : "=r"(x));
|
asm volatile("movq %%gs:0x8A0, %0" : "=r"(x));
|
||||||
# else
|
# else
|
||||||
asm volatile("movl %%gs:0x468, %0" : "=r"(x));
|
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
|
# endif
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,10 +178,8 @@ static int do_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, vo
|
||||||
return return_code;
|
return return_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void *data) XFORM_SKIP_PROC
|
#if defined(IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS) && defined(INLINE_GETSPECIFIC_ASSEMBLY_CODE)
|
||||||
{
|
static void macosx_get_thread_local_key_for_assembly_code() {
|
||||||
#ifdef IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
|
|
||||||
# ifdef INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
|
||||||
/* Our [highly questionable] strategy for inlining pthread_getspecific() is taken from
|
/* Our [highly questionable] strategy for inlining pthread_getspecific() is taken from
|
||||||
the Go implementation (see "http://golang.org/src/libcgo/darwin_386.c").
|
the Go implementation (see "http://golang.org/src/libcgo/darwin_386.c").
|
||||||
In brief, we assume that thread-local variables are going to be
|
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. */
|
that particular key and double-check that it worked. */
|
||||||
pthread_key_t unwanted[16];
|
pthread_key_t unwanted[16];
|
||||||
int num_unwanted = 0;
|
int num_unwanted = 0;
|
||||||
# endif
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (pthread_key_create(&scheme_thread_local_key, NULL)) {
|
if (pthread_key_create(&scheme_thread_local_key, NULL)) {
|
||||||
fprintf(stderr, "pthread key create failed\n");
|
fprintf(stderr, "pthread key create failed\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
# ifdef INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
|
||||||
if (scheme_thread_local_key == 0x108)
|
if (scheme_thread_local_key == 0x108)
|
||||||
break;
|
break;
|
||||||
else {
|
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;
|
unwanted[num_unwanted++] = scheme_thread_local_key;
|
||||||
}
|
}
|
||||||
# else
|
|
||||||
break;
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef INLINE_GETSPECIFIC_ASSEMBLY_CODE
|
|
||||||
pthread_setspecific(scheme_thread_local_key, (void *)0xaced);
|
pthread_setspecific(scheme_thread_local_key, (void *)0xaced);
|
||||||
if (scheme_get_thread_local_variables() != (Thread_Local_Variables *)0xaced) {
|
if (scheme_get_thread_local_variables() != (Thread_Local_Variables *)0xaced) {
|
||||||
fprintf(stderr, "pthread getspecific inline hack failed\n");
|
fprintf(stderr, "pthread getspecific inline hack failed\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (num_unwanted--) {
|
while (num_unwanted--) {
|
||||||
pthread_key_delete(unwanted[num_unwanted]);
|
pthread_key_delete(unwanted[num_unwanted]);
|
||||||
}
|
}
|
||||||
# endif
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
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();
|
scheme_init_os_thread();
|
||||||
|
|
||||||
return do_main_stack_setup(no_auto_statics, _main, data);
|
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
|
||||||
#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
|
void scheme_init_os_thread() XFORM_SKIP_PROC
|
||||||
{
|
{
|
||||||
#ifdef IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
|
#ifdef IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
|
||||||
|
|
Loading…
Reference in New Issue
Block a user