From 3ec8d801c187bbcdbb9c1552aafb3ec7b7a95df6 Mon Sep 17 00:00:00 2001 From: Petter Urkedal Date: Fri, 20 Apr 2012 10:03:28 +0200 Subject: [PATCH] Fix checks of thread-local free-lists. * 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 | 24 ++++++++++++++++-------- include/private/gc_priv.h | 2 +- thread_local_alloc.c | 14 ++++---------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/alloc.c b/alloc.c index ac019079..32f1b716 100644 --- 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 diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index eeac7ec3..70099559 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -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. */ diff --git a/thread_local_alloc.c b/thread_local_alloc.c index 36289101..81413907 100644 --- a/thread_local_alloc.c +++ b/thread_local_alloc.c @@ -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 } } -- 2.40.0