summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2018-05-07 11:05:15 +0300
committerIvan Maidanski <ivmai@mail.ru>2018-05-07 11:05:15 +0300
commit38d194a365e2e0cbb88601f380df9b8dbf6b0b1d (patch)
tree4e45b0c0783e7bd1a43ba67e12cb74b7648f980e
parent7924905759fe3b259b04ac8f66ee54c9a6498f4f (diff)
downloadbdwgc-38d194a365e2e0cbb88601f380df9b8dbf6b0b1d.tar.gz
Fix infinite restarting of mark_some when a static root disappeared (Linux)
Issue #218 (bdwgc). * dyn_load.c [USE_PROC_FOR_LIBRARIES] (GC_register_map_entries): Call GC_remove_roots_subregion for each region which has prot starting with "---"; add comment. * include/private/gc_priv.h [USE_PROC_FOR_LIBRARIES] (GC_remove_roots_subregion): Declare function. * mark_rts.c[USE_PROC_FOR_LIBRARIES] (GC_remove_roots_subregion): Implement.
-rw-r--r--dyn_load.c4
-rw-r--r--include/private/gc_priv.h3
-rw-r--r--mark_rts.c43
3 files changed, 50 insertions, 0 deletions
diff --git a/dyn_load.c b/dyn_load.c
index 4072751e..6692321c 100644
--- a/dyn_load.c
+++ b/dyn_load.c
@@ -389,6 +389,10 @@ STATIC void GC_register_map_entries(char *maps)
}
if ((word)start < (word)end)
GC_add_roots_inner(start, end, TRUE);
+ } else if (prot[0] == '-' && prot[1] == '-' && prot[2] == '-') {
+ /* Even roots added statically might disappear partially */
+ /* (e.g. the roots added by INCLUDE_LINUX_THREAD_DESCR). */
+ GC_remove_roots_subregion(start, end);
}
}
}
diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h
index 5ac127a0..e4f0c228 100644
--- a/include/private/gc_priv.h
+++ b/include/private/gc_priv.h
@@ -1803,6 +1803,9 @@ GC_INNER void GC_set_fl_marks(ptr_t p);
/* set. Abort if not. */
#endif
void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp);
+#ifdef USE_PROC_FOR_LIBRARIES
+ GC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e);
+#endif
GC_INNER void GC_exclude_static_roots_inner(void *start, void *finish);
#if defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \
|| defined(CYGWIN32) || defined(PCR)
diff --git a/mark_rts.c b/mark_rts.c
index 1499e457..a179effb 100644
--- a/mark_rts.c
+++ b/mark_rts.c
@@ -372,6 +372,49 @@ STATIC void GC_remove_tmp_roots(void)
}
#endif /* !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) */
+#ifdef USE_PROC_FOR_LIBRARIES
+ /* If there is a static root containing [b,e) then replace this root */
+ /* [r_start,r_end) with roots [r_start,b) and [e,r_end). */
+ /* It is assumed that GC_remove_tmp_roots() is called before this */
+ /* function is called repeatedly by GC_register_map_entries(). */
+ GC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e)
+ {
+ int i;
+
+ GC_ASSERT(I_HOLD_LOCK());
+ for (i = 0; i < n_root_sets; i++) {
+ ptr_t r_start, r_end;
+
+ if (GC_static_roots[i].r_tmp) {
+ /* The remaining roots are skipped as they are all temporary. */
+# ifdef GC_ASSERTIONS
+ int j;
+ for (j = i + 1; j < n_root_sets; j++) {
+ GC_ASSERT(GC_static_roots[j].r_tmp);
+ }
+# endif
+ break;
+ }
+ r_start = GC_static_roots[i].r_start;
+ r_end = GC_static_roots[i].r_end;
+ if (EXPECT((word)r_start <= (word)b && (word)e <= (word)r_end, FALSE)) {
+# ifdef DEBUG_ADD_DEL_ROOTS
+ GC_log_printf("Removing %p .. %p from root section %d (%p .. %p)\n",
+ (void *)b, (void *)e,
+ i, (void *)r_start, (void *)r_end);
+# endif
+ GC_remove_root_at_pos(i);
+ GC_rebuild_root_index();
+ if ((word)r_start < (word)b)
+ GC_add_roots_inner(r_start, b, FALSE);
+ if ((word)e < (word)r_end)
+ GC_add_roots_inner(e, r_end, FALSE);
+ break;
+ }
+ }
+ }
+#endif /* USE_PROC_FOR_LIBRARIES */
+
#if !defined(NO_DEBUGGING)
/* For the debugging purpose only. */
/* Workaround for the OS mapping and unmapping behind our back: */