# 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)
}
}
+#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)
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;