diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2018-05-07 11:05:15 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2018-05-07 11:05:15 +0300 |
commit | 38d194a365e2e0cbb88601f380df9b8dbf6b0b1d (patch) | |
tree | 4e45b0c0783e7bd1a43ba67e12cb74b7648f980e | |
parent | 7924905759fe3b259b04ac8f66ee54c9a6498f4f (diff) | |
download | bdwgc-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.c | 4 | ||||
-rw-r--r-- | include/private/gc_priv.h | 3 | ||||
-rw-r--r-- | mark_rts.c | 43 |
3 files changed, 50 insertions, 0 deletions
@@ -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) @@ -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: */ |