From: ivmai Date: Wed, 11 May 2011 07:19:46 +0000 (+0000) Subject: 2011-05-11 Ivan Maidanski X-Git-Tag: gc7_2alpha6~33 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=88a952ac5dd3c0582a82a1f2acfa277f5eaf4047;p=gc 2011-05-11 Ivan Maidanski * pthread_support.c (GC_unregister_my_thread_inner): Don't call GC_remove_specific. * include/private/thread_local_alloc.h (GC_remove_specific): Remove (since it is empty for all targets). * pthread_support.c (GC_record_stack_base): New inline function. * win32_threads.c (GC_record_stack_base): Ditto. * pthread_support.c (GC_register_my_thread_inner): Invoke GC_record_stack_base. * win32_threads.c (GC_register_my_thread_inner): Ditto. * pthread_support.c (GC_register_my_thread): If thread is FINISHED then call GC_record_stack_base, clear FINISHED, initialize thread-local list and return success. * win32_threads.c (GC_register_my_thread): Ditto. * include/gc.h (GC_register_my_thread): Update documentation. * include/private/thread_local_alloc.h (GC_thread_key): Ditto. --- diff --git a/ChangeLog b/ChangeLog index 457a1d76..8820d38d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2011-05-11 Ivan Maidanski + + * pthread_support.c (GC_unregister_my_thread_inner): Don't call + GC_remove_specific. + * include/private/thread_local_alloc.h (GC_remove_specific): + Remove (since it is empty for all targets). + * pthread_support.c (GC_record_stack_base): New inline function. + * win32_threads.c (GC_record_stack_base): Ditto. + * pthread_support.c (GC_register_my_thread_inner): Invoke + GC_record_stack_base. + * win32_threads.c (GC_register_my_thread_inner): Ditto. + * pthread_support.c (GC_register_my_thread): If thread is FINISHED + then call GC_record_stack_base, clear FINISHED, initialize + thread-local list and return success. + * win32_threads.c (GC_register_my_thread): Ditto. + * include/gc.h (GC_register_my_thread): Update documentation. + * include/private/thread_local_alloc.h (GC_thread_key): Ditto. + 2011-05-10 Ivan Maidanski * thread_local_alloc.c (GC_malloc, GC_malloc_atomic): Join diff --git a/include/gc.h b/include/gc.h index e94a943e..8c996cbc 100644 --- a/include/gc.h +++ b/include/gc.h @@ -1044,7 +1044,10 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */, /* always done implicitly. This is normally done implicitly if GC_ */ /* functions are called to create the thread, e.g. by including gc.h */ /* (which redefines some system functions) before calling the system */ - /* thread creation function. */ + /* thread creation function. Nonetheless, thread cleanup routines */ + /* (eg., pthread key destructor) typically require manual thread */ + /* registering (and unregistering) if pointers to GC-allocated */ + /* objects are manipulated inside. */ /* It is also always done implicitly on some platforms if */ /* GC_use_threads_discovery() is called at start-up. Except for the */ /* latter case, the explicit call is normally required for threads */ diff --git a/include/private/thread_local_alloc.h b/include/private/thread_local_alloc.h index 20995a8c..93f943d2 100644 --- a/include/private/thread_local_alloc.h +++ b/include/private/thread_local_alloc.h @@ -97,13 +97,11 @@ typedef struct thread_local_freelists { # define GC_getspecific pthread_getspecific # define GC_setspecific pthread_setspecific # define GC_key_create pthread_key_create -# define GC_remove_specific(key) /* No need for cleanup on exit. */ typedef pthread_key_t GC_key_t; # elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS) # define GC_getspecific(x) (x) # define GC_setspecific(key, v) ((key) = (v), 0) # define GC_key_create(key, d) 0 -# define GC_remove_specific(key) /* No need for cleanup on exit. */ typedef void * GC_key_t; # elif defined(USE_WIN32_SPECIFIC) # ifndef WIN32_LEAN_AND_MEAN @@ -120,7 +118,6 @@ typedef struct thread_local_freelists { # endif # define GC_key_create(key, d) \ ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0) -# define GC_remove_specific(key) /* No need for cleanup on thread exit. */ /* Need TlsFree on process exit/detach ? */ typedef DWORD GC_key_t; # elif defined(USE_CUSTOM_SPECIFIC) @@ -152,12 +149,9 @@ extern __declspec(thread) #endif GC_key_t GC_thread_key; - -/* This is set up by the thread_local_alloc implementation. But the */ -/* thread support layer calls GC_remove_specific(GC_thread_key) */ -/* before a thread exits. */ -/* And the thread support layer makes sure that GC_thread_key is traced,*/ -/* if necessary. */ +/* This is set up by the thread_local_alloc implementation. No need */ +/* for cleanup on thread exit. But the thread support layer makes sure */ +/* that GC_thread_key is traced, if necessary. */ #endif /* THREAD_LOCAL_ALLOC */ diff --git a/pthread_support.c b/pthread_support.c index a6a5a5a3..af16a57d 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1183,9 +1183,6 @@ STATIC void GC_unregister_my_thread_inner(GC_thread me) } else { me -> flags |= FINISHED; } -# if defined(THREAD_LOCAL_ALLOC) - GC_remove_specific(GC_thread_key); -# endif } GC_API int GC_CALL GC_unregister_my_thread(void) @@ -1344,6 +1341,20 @@ GC_API int WRAP_FUNC(pthread_detach)(pthread_t thread) GC_INNER GC_bool GC_in_thread_creation = FALSE; /* Protected by allocation lock. */ +GC_INLINE void GC_record_stack_base(GC_thread me, + const struct GC_stack_base *sb) +{ +# ifndef GC_DARWIN_THREADS + me -> stop_info.stack_ptr = sb -> mem_base; +# endif + me -> stack_end = sb -> mem_base; + if (me -> stack_end == NULL) + ABORT("Bad stack base in GC_register_my_thread"); +# ifdef IA64 + me -> backing_store_end = sb -> reg_base; +# endif +} + STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, pthread_t my_pthread) { @@ -1356,15 +1367,8 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, ABORT("Failed to allocate memory for thread registering"); # ifdef GC_DARWIN_THREADS me -> stop_info.mach_thread = mach_thread_self(); -# else - me -> stop_info.stack_ptr = sb -> mem_base; # endif - me -> stack_end = sb -> mem_base; - if (me -> stack_end == NULL) - ABORT("Bad stack base in GC_register_my_thread"); -# ifdef IA64 - me -> backing_store_end = sb -> reg_base; -# endif /* IA64 */ + GC_record_stack_base(me, sb); return me; } @@ -1387,8 +1391,13 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) LOCK(); me = GC_lookup_thread(self); - if (0 == me) { - me = GC_register_my_thread_inner(sb, self); + if (0 == me || (me -> flags & FINISHED) != 0) { + if (me == 0) { + me = GC_register_my_thread_inner(sb, self); + } else { + GC_record_stack_base(me, sb); + me -> flags &= ~FINISHED; + } me -> flags |= DETACHED; /* Treat as detached, since we do not need to worry about */ /* pointer results. */ diff --git a/win32_threads.c b/win32_threads.c index a9b406ab..8e0bcc53 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -364,6 +364,17 @@ STATIC GC_thread GC_new_thread(DWORD id) STATIC GC_bool GC_in_thread_creation = FALSE; /* Protected by allocation lock. */ +GC_INLINE void GC_record_stack_base(GC_vthread me, + const struct GC_stack_base *sb) +{ + me -> stack_base = sb -> mem_base; +# ifdef IA64 + me -> backing_store_end = sb -> reg_base; +# endif + if (me -> stack_base == NULL) + ABORT("Bad stack base in GC_register_my_thread"); +} + /* This may be called from DllMain, and hence operates under unusual */ /* constraints. In particular, it must be lock-free if */ /* GC_win32_dll_threads is set. Always called from the thread being */ @@ -456,10 +467,7 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, } # endif me -> last_stack_min = ADDR_LIMIT; - me -> stack_base = sb -> mem_base; -# ifdef IA64 - me -> backing_store_end = sb -> reg_base; -# endif + GC_record_stack_base(me, sb); /* Up until this point, GC_push_all_stacks considers this thread */ /* invalid. */ /* Up until this point, this entry is viewed as reserved but invalid */ @@ -468,8 +476,6 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb, # if defined(THREAD_LOCAL_ALLOC) GC_init_thread_local((GC_tlfs)(&(me->tlfs))); # endif - if (me -> stack_base == NULL) - ABORT("Bad stack base in GC_register_my_thread_inner"); # ifndef GC_NO_THREADS_DISCOVERY if (GC_win32_dll_threads) { if (GC_please_stop) { @@ -707,6 +713,7 @@ GC_API void GC_CALL GC_allow_register_threads(void) GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) { + GC_thread me; DWORD thread_id = GetCurrentThreadId(); DCL_LOCK_STATE; @@ -715,11 +722,27 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) /* We lock here, since we want to wait for an ongoing GC. */ LOCK(); - if (0 == GC_lookup_thread_inner(thread_id)) { + me = GC_lookup_thread_inner(thread_id); + if (me == 0) { GC_register_my_thread_inner(sb, thread_id); +# ifdef GC_PTHREADS + me -> flags |= DETACHED; +# endif UNLOCK(); return GC_SUCCESS; - } else { + } else +# ifdef GC_PTHREADS + /* else */ if ((me -> flags & FINISHED) != 0) { + GC_record_stack_base(me, sb); + me -> flags = (me -> flags & ~FINISHED) | DETACHED; +# ifdef THREAD_LOCAL_ALLOC + GC_init_thread_local((GC_tlfs)(&me->tlfs)); +# endif + UNLOCK(); + return GC_SUCCESS; + } else +# endif + /* else */ { UNLOCK(); return GC_DUPLICATE; }