X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=libgc%2Fpthread_support.c;h=6306f2cd0ceb244d445e0701e0d8ca2ef01bf71b;hb=83569e1ef07325ec30b00d3e2b955718f210e608;hp=9def3e117cb6c954660de365d52b014ba1c35b55;hpb=38f320d19a29a3e7d6a92cdb0b3ebec149d7c1a7;p=mono.git diff --git a/libgc/pthread_support.c b/libgc/pthread_support.c index 9def3e117cb..6306f2cd0ce 100644 --- a/libgc/pthread_support.c +++ b/libgc/pthread_support.c @@ -2,7 +2,7 @@ * Copyright (c) 1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996 by Silicon Graphics. All rights reserved. * Copyright (c) 1998 by Fergus Henderson. All rights reserved. - * Copyright (c) 2000-2001 by Hewlett-Packard Company. All rights reserved. + * Copyright (c) 2000-2004 by Hewlett-Packard Company. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -50,8 +50,7 @@ # include "private/pthread_support.h" # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ - && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) \ - && !defined(GC_AIX_THREADS) + && !defined(GC_WIN32_THREADS) # if defined(GC_HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \ && !defined(USE_COMPILER_TLS) @@ -68,7 +67,8 @@ # endif # if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \ - defined(GC_DARWIN_THREADS)) && !defined(USE_PTHREAD_SPECIFIC) + defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \ + defined(GC_NETBSD_THREADS) && !defined(USE_PTHREAD_SPECIFIC) # define USE_PTHREAD_SPECIFIC # endif @@ -84,6 +84,12 @@ # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_COMPILER_TLS) # include "private/specific.h" # endif + +/* Note that these macros should be used only to get/set the GC_thread pointer. + * We need to use both tls and pthread because we use the pthread_create function hook to + * free the data for foreign threads. When that doesn't happen, libgc could have old + * pthread_t that get reused... + */ # if defined(USE_PTHREAD_SPECIFIC) # define GC_getspecific pthread_getspecific # define GC_setspecific pthread_setspecific @@ -91,10 +97,10 @@ typedef pthread_key_t GC_key_t; # endif # if defined(USE_COMPILER_TLS) -# define GC_getspecific(x) (x) -# define GC_setspecific(key, v) ((key) = (v), 0) -# define GC_key_create(key, d) 0 - typedef void * GC_key_t; +# 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 # endif # include @@ -116,10 +122,15 @@ # include #endif /* !GC_DARWIN_THREADS */ -#if defined(GC_DARWIN_THREADS) +#if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS) # include #endif /* GC_DARWIN_THREADS */ +#if defined(GC_NETBSD_THREADS) +# include +# include +#endif + #if defined(GC_DGUX386_THREADS) @@ -177,13 +188,25 @@ void GC_init_parallel(); #include "mono/utils/mono-compiler.h" static +GC_key_t GC_thread_key; + #ifdef USE_COMPILER_TLS - __thread MONO_TLS_FAST +/* + * gcc errors out with /tmp/ccdPMFuq.s:2994: Error: symbol `.LTLS4' is already defined + * if the static is removed on ppc. + */ +#if defined(__ppc__) || defined(__powerpc__) +static +#endif +__thread MONO_TLS_FAST void* GC_thread_tls; #endif -GC_key_t GC_thread_key; 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. */ @@ -221,7 +244,8 @@ static void return_freelists(ptr_t *fl, ptr_t *gfl) /* we arrange for those to fault asap.) */ static ptr_t size_zero_object = (ptr_t)(&size_zero_object); -void GC_delete_thread(pthread_t id); +void GC_delete_gc_thread(pthread_t id, GC_thread gct); +void GC_destroy_thread_local(GC_thread p); void GC_thread_deregister_foreign (void *data) { @@ -230,7 +254,10 @@ void GC_thread_deregister_foreign (void *data) if (me -> flags & FOREIGN_THREAD) { LOCK(); /* GC_fprintf0( "\n\n\n\n --- FOO ---\n\n\n\n\n" ); */ - GC_delete_thread(me->id); +#if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) + GC_destroy_thread_local (me); +#endif + GC_delete_gc_thread(me->id, me); UNLOCK(); } } @@ -681,6 +708,15 @@ 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); +#endif + GC_INTERNAL_FREE(p); } @@ -703,6 +739,11 @@ void GC_delete_gc_thread(pthread_t id, GC_thread gc_id) } else { prev -> next = p -> next; } + +#ifdef GC_DARWIN_THREADS + mach_port_deallocate(mach_task_self(), p->stop_info.mach_thread); +#endif + GC_INTERNAL_FREE(p); } @@ -756,11 +797,12 @@ void GC_remove_all_threads_but_me(void) GC_destroy_thread_local(p); } # endif /* THREAD_LOCAL_ALLOC */ - if (p != &first_thread) GC_INTERNAL_FREE(p); + if (p != &first_thread) GC_INTERNAL_FREE(p); } } GC_threads[hv] = me; } + GC_INTERNAL_FREE(p); } #endif /* HANDLE_FORK */ @@ -937,9 +979,9 @@ int GC_get_nprocs() /* We hold the allocation lock. */ void GC_thr_init() { -# ifndef GC_DARWIN_THREADS - int dummy; -# endif +# ifndef GC_DARWIN_THREADS + int dummy; +# endif GC_thread t; if (GC_thr_initialized) return; @@ -958,6 +1000,10 @@ 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) + gc_thread_vtable->thread_created (pthread_self (), &t->stop_info.stack_ptr); +#endif GC_stop_init(); @@ -971,14 +1017,15 @@ void GC_thr_init() # if defined(GC_HPUX_THREADS) GC_nprocs = pthread_num_processors_np(); # endif -# if defined(GC_OSF1_THREADS) +# if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS) GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN); if (GC_nprocs <= 0) GC_nprocs = 1; # endif -# if defined(GC_FREEBSD_THREADS) - GC_nprocs = 1; +# if defined(GC_IRIX_THREADS) + GC_nprocs = sysconf(_SC_NPROC_ONLN); + if (GC_nprocs <= 0) GC_nprocs = 1; # endif -# if defined(GC_DARWIN_THREADS) +# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS) || defined(GC_NETBSD_THREADS) int ncpus = 1; size_t len = sizeof(ncpus); sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0); @@ -1025,6 +1072,8 @@ void GC_thr_init() /* Disable true incremental collection, but generational is OK. */ GC_time_limit = GC_TIME_UNLIMITED; } + /* If we are using a parallel marker, actually start helper threads. */ + if (GC_parallel) start_mark_threads(); # endif } @@ -1041,10 +1090,6 @@ void GC_init_parallel() /* GC_init() calls us back, so set flag first. */ if (!GC_is_initialized) GC_init(); - /* If we are using a parallel marker, start the helper threads. */ -# ifdef PARALLEL_MARK - if (GC_parallel) start_mark_threads(); -# endif /* Initialize thread local free lists if used. */ # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) LOCK(); @@ -1264,6 +1309,10 @@ 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) + gc_thread_vtable->thread_created (my_pthread, &me->stop_info.stack_ptr); +#endif UNLOCK(); if (start) *start = si -> start_routine; @@ -1285,7 +1334,9 @@ int GC_thread_register_foreign (void *base_addr) struct start_info si = { 0, }; /* stacked for legibility & locking */ GC_thread me; - GC_printf1( "GC_thread_register_foreign %p\n", &si ); +# ifdef DEBUG_THREADS + GC_printf1( "GC_thread_register_foreign %p\n", &si ); +# endif si.flags = FOREIGN_THREAD; @@ -1356,7 +1407,7 @@ WRAP_FUNC(pthread_create)(pthread_t *new_thread, if (!GC_thr_initialized) GC_thr_init(); # ifdef GC_ASSERTIONS { - int stack_size; + size_t stack_size; if (NULL == attr) { pthread_attr_t my_attr; pthread_attr_init(&my_attr); @@ -1364,7 +1415,13 @@ WRAP_FUNC(pthread_create)(pthread_t *new_thread, } else { pthread_attr_getstacksize(attr, &stack_size); } - GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word))); +# ifdef PARALLEL_MARK + GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word))); +# else + /* FreeBSD-5.3/Alpha: default pthread stack is 64K, */ + /* HBLKSIZE=8192, sizeof(word)=8 */ + GC_ASSERT(stack_size >= 65536); +# endif /* Our threads may need to do some work for the GC. */ /* Ridiculously small threads won't work, and they */ /* probably wouldn't work anyway. */