X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=libgc%2Fpthread_support.c;h=097d588a7b55fd77569d2def2b9e80348068085c;hb=30cddad5fb4c3d290906a6e6c33ecd8b07d8b48c;hp=bc31c9733a7d40e77e2c7ed3156516401901d576;hpb=600a57c98da0c5e40b4fa63c1156686c76d31c5a;p=mono.git diff --git a/libgc/pthread_support.c b/libgc/pthread_support.c index bc31c9733a7..097d588a7b5 100644 --- a/libgc/pthread_support.c +++ b/libgc/pthread_support.c @@ -66,6 +66,7 @@ --> Macro replaced by USE_COMPILER_TLS # endif +#ifndef USE_COMPILER_TLS # if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \ defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \ defined(GC_NETBSD_THREADS) && !defined(USE_PTHREAD_SPECIFIC) || \ @@ -73,6 +74,7 @@ defined(GC_OPENBSD_THREADS) # define USE_PTHREAD_SPECIFIC # endif +#endif # if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE) # define _POSIX4A_DRAFT10_SOURCE 1 @@ -203,7 +205,7 @@ static 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 @@ -220,10 +222,6 @@ static int GC_setspecific (GC_key_t key, void *value) { static GC_bool keys_initialized; -#ifdef MONO_DEBUGGER_SUPPORTED -#include "include/libgc-mono-debugger.h" -#endif - /* Recover the contents of the freelist array fl into the global one gfl.*/ /* Note that the indexing scheme differs, in that gfl has finer size */ /* resolution, even if not all entries are used. */ @@ -296,17 +294,17 @@ void GC_init_thread_local(GC_thread p) ABORT("Failed to set thread specific allocation pointers"); } for (i = 1; i < NFREELISTS; ++i) { - p -> ptrfree_freelists[i] = (ptr_t)1; - p -> normal_freelists[i] = (ptr_t)1; + p -> tlfs.ptrfree_freelists[i] = (ptr_t)1; + p -> tlfs.normal_freelists[i] = (ptr_t)1; # ifdef GC_GCJ_SUPPORT - p -> gcj_freelists[i] = (ptr_t)1; + p -> tlfs.gcj_freelists[i] = (ptr_t)1; # endif } /* Set up the size 0 free lists. */ - p -> ptrfree_freelists[0] = (ptr_t)(&size_zero_object); - p -> normal_freelists[0] = (ptr_t)(&size_zero_object); + p -> tlfs.ptrfree_freelists[0] = (ptr_t)(&size_zero_object); + p -> tlfs.normal_freelists[0] = (ptr_t)(&size_zero_object); # ifdef GC_GCJ_SUPPORT - p -> gcj_freelists[0] = (ptr_t)(-1); + p -> tlfs.gcj_freelists[0] = (ptr_t)(-1); # endif } @@ -322,10 +320,10 @@ void GC_destroy_thread_local(GC_thread p) # ifndef HANDLE_FORK GC_ASSERT(GC_getspecific(GC_thread_key) == (void *)p); # endif - return_freelists(p -> ptrfree_freelists, GC_aobjfreelist); - return_freelists(p -> normal_freelists, GC_objfreelist); + return_freelists(p -> tlfs.ptrfree_freelists, GC_aobjfreelist); + return_freelists(p -> tlfs.normal_freelists, GC_objfreelist); # ifdef GC_GCJ_SUPPORT - return_freelists(p -> gcj_freelists, GC_gcjobjfreelist); + return_freelists(p -> tlfs.gcj_freelists, GC_gcjobjfreelist); # endif } @@ -359,7 +357,7 @@ GC_PTR GC_local_malloc(size_t bytes) GC_ASSERT(tsd == (void *)GC_lookup_thread(pthread_self())); UNLOCK(); # endif - my_fl = ((GC_thread)tsd) -> normal_freelists + index; + my_fl = ((GC_thread)tsd) -> tlfs.normal_freelists + index; my_entry = *my_fl; if (EXPECT((word)my_entry >= HBLKSIZE, 1)) { ptr_t next = obj_link(my_entry); @@ -386,7 +384,7 @@ GC_PTR GC_local_malloc_atomic(size_t bytes) } else { int index = INDEX_FROM_BYTES(bytes); ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key)) - -> ptrfree_freelists + index; + -> tlfs.ptrfree_freelists + index; ptr_t my_entry = *my_fl; if (EXPECT((word)my_entry >= HBLKSIZE, 1)) { @@ -426,7 +424,7 @@ GC_PTR GC_local_gcj_malloc(size_t bytes, } else { int index = INDEX_FROM_BYTES(bytes); ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key)) - -> gcj_freelists + index; + -> tlfs.gcj_freelists + index; ptr_t my_entry = *my_fl; if (EXPECT((word)my_entry >= HBLKSIZE, 1)) { GC_PTR result = (GC_PTR)my_entry; @@ -465,7 +463,7 @@ GC_PTR GC_local_gcj_malloc(size_t bytes, void * GC_local_gcj_fast_malloc(size_t lw, void * ptr_to_struct_containing_descr) { ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key)) - -> gcj_freelists + lw; + -> tlfs.gcj_freelists + lw; ptr_t my_entry = *my_fl; GC_ASSERT(GC_gcj_malloc_initialized); @@ -668,12 +666,12 @@ void GC_mark_thread_local_free_lists(void) for (i = 0; i < THREAD_TABLE_SZ; ++i) { for (p = GC_threads[i]; 0 != p; p = p -> next) { for (j = 1; j < NFREELISTS; ++j) { - q = p -> ptrfree_freelists[j]; + q = p -> tlfs.ptrfree_freelists[j]; if ((word)q > HBLKSIZE) GC_set_fl_marks(q); - q = p -> normal_freelists[j]; + q = p -> tlfs.normal_freelists[j]; if ((word)q > HBLKSIZE) GC_set_fl_marks(q); # ifdef GC_GCJ_SUPPORT - q = p -> gcj_freelists[j]; + q = p -> tlfs.gcj_freelists[j]; if ((word)q > HBLKSIZE) GC_set_fl_marks(q); # endif /* GC_GCJ_SUPPORT */ } @@ -685,10 +683,10 @@ void GC_mark_thread_local_free_lists(void) static struct GC_Thread_Rep first_thread; #ifdef NACL -extern int nacl_thread_parked[MAX_NACL_GC_THREADS]; -extern int nacl_thread_used[MAX_NACL_GC_THREADS]; -extern int nacl_thread_parking_inited; -extern int nacl_num_gc_threads; +extern volatile int nacl_thread_parked[MAX_NACL_GC_THREADS]; +extern volatile int nacl_thread_used[MAX_NACL_GC_THREADS]; +extern volatile int nacl_thread_parking_inited; +extern volatile int nacl_num_gc_threads; extern pthread_mutex_t nacl_thread_alloc_lock; extern __thread int nacl_thread_idx; extern __thread GC_thread nacl_gc_thread_self; @@ -697,10 +695,20 @@ extern void nacl_pre_syscall_hook(); extern void nacl_post_syscall_hook(); extern void nacl_register_gc_hooks(void (*pre)(), void (*post)()); +#include + +struct nacl_irt_blockhook { + int (*register_block_hooks)(void (*pre)(void), void (*post)(void)); +}; + +extern size_t nacl_interface_query(const char *interface_ident, + void *table, size_t tablesize); + void nacl_initialize_gc_thread() { int i; - nacl_register_gc_hooks(nacl_pre_syscall_hook, nacl_post_syscall_hook); + static struct nacl_irt_blockhook gc_hook; + pthread_mutex_lock(&nacl_thread_alloc_lock); if (!nacl_thread_parking_inited) { @@ -708,6 +716,10 @@ void nacl_initialize_gc_thread() nacl_thread_used[i] = 0; nacl_thread_parked[i] = 0; } + // TODO: replace with public 'register hook' function when + // available from glibc + nacl_interface_query("nacl-irt-blockhook-0.1", &gc_hook, sizeof(gc_hook)); + gc_hook.register_block_hooks(nacl_pre_syscall_hook, nacl_post_syscall_hook); nacl_thread_parking_inited = 1; } GC_ASSERT(nacl_num_gc_threads <= MAX_NACL_GC_THREADS); @@ -752,7 +764,7 @@ GC_thread GC_new_thread(pthread_t id) } if (result == 0) return(0); result -> id = id; -#ifdef PLATFORM_ANDROID +#ifdef HOST_ANDROID result -> kernel_id = gettid(); #endif result -> next = GC_threads[hv]; @@ -788,10 +800,6 @@ void GC_delete_thread(pthread_t id) } else { prev -> next = p -> next; } -#ifdef MONO_DEBUGGER_SUPPORTED - if (gc_thread_vtable && gc_thread_vtable->thread_exited) - gc_thread_vtable->thread_exited (id, &p->stop_info.stack_ptr); -#endif #ifdef GC_DARWIN_THREADS mach_port_deallocate(mach_task_self(), p->stop_info.mach_thread); @@ -940,6 +948,7 @@ int GC_segment_is_thread_stack(ptr_t lo, ptr_t hi) /* Return the number of processors, or i<= 0 if it can't be determined. */ int GC_get_nprocs() { +#ifndef NACL /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that */ /* appears to be buggy in many cases. */ /* We look for lines "cpu" in /proc/stat. */ @@ -969,6 +978,9 @@ int GC_get_nprocs() } close(f); return result; +#else /* NACL */ + return sysconf(_SC_NPROCESSORS_ONLN); +#endif } #endif /* GC_LINUX_THREADS */ @@ -1104,14 +1116,6 @@ void GC_thr_init() t -> stop_info.stack_ptr = (ptr_t)(&dummy); # endif t -> flags = DETACHED | MAIN_THREAD; -#ifdef MONO_DEBUGGER_SUPPORTED - if (gc_thread_vtable && gc_thread_vtable->thread_created) -# ifdef GC_DARWIN_THREADS - gc_thread_vtable->thread_created (mach_thread_self (), &t->stop_info.stack_ptr); -# else - gc_thread_vtable->thread_created (pthread_self (), &t->stop_info.stack_ptr); -# endif -#endif if (pthread_self () == main_pthread_self) { t->stack = main_stack; t->stack_size = main_stack_size; @@ -1360,12 +1364,10 @@ int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) } #ifdef NACL -/* Native Client doesn't support pthread cleanup functions, */ -/* so wrap pthread_exit and manually cleanup the thread. */ +/* TODO: remove, NaCl glibc now supports pthread cleanup functions. */ void WRAP_FUNC(pthread_exit)(void *status) { - GC_thread_exit_proc(0); REAL_FUNC(pthread_exit)(status); } #endif @@ -1443,14 +1445,6 @@ void * GC_start_routine_head(void * arg, void *base_addr, /* This is also < 100% convincing. We should also read this */ /* from /proc, but the hook to do so isn't there yet. */ # endif /* IA64 */ -#ifdef MONO_DEBUGGER_SUPPORTED - if (gc_thread_vtable && gc_thread_vtable->thread_created) -# ifdef GC_DARWIN_THREADS - gc_thread_vtable->thread_created (mach_thread_self(), &me->stop_info.stack_ptr); -# else - gc_thread_vtable->thread_created (my_pthread, &me->stop_info.stack_ptr); -# endif -#endif UNLOCK(); if (start) *start = si -> start_routine; @@ -1468,13 +1462,18 @@ void * GC_start_routine_head(void * arg, void *base_addr, return me; } -int GC_thread_register_foreign (void *base_addr) +void GC_allow_register_threads (void) +{ + /* No-op for GC pre-v7. */ +} + +int GC_register_my_thread (struct GC_stack_base *sb) { struct start_info si = { 0, }; /* stacked for legibility & locking */ GC_thread me; # ifdef DEBUG_THREADS - GC_printf1( "GC_thread_register_foreign %p\n", &si ); + GC_printf1( "GC_register_my_thread %p\n", &si ); # endif si.flags = FOREIGN_THREAD; @@ -1482,12 +1481,13 @@ int GC_thread_register_foreign (void *base_addr) if (!parallel_initialized) GC_init_parallel(); LOCK(); if (!GC_thr_initialized) GC_thr_init(); - + me = GC_lookup_thread(pthread_self()); UNLOCK(); + if (me != NULL) + return GC_DUPLICATE; - me = GC_start_routine_head(&si, base_addr, NULL, NULL); - - return me != NULL; + (void)GC_start_routine_head(&si, sb -> mem_base, NULL, NULL); + return GC_SUCCESS; } void * GC_start_routine(void * arg)