summaryrefslogtreecommitdiff
path: root/specific.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2017-08-28 09:27:07 +0300
committerIvan Maidanski <ivmai@mail.ru>2017-08-28 10:46:55 +0300
commit6383cee08869517ec3dee257d0adb582c4fc7805 (patch)
treed8e2caa793f41722461489048ce0929ad334b3e0 /specific.c
parenteb41b8b6ad7efbf740db8c717a2e019cb0bb71d3 (diff)
downloadbdwgc-6383cee08869517ec3dee257d0adb582c4fc7805.tar.gz
Fix GC_remove_specific invocation from remove_all_threads_but_me
(fix commits fcfae7f, 38e65ea) * include/private/specific.h (GC_remove_specific): Define as macro (calls GC_remove_specific_after_fork). * include/private/specific.h (GC_remove_specific_after_fork): New GC_INNER function declaration. * include/private/thread_local_alloc.h [USE_PTHREAD_SPECIFIC || USE_COMPILER_TLS || USE_WIN32_COMPILER_TLS || USE_WIN32_SPECIFIC] (GC_remove_specific_after_fork): New macro (defined to no-op). * pthread_support.c [CAN_HANDLE_FORK && THREAD_LOCAL_ALLOC] (GC_remove_all_threads_but_me): Call GC_remove_specific_after_fork instead of GC_remove_specific (i.e. delete thread-specific control data for the given thread instead of the current one). * win32_threads.c [CAN_HANDLE_FORK && THREAD_LOCAL_ALLOC] Like * specific.c [USE_CUSTOM_SPECIFIC] (GC_setspecific): Add assertion that the allocation lock is held; remove the corresponding comment. * specific.c [USE_CUSTOM_SPECIFIC] (GC_remove_specific): Replace to GC_remove_specific_after_fork (add t argument); replace self local variable with t argument; update comment; * specific.c [USE_CUSTOM_SPECIFIC && CAN_HANDLE_FORK] (GC_remove_specific_after_fork): Add assertion that the allocation lock is held; add comment.
Diffstat (limited to 'specific.c')
-rw-r--r--specific.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/specific.c b/specific.c
index f787fa59..eca2d937 100644
--- a/specific.c
+++ b/specific.c
@@ -46,13 +46,13 @@ GC_INNER int GC_key_create_inner(tsd ** key_ptr)
return 0;
}
-/* Called with the lock held. */
GC_INNER int GC_setspecific(tsd * key, void * value)
{
pthread_t self = pthread_self();
int hash_val = HASH(self);
volatile tse * entry;
+ GC_ASSERT(I_HOLD_LOCK());
GC_ASSERT(self != INVALID_THREADID);
GC_dont_gc++; /* disable GC */
entry = (volatile tse *)MALLOC_CLEAR(sizeof(tse));
@@ -72,18 +72,24 @@ GC_INNER int GC_setspecific(tsd * key, void * value)
return 0;
}
-/* Remove thread-specific data for this thread. Should be called on */
-/* thread exit. */
-GC_INNER void GC_remove_specific(tsd * key)
+/* Remove thread-specific data for a given thread. This function is */
+/* called at fork from the child process for all threads except for the */
+/* survived one. GC_remove_specific() should be called on thread exit. */
+GC_INNER void GC_remove_specific_after_fork(tsd * key, pthread_t t)
{
- pthread_t self = pthread_self();
- unsigned hash_val = HASH(self);
+ unsigned hash_val = HASH(t);
tse *entry;
tse **link = &key->hash[hash_val].p;
+# ifdef CAN_HANDLE_FORK
+ /* Both GC_setspecific and GC_remove_specific should be called */
+ /* with the allocation lock held to ensure the consistency of */
+ /* the hash table in the forked child. */
+ GC_ASSERT(I_HOLD_LOCK());
+# endif
pthread_mutex_lock(&(key -> lock));
entry = *link;
- while (entry != NULL && entry -> thread != self) {
+ while (entry != NULL && entry -> thread != t) {
link = &(entry -> next);
entry = *link;
}