diff options
author | Niklas Therning <niklas@therning.org> | 2015-01-06 23:32:43 +0100 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2015-09-04 20:36:50 +0300 |
commit | 2c870edc641f6b9e565f7cd297251cfd83de76af (patch) | |
tree | 740321c4b4718e4f0235c4b7ba47907062470030 | |
parent | 60db5e97e8c61652f9b29b201832eaadd18f1dfc (diff) | |
download | bdwgc-2c870edc641f6b9e565f7cd297251cfd83de76af.tar.gz |
Fix (allow) thread local allocations from within pthread TLS destructors
Prevents the GC_thread_key from being cleared on thread exit until
after the thread has been unregistered by GC_unregister_my_thread_inner.
* include/private/thread_local_alloc.h (GC_remove_specific): Call
pthread_setspecific(key, NULL) if USE_PTHREAD_SPECIFIC; update comment.
* thread_local_alloc.c (reset_thread_key): New static function if
USE_PTHREAD_SPECIFIC); define (as macro) to 0 otherwise.
* thread_local_alloc.c (GC_init_thread_local): Pass reset_thread_key
(instead of 0) to GC_key_create.
-rw-r--r-- | include/private/thread_local_alloc.h | 4 | ||||
-rw-r--r-- | thread_local_alloc.c | 15 |
2 files changed, 17 insertions, 2 deletions
diff --git a/include/private/thread_local_alloc.h b/include/private/thread_local_alloc.h index 82fe2987..ffa98c49 100644 --- a/include/private/thread_local_alloc.h +++ b/include/private/thread_local_alloc.h @@ -108,7 +108,9 @@ 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. */ +# define GC_remove_specific(key) pthread_setspecific(key, NULL) + /* Explicitly delete the value to stop the TLS */ + /* destructor from being called repeatedly. */ typedef pthread_key_t GC_key_t; #elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS) # define GC_getspecific(x) (x) diff --git a/thread_local_alloc.c b/thread_local_alloc.c index 8d184f51..29a337b2 100644 --- a/thread_local_alloc.c +++ b/thread_local_alloc.c @@ -82,6 +82,19 @@ static void return_freelists(void **fl, void **gfl) } } +#ifdef USE_PTHREAD_SPECIFIC + /* Re-set the TLS value on thread cleanup to allow thread-local */ + /* allocations to happen in the TLS destructors. */ + /* GC_unregister_my_thread (and similar routines) will finally set */ + /* the GC_thread_key to NULL preventing this destructor from being */ + /* called repeatedly. */ + static void reset_thread_key(void* v) { + pthread_setspecific(GC_thread_key, v); + } +#else +# define reset_thread_key 0 +#endif + /* Each thread structure must be initialized. */ /* This call must be made from the new thread. */ GC_INNER void GC_init_thread_local(GC_tlfs p) @@ -91,7 +104,7 @@ GC_INNER void GC_init_thread_local(GC_tlfs p) GC_ASSERT(I_HOLD_LOCK()); if (!EXPECT(keys_initialized, TRUE)) { GC_ASSERT((word)&GC_thread_key % sizeof(word) == 0); - if (0 != GC_key_create(&GC_thread_key, 0)) { + if (0 != GC_key_create(&GC_thread_key, reset_thread_key)) { ABORT("Failed to create key for local allocator"); } keys_initialized = TRUE; |