X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=libgc%2Fpthread_support.c;h=3e588ace211abdcd0ed62b104f94f2a57d8b336b;hb=5979d6f01982aba922f86e1273b0173eab7b285e;hp=0346a8022a6dcff525eb9b899c9ed933ff1c42b2;hpb=6110fc90713ce59ff0996fcd3520e09a96575820;p=mono.git diff --git a/libgc/pthread_support.c b/libgc/pthread_support.c index 0346a8022a6..3e588ace211 100644 --- a/libgc/pthread_support.c +++ b/libgc/pthread_support.c @@ -67,8 +67,9 @@ # endif # if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \ - defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) \ - && !defined(USE_PTHREAD_SPECIFIC) + defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \ + defined(GC_NETBSD_THREADS) && !defined(USE_PTHREAD_SPECIFIC) || \ + defined(GC_OPENBSD_THREADS) # define USE_PTHREAD_SPECIFIC # endif @@ -97,8 +98,11 @@ typedef pthread_key_t GC_key_t; # endif # if defined(USE_COMPILER_TLS) +/* Note sles9 gcc on powerpc gets confused by the define to set GC_thread_tls and pthread_setspecific + * so we actually use a static inline function decalred below that is equivalent to: + * define GC_setspecific(key, v) (GC_thread_tls = (v), pthread_setspecific ((key), (v))) + */ # define GC_getspecific(x) (GC_thread_tls) -# define GC_setspecific(key, v) (GC_thread_tls = (v), pthread_setspecific ((key), (v))) # define GC_key_create pthread_key_create typedef pthread_key_t GC_key_t; # endif @@ -126,6 +130,11 @@ # include #endif /* GC_DARWIN_THREADS */ +#if defined(GC_NETBSD_THREADS) || defined(GC_OPENBSD_THREADS) +# include +# include +#endif + #if defined(GC_DGUX386_THREADS) @@ -155,6 +164,9 @@ # endif # undef pthread_join # undef pthread_detach +# if defined(NACL) +# undef pthread_exit +# endif # if defined(GC_OSF1_THREADS) && defined(_PTHREAD_USE_MANGLED_NAMES_) \ && !defined(_PTHREAD_USE_PTDNAM_) /* Restore the original mangled names on Tru64 UNIX. */ @@ -186,7 +198,19 @@ static GC_key_t GC_thread_key; #ifdef USE_COMPILER_TLS -static __thread MONO_TLS_FAST void* GC_thread_tls; +__thread MONO_TLS_FAST void* GC_thread_tls; + +/* + * gcc errors out with /tmp/ccdPMFuq.s:2994: Error: symbol `.LTLS4' is already defined + * if the inline is added on powerpc + */ +#if !defined(__ppc__) && !defined(__powerpc__) +inline +#endif +static int GC_setspecific (GC_key_t key, void *value) { + GC_thread_tls = value; + return pthread_setspecific (key, value); +} #endif static GC_bool keys_initialized; @@ -655,6 +679,52 @@ 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 pthread_mutex_t nacl_thread_alloc_lock; +extern __thread int nacl_thread_idx; +extern __thread GC_thread nacl_gc_thread_self; + +void nacl_initialize_gc_thread() +{ + int i; + pthread_mutex_lock(&nacl_thread_alloc_lock); + if (!nacl_thread_parking_inited) + { + for (i = 0; i < MAX_NACL_GC_THREADS; i++) { + nacl_thread_used[i] = 0; + nacl_thread_parked[i] = 0; + } + nacl_thread_parking_inited = 1; + } + GC_ASSERT(nacl_num_gc_threads <= MAX_NACL_GC_THREADS); + for (i = 0; i < MAX_NACL_GC_THREADS; i++) { + if (nacl_thread_used[i] == 0) { + nacl_thread_used[i] = 1; + nacl_thread_idx = i; + nacl_num_gc_threads++; + break; + } + } + pthread_mutex_unlock(&nacl_thread_alloc_lock); +} + +void nacl_shutdown_gc_thread() +{ + pthread_mutex_lock(&nacl_thread_alloc_lock); + GC_ASSERT(nacl_thread_idx >= 0 && nacl_thread_idx < MAX_NACL_GC_THREADS); + GC_ASSERT(nacl_thread_used[nacl_thread_idx] != 0); + nacl_thread_used[nacl_thread_idx] = 0; + nacl_thread_idx = -1; + nacl_num_gc_threads--; + pthread_mutex_unlock(&nacl_thread_alloc_lock); +} + +#endif /* NACL */ + /* Add a thread to GC_threads. We assume it wasn't already there. */ /* Caller holds allocation lock. */ GC_thread GC_new_thread(pthread_t id) @@ -672,8 +742,15 @@ GC_thread GC_new_thread(pthread_t id) } if (result == 0) return(0); result -> id = id; +#ifdef PLATFORM_ANDROID + result -> kernel_id = gettid(); +#endif result -> next = GC_threads[hv]; GC_threads[hv] = result; +#ifdef NACL + nacl_gc_thread_self = result; + nacl_initialize_gc_thread(); +#endif GC_ASSERT(result -> flags == 0 && result -> thread_blocked == 0); return(result); } @@ -687,6 +764,11 @@ void GC_delete_thread(pthread_t id) register GC_thread p = GC_threads[hv]; register GC_thread prev = 0; +#ifdef NACL + nacl_shutdown_gc_thread(); + nacl_gc_thread_self = NULL; +#endif + while (!pthread_equal(p -> id, id)) { prev = p; p = p -> next; @@ -990,7 +1072,11 @@ void GC_thr_init() t -> flags = DETACHED | MAIN_THREAD; #ifdef MONO_DEBUGGER_SUPPORTED if (gc_thread_vtable && gc_thread_vtable->thread_created) - gc_thread_vtable->thread_created (pthread_self (), &t->stop_info.stack_ptr); +# 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 GC_stop_init(); @@ -1013,7 +1099,7 @@ void GC_thr_init() GC_nprocs = sysconf(_SC_NPROC_ONLN); if (GC_nprocs <= 0) GC_nprocs = 1; # endif -# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS) +# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS) || defined(GC_NETBSD_THREADS) || defined(GC_OPENBSD_THREADS) int ncpus = 1; size_t len = sizeof(ncpus); sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0); @@ -1037,6 +1123,8 @@ void GC_thr_init() GC_markers = atoi(markers_string); } else { GC_markers = GC_nprocs; + if (GC_markers > MAX_MARKERS) + GC_markers = MAX_MARKERS; } } # endif @@ -1087,7 +1175,8 @@ void GC_init_parallel() } -#if !defined(GC_DARWIN_THREADS) +#if !defined(GC_DARWIN_THREADS) && !defined(GC_OPENBSD_THREADS) +#ifndef NACL int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset) { sigset_t fudged_set; @@ -1099,6 +1188,7 @@ int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset) } return(REAL_FUNC(pthread_sigmask)(how, set, oset)); } +#endif #endif /* !GC_DARWIN_THREADS */ /* Wrappers for functions that are likely to block for an appreciable */ @@ -1180,6 +1270,11 @@ void GC_thread_exit_proc(void *arg) me = GC_lookup_thread(pthread_self()); GC_destroy_thread_local(me); if (me -> flags & DETACHED) { +# ifdef THREAD_LOCAL_ALLOC + /* NULL out the tls key to prevent the dtor function from being called */ + if (0 != GC_setspecific(GC_thread_key, NULL)) + ABORT("Failed to set thread specific allocation pointers"); +#endif GC_delete_thread(pthread_self()); } else { me -> flags |= FINISHED; @@ -1224,6 +1319,17 @@ int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) return result; } +#ifdef NACL +/* Native Client doesn't support pthread cleanup functions, */ +/* so wrap pthread_exit and manually cleanup the thread. */ +void +WRAP_FUNC(pthread_exit)(void *status) +{ + GC_thread_exit_proc(0); + REAL_FUNC(pthread_exit)(status); +} +#endif + int WRAP_FUNC(pthread_detach)(pthread_t thread) { @@ -1299,14 +1405,19 @@ void * GC_start_routine_head(void * arg, void *base_addr, # endif /* IA64 */ #ifdef MONO_DEBUGGER_SUPPORTED if (gc_thread_vtable && gc_thread_vtable->thread_created) - gc_thread_vtable->thread_created (my_pthread, &me->stop_info.stack_ptr); +# 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; if (start_arg) *start_arg = si -> arg; - sem_post(&(si -> registered)); /* Last action on si. */ + if (!(si->flags & FOREIGN_THREAD)) + sem_post(&(si -> registered)); /* Last action on si. */ /* OK to deallocate. */ # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) LOCK();