]> granicus.if.org Git - gc/commitdiff
Keep pointer to the start of previous entry in remove_specific_after_fork
authorIvan Maidanski <ivmai@mail.ru>
Tue, 8 May 2018 18:36:41 +0000 (21:36 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 17 Jul 2018 07:29:43 +0000 (10:29 +0300)
(a cherry-pick of commit 510fb9f6 from 'master')

* specific.c [USE_CUSTOM_SPECIFIC] (GC_remove_specific_after_fork):
Replace tse** link local variable with tse* prev one; replace *link
with either key->hash[hash_val].p or prev->next.

specific.c

index 8f883af8a966fb9399ca936a25446ee1712441f9..3c25a622104184971d278d58ab8d6543ee84efe7 100644 (file)
@@ -79,7 +79,7 @@ GC_INNER void GC_remove_specific_after_fork(tsd * key, pthread_t t)
 {
     unsigned hash_val = HASH(t);
     tse *entry;
-    tse **link = &key->hash[hash_val].p;
+    tse *prev = NULL;
 
 #   ifdef CAN_HANDLE_FORK
       /* Both GC_setspecific and GC_remove_specific should be called    */
@@ -88,16 +88,20 @@ GC_INNER void GC_remove_specific_after_fork(tsd * key, pthread_t t)
       GC_ASSERT(I_HOLD_LOCK());
 #   endif
     pthread_mutex_lock(&(key -> lock));
-    entry = *link;
+    entry = key->hash[hash_val].p;
     while (entry != NULL && entry -> thread != t) {
-      link = &(entry -> next);
-      entry = *link;
+      prev = entry;
+      entry = entry->next;
     }
     /* Invalidate qtid field, since qtids may be reused, and a later    */
     /* cache lookup could otherwise find this entry.                    */
     if (entry != NULL) {
       entry -> qtid = INVALID_QTID;
-      *link = entry -> next;
+      if (NULL == prev) {
+        key->hash[hash_val].p = entry->next;
+      } else {
+        prev->next = entry->next;
+      }
       /* Atomic! concurrent accesses still work.        */
       /* They must, since readers don't lock.           */
       /* We shouldn't need a volatile access here,      */