]> granicus.if.org Git - gc/commitdiff
Fix checks of thread-local free-lists.
authorPetter Urkedal <paurkedal@gmail.com>
Fri, 20 Apr 2012 08:03:28 +0000 (10:03 +0200)
committerPetter Urkedal <paurkedal@gmail.com>
Fri, 20 Apr 2012 08:03:28 +0000 (10:03 +0200)
* include/private/gc_priv.h, alloc.c (GC_check_fl_marks): Re-read each
pointer before following the pointed-to link, and bail out if the result is
different.  This can happen if the thread has popped the object off the
free-list.  The prototype is changed to allow re-reading the pointers.
* thread_local_alloc.c (GC_check_tls_for): Adjust the calls accordingly.

alloc.c
include/private/gc_priv.h
thread_local_alloc.c

diff --git a/alloc.c b/alloc.c
index ac019079af2b247214c60386e499f2e6c3fe5474..32f1b7169b7d754708da3019b43b555d0027f8c6 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -732,15 +732,23 @@ GC_INNER void GC_set_fl_marks(ptr_t q)
 #ifdef GC_ASSERTIONS
   /* Check that all mark bits for the free list whose first entry is q  */
   /* are set.                                                           */
-  void GC_check_fl_marks(ptr_t q)
+  void GC_check_fl_marks(AO_t *q)
   {
-   ptr_t p;
-   for (p = q; p != 0; p = obj_link(p)) {
-       if (!GC_is_marked(p)) {
-           GC_err_printf("Unmarked object %p on list %p\n", p, q);
-           ABORT("Unmarked local free list entry");
-       }
-   }
+    AO_t *p, *p_next;
+    p = (AO_t *)AO_load_acquire_read(q);
+    if ((word)p < HBLKSIZE)
+        return;
+    while (p != NULL) {
+        if (!GC_is_marked(p)) {
+            GC_err_printf("Unmarked object %p on list %p\n", p, q);
+            ABORT("Unmarked local free list entry");
+        }
+        p_next = (AO_t *)AO_load_acquire_read(p);
+        if (p != (AO_t *)AO_load_acquire_read(q))
+            break;
+        q = p;
+        p = p_next;
+    }
   }
 #endif
 
index eeac7ec3e65564eacb5c5f0a0709f971a27b0a28..70099559ac262ca1d867e0abe8393c9078ab26c8 100644 (file)
@@ -1588,7 +1588,7 @@ GC_INNER void GC_set_fl_marks(ptr_t p);
                                     /* Set all mark bits associated with */
                                     /* a free list.                      */
 #ifdef GC_ASSERTIONS
-  void GC_check_fl_marks(ptr_t p);
+  void GC_check_fl_marks(AO_t *p);
                                     /* Check that all mark bits         */
                                     /* associated with a free list are  */
                                     /* set.  Abort if not.              */
index 362891017c062a0f3be8b5e92ff0f91eb142f5cf..814139072475377d479332c56c97d2a15332cafb 100644 (file)
@@ -310,22 +310,16 @@ GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p)
     /* Check that all thread-local free-lists in p are completely marked. */
     void GC_check_tls_for(GC_tlfs p)
     {
-        ptr_t q;
         int j;
 
         for (j = 1; j < TINY_FREELISTS; ++j) {
-          q = p -> ptrfree_freelists[j];
-          if ((word)q > HBLKSIZE) GC_check_fl_marks(q);
-          q = p -> normal_freelists[j];
-          if ((word)q > HBLKSIZE) GC_check_fl_marks(q);
+          GC_check_fl_marks((AO_t *)&p -> ptrfree_freelists[j]);
+          GC_check_fl_marks((AO_t *)&p -> normal_freelists[j]);
 #         ifdef GC_GCJ_SUPPORT
-            q = p -> gcj_freelists[j];
-            if ((word)q > HBLKSIZE) GC_check_fl_marks(q);
+            GC_check_fl_marks((AO_t *)&p -> gcj_freelists[j]);
 #         endif
 #         ifdef ENABLE_DISCLAIM
-            q = p -> finalized_freelists[j];
-            if ((word)q > HBLKSIZE)
-              GC_check_fl_marks(q);
+            GC_check_fl_marks((AO_t *)&p -> finalized_freelists[j]);
 #         endif
         }
     }